i2c_avr.c

Go to the documentation of this file.
00001 
00041 #include "hw/hw_cpu.h"  /* CLOCK_FREQ */
00042 
00043 #include "cfg/cfg_i2c.h"
00044 
00045 #define LOG_LEVEL  I2C_LOG_LEVEL
00046 #define LOG_FORMAT I2C_LOG_FORMAT
00047 
00048 #include <cfg/log.h>
00049 
00050 #include <cfg/debug.h>
00051 #include <cfg/macros.h> // BV()
00052 #include <cfg/module.h>
00053 
00054 #include <cpu/detect.h>
00055 #include <cpu/irq.h>
00056 #include <drv/timer.h>
00057 #include <drv/i2c.h>
00058 
00059 #include <compat/twi.h>
00060 
00061 
00062 /* Wait for TWINT flag set: bus is ready */
00063 #define WAIT_TWI_READY  do {} while (!(TWCR & BV(TWINT)))
00064 
00070 static bool i2c_builtin_start(void)
00071 {
00072     TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
00073     WAIT_TWI_READY;
00074 
00075     if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
00076         return true;
00077 
00078     LOG_ERR("!TW_(REP)START: %x\n", TWSR);
00079     return false;
00080 }
00081 
00082 
00090 bool i2c_builtin_start_w(uint8_t id)
00091 {
00092     /*
00093      * Loop on the select write sequence: when the eeprom is busy
00094      * writing previously sent data it will reply to the SLA_W
00095      * control byte with a NACK.  In this case, we must
00096      * keep trying until the eeprom responds with an ACK.
00097      */
00098     ticks_t start = timer_clock();
00099     while (i2c_builtin_start())
00100     {
00101         TWDR = id & ~I2C_READBIT;
00102         TWCR = BV(TWINT) | BV(TWEN);
00103         WAIT_TWI_READY;
00104 
00105         if (TW_STATUS == TW_MT_SLA_ACK)
00106             return true;
00107         else if (TW_STATUS != TW_MT_SLA_NACK)
00108         {
00109             LOG_ERR("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
00110             break;
00111         }
00112         else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
00113         {
00114             LOG_ERR("Timeout on TWI_MT_START\n");
00115             break;
00116         }
00117     }
00118 
00119     return false;
00120 }
00121 
00122 
00130 bool i2c_builtin_start_r(uint8_t id)
00131 {
00132     if (i2c_builtin_start())
00133     {
00134         TWDR = id | I2C_READBIT;
00135         TWCR = BV(TWINT) | BV(TWEN);
00136         WAIT_TWI_READY;
00137 
00138         if (TW_STATUS == TW_MR_SLA_ACK)
00139             return true;
00140 
00141         LOG_ERR("!TW_MR_SLA_ACK: %x\n", TWSR);
00142     }
00143 
00144     return false;
00145 }
00146 
00147 
00151 void i2c_builtin_stop(void)
00152 {
00153         TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
00154 }
00155 
00156 
00163 bool i2c_builtin_put(const uint8_t data)
00164 {
00165     TWDR = data;
00166     TWCR = BV(TWINT) | BV(TWEN);
00167     WAIT_TWI_READY;
00168     if (TW_STATUS != TW_MT_DATA_ACK)
00169     {
00170         LOG_ERR("!TW_MT_DATA_ACK: %x\n", TWSR);
00171         return false;
00172     }
00173     return true;
00174 }
00175 
00184 int i2c_builtin_get(bool ack)
00185 {
00186     TWCR = BV(TWINT) | BV(TWEN) | (ack ? BV(TWEA) : 0);
00187     WAIT_TWI_READY;
00188 
00189     if (ack)
00190     {
00191         if (TW_STATUS != TW_MR_DATA_ACK)
00192         {
00193             LOG_ERR("!TW_MR_DATA_ACK: %x\n", TWSR);
00194             return EOF;
00195         }
00196     }
00197     else
00198     {
00199         if (TW_STATUS != TW_MR_DATA_NACK)
00200         {
00201             LOG_ERR("!TW_MR_DATA_NACK: %x\n", TWSR);
00202             return EOF;
00203         }
00204     }
00205 
00206     /* avoid sign extension */
00207     return (int)(uint8_t)TWDR;
00208 }
00209 
00210 MOD_DEFINE(i2c);
00211 
00215 void i2c_builtin_init(void)
00216 {
00217     ATOMIC(
00218         /*
00219          * This is pretty useless according to AVR's datasheet,
00220          * but it helps us driving the TWI data lines on boards
00221          * where the bus pull-up resistors are missing.  This is
00222          * probably due to some unwanted interaction between the
00223          * port pin and the TWI lines.
00224          */
00225 #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281
00226         PORTD |= BV(PD0) | BV(PD1);
00227         DDRD  |= BV(PD0) | BV(PD1);
00228 #elif CPU_AVR_ATMEGA8
00229         PORTC |= BV(PC4) | BV(PC5);
00230         DDRC  |= BV(PC4) | BV(PC5);
00231 #elif CPU_AVR_ATMEGA32
00232         PORTC |= BV(PC1) | BV(PC0);
00233         DDRC  |= BV(PC1) | BV(PC0);
00234 #else
00235         #error Unsupported architecture
00236 #endif
00237 
00238         /*
00239          * Set speed:
00240          * F = CLOCK_FREQ / (16 + 2*TWBR * 4^TWPS)
00241          */
00242         #ifndef CONFIG_I2C_FREQ
00243             #warning Using default value of 300000L for CONFIG_I2C_FREQ
00244             #define CONFIG_I2C_FREQ  300000L /* ~300 kHz */
00245         #endif
00246         #define TWI_PRESC 1       /* 4 ^ TWPS */
00247 
00248         TWBR = (CLOCK_FREQ / (2 * CONFIG_I2C_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);
00249         TWSR = 0;
00250         TWCR = BV(TWEN);
00251     );
00252     MOD_INIT(i2c);
00253 }