aboutsummaryrefslogtreecommitdiff
path: root/digital-driver-board/firmware/TinyWire-master/TinyWireS/examples/attiny85_i2c_slave/attiny85_i2c_slave.ino
diff options
context:
space:
mode:
Diffstat (limited to 'digital-driver-board/firmware/TinyWire-master/TinyWireS/examples/attiny85_i2c_slave/attiny85_i2c_slave.ino')
-rw-r--r--digital-driver-board/firmware/TinyWire-master/TinyWireS/examples/attiny85_i2c_slave/attiny85_i2c_slave.ino152
1 files changed, 152 insertions, 0 deletions
diff --git a/digital-driver-board/firmware/TinyWire-master/TinyWireS/examples/attiny85_i2c_slave/attiny85_i2c_slave.ino b/digital-driver-board/firmware/TinyWire-master/TinyWireS/examples/attiny85_i2c_slave/attiny85_i2c_slave.ino
new file mode 100644
index 0000000..df2532f
--- /dev/null
+++ b/digital-driver-board/firmware/TinyWire-master/TinyWireS/examples/attiny85_i2c_slave/attiny85_i2c_slave.ino
@@ -0,0 +1,152 @@
+/**
+ * Example sketch for writing to and reading from a slave in transactional manner
+ *
+ * NOTE: You must not use delay() or I2C communications will fail, use tws_delay() instead (or preferably some smarter timing system)
+ *
+ * On write the first byte received is considered the register addres to modify/read
+ * On each byte sent or read the register address is incremented (and it will loop back to 0)
+ *
+ * You can try this with the Arduino I2C REPL sketch at https://github.com/rambo/I2C/blob/master/examples/i2crepl/i2crepl.ino
+ * If you have bus-pirate remember that the older revisions do not like the slave streching the clock, this leads to all sorts of weird behaviour
+ *
+ * To read third value (register number 2 since counting starts at 0) send "[ 8 2 [ 9 r ]", value read should be 0xBE
+ * If you then send "[ 9 r r r ]" you should get 0xEF 0xDE 0xAD as response (demonstrating the register counter looping back to zero)
+ *
+ * You need to have at least 8MHz clock on the ATTiny for this to work (and in fact I have so far tested it only on ATTiny85 @8MHz using internal oscillator)
+ * Remember to "Burn bootloader" to make sure your chip is in correct mode
+ */
+
+
+/**
+ * Pin notes by Suovula, see also http://hlt.media.mit.edu/?p=1229
+ *
+ * DIP and SOIC have same pinout, however the SOIC chips are much cheaper, especially if you buy more than 5 at a time
+ * For nice breakout boards see https://github.com/rambo/attiny_boards
+ *
+ * Basically the arduino pin numbers map directly to the PORTB bit numbers.
+ *
+// I2C
+arduino pin 0 = not(OC1A) = PORTB <- _BV(0) = SOIC pin 5 (I2C SDA, PWM)
+arduino pin 2 = = PORTB <- _BV(2) = SOIC pin 7 (I2C SCL, Analog 1)
+// Timer1 -> PWM
+arduino pin 1 = OC1A = PORTB <- _BV(1) = SOIC pin 6 (PWM)
+arduino pin 3 = not(OC1B) = PORTB <- _BV(3) = SOIC pin 2 (Analog 3)
+arduino pin 4 = OC1B = PORTB <- _BV(4) = SOIC pin 3 (Analog 2)
+ */
+#define I2C_SLAVE_ADDRESS 0x4 // the 7-bit address (remember to change this when adapting this example)
+// Get this from https://github.com/rambo/TinyWire
+#include <TinyWireS.h>
+// The default buffer size, Can't recall the scope of defines right now
+#ifndef TWI_RX_BUFFER_SIZE
+#define TWI_RX_BUFFER_SIZE ( 16 )
+#endif
+
+
+volatile uint8_t i2c_regs[] =
+{
+ 0xDE,
+ 0xAD,
+ 0xBE,
+ 0xEF,
+};
+// Tracks the current register pointer position
+volatile byte reg_position;
+const byte reg_size = sizeof(i2c_regs);
+
+/**
+ * This is called for each read request we receive, never put more than one byte of data (with TinyWireS.send) to the
+ * send-buffer when using this callback
+ */
+void requestEvent()
+{
+ TinyWireS.send(i2c_regs[reg_position]);
+ // Increment the reg position on each read, and loop back to zero
+ reg_position++;
+ if (reg_position >= reg_size)
+ {
+ reg_position = 0;
+ }
+}
+
+// TODO: Either update this to use something smarter for timing or remove it alltogether
+void blinkn(uint8_t blinks)
+{
+ digitalWrite(3, HIGH);
+ while(blinks--)
+ {
+ digitalWrite(3, LOW);
+ tws_delay(50);
+ digitalWrite(3, HIGH);
+ tws_delay(100);
+ }
+}
+
+/**
+ * The I2C data received -handler
+ *
+ * This needs to complete before the next incoming transaction (start, data, restart/stop) on the bus does
+ * so be quick, set flags for long running tasks to be called from the mainloop instead of running them directly,
+ */
+void receiveEvent(uint8_t howMany)
+{
+ if (howMany < 1)
+ {
+ // Sanity-check
+ return;
+ }
+ if (howMany > TWI_RX_BUFFER_SIZE)
+ {
+ // Also insane number
+ return;
+ }
+
+ reg_position = TinyWireS.receive();
+ howMany--;
+ if (!howMany)
+ {
+ // This write was only to set the buffer for next read
+ return;
+ }
+ while(howMany--)
+ {
+ i2c_regs[reg_position] = TinyWireS.receive();
+ reg_position++;
+ if (reg_position >= reg_size)
+ {
+ reg_position = 0;
+ }
+ }
+}
+
+
+void setup()
+{
+ // TODO: Tri-state this and wait for input voltage to stabilize
+ pinMode(3, OUTPUT); // OC1B-, Arduino pin 3, ADC
+ digitalWrite(3, LOW); // Note that this makes the led turn on, it's wire this way to allow for the voltage sensing above.
+
+ pinMode(1, OUTPUT); // OC1A, also The only HW-PWM -pin supported by the tiny core analogWrite
+
+ /**
+ * Reminder: taking care of pull-ups is the masters job
+ */
+
+ TinyWireS.begin(I2C_SLAVE_ADDRESS);
+ TinyWireS.onReceive(receiveEvent);
+ TinyWireS.onRequest(requestEvent);
+
+
+ // Whatever other setup routines ?
+
+ digitalWrite(3, HIGH);
+}
+
+void loop()
+{
+ /**
+ * This is the only way we can detect stop condition (http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=984716&sid=82e9dc7299a8243b86cf7969dd41b5b5#984716)
+ * it needs to be called in a very tight loop in order not to miss any (REMINDER: Do *not* use delay() anywhere, use tws_delay() instead).
+ * It will call the function registered via TinyWireS.onReceive(); if there is data in the buffer on stop.
+ */
+ TinyWireS_stop_check();
+}