X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;ds=sidebyside;f=bertos%2Fdrv%2Fi2c.h;h=1c58619a146c125879bf418611d059105794cf34;hb=64ed7d8f2437c3489152ecd0ca462d74fded1328;hp=dff995ccd11ba5ee7bc14f50f23d1e2deee00c48;hpb=4d0bb5f77cf16b3c153b3acb280376d0d3c86d58;p=bertos.git diff --git a/bertos/drv/i2c.h b/bertos/drv/i2c.h index dff995cc..1c58619a 100644 --- a/bertos/drv/i2c.h +++ b/bertos/drv/i2c.h @@ -44,10 +44,21 @@ #define DRV_I2C_H #include "cfg/cfg_i2c.h" + #include +#include +#include + +#include #define I2C_READBIT BV(0) +#if COMPILER_C99 + #define i2c_init(...) PP_CAT(i2c_init ## _, COUNT_PARMS(__VA_ARGS__)) (__VA_ARGS__) +#else + #define i2c_init(args...) PP_CAT(i2c_init ## _, COUNT_PARMS(args)) (args) +#endif + /** * I2C Backends. * Sometimes your cpu does not have a builtin @@ -60,6 +71,7 @@ #define I2C_BACKEND_BUILTIN 0 ///< Uses cpu builtin i2c driver #define I2C_BACKEND_BITBANG 1 ///< Uses emulated bitbang driver +#if 0 /** * I2c builtin prototypes. @@ -94,24 +106,178 @@ int i2c_bitbang_get(bool ack); /*\}*/ #if CONFIG_I2C_BACKEND == I2C_BACKEND_BUILTIN - #define i2c_init i2c_builtin_init - #define i2c_start_w i2c_builtin_start_w - #define i2c_start_r i2c_builtin_start_r - #define i2c_stop i2c_builtin_stop - #define i2c_put i2c_builtin_put - #define i2c_get i2c_builtin_get + #define i2c_init_0 i2c_builtin_init + #define i2c_start_w i2c_builtin_start_w + #define i2c_start_r i2c_builtin_start_r + #define i2c_stop i2c_builtin_stop + #define i2c_put i2c_builtin_put + #define i2c_get i2c_builtin_get #elif CONFIG_I2C_BACKEND == I2C_BACKEND_BITBANG - #define i2c_init i2c_bitbang_init - #define i2c_start_w i2c_bitbang_start_w - #define i2c_start_r i2c_bitbang_start_r - #define i2c_stop i2c_bitbang_stop - #define i2c_put i2c_bitbang_put - #define i2c_get i2c_bitbang_get + #define i2c_init_0 i2c_bitbang_init + #define i2c_start_w i2c_bitbang_start_w + #define i2c_start_r i2c_bitbang_start_r + #define i2c_stop i2c_bitbang_stop + #define i2c_put i2c_bitbang_put + #define i2c_get i2c_bitbang_get #else #error Unsupported i2c backend. #endif + bool i2c_send(const void *_buf, size_t count); bool i2c_recv(void *_buf, size_t count); #endif + +/* + * I2c new api + * + */ +#define I2C_OK 0 +#define I2C_ARB_LOST BV(2) +#define I2C_START_TIMEOUT BV(0) +#define I2C_NO_ACK BV(1) + + + +#define I2C_NOSTOP 0 +#define I2C_STOP BV(0) +#define I2C_START_R BV(1) +#define I2C_START_W 0 + + +#define I2C_TEST_START(flag) ((flag) & I2C_START_R) + +struct I2cHardware; +struct I2c; + +typedef void (*i2c_start_t)(struct I2c *i2c, uint16_t slave_addr); +typedef uint8_t (*i2c_get_t)(struct I2c *i2c); +typedef void (*i2c_put_t)(struct I2c *i2c, uint8_t data); +typedef void (*i2c_send_t)(struct I2c *i2c, const void *_buf, size_t count); +typedef void (*i2c_recv_t)(struct I2c *i2c, void *_buf, size_t count); + +typedef struct I2cVT +{ + i2c_start_t start; + i2c_get_t get; + i2c_put_t put; + i2c_send_t send; + i2c_recv_t recv; +} I2cVT; + +typedef struct I2c +{ + int errors; + int flags; + size_t xfer_size; + struct I2cHardware* hw; + const struct I2cVT *vt; +} I2c; + + +#include CPU_HEADER(i2c) + +INLINE void i2c_start(I2c *i2c, uint16_t slave_addr, size_t size) +{ + ASSERT(i2c->vt); + ASSERT(i2c->vt->start); + ASSERT(i2c->xfer_size == 0); + + i2c->errors = 0; + i2c->xfer_size = size; + + i2c->vt->start(i2c, slave_addr); +} + +INLINE void i2c_start_r(I2c *i2c, uint16_t slave_addr, size_t size, int flags) +{ + ASSERT(i2c); + i2c->flags = flags | I2C_START_R; + i2c_start(i2c, slave_addr, size); +} + +INLINE void i2c_start_w(I2c *i2c, uint16_t slave_addr, size_t size, int flags) +{ + ASSERT(i2c); + i2c->flags = flags & ~I2C_START_R; + i2c_start(i2c, slave_addr, size); +} + +INLINE uint8_t i2c_get(I2c *i2c) +{ + ASSERT(i2c); + ASSERT(i2c->vt); + ASSERT(i2c->vt->get); + + ASSERT(i2c->xfer_size >= 1); + + ASSERT(I2C_TEST_START(i2c->flags) == I2C_START_R); + + if (!i2c->errors) + return i2c->vt->get(i2c); + else + return 0xFF; +} + +INLINE void i2c_put(I2c *i2c, uint8_t data) +{ + ASSERT(i2c); + ASSERT(i2c->vt); + ASSERT(i2c->vt->put); + + ASSERT(i2c->xfer_size >= 1); + + ASSERT(I2C_TEST_START(i2c->flags) == I2C_START_W); + + if (!i2c->errors) + i2c->vt->put(i2c, data); +} + +INLINE void i2c_send(I2c *i2c, const void *_buf, size_t count) +{ + ASSERT(i2c); + ASSERT(i2c->vt); + ASSERT(i2c->vt->send); + + ASSERT(_buf); + ASSERT(count); + ASSERT(count <= i2c->xfer_size); + + ASSERT(I2C_TEST_START(i2c->flags) == I2C_START_W); + + if (!i2c->errors) + i2c->vt->send(i2c, _buf, count); +} + + +INLINE void i2c_recv(I2c *i2c, void *_buf, size_t count) +{ + ASSERT(i2c); + ASSERT(i2c->vt); + ASSERT(i2c->vt->recv); + + ASSERT(_buf); + ASSERT(count); + ASSERT(count <= i2c->xfer_size); + + ASSERT(I2C_TEST_START(i2c->flags) == I2C_START_R); + + if (!i2c->errors) + i2c->vt->recv(i2c, _buf, count); +} + +INLINE int i2c_error(I2c *i2c) +{ + ASSERT(i2c); + int err = i2c->errors; + i2c->errors = 0; + return err; +} + +INLINE void i2c_init_3(I2c *i2c, int dev, uint32_t clock) +{ + i2c_hw_init(i2c, dev, clock); +} + +#endif