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/display.cc | 2 +- src/i2c.cc | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/i2c.h | 14 ++++++++++++++ src/main.cc | 14 ++++++++++++++ 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/i2c.cc create mode 100644 src/i2c.h diff --git a/src/display.cc b/src/display.cc index 3bffacd..1cdc0a2 100644 --- a/src/display.cc +++ b/src/display.cc @@ -102,11 +102,11 @@ void Display::setString(const char *new_str) void Display::setString(char *new_str) { int i; - reset(); for (i = 0; new_str[i] != 0; i++) { string[i] = new_str[i]; } string[i] = 0; // trailing null byte + reset(); } /* 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); +} diff --git a/src/i2c.h b/src/i2c.h new file mode 100644 index 0000000..818db23 --- /dev/null +++ b/src/i2c.h @@ -0,0 +1,14 @@ +#include +#include +#include + +#define I2C_EEPROM_ADDR 0x50 + +class I2C { + public: + I2C() {}; + void enable(); + void xmit(int num_tx, int num_rx, uint8_t *txbuf, uint8_t *rxbuf); +}; + +extern I2C i2c; diff --git a/src/main.cc b/src/main.cc index 4398d02..0fb68ff 100644 --- a/src/main.cc +++ b/src/main.cc @@ -6,11 +6,16 @@ #include "display.h" #include "font.h" +#include "i2c.h" #include "modem.h" #include "system.h" int main (void) { + char testbuf[] = "..Olol I2C extra lang bla foo wololo moep "; + char testbuf2[32]; + testbuf[0] = 1; + testbuf[1] = 0; // disable ADC to save power PRR |= _BV(PRADC); @@ -24,8 +29,17 @@ int main (void) display.enable(); modem.enable(); + i2c.enable(); sei(); + //display.setString("tx"); + + i2c.xmit(64, 0, (uint8_t *)testbuf, (uint8_t *)testbuf); + + //display.setString("rx"); + + i2c.xmit(2, 64, (uint8_t *)testbuf, (uint8_t *)testbuf2); + display.setString(testbuf2); while (1) { // nothing to do here, go to idle to save power -- cgit v1.2.3