BeRTOS
i2c_bitbang.c
Go to the documentation of this file.
00001 
00039 #include "hw/hw_i2c_bitbang.h"
00040 
00041 #include "cfg/cfg_i2c.h"
00042 
00043 #define LOG_LEVEL  I2C_LOG_LEVEL
00044 #define LOG_FORMAT I2C_LOG_FORMAT
00045 
00046 #include <cfg/log.h>
00047 #include <cfg/macros.h>
00048 #include <cfg/module.h>
00049 
00050 #include <drv/timer.h>
00051 #include <drv/i2c.h>
00052 
00053 #include <cpu/irq.h>
00054 
00055 #include <cpu/attr.h>
00056 
00057 #if !CONFIG_I2C_DISABLE_OLD_API
00058 
00059 INLINE bool i2c_bitbang_start(void)
00060 {
00061     SDA_HI;
00062     SCL_HI;
00063     I2C_HALFBIT_DELAY();
00064     SDA_LO;
00065     I2C_HALFBIT_DELAY();
00066 
00067     return !SDA_IN;
00068 }
00069 
00070 void i2c_bitbang_stop(void)
00071 {
00072     SDA_LO;
00073     SCL_HI;
00074     I2C_HALFBIT_DELAY();
00075     SDA_HI;
00076 }
00077 
00078 bool i2c_bitbang_put(uint8_t _data)
00079 {
00080     /* Add ACK bit */
00081     uint16_t data = (_data << 1) | 1;
00082 
00083     for (uint16_t i = 0x100; i != 0; i >>= 1)
00084     {
00085         SCL_LO;
00086         if (data & i)
00087             SDA_HI;
00088         else
00089             SDA_LO;
00090         I2C_HALFBIT_DELAY();
00091 
00092         SCL_HI;
00093         I2C_HALFBIT_DELAY();
00094     }
00095 
00096     bool ack = !SDA_IN;
00097     SCL_LO;
00098     I2C_HALFBIT_DELAY();
00099     return ack;
00100 }
00101 
00102 bool i2c_bitbang_start_w(uint8_t id)
00103 {
00104     id &= ~I2C_READBIT;
00105     /*
00106      * Loop on the select write sequence: when the device is busy
00107      * writing previously sent data it will reply to the SLA_W
00108      * control byte with a NACK.  In this case, we must
00109      * keep trying until the deveice responds with an ACK.
00110      */
00111     ticks_t start = timer_clock();
00112     while (i2c_bitbang_start())
00113     {
00114         if (i2c_bitbang_put(id))
00115             return true;
00116         else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
00117         {
00118             LOG_ERR("Timeout on I2C start write\n");
00119             break;
00120         }
00121         //LOG_INFO("Rep start\n");
00122     }
00123 
00124     return false;
00125 }
00126 
00127 bool i2c_bitbang_start_r(uint8_t id)
00128 {
00129     id |= I2C_READBIT;
00130     if (i2c_bitbang_start())
00131     {
00132         if (i2c_bitbang_put(id))
00133             return true;
00134 
00135         LOG_ERR("NACK on I2c start read\n");
00136     }
00137 
00138     return false;
00139 }
00140 
00141 int i2c_bitbang_get(bool ack)
00142 {
00143     uint8_t data = 0;
00144     for (uint8_t i = 0x80; i != 0; i >>= 1)
00145     {
00146         SCL_LO;
00147         I2C_HALFBIT_DELAY();
00148         SCL_HI;
00149         if (SDA_IN)
00150             data |= i;
00151         else
00152             data &= ~i;
00153 
00154         I2C_HALFBIT_DELAY();
00155     }
00156     SCL_LO;
00157 
00158     if (ack)
00159         SDA_LO;
00160     else
00161         SDA_HI;
00162 
00163     I2C_HALFBIT_DELAY();
00164     SCL_HI;
00165     I2C_HALFBIT_DELAY();
00166     SCL_LO;
00167     SDA_HI;
00168     /* avoid sign extension */
00169     return (int)(uint8_t)data;
00170 }
00171 
00172 #endif /* !CONFIG_I2C_DISABLE_OLD_API */
00173 
00174 /*
00175  * New I2C API
00176  */
00177 static bool old_api = false;
00178 #define I2C_DEV(i2c)            ((int)((i2c)->hw))
00179 
00180 static void i2c_bitbang_stop_1(struct I2c *i2c)
00181 {
00182     if (old_api)
00183     {
00184         SDA_LO;
00185         SCL_HI;
00186         I2C_HALFBIT_DELAY();
00187         SDA_HI;
00188     }
00189     else
00190     {
00191         i2c_sdaLo(I2C_DEV(i2c));
00192         i2c_sclHi(I2C_DEV(i2c));
00193         i2c_halfbitDelay(I2C_DEV(i2c));
00194         i2c_sdaHi(I2C_DEV(i2c));
00195     }
00196 }
00197 
00198 INLINE bool i2c_bitbang_start_1(struct I2c *i2c)
00199 {
00200     bool ret;
00201     /* Clear all error, we restart */
00202     i2c->errors &= ~(I2C_NO_ACK | I2C_ARB_LOST);
00203 
00204     if (old_api)
00205     {
00206         SDA_HI;
00207         SCL_HI;
00208         I2C_HALFBIT_DELAY();
00209         SDA_LO;
00210         I2C_HALFBIT_DELAY();
00211 
00212         ret = !SDA_IN;
00213     }
00214     else
00215     {
00216         i2c_sdaHi(I2C_DEV(i2c));
00217         i2c_sclHi(I2C_DEV(i2c));
00218         i2c_halfbitDelay(I2C_DEV(i2c));
00219         i2c_sdaLo(I2C_DEV(i2c));
00220         i2c_halfbitDelay(I2C_DEV(i2c));
00221 
00222         ret = !i2c_sdaIn(I2C_DEV(i2c));
00223     }
00224 
00225     return ret;
00226 }
00227 
00228 
00229 static uint8_t i2c_bitbang_getc(struct I2c *i2c)
00230 {
00231     uint8_t data = 0;
00232     if (old_api)
00233     {
00234         for (uint8_t i = 0x80; i != 0; i >>= 1)
00235         {
00236             SCL_LO;
00237             I2C_HALFBIT_DELAY();
00238             SCL_HI;
00239             if (SDA_IN)
00240                 data |= i;
00241             else
00242                 data &= ~i;
00243 
00244             I2C_HALFBIT_DELAY();
00245         }
00246         SCL_LO;
00247 
00248         /* Generate ACK/NACK */
00249         if (i2c->xfer_size > 1)
00250             SDA_LO;
00251         else
00252             SDA_HI;
00253 
00254         I2C_HALFBIT_DELAY();
00255         SCL_HI;
00256         I2C_HALFBIT_DELAY();
00257         SCL_LO;
00258         SDA_HI;
00259     }
00260     else
00261     {
00262         for (uint8_t i = 0x80; i != 0; i >>= 1)
00263         {
00264             i2c_sclLo(I2C_DEV(i2c));
00265             i2c_halfbitDelay(I2C_DEV(i2c));
00266             i2c_sclHi(I2C_DEV(i2c));
00267             if (i2c_sdaIn(I2C_DEV(i2c)))
00268                 data |= i;
00269             else
00270                 data &= ~i;
00271 
00272             i2c_halfbitDelay(I2C_DEV(i2c));
00273         }
00274         i2c_sclLo(I2C_DEV(i2c));
00275 
00276         /* Generate ACK/NACK */
00277         if (i2c->xfer_size > 1)
00278             i2c_sdaLo(I2C_DEV(i2c));
00279         else
00280             i2c_sdaHi(I2C_DEV(i2c));
00281 
00282         i2c_halfbitDelay(I2C_DEV(i2c));
00283         i2c_sclHi(I2C_DEV(i2c));
00284         i2c_halfbitDelay(I2C_DEV(i2c));
00285         i2c_sclLo(I2C_DEV(i2c));
00286         i2c_sdaHi(I2C_DEV(i2c));
00287     }
00288 
00289     /* Generate stop condition (if requested) */
00290     if ((i2c->xfer_size == 1) && (i2c->flags & I2C_STOP))
00291         i2c_bitbang_stop_1(i2c);
00292 
00293     return data;
00294 }
00295 
00296 INLINE void i2c_bitbang_putcStop(struct I2c *i2c, uint8_t _data, bool stop)
00297 {
00298     /* Add ACK bit */
00299     uint16_t data = (_data << 1) | 1;
00300     bool ack;
00301 
00302     if (old_api)
00303     {
00304         for (uint16_t i = 0x100; i != 0; i >>= 1)
00305         {
00306             SCL_LO;
00307             if (data & i)
00308                 SDA_HI;
00309             else
00310                 SDA_LO;
00311             I2C_HALFBIT_DELAY();
00312 
00313             SCL_HI;
00314             I2C_HALFBIT_DELAY();
00315         }
00316 
00317         ack = !SDA_IN;
00318         SCL_LO;
00319         I2C_HALFBIT_DELAY();
00320     }
00321     else
00322     {
00323         for (uint16_t i = 0x100; i != 0; i >>= 1)
00324         {
00325             i2c_sclLo(I2C_DEV(i2c));
00326             if (data & i)
00327                 i2c_sdaHi(I2C_DEV(i2c));
00328             else
00329                 i2c_sdaLo(I2C_DEV(i2c));
00330             i2c_halfbitDelay(I2C_DEV(i2c));
00331 
00332             i2c_sclHi(I2C_DEV(i2c));
00333             i2c_halfbitDelay(I2C_DEV(i2c));
00334         }
00335         ack = !i2c_sdaIn(I2C_DEV(i2c));
00336 
00337         i2c_sclLo(I2C_DEV(i2c));
00338         i2c_halfbitDelay(I2C_DEV(i2c));
00339     }
00340 
00341     if (!ack)
00342         i2c->errors |= I2C_NO_ACK;
00343 
00344     /* Generate stop condition (if requested) */
00345     if (stop || i2c->errors)
00346         i2c_bitbang_stop_1(i2c);
00347 }
00348 
00349 static void i2c_bitbang_putc(struct I2c *i2c, uint8_t data)
00350 {
00351     i2c_bitbang_putcStop(i2c, data,
00352         (i2c->xfer_size == 1) && (i2c->flags & I2C_STOP));
00353 }
00354 
00355 static void i2c_bitbang_start_2(struct I2c *i2c, uint16_t slave_addr)
00356 {
00357     if (i2c->flags & I2C_START_R)
00358         slave_addr |= I2C_READBIT;
00359     else
00360         slave_addr &= ~I2C_READBIT;
00361 
00362     /*
00363      * Loop on the select write sequence: when the device is busy
00364      * writing previously sent data it will reply to the SLA_W
00365      * control byte with a NACK.  In this case, we must
00366      * keep trying until the device responds with an ACK.
00367      */
00368     ticks_t start = timer_clock();
00369     while (i2c_bitbang_start_1(i2c))
00370     {
00371         i2c_bitbang_putcStop(i2c, slave_addr, false);
00372 
00373         if (!(i2c->errors & I2C_NO_ACK))
00374             return;
00375         else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
00376         {
00377             LOG_ERR("Timeout on I2C start\n");
00378             i2c->errors |= I2C_START_TIMEOUT;
00379             i2c_bitbang_stop_1(i2c);
00380             return;
00381         }
00382     }
00383 
00384     LOG_ERR("START arbitration lost\n");
00385     i2c->errors |= I2C_ARB_LOST;
00386     i2c_bitbang_stop_1(i2c);
00387     return;
00388 }
00389 
00390 
00391 static const I2cVT i2c_bitbang_vt =
00392 {
00393     .start = i2c_bitbang_start_2,
00394     .getc = i2c_bitbang_getc,
00395     .putc = i2c_bitbang_putc,
00396     .write = i2c_genericWrite,
00397     .read = i2c_genericRead,
00398 };
00399 
00400 
00404 void i2c_hw_bitbangInit(I2c *i2c, int dev)
00405 {
00406     MOD_CHECK(timer);
00407     if (dev == I2C_BITBANG_OLD)
00408         old_api = true;
00409     else
00410         i2c->hw = (struct I2cHardware *)(dev - I2C_BITBANG0);
00411 
00412     i2c->vt = &i2c_bitbang_vt;
00413 
00414     if (old_api)
00415     {
00416         I2C_BITBANG_HW_INIT;
00417         SDA_HI;
00418         SCL_HI;
00419     }
00420     else
00421     {
00422         i2c_bitbangInit(I2C_DEV(i2c));
00423         i2c_sdaHi(I2C_DEV(i2c));
00424         i2c_sclHi(I2C_DEV(i2c));
00425     }
00426 }
00427