summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2016-01-24 16:42:58 +0100
committerDaniel Friesel <derf@finalrewind.org>2016-01-24 16:42:58 +0100
commitd6b2c7707b92f6daada2577dac51ba226f7b5046 (patch)
tree8cbf1c696da5363cf3c9451f27a6fa833202bb38
parentb69f2a177a4613d1d9ccf93b5fe2f7dff68f468a (diff)
I2C proof of concept: works!
-rw-r--r--src/display.cc2
-rw-r--r--src/i2c.cc57
-rw-r--r--src/i2c.h14
-rw-r--r--src/main.cc14
4 files changed, 86 insertions, 1 deletions
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 <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include <stdlib.h>
+
+#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 <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdlib.h>
+
+#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