i2c_bitbang.c

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