diff --git a/extras/i2c/i2c.c b/extras/i2c/i2c.c index a41dff7..7fbae65 100644 --- a/extras/i2c/i2c.c +++ b/extras/i2c/i2c.c @@ -27,10 +27,13 @@ #include #include "i2c.h" +//#define I2C_DEBUG true -// I2C driver for ESP8266 written for use with esp-open-rtos -// Based on https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I.C2.B2C_Master_protocol -// With calling overhead, we end up at ~320kbit/s +#ifdef I2C_DEBUG +#define debug(fmt, ...) printf("%s: " fmt "\n", "I2C", ## __VA_ARGS__) +#else +#define debug(fmt, ...) +#endif #define CLK_STRETCH (10) @@ -38,6 +41,11 @@ static bool started; static uint8_t g_scl_pin; static uint8_t g_sda_pin; +inline bool i2c_status(void) +{ + return started; +} + void i2c_init(uint8_t scl_pin, uint8_t sda_pin) { started = false; @@ -110,14 +118,14 @@ void i2c_start(void) // Repeated start setup time, minimum 4.7us i2c_delay(); } + started = true; if (read_sda() == 0) { - printf("I2C: arbitration lost in i2c_start\n"); + debug("arbitration lost in i2c_start"); } // SCL is high, set SDA from 1 to 0. clear_sda(); i2c_delay(); clear_scl(); - started = true; } // Output stop condition @@ -133,7 +141,7 @@ void i2c_stop(void) i2c_delay(); // SCL is high, set SDA from 0 to 1 if (read_sda() == 0) { - printf("I2C: arbitration lost in i2c_stop\n"); + debug("arbitration lost in i2c_stop"); } i2c_delay(); started = false; @@ -154,7 +162,7 @@ static void i2c_write_bit(bool bit) // SCL is high, now data is valid // If SDA is high, check that nobody else is driving SDA if (bit && read_sda() == 0) { - printf("I2C: arbitration lost in i2c_write_bit\n"); + debug("arbitration lost in i2c_write_bit"); } i2c_delay(); clear_scl(); @@ -203,6 +211,7 @@ uint8_t i2c_read(bool ack) bool i2c_slave_write(uint8_t slave_addr, uint8_t *data, uint8_t len) { bool success = false; + if (i2c_status()) return success ; // If bus busy, dont write do { i2c_start(); if (!i2c_write(slave_addr << 1)) @@ -220,6 +229,7 @@ bool i2c_slave_write(uint8_t slave_addr, uint8_t *data, uint8_t len) bool i2c_slave_read(uint8_t slave_addr, uint8_t data, uint8_t *buf, uint32_t len) { bool success = false; + if (i2c_status()) return success ; // If bus busy, dont read do { i2c_start(); if (!i2c_write(slave_addr << 1)) { @@ -240,7 +250,7 @@ bool i2c_slave_read(uint8_t slave_addr, uint8_t data, uint8_t *buf, uint32_t len } while(0); i2c_stop(); if (!success) { - printf("I2C: write error\n"); + debug("write error"); } return success; } diff --git a/extras/i2c/i2c.h b/extras/i2c/i2c.h index bfb3811..8654594 100644 --- a/extras/i2c/i2c.h +++ b/extras/i2c/i2c.h @@ -32,26 +32,71 @@ extern "C" { #endif -// Init bitbanging I2C driver on given pins +// I2C driver for ESP8266 written for use with esp-open-rtos +// Based on https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I.C2.B2C_Master_protocol +// With calling overhead, we end up at ~320kbit/s + +///////Level 0 API + +/** + * Init bitbanging I2C driver on given pins + * @param scl_pin SCL pin for I2C + * @param sda_pin SDA pin for I2C + */ void i2c_init(uint8_t scl_pin, uint8_t sda_pin); -// Write a byte to I2C bus. Return true if slave acked. +/** + * Write a byte to I2C bus. + * @param byte Pointer to device descriptor + * @return true if slave acked + */ bool i2c_write(uint8_t byte); -// Read a byte from I2C bus. Return true if slave acked. +/** + * Read a byte from I2C bus. + * @param ack Set Ack for slave (false: Ack // true: NoAck) + * @return byte read from slave. + */ uint8_t i2c_read(bool ack); -// Write 'len' bytes from 'buf' to slave. Return true if slave acked. +/** + * Send start or restart condition + */ +void i2c_start(void); + +/** + * Send stop condition + */ +void i2c_stop(void); + +/** + * get status from I2C bus. + * @return true if busy. + */ +bool i2c_status(void); + +///////Level 1 API (Don't need functions above) + +/** + * Write 'len' bytes from 'buf' to slave. Return true if slave acked. + * @param slave_addr slave device address + * @param buf Pointer to data buffer + * @param len Number of byte to send + * @return false if error occured + */ bool i2c_slave_write(uint8_t slave_addr, uint8_t *buf, uint8_t len); -// Issue a read operation and send 'data', followed by reading 'len' bytes -// from slave into 'buf'. Return true if slave acked. +/** + * Issue a read operation and send 'data', followed by reading 'len' bytes + * from slave into 'buf'. + * @param slave_addr slave device address + * @param data register address to send + * @param buf Pointer to data buffer + * @param len Number of byte to read + * @return false if error occured + */ bool i2c_slave_read(uint8_t slave_addr, uint8_t data, uint8_t *buf, uint32_t len); -// Send start and stop conditions. Only needed when implementing protocols for -// devices where the i2c_slave_[read|write] functions above are of no use. -void i2c_start(void); -void i2c_stop(void); #ifdef __cplusplus }