X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=drv%2Ftwi_avr.c;h=bd4fcfd7bbe3d83a869c29ea8d827ec81359d8d2;hb=HEAD;hp=0d03950f95fe22d74e5763be804c0f0abd448ff5;hpb=1121818c76981217b8f9224a20cd084cc4f113a4;p=bertos.git diff --git a/drv/twi_avr.c b/drv/twi_avr.c deleted file mode 100644 index 0d03950f..00000000 --- a/drv/twi_avr.c +++ /dev/null @@ -1,293 +0,0 @@ -/** - * \file - * - * - * \brief Driver for the AVR ATMega TWI (implementation) - * - * \version $Id$ - * - * \author Stefano Fedrigo - * \author Bernardo Innocenti - */ - -/*#* - *#* $Log$ - *#* Revision 1.8 2007/06/07 14:35:12 batt - *#* Merge from project_ks. - *#* - *#* Revision 1.7 2006/07/19 12:56:26 bernie - *#* Convert to new Doxygen style. - *#* - *#* Revision 1.6 2006/03/20 17:49:50 bernie - *#* Make the TWI driver more generic to work with devices other than EEPROMS. - *#* - *#* Revision 1.5 2005/11/27 23:33:40 bernie - *#* Use appconfig.h instead of cfg/config.h. - *#* - *#* Revision 1.4 2005/04/11 19:10:28 bernie - *#* Include top-level headers from cfg/ subdir. - *#* - *#* Revision 1.3 2005/03/01 23:26:00 bernie - *#* Header fix. - *#* - *#* Revision 1.2 2005/01/25 08:36:56 bernie - *#* CONFIG_TWI_FREQ: New config param. - *#* - *#* Revision 1.1 2005/01/06 16:09:40 aleph - *#* Split twi/eeprom functions from eeprom module in separate twi module - *#* - *#*/ - -#include "twi.h" - -#include -#include -#include // BV() -#include /* CLOCK_FREQ */ -#include - -#include - - -/* Wait for TWINT flag set: bus is ready */ -#define WAIT_TWI_READY do {} while (!(TWCR & BV(TWINT))) - -#define READ_BIT BV(0) - - -/** - * Send START condition on the bus. - * - * \return true on success, false otherwise. - */ -static bool twi_start(void) -{ - TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN); - WAIT_TWI_READY; - - if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START) - return true; - - kprintf("!TW_(REP)START: %x\n", TWSR); - return false; -} - - -/** - * Send START condition and select slave for write. - * \c id is the device id comprehensive of address left shifted by 1. - * The LSB of \c id is ignored and reset to 0 for write operation. - * - * \return true on success, false otherwise. - */ -bool twi_start_w(uint8_t id) -{ - /* - * Loop on the select write sequence: when the eeprom is busy - * writing previously sent data it will reply to the SLA_W - * control byte with a NACK. In this case, we must - * keep trying until the eeprom responds with an ACK. - */ - while (twi_start()) - { - TWDR = id & ~READ_BIT; - TWCR = BV(TWINT) | BV(TWEN); - WAIT_TWI_READY; - - if (TW_STATUS == TW_MT_SLA_ACK) - return true; - else if (TW_STATUS != TW_MT_SLA_NACK) - { - kprintf("!TW_MT_SLA_(N)ACK: %x\n", TWSR); - break; - } - } - - return false; -} - - -/** - * Send START condition and select slave for read. - * \c id is the device id comprehensive of address left shifted by 1. - * The LSB of \c id is ignored and set to 1 for read operation. - * - * \return true on success, false otherwise. - */ -bool twi_start_r(uint8_t id) -{ - if (twi_start()) - { - TWDR = id | READ_BIT; - TWCR = BV(TWINT) | BV(TWEN); - WAIT_TWI_READY; - - if (TW_STATUS == TW_MR_SLA_ACK) - return true; - - kprintf("!TW_MR_SLA_ACK: %x\n", TWSR); - } - - return false; -} - - -/** - * Send STOP condition. - */ -void twi_stop(void) -{ - TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO); -} - - -/** - * Put a single byte in master transmitter mode - * to the selected slave device through the TWI bus. - * - * \return true on success, false on error. - */ -bool twi_put(const uint8_t data) -{ - TWDR = data; - TWCR = BV(TWINT) | BV(TWEN); - WAIT_TWI_READY; - if (TW_STATUS != TW_MT_DATA_ACK) - { - kprintf("!TW_MT_DATA_ACK: %x\n", TWSR); - return false; - } - return true; -} - - -/** - * Send a sequence of bytes in master transmitter mode - * to the selected slave device through the TWI bus. - * - * \return true on success, false on error. - */ -bool twi_send(const void *_buf, size_t count) -{ - const uint8_t *buf = (const uint8_t *)_buf; - - while (count--) - { - if (!twi_put(*buf++)) - return false; - } - return true; -} - - -/** - * Receive a sequence of one or more bytes from the - * selected slave device in master receive mode through - * the TWI bus. - * - * Received data is placed in \c buf. - * - * \return true on success, false on error - */ -bool twi_recv(void *_buf, size_t count) -{ - uint8_t *buf = (uint8_t *)_buf; - - /* - * When reading the last byte the TWEA bit is not - * set, and the eeprom should answer with NACK - */ - while (count--) - { - TWCR = BV(TWINT) | BV(TWEN) | (count ? BV(TWEA) : 0); - WAIT_TWI_READY; - - if (count) - { - if (TW_STATUS != TW_MR_DATA_ACK) - { - kprintf("!TW_MR_DATA_ACK: %x\n", TWSR); - return false; - } - } - else - { - if (TW_STATUS != TW_MR_DATA_NACK) - { - kprintf("!TW_MR_DATA_NACK: %x\n", TWSR); - return false; - } - } - *buf++ = TWDR; - } - - return true; -} - - -/** - * Initialize TWI module. - */ -void twi_init(void) -{ - ATOMIC( - /* - * This is pretty useless according to AVR's datasheet, - * but it helps us driving the TWI data lines on boards - * where the bus pull-up resistors are missing. This is - * probably due to some unwanted interaction between the - * port pin and the TWI lines. - */ -#if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281 - PORTD |= BV(PD0) | BV(PD1); - DDRD |= BV(PD0) | BV(PD1); -#elif CPU_AVR_ATMEGA8 - PORTC |= BV(PC4) | BV(PC5); - DDRC |= BV(PC4) | BV(PC5); -#else - #error Unsupported architecture -#endif - - /* - * Set speed: - * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS) - */ - #ifndef CONFIG_TWI_FREQ - #warning Using default value of 300000L for CONFIG_TWI_FREQ - #define CONFIG_TWI_FREQ 300000L /* ~300 kHz */ - #endif - #define TWI_PRESC 1 /* 4 ^ TWPS */ - - TWBR = (CLOCK_FREQ / (2 * CONFIG_TWI_FREQ * TWI_PRESC)) - (8 / TWI_PRESC); - TWSR = 0; - TWCR = BV(TWEN); - ); -}