i2c_avr.c
Go to the documentation of this file.00001
00041 #include <hw/hw_cpufreq.h>
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>
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
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
00094
00095
00096
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
00207 return (int)(uint8_t)TWDR;
00208 }
00209
00210 MOD_DEFINE(i2c);
00211
00215 void i2c_builtin_init(void)
00216 {
00217 ATOMIC(
00218
00219
00220
00221
00222
00223
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
00240
00241
00242 #ifndef CONFIG_I2C_FREQ
00243 #warning Using default value of 300000L for CONFIG_I2C_FREQ
00244 #define CONFIG_I2C_FREQ 300000L
00245 #endif
00246 #define TWI_PRESC 1
00247
00248 TWBR = (CPU_FREQ / (2 * CONFIG_I2C_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);
00249 TWSR = 0;
00250 TWCR = BV(TWEN);
00251 );
00252 MOD_INIT(i2c);
00253 }