i2c_bitbang.c

Go to the documentation of this file.
00001 
00038 #include "i2c.h"
00039 #include "cfg/cfg_i2c.h"
00040 
00041 #define LOG_LEVEL  I2C_LOG_LEVEL
00042 #define LOG_FORMAT I2C_LOG_FORMAT
00043 
00044 #include <cfg/log.h>
00045 #include <cfg/macros.h>
00046 #include <cfg/module.h>
00047 
00048 #include <drv/timer.h>
00049 #include <cpu/irq.h>
00050 
00051 #include "hw/hw_i2c_bitbang.h"
00052 
00053 INLINE bool i2c_bitbang_start(void)
00054 {
00055     SDA_HI;
00056     SCL_HI;
00057     I2C_HALFBIT_DELAY();
00058     SDA_LO;
00059     I2C_HALFBIT_DELAY();
00060     ASSERT(!SDA_IN);
00061     return !SDA_IN;
00062 }
00063 
00064 void i2c_bitbang_stop(void)
00065 {
00066     SDA_LO;
00067     SCL_HI;
00068     I2C_HALFBIT_DELAY();
00069     SDA_HI;
00070 }
00071 
00072 bool i2c_bitbang_put(uint8_t _data)
00073 {
00074     /* Add ACK bit */
00075     uint16_t data = (_data << 1) | 1;
00076 
00077     for (uint16_t i = 0x100; i != 0; i >>= 1)
00078     {
00079         SCL_LO;
00080         if (data & i)
00081             SDA_HI;
00082         else
00083             SDA_LO;
00084         I2C_HALFBIT_DELAY();
00085 
00086         SCL_HI;
00087         I2C_HALFBIT_DELAY();
00088     }
00089 
00090     bool ack = !SDA_IN;
00091     SCL_LO;
00092     I2C_HALFBIT_DELAY();
00093     return ack;
00094 }
00095 
00096 bool i2c_bitbang_start_w(uint8_t id)
00097 {
00098     id &= ~I2C_READBIT;
00099     /*
00100      * Loop on the select write sequence: when the device is busy
00101      * writing previously sent data it will reply to the SLA_W
00102      * control byte with a NACK.  In this case, we must
00103      * keep trying until the deveice responds with an ACK.
00104      */
00105     ticks_t start = timer_clock();
00106     while (i2c_bitbang_start())
00107     {
00108         if (i2c_bitbang_put(id))
00109             return true;
00110         else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
00111         {
00112             LOG_ERR("Timeout on I2C start write\n");
00113             break;
00114         }
00115         //LOG_INFO("Rep start\n");
00116     }
00117 
00118     return false;
00119 }
00120 
00121 bool i2c_bitbang_start_r(uint8_t id)
00122 {
00123     id |= I2C_READBIT;
00124     if (i2c_bitbang_start())
00125     {
00126         if (i2c_bitbang_put(id))
00127             return true;
00128 
00129         LOG_ERR("NACK on I2c start read\n");
00130     }
00131 
00132     return false;
00133 }
00134 
00135 int i2c_bitbang_get(bool ack)
00136 {
00137     uint8_t data = 0;
00138     for (uint8_t i = 0x80; i != 0; i >>= 1)
00139     {
00140         SCL_LO;
00141         I2C_HALFBIT_DELAY();
00142         SCL_HI;
00143         if (SDA_IN)
00144             data |= i;
00145         else
00146             data &= ~i;
00147 
00148         I2C_HALFBIT_DELAY();
00149     }
00150     SCL_LO;
00151 
00152     if (ack)
00153         SDA_LO;
00154     else
00155         SDA_HI;
00156 
00157     I2C_HALFBIT_DELAY();
00158     SCL_HI;
00159     I2C_HALFBIT_DELAY();
00160     SCL_LO;
00161     SDA_HI;
00162     /* avoid sign extension */
00163     return (int)(uint8_t)data;
00164 }
00165 
00166 MOD_DEFINE(i2c);
00167 
00171 void i2c_bitbang_init(void)
00172 {
00173     MOD_CHECK(timer);
00174     I2C_BITBANG_HW_INIT;
00175     SDA_HI;
00176     SCL_HI;
00177     MOD_INIT(i2c);
00178 }
00179