*/
#define CONFIG_I2C_START_TIMEOUT 100
+/**
+ * I2C driver can have 2 backends:
+ * I2C_BACKEND_BUILTIN: Use (if present) the builtin i2c hardware.
+ * I2C_BACKEND_BITBANG: Use the emulated bitbang driver.
+ */
+#define CONFIG_I2C_BACKEND I2C_BACKEND_BUILTIN
+
/// Module logging level definition.
#define I2C_LOG_LEVEL LOG_LVL_INFO
*
* \return true on success, false otherwise.
*/
-static bool i2c_start(void)
+static bool i2c_builtin_start(void)
{
TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
WAIT_TWI_READY;
*
* \return true on success, false otherwise.
*/
-bool i2c_start_w(uint8_t id)
+bool i2c_builtin_start_w(uint8_t id)
{
/*
* Loop on the select write sequence: when the eeprom is busy
* keep trying until the eeprom responds with an ACK.
*/
ticks_t start = timer_clock();
- while (i2c_start())
+ while (i2c_builtin_start())
{
TWDR = id & ~I2C_READBIT;
TWCR = BV(TWINT) | BV(TWEN);
*
* \return true on success, false otherwise.
*/
-bool i2c_start_r(uint8_t id)
+bool i2c_builtin_start_r(uint8_t id)
{
- if (i2c_start())
+ if (i2c_builtin_start())
{
TWDR = id | I2C_READBIT;
TWCR = BV(TWINT) | BV(TWEN);
/**
* Send STOP condition.
*/
-void i2c_stop(void)
+void i2c_builtin_stop(void)
{
TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
}
*
* \return true on success, false on error.
*/
-bool i2c_put(const uint8_t data)
+bool i2c_builtin_put(const uint8_t data)
{
TWDR = data;
TWCR = BV(TWINT) | BV(TWEN);
*
* \return the byte read if ok, EOF on errors.
*/
-int i2c_get(bool ack)
+int i2c_builtin_get(bool ack)
{
TWCR = BV(TWINT) | BV(TWEN) | (ack ? BV(TWEA) : 0);
WAIT_TWI_READY;
/**
* Initialize TWI module.
*/
-void i2c_init(void)
+void i2c_builtin_init(void)
{
ATOMIC(
/*
#ifndef DRV_I2C_H
#define DRV_I2C_H
+#include "cfg/cfg_i2c.h"
#include <cfg/compiler.h>
#define I2C_READBIT BV(0)
-void i2c_init(void);
-bool i2c_start_w(uint8_t id);
-bool i2c_start_r(uint8_t id);
-void i2c_stop(void);
-bool i2c_put(uint8_t _data);
-int i2c_get(bool ack);
+/**
+ * I2C Backends.
+ * \{
+ */
+#define I2C_BACKEND_BUILTIN 0 ///< Uses cpu builtin i2c driver
+#define I2C_BACKEND_BITBANG 1 ///< Uses emulated bitbang driver
+/*\}*/
+
+void i2c_builtin_init(void);
+bool i2c_builtin_start_w(uint8_t id);
+bool i2c_builtin_start_r(uint8_t id);
+void i2c_builtin_stop(void);
+bool i2c_builtin_put(uint8_t _data);
+int i2c_builtin_get(bool ack);
+
+void i2c_bitbang_init(void);
+bool i2c_bitbang_start_w(uint8_t id);
+bool i2c_bitbang_start_r(uint8_t id);
+void i2c_bitbang_stop(void);
+bool i2c_bitbang_put(uint8_t _data);
+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
+#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
+#else
+ #error Unsupported i2c backend.
+#endif
+
bool i2c_send(const void *_buf, size_t count);
bool i2c_recv(void *_buf, size_t count);
#include "hw/hw_i2c_bitbang.h"
-INLINE bool i2c_start(void)
+INLINE bool i2c_bitbang_start(void)
{
SDA_HI;
SCL_HI;
return !SDA_IN;
}
-void i2c_stop(void)
+void i2c_bitbang_stop(void)
{
SDA_LO;
SCL_HI;
SDA_HI;
}
-bool i2c_put(uint8_t _data)
+bool i2c_bitbang_put(uint8_t _data)
{
/* Add ACK bit */
uint16_t data = (_data << 1) | 1;
return ack;
}
-bool i2c_start_w(uint8_t id)
+bool i2c_bitbang_start_w(uint8_t id)
{
id &= ~I2C_READBIT;
/*
* keep trying until the deveice responds with an ACK.
*/
ticks_t start = timer_clock();
- while (i2c_start())
+ while (i2c_bitbang_start())
{
- if (i2c_put(id))
+ if (i2c_bitbang_put(id))
return true;
else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
{
return false;
}
-bool i2c_start_r(uint8_t id)
+bool i2c_bitbang_start_r(uint8_t id)
{
id |= I2C_READBIT;
- if (i2c_start())
+ if (i2c_bitbang_start())
{
- if (i2c_put(id))
+ if (i2c_bitbang_put(id))
return true;
LOG_ERR("NACK on I2c start read\n");
return false;
}
-int i2c_get(bool ack)
+int i2c_bitbang_get(bool ack)
{
uint8_t data = 0;
for (uint8_t i = 0x80; i != 0; i >>= 1)
/**
* Initialize i2c module.
*/
-void i2c_init(void)
+void i2c_bitbang_init(void)
{
MOD_CHECK(timer);
I2C_BITBANG_HW_INIT;