From d6b2c7707b92f6daada2577dac51ba226f7b5046 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sun, 24 Jan 2016 16:42:58 +0100 Subject: I2C proof of concept: works! --- src/i2c.cc | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/i2c.cc (limited to 'src/i2c.cc') diff --git a/src/i2c.cc b/src/i2c.cc new file mode 100644 index 0000000..37af104 --- /dev/null +++ b/src/i2c.cc @@ -0,0 +1,57 @@ +#include +#include +#include +#include + +#include "i2c.h" + +I2C i2c; + +void I2C::enable() +{ + /* + * Set I2C clock frequency to 100kHz. + * freq = F_CPU / (16 + (2 * TWBR * TWPS) ) + * let TWPS = "00" = 1 + * -> TWBR = (F_CPU / 100000) - 16 / 2 + */ + TWSR = 0; // the lower two bits control TWPS + TWBR = ((F_CPU / 100000UL) - 16) / 2; +} + +// TODO Everything[tm] (error handling and generic code) +// Also TODO: Use interrupts instead of polling +void I2C::xmit(int num_tx, int num_rx, uint8_t *txbuf, uint8_t *rxbuf) +{ + int i; + + if (num_tx) { + TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); + while (!(TWCR & _BV(TWINT))); + TWDR = (I2C_EEPROM_ADDR << 1) | 0; + TWCR = _BV(TWINT) | _BV(TWEN); + while (!(TWCR & _BV(TWINT))); + for (i = 0; i < num_tx; i++) { + TWDR = txbuf[i]; + TWCR = _BV(TWINT) | _BV(TWEN); + while (!(TWCR & _BV(TWINT))); + } + } + if (num_rx) { + TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); + while (!(TWCR & _BV(TWINT))); + TWDR = (I2C_EEPROM_ADDR << 1) | 1; + TWCR = _BV(TWINT) | _BV(TWEN); + while (!(TWCR & _BV(TWINT))); + for (i = 0; i < num_rx; i++) { + if (i == num_rx-1) { + TWCR = _BV(TWINT) | _BV(TWEN); + } else { + TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWEA); + } + while (!(TWCR & _BV(TWINT))); + rxbuf[i] = TWDR; + } + } + TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN); +} -- cgit v1.2.3