diff options
author | Philip Lampkin <plampkin@chem.wisc.edu> | 2021-04-24 12:07:04 -0500 |
---|---|---|
committer | Philip Lampkin <plampkin@chem.wisc.edu> | 2021-04-24 12:07:04 -0500 |
commit | 40ab1463c3da0c844eedba5c5f52d5ef8af322c4 (patch) | |
tree | d7984802dbe72f0d203d7b86372ca355ac0c833d /digital-driver/firmware/TinyWireS | |
parent | d6df6a65cf04da7ed29e8f09c0bf14c8b2cfb2e6 (diff) |
terminology update
Diffstat (limited to 'digital-driver/firmware/TinyWireS')
12 files changed, 0 insertions, 1961 deletions
diff --git a/digital-driver/firmware/TinyWireS/TinyWireS.cpp b/digital-driver/firmware/TinyWireS/TinyWireS.cpp deleted file mode 100644 index 783e8e7..0000000 --- a/digital-driver/firmware/TinyWireS/TinyWireS.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/*
- TinyWireS.cpp - a wrapper class for Don Blake's usiTwiSlave routines.
- Provides TWI/I2C Slave functionality on ATtiny processers in Arduino environment.
- 1/23/2011 BroHogan - brohoganx10 at gmail dot com
-
- **** See TinyWireS.h for Credits and Usage information ****
-
- This library is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2.1 of the License, or any later version.
- This program is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- PARTICULAR PURPOSE. See the GNU General Public License for more details.
-*/
-
-extern "C" {
- #include <inttypes.h>
- #include "usiTwiSlave.h"
- #include <avr/interrupt.h>
- }
-
-#include "TinyWireS.h"
-#include "Arduino.h"
-
-// Constructors ////////////////////////////////////////////////////////////////
-
-USI_TWI_S::USI_TWI_S(){
-}
-
-
-// Public Methods //////////////////////////////////////////////////////////////
-
-void USI_TWI_S::begin(uint8_t slaveAddr){ // initialize I2C lib
- usiTwiSlaveInit(slaveAddr);
-}
-
-void USI_TWI_S::send(uint8_t data){ // send it back to master
- usiTwiTransmitByte(data);
-}
-
-uint8_t USI_TWI_S::available(){ // the bytes available that haven't been read yet
- return usiTwiAmountDataInReceiveBuffer();
- //return usiTwiDataInReceiveBuffer(); // This is wrong as far as the Wire API is concerned since it returns boolean and not amount
-}
-
-uint8_t USI_TWI_S::receive(){ // returns the bytes received one at a time
- return usiTwiReceiveByte();
-}
-
-// sets function called on slave write
-void USI_TWI_S::onReceive( void (*function)(uint8_t) )
-{
- usi_onReceiverPtr = function;
-}
-
-// sets function called on slave read
-void USI_TWI_S::onRequest( void (*function)(void) )
-{
- usi_onRequestPtr = function;
-}
-
-// This routine is no longer used now that the usiTwiSlave is completely
-// interrupt driven. The function is maintained here so that programs
-// written for the pre-interrupt driven version will still compile and function.
-void TinyWireS_stop_check()
-{
- // empty functions
-}
-
-// Implement a delay loop that checks for the stop bit (basically direct copy of the stock arduino implementation from wiring.c)
-// I don't think this function is necessary now that the
-// usiTwiSlave is completely interrupt driven. I'm not sure, and the function is
-// behaviorally harmless because TinyWireS_stop_check() is empty, so I'm leaving it alone.
-void tws_delay(unsigned long ms)
-{
- uint16_t start = (uint16_t)micros();
- while (ms > 0)
- {
- TinyWireS_stop_check();
- if (((uint16_t)micros() - start) >= 1000)
- {
- ms--;
- start += 1000;
- }
- }
-}
-
-// Preinstantiate Objects //////////////////////////////////////////////////////
-
-USI_TWI_S TinyWireS = USI_TWI_S();
-
diff --git a/digital-driver/firmware/TinyWireS/TinyWireS.h b/digital-driver/firmware/TinyWireS/TinyWireS.h deleted file mode 100644 index ccef042..0000000 --- a/digital-driver/firmware/TinyWireS/TinyWireS.h +++ /dev/null @@ -1,64 +0,0 @@ -/*
- TinyWireS.h - a wrapper class for Don Blake's usiTwiSlave routines.
- Provides TWI/I2C Slave functionality on ATtiny processers in Arduino environment.
- 1/23/2011 BroHogan - brohoganx10 at gmail dot com
-
- Major credit and thanks to Don Blake for his usiTwiSlave code which makes this possible
- http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=51467&start=all&postdays=0&postorder=asc
- (Changed #define USI_START_COND_INT USISIF (was USICIF) in usiTwiSlave.h)
-
- NOTE! - It's very important to use pullups on the SDA & SCL lines! More so than with the Wire lib.
- Current Rx & Tx buffers set at 32 bytes - see usiTwiSlave.h
-
- USAGE is modeled after the standard Wire library . . .
- Put in setup():
- TinyWireS.begin(I2C_SLAVE_ADDR); // initialize I2C lib & setup slave's address (7 bit - same as Wire)
-
- To Receive:
- someByte = TinyWireS.available(){ // returns the number of bytes in the received buffer
- someByte = TinyWireS.receive(){ // returns the next byte in the received buffer
-
- To Send:
- TinyWireS.send(uint8_t data){ // sends a requested byte to master
-
- TODO: (by others!)
- - onReceive and onRequest handlers are not implimented.
- - merge this class with TinyWireM for master & slave support in one library
-
- This library is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2.1 of the License, or any later version.
- This program is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- PARTICULAR PURPOSE. See the GNU General Public License for more details.
-*/
-
-#ifndef TinyWireS_h
-#define TinyWireS_h
-
-#include <inttypes.h>
-
-
-class USI_TWI_S
-{
- private:
- //static uint8_t USI_BytesAvail;
-
- public:
- USI_TWI_S();
- void begin(uint8_t I2C_SLAVE_ADDR);
- void send(uint8_t data);
- uint8_t available();
- uint8_t receive();
- void onReceive( void (*)(uint8_t) );
- void onRequest( void (*)(void) );
-};
-
-void TinyWireS_stop_check();
-// Implement a delay loop that checks for the stop bit (basically direct copy of the stock arduino implementation from wiring.c)
-void tws_delay(unsigned long);
-
-extern USI_TWI_S TinyWireS;
-
-#endif
-
diff --git a/digital-driver/firmware/TinyWireS/avr_usi_i2c_master.pdf b/digital-driver/firmware/TinyWireS/avr_usi_i2c_master.pdf Binary files differdeleted file mode 100644 index dc8f460..0000000 --- a/digital-driver/firmware/TinyWireS/avr_usi_i2c_master.pdf +++ /dev/null diff --git a/digital-driver/firmware/TinyWireS/avr_usi_i2c_slave.pdf b/digital-driver/firmware/TinyWireS/avr_usi_i2c_slave.pdf Binary files differdeleted file mode 100644 index e4704c7..0000000 --- a/digital-driver/firmware/TinyWireS/avr_usi_i2c_slave.pdf +++ /dev/null diff --git a/digital-driver/firmware/TinyWireS/examples/TinyWireS_Stress_Master/TinyWireS_Stress_Master.ino b/digital-driver/firmware/TinyWireS/examples/TinyWireS_Stress_Master/TinyWireS_Stress_Master.ino deleted file mode 100644 index d50adb7..0000000 --- a/digital-driver/firmware/TinyWireS/examples/TinyWireS_Stress_Master/TinyWireS_Stress_Master.ino +++ /dev/null @@ -1,184 +0,0 @@ -// --------------------------------- -// Stress test program/example for TinyWireS I2C library. -// Run this master program on the Arduino Uno R3. -// Run the other slave program on the Attiny. -// --------------------------------- -// Written by Scott Hartog, 2/6/2016 -// This is the I2C master program which runs on on a regular Arduino -// (not a AtTiny). This program uses the regular Wire library from the Arduino IDE. -// -// It performs these steps in a loop: -// 1. picks a random number of bytes between 1 and 12 -// 2. sends that many bytes of random data to the AtTiny slave within -// a single Wire.beginTransmission() / Wire.write() / Wire.endTransmission() set -// 3. reads that same number of bytes back with a single Wire.requestFrom() call -// 4. compares the received data to the originally transmitted data -// 5. displays the number of requests, number of requests with mismatches, -// and enough of the data so that the operator can tell it's working. -// -#include <Wire.h> - -// BREADBOARD SETUP: -// Arduino Uno R3 (D18/SDA) = I2C SDA -// connect to SDA on slave with external pull-up (~4.7K) -// Arduino Uno R3 (D19/SCL) = I2C SCL -// connect to SCL on slave with external pull-up (~4.7K) -// Arduino Uno R3 (D2) -// connect to !RST on slave -// Can alternatively connect !RST on slave to the Ardiuno "!RESET" pin - -#define I2C_SLAVE_ADDR 0x26 // i2c slave address (38, 0x26) - -#if defined(ESP8266) - // pins that work for Monkey Board ESP8266 12-E - // SCL=5, SDA=4 - #define SLAVE_RESET_PIN 2 - #define ALL_OK_LED_PIN 16 - #define OK_LED_PIN 14 - #define ERROR_LED_PIN 13 -#else - // pins that work for Micro Pro, Uno, Mega 2560 - // reference documentation for SCL and SDA pin locations - // Uno SDA=D18, SCL=D19 - #define SLAVE_RESET_PIN 6 - #define ALL_OK_LED_PIN 9 - #define OK_LED_PIN 7 - #define ERROR_LED_PIN 8 -#endif - -uint16_t count = 0; // total number of passes so far -uint16_t error_count = 0; // total errors encountered so far - -char c_buf[64]; // for creating messages - -void setup() -{ - // set pin modes - pinMode(SLAVE_RESET_PIN,OUTPUT); // active low reset to slave device - pinMode(OK_LED_PIN,OUTPUT); // indicates last transaction matched - pinMode(ALL_OK_LED_PIN,OUTPUT); // indicates all transactions so far have matched - pinMode(ERROR_LED_PIN,OUTPUT); // indicates last transaction mismatched - - // init the serial port - Serial.begin(9600); - - // print some useful pinnout info for the Arduino - //Serial.println(String("SCL:")+String(SCL)+String(", SDA:")+String(SDA)); - //Serial.println(String("MOSI:")+String(MOSI)+String(", SCK:")+String(SCK)); - - // init the Wire object (for I2C) - Wire.begin(); - - // init the i2c clock - // default is 100kHz if not changed - // Wire.setClock(400000L); // 400kHz - - // reset the slave - digitalWrite(SLAVE_RESET_PIN, LOW); - delay(10); - digitalWrite(SLAVE_RESET_PIN, HIGH); - - // set the all okay pin high - digitalWrite(ALL_OK_LED_PIN, HIGH); - - // wait for slave to finish any init sequence - delay(2000); -} - -void loop() -{ - uint8_t i; - uint8_t req_rtn; // num bytes returned by requestFrom() call - uint8_t rand_byte_count; - uint8_t out_rand[16]; // data written from master - uint8_t in_rand[16]; // data read back from slave - - bool mismatch; - - // count total number of request - count++; - - // compute random number of bytes for this pass - rand_byte_count = random(16) + 1; - - // force the first three requests to be small so that the tx buffer doesn't overflow - // instantly and the user can see at least one successful transaction and some - // mismtaches before the usiTwiSlave.c library hangs on the line "while ( !txCount );". - if (count <= 3) rand_byte_count = 2; - - // generate, save, and send N random byte values - Wire.beginTransmission(I2C_SLAVE_ADDR); - for (i = 0; i < rand_byte_count; i++) - Wire.write(out_rand[i] = random(256)); - Wire.endTransmission(); - - // delay 20 milliseconds to accomodate slave onReceive() callback - // function. The actual time that slave takes is application dependent, but - // just storing the master's transmitted data does not take - // anywhere near 20ms. - delay(20); - - // read N bytes from slave - req_rtn = Wire.requestFrom(I2C_SLAVE_ADDR, (int)rand_byte_count); // Request N bytes from slave - for (i = 0; i < req_rtn; i++) - in_rand[i] = Wire.read(); - - // compare in/out data values - mismatch = false; - for (i = 0; i < rand_byte_count; i++) - mismatch = mismatch || (out_rand[i] != in_rand[i]); - - // increment the error counter if the number of byte variables don't match or - // if the data itself doesn't match - if (mismatch || (rand_byte_count != req_rtn)) - { - error_count++; - digitalWrite(ERROR_LED_PIN, HIGH); - digitalWrite(OK_LED_PIN, LOW); - // If there's ever an error, reset the ALL_OK_LED - // and it is not set again until the master resets. - digitalWrite(ALL_OK_LED_PIN, LOW); - } - else - { - digitalWrite(ERROR_LED_PIN, LOW); - digitalWrite(OK_LED_PIN, HIGH); - } - - // The rest of the program just displays the results to the serial port - - // display total requests so far and error count so far - snprintf(c_buf, sizeof(c_buf), "req: %3d,err: %3d", count, error_count); - Serial.println(c_buf); - - // display the random byte count, the number of bytes read back, and "MATCH"/"MISMATCH" - snprintf(c_buf, sizeof(c_buf), "size: %2d/%2d,%s", rand_byte_count, req_rtn, rand_byte_count != req_rtn?"MISMATCH <<--- !!!":"MATCH"); - Serial.println(c_buf); - - // display whether the data compare matched or mismatched - snprintf(c_buf, sizeof(c_buf), "data: %s", mismatch?"MISMATCH <<--- !!!":"MATCH"); - Serial.println(c_buf); - - // send up to three tx/rx bytes so that random data can be - // visually verified - if (rand_byte_count >= 1) - { - snprintf(c_buf, sizeof(c_buf), "rand[0]: %02x/%02x", out_rand[0], in_rand[0]); - Serial.println(c_buf); - } - - if (rand_byte_count >= 2) - { - snprintf(c_buf, sizeof(c_buf), "rand[1]: %02x/%02x", out_rand[1], in_rand[1]); - Serial.println(c_buf); - } - - if (rand_byte_count >= 3) - { - snprintf(c_buf, sizeof(c_buf), "rand[2]: %02x/%02x", out_rand[2], in_rand[2]); - Serial.println(c_buf); - } - - // delay 1 second so user can watch results - delay(1000); -} diff --git a/digital-driver/firmware/TinyWireS/examples/TinyWireS_Stress_Slave/TinyWireS_Stress_Slave.ino b/digital-driver/firmware/TinyWireS/examples/TinyWireS_Stress_Slave/TinyWireS_Stress_Slave.ino deleted file mode 100644 index c7fbe41..0000000 --- a/digital-driver/firmware/TinyWireS/examples/TinyWireS_Stress_Slave/TinyWireS_Stress_Slave.ino +++ /dev/null @@ -1,143 +0,0 @@ -// --------------------------------- -// Stress test program/example for TinyWireS I2C library. -// Run this slave program on the Attiny. -// Run the other master program on the Arduino Uno R3. -// --------------------------------- -// // Written by Scott Hartog, 2/6/2016, to stress test the TinyWireS library. -// https://github.com/rambo/TinyWire -// -// This project uses the Tiny85 as an I2C slave. -// -// The slave program using TinyWireS, running on a Attiny85, receives -// N bytes of random data in a single receiveEvent() callback and -// stores that data in a global buffer. It then responds the first requestEvent() -// callback with that same data. The requestEvent() callback overwrites the data -// buffer with zeros after responding so it will only respond correctly to the -// first requestEvent() callback after each receiveEvent() callback. Subsequent -// requestEvent() will respond with 0xff for all data bytes. -// -// -// SETUP: -// AtTiny Pin 5 (PB0/SDA) = I2C SDA -// connect to SDA on master with external pull-up (~4.7K) -// AtTiny Pin 7 (PB0/SCL) = I2C SCL -// connect to SCL on master with external pull-up (~4.7K) -// AtTiny Pin 1 (PB5/!RST) -// connect to reset on master (or just pull-up) -// -// Please see credits and usage for usiTwiSlave and TinyWireS in the .h files of -// those libraries. - -#include <avr/sleep.h> -#include <avr/wdt.h> -#include "TinyWireS.h" // wrapper class for I2C slave routines - -#define I2C_SLAVE_ADDR 0x26 // i2c slave address (38, 0x26) - -// turns on code that makes the Tiny85 sleep between transactions -// This is optional. The Tiny85 current drops from -// about 2mA to about 20uA when the CPU is put into -// PowerDown sleep mode. -#define USE_CPU_SLEEP - -// global buffer to store data sent from the master. -uint8_t master_data[16]; -// global variable to number of bytes sent from the master. -uint8_t master_bytes; - -// Gets called when the ATtiny receives an i2c write slave request -// This routine runs from the usiTwiSlave interrupt service routine (ISR) -// so interrupts are disabled while it runs. -void receiveEvent(uint8_t num_bytes) -{ - uint8_t i; - - // save the number of bytes sent from the master - master_bytes = num_bytes; - - // store the data from the master into the data buffer - for (i = 0; i < master_bytes; i++) - master_data[i] = TinyWireS.receive(); - -} - -// Gets called when the ATtiny receives an i2c read slave request -// This routine runs from the usiTwiSlave interrupt service routine (ISR) -// so interrupts are disabled while it runs. -void requestEvent() -{ - uint8_t i; - - // send the data buffer back to the master - for (i = 0; i < master_bytes; i++) - TinyWireS.send(master_data[i]); - - // corrupt the byte values in the data buffer - // so that any subsequent call won't match - for (i = 0; i < master_bytes; i++) - master_data[i] += 0x5a; - - // corrupt length of the request, but don't make it zero - - // if the usiTwiSlave.c is working fine, then this number is completely irrelevant - // because the requestEvent() callback will not be called again until - // after the next receiveEvent() callback, so the master_data and - // master_bytes variables will be overwritten by that call. - - // If the usiTwiSlave.c has the issue of calling the requestFrom() callback - // for each byte sent, the buffer will accumulate by this amount *for each byte - // in the original request*. (This problem is fixed in the recent version.) - // - // Making it zero will obscure the 1-byte send issue in the usiTwiSlave.c - // that is being tested. - // Making it small will allow a few requests to succeed before the tx buffer - // overflows and the usiTwiSlave.c hangs on the "while ( tmphead == txTail );" - // line - master_bytes = 2; -} - -void setup() -{ - //pinMode(1,OUTPUT); // This pin can be used for rudimentary debug - - // initialize the TinyWireS and usiTwiSlave libraries - TinyWireS.begin(I2C_SLAVE_ADDR); // init I2C Slave mode - - // register the onReceive() callback function - TinyWireS.onReceive(receiveEvent); - - // register the onRequest() callback function - TinyWireS.onRequest(requestEvent); - - // disable the watchdog timer so that it doesn't - // cause power-up, code is from datasheet - // Clear WDRF in MCUSR – MCU Status Register - // MCUSR provides information on which reset source caused an MCU Reset. - MCUSR = 0x00; - // WDTCR - Watchdog Timer Control Register - // Write logical one to WDCE and WDE (must be done before disabling) - WDTCR |= ( _BV(WDCE) | _BV(WDE) ); - // Turn off WDT - WDTCR = 0x00; - -#ifdef USE_CPU_SLEEP - // enable power down sleep mode - set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode - sleep_enable(); -#endif - - sei(); // enable interrupts - -} - -void loop() -{ - -#ifdef USE_CPU_SLEEP - // optionally put the CPU to sleep. It will be woken by a USI interrupt - // when it sees a "start condition" on the I2C bus. Everything interesting - // happens in the usiTwiSlave ISR. - sleep_cpu(); -#endif - -} diff --git a/digital-driver/firmware/TinyWireS/examples/attiny85_i2c_analog/attiny85_i2c_analog.ino b/digital-driver/firmware/TinyWireS/examples/attiny85_i2c_analog/attiny85_i2c_analog.ino deleted file mode 100644 index 7190c93..0000000 --- a/digital-driver/firmware/TinyWireS/examples/attiny85_i2c_analog/attiny85_i2c_analog.ino +++ /dev/null @@ -1,210 +0,0 @@ -/** - * 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 - * Examples use bus-pirate semantics (like the REPL) - * - * The basic idea is: - * 1. Choose your ADC channel (0-X), use "byte ch = 1;" for example. - * 2. Combine the channel and conversion start flag to single calue: byte start_on_ch = (ch | _BV(7)); // This is 0x81 - * 3. Write start_on_ch to the first register on the attiny [ 8 0 81 ] - * 4. Come back later and check the first register [ 8 0 [ r ], if the value is same as ch then the conversion is complete, you can now read the value - * 5. read the value [ 8 2 [ r r ] (first one is low, second high byte) - * - * 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, though we cannot actually affect it by defining it in the sketch -#ifndef TWI_RX_BUFFER_SIZE -#define TWI_RX_BUFFER_SIZE ( 16 ) -#endif -// For the ADC_xxx helpers -#include <core_adc.h> - -// The "registers" we expose to I2C -volatile uint8_t i2c_regs[] = -{ - 0x0, // Status register, writing (1<<7 & channel) will start a conversion on that channel, the flag will be set low when conversion is done. - 0x1, // Averaging count, make this many conversions in row and average the result (well, actually it's a rolling average since we do not want to have the possibility of integer overflows) - 0x0, // low byte - 0x0, // high byte -}; -const byte reg_size = sizeof(i2c_regs); -// Tracks the current register pointer position -volatile byte reg_position; -// Tracks wheter to start a conversion cycle -volatile boolean start_conversion; -// Counter to track where we are averaging -byte avg_count; -// Some temp value holders -int avg_temp1; -int avg_temp2; - -/** - * 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; - } -} - -/** - * 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(); - if ( reg_position == 0 // If it was the first register - && bitRead(i2c_regs[0], 7) // And the highest bit is set - && !ADC_ConversionInProgress() // and we do not actually have a conversion running already - ) - { - start_conversion = true; - } - 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(); - - // Thus stuff is basically copied from wiring_analog.c - if (start_conversion) - { - //Avoid doubled starts - start_conversion = false; - byte adcpin = (i2c_regs[0] & 0x7f); // Set the channel from the control reg, dropping the highest bit. -#if defined( CORE_ANALOG_FIRST ) - if ( adcpin >= CORE_ANALOG_FIRST ) adcpin -= CORE_ANALOG_FIRST; // allow for channel or pin numbers -#endif - // NOTE: These handy helpers (ADC_xxx) are only present in the tiny-core, for other cores you need to check their wiring_analog.c source. - ADC_SetInputChannel( (adc_ic_t)adcpin ); // we need to typecast - ADC_StartConversion(); - // Reset these variables - avg_count = 0; - avg_temp2 = 0; - } - - if ( bitRead(i2c_regs[0], 7) // We have conversion flag up - && !ADC_ConversionInProgress()) // But the conversion is complete - { - // So handle it - avg_temp1 = ADC_GetDataRegister(); - // Rolling average - if (avg_count) - { - avg_temp2 = (avg_temp2+avg_temp1)/2; - } - else - { - avg_temp2 = avg_temp1; - } - avg_count++; - if (avg_count >= i2c_regs[1]) - { - // All done, set the bytes to registers - cli(); - i2c_regs[2] = lowByte(avg_temp2); - i2c_regs[3] = highByte(avg_temp2); - sei(); - // And clear the conversion flag so the master knows we're ready - bitClear(i2c_regs[0], 7); - } - else - { - // Re-trigger conversion - ADC_StartConversion(); - } - } - -} diff --git a/digital-driver/firmware/TinyWireS/examples/attiny85_i2c_slave/attiny85_i2c_slave.ino b/digital-driver/firmware/TinyWireS/examples/attiny85_i2c_slave/attiny85_i2c_slave.ino deleted file mode 100644 index df2532f..0000000 --- a/digital-driver/firmware/TinyWireS/examples/attiny85_i2c_slave/attiny85_i2c_slave.ino +++ /dev/null @@ -1,152 +0,0 @@ -/** - * 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(); -} diff --git a/digital-driver/firmware/TinyWireS/examples/attiny85_i2c_slave_task/attiny85_i2c_slave_task.ino b/digital-driver/firmware/TinyWireS/examples/attiny85_i2c_slave_task/attiny85_i2c_slave_task.ino deleted file mode 100644 index 4b3f269..0000000 --- a/digital-driver/firmware/TinyWireS/examples/attiny85_i2c_slave_task/attiny85_i2c_slave_task.ino +++ /dev/null @@ -1,246 +0,0 @@ -/** - * Example sketch for writing to and reading from a slave in transactional manner, it will also blink a led attached to pin 3 (which is the SOIC pin 2) - * (provided you're using one of my ATTiny85 boards from https://github.com/rambo/attiny_boards with the led soldered) - * - * NOTE: You must not use delay() or I2C communications will fail, use tws_delay() instead (or preferably some smarter timing system, like the Task library used in this example) - * - * 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 - * - * By default this blinks the SOS morse pattern and then has long on/off time to indicate end of pattern, send [ 8 0 32 ] (using the REPL/bus-pirate - * semantics) to make the delay per bit smaller (and thus blinking faster). The pattern lenght is calculated from the register size, it would be fairly - * trivial to make it yet another variable changeable via I2C. - * - * 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 -// Get this library from http://bleaklow.com/files/2010/Task.tar.gz -// and read http://bleaklow.com/2010/07/20/a_very_simple_arduino_task_manager.html for background and instructions -#include <Task.h> -#include <TaskScheduler.h> - -// The led is connected so that the tiny sinks current -#define LED_ON LOW -#define LED_OFF HIGH - -// The I2C registers -volatile uint8_t i2c_regs[] = -{ - 150, // Delay between each position (ms, remeber that this isa byte so 255 is max) - B10101000, // SOS pattern - B01110111, - B01110001, - B01010000, - B00000000, - B11111111, // Long on and off to mark end of pattern - B00000000, -}; -// Tracks the current register pointer position -volatile byte reg_position; -const byte reg_size = sizeof(i2c_regs); - - -/** - * BEGIN: PatternBlinker task based on the Task library Blinker example - */ -// Timed task to blink a LED. -const byte pattern_lenght = (sizeof(i2c_regs)-1) * 8; // bits (first is the speed, rest is the pattern) -class PatternBlinker : public TimedTask -{ -public: - // Create a new blinker for the specified pin and rate. - PatternBlinker(uint8_t _pin); - virtual void run(uint32_t now); -private: - uint8_t pin; // LED pin. - uint8_t pattern_position; // Used to calcuate the register and bit offset -}; - -PatternBlinker::PatternBlinker(uint8_t _pin) -: TimedTask(millis()), - pin(_pin) -{ - pinMode(pin, OUTPUT); // Set pin for output. -} - -void PatternBlinker::run(uint32_t now) -{ - // Start by setting the next runtime - incRunTime(i2c_regs[0]); - - // Written out for clear code, the complier might optimize it to something more efficient even without it being unrolled into one line - byte reg = i2c_regs[1+(pattern_position/8)]; // Get the register where the bit pattern position is stored - byte shift_amount = 7 - (pattern_position % 7); // To have "natural" left-to-right pattern flow. - bool state = (reg >> shift_amount) & 0x1; - if (state) { - digitalWrite(pin, LED_ON); - } else { - digitalWrite(pin, LED_OFF); - } - // Calculate the next pattern position - pattern_position = (pattern_position+1) % pattern_lenght; -} -/** - * END: PatternBlinker task copied from the Task library example - */ -/** - * BEGIN: I2C Stop flag checker - * - * This task needs to run almost all the time due to the USI I2C implementation limitations - * - * So I2CStopCheck_YIELD_TICKS below is used to specify how often the task is run, not it's every 4 ticks - */ -#define I2CStopCheck_YIELD_TICKS 4 -class I2CStopCheck : public Task -{ -public: - I2CStopCheck(); - virtual void run(uint32_t now); - virtual bool canRun(uint32_t now); -private: - uint8_t yield_counter; // Incremented on each canRun call, used to yield to other tasks. -}; - -I2CStopCheck::I2CStopCheck() -: Task() -{ -} - -// We can't just return true since then no other task could ever run (since we have the priority) -bool I2CStopCheck::canRun(uint32_t now) -{ - yield_counter++; - bool ret = false; - if (yield_counter == I2CStopCheck_YIELD_TICKS) - { - ret = true; - yield_counter = 0; - } - return ret; -} - -void I2CStopCheck::run(uint32_t now) -{ - TinyWireS_stop_check(); -} -/** - * END: I2C Stop flag checker - */ - -// Create the tasks. -PatternBlinker blinker(3); -I2CStopCheck checker; - -// Tasks are in priority order, only one task is run per tick -Task *tasks[] = { &checker, &blinker, }; -TaskScheduler sched(tasks, NUM_TASKS(tasks)); - - -/** - * 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; - } -} - -/** - * 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, LED_ON); // 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, LED_OFF); -} - -void loop() -{ - // Run the scheduler - never returns. - sched.run(); -} diff --git a/digital-driver/firmware/TinyWireS/keywords.txt b/digital-driver/firmware/TinyWireS/keywords.txt deleted file mode 100644 index ccc0b46..0000000 --- a/digital-driver/firmware/TinyWireS/keywords.txt +++ /dev/null @@ -1,27 +0,0 @@ -#######################################
-# Syntax Coloring Map For TinyWireS
-#######################################
-
-#######################################
-# Datatypes (KEYWORD1)
-#######################################
-
-#######################################
-# Methods and Functions (KEYWORD2)
-#######################################
-
-begin KEYWORD2
-send KEYWORD2
-available KEYWORD2
-receive KEYWORD2
-
-#######################################
-# Instances (KEYWORD2)
-#######################################
-
-TinyWireS KEYWORD2
-
-#######################################
-# Constants (LITERAL1)
-#######################################
-
diff --git a/digital-driver/firmware/TinyWireS/usiTwiSlave.c b/digital-driver/firmware/TinyWireS/usiTwiSlave.c deleted file mode 100644 index a263184..0000000 --- a/digital-driver/firmware/TinyWireS/usiTwiSlave.c +++ /dev/null @@ -1,748 +0,0 @@ -/******************************************************************************** - -USI TWI Slave driver. - -Created by Donald R. Blake. donblake at worldnet.att.net -Adapted by Jochen Toppe, jochen.toppe at jtoee.com - ---------------------------------------------------------------------------------- - -Created from Atmel source files for Application Note AVR312: Using the USI Module -as an I2C slave. - -This program is free software; you can redistribute it and/or modify it under the -terms of the GNU General Public License as published by the Free Software -Foundation; either version 2 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - ---------------------------------------------------------------------------------- - -Change Activity: - - Date Description - ------ ------------- - 16 Mar 2007 Created. - 27 Mar 2007 Added support for ATtiny261, 461 and 861. - 26 Apr 2007 Fixed ACK of slave address on a read. - 04 Jul 2007 Fixed USISIF in ATtiny45 def - 12 Dev 2009 Added callback functions for data requests - 06 Feb 2016 Minor change to allow mutli-byte requestFrom() from master. - 10 Feb 2016 Simplied RX/TX buffer code and allowed use of full buffer. - 13 Feb 2016 Made USI_RECEIVE_CALLBACK() callback fully interrupt-driven - 12 Dec 2016 Added support for ATtiny167 - 23 Dec 2017 Fixed repeated restart (which broke when making receive callback - interrupt-driven) - -********************************************************************************/ - - -/******************************************************************************** - includes -********************************************************************************/ - -#include <avr/io.h> -#include <avr/interrupt.h> - -#include "usiTwiSlave.h" -//#include "../common/util.h" - - -/******************************************************************************** - device dependent defines -********************************************************************************/ - -#if defined( __AVR_ATtiny167__ ) -# define DDR_USI DDRB -# define PORT_USI PORTB -# define PIN_USI PINB -# define PORT_USI_SDA PB0 -# define PORT_USI_SCL PB2 -# define PIN_USI_SDA PINB0 -# define PIN_USI_SCL PINB2 -# define USI_START_COND_INT USISIF -# define USI_START_VECTOR USI_START_vect -# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect -#endif - -#if defined( __AVR_ATtiny2313__ ) -# define DDR_USI DDRB -# define PORT_USI PORTB -# define PIN_USI PINB -# define PORT_USI_SDA PB5 -# define PORT_USI_SCL PB7 -# define PIN_USI_SDA PINB5 -# define PIN_USI_SCL PINB7 -# define USI_START_COND_INT USISIF -# define USI_START_VECTOR USI_START_vect -# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect -#endif - -#if defined(__AVR_ATtiny84__) | \ - defined(__AVR_ATtiny44__) -# define DDR_USI DDRA -# define PORT_USI PORTA -# define PIN_USI PINA -# define PORT_USI_SDA PORTA6 -# define PORT_USI_SCL PORTA4 -# define PIN_USI_SDA PINA6 -# define PIN_USI_SCL PINA4 -# define USI_START_COND_INT USISIF -# define USI_START_VECTOR USI_START_vect -# define USI_OVERFLOW_VECTOR USI_OVF_vect -#endif - -#if defined( __AVR_ATtiny25__ ) | \ - defined( __AVR_ATtiny45__ ) | \ - defined( __AVR_ATtiny85__ ) -# define DDR_USI DDRB -# define PORT_USI PORTB -# define PIN_USI PINB -# define PORT_USI_SDA PB0 -# define PORT_USI_SCL PB2 -# define PIN_USI_SDA PINB0 -# define PIN_USI_SCL PINB2 -# define USI_START_COND_INT USISIF -# define USI_START_VECTOR USI_START_vect -# define USI_OVERFLOW_VECTOR USI_OVF_vect -#endif - -#if defined( __AVR_ATtiny26__ ) -# define DDR_USI DDRB -# define PORT_USI PORTB -# define PIN_USI PINB -# define PORT_USI_SDA PB0 -# define PORT_USI_SCL PB2 -# define PIN_USI_SDA PINB0 -# define PIN_USI_SCL PINB2 -# define USI_START_COND_INT USISIF -# define USI_START_VECTOR USI_STRT_vect -# define USI_OVERFLOW_VECTOR USI_OVF_vect -#endif - -#if defined( __AVR_ATtiny261__ ) | \ - defined( __AVR_ATtiny461__ ) | \ - defined( __AVR_ATtiny861__ ) -# define DDR_USI DDRB -# define PORT_USI PORTB -# define PIN_USI PINB -# define PORT_USI_SDA PB0 -# define PORT_USI_SCL PB2 -# define PIN_USI_SDA PINB0 -# define PIN_USI_SCL PINB2 -# define USI_START_COND_INT USISIF -# define USI_START_VECTOR USI_START_vect -# define USI_OVERFLOW_VECTOR USI_OVF_vect -#endif - -#if defined( __AVR_ATmega165__ ) | \ - defined( __AVR_ATmega325__ ) | \ - defined( __AVR_ATmega3250__ ) | \ - defined( __AVR_ATmega645__ ) | \ - defined( __AVR_ATmega6450__ ) | \ - defined( __AVR_ATmega329__ ) | \ - defined( __AVR_ATmega3290__ ) -# define DDR_USI DDRE -# define PORT_USI PORTE -# define PIN_USI PINE -# define PORT_USI_SDA PE5 -# define PORT_USI_SCL PE4 -# define PIN_USI_SDA PINE5 -# define PIN_USI_SCL PINE4 -# define USI_START_COND_INT USISIF -# define USI_START_VECTOR USI_START_vect -# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect -#endif - -#if defined( __AVR_ATmega169__ ) -# define DDR_USI DDRE -# define PORT_USI PORTE -# define PIN_USI PINE -# define PORT_USI_SDA PE5 -# define PORT_USI_SCL PE4 -# define PIN_USI_SDA PINE5 -# define PIN_USI_SCL PINE4 -# define USI_START_COND_INT USISIF -# define USI_START_VECTOR USI_START_vect -# define USI_OVERFLOW_VECTOR USI_OVERFLOW_vect -#endif - -// These macros make the stop condition detection code more readable. -#define USI_PINS_SCL_SDA ( ( 1 << PIN_USI_SDA ) | ( 1 << PIN_USI_SCL ) ) -#define USI_PINS_SDA ( 1 << PIN_USI_SDA ) -#define USI_PINS_SCL ( 1 << PIN_USI_SCL ) - -/******************************************************************************** - - functions implemented as macros - -********************************************************************************/ - -#define SET_USI_TO_SEND_ACK( ) \ -{ \ - /* prepare ACK, ack is a zero */ \ - USIDR = 0; \ - /* set SDA as output */ \ - DDR_USI |= ( 1 << PORT_USI_SDA ); \ - /* clear all interrupt flags, except Start Cond */ \ - USISR = \ - ( 0 << USI_START_COND_INT ) | \ - ( 1 << USIOIF ) | ( 1 << USIPF ) | \ - ( 1 << USIDC )| \ - /* set USI counter to shift 1 bit */ \ - ( 0x0E << USICNT0 ); \ -} - -#define SET_USI_TO_READ_ACK( ) \ -{ \ - /* set SDA as input */ \ - DDR_USI &= ~( 1 << PORT_USI_SDA ); \ - /* prepare ACK */ \ - USIDR = 0; \ - /* clear all interrupt flags, except Start Cond */ \ - USISR = \ - ( 0 << USI_START_COND_INT ) | \ - ( 1 << USIOIF ) | \ - ( 1 << USIPF ) | \ - ( 1 << USIDC ) | \ - /* set USI counter to shift 1 bit */ \ - ( 0x0E << USICNT0 ); \ -} - -#define SET_USI_TO_TWI_START_CONDITION_MODE( ) \ -{ \ - USICR = \ - /* enable Start Condition Interrupt, disable Overflow Interrupt */ \ - ( 1 << USISIE ) | ( 0 << USIOIE ) | \ - /* set USI in Two-wire mode, no USI Counter overflow hold */ \ - ( 1 << USIWM1 ) | ( 0 << USIWM0 ) | \ - /* Shift Register Clock Source = External, positive edge */ \ - /* 4-Bit Counter Source = external, both edges */ \ - ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) | \ - /* no toggle clock-port pin */ \ - ( 0 << USITC ); \ - USISR = \ - /* clear all interrupt flags, except Start Cond */ \ - ( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | \ - ( 1 << USIDC ) | ( 0x0 << USICNT0 ); \ -} - -#define SET_USI_TO_SEND_DATA( ) \ -{ \ - /* set SDA as output */ \ - DDR_USI |= ( 1 << PORT_USI_SDA ); \ - /* clear all interrupt flags, except Start Cond */ \ - USISR = \ - ( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | \ - ( 1 << USIDC) | \ - /* set USI to shift out 8 bits */ \ - ( 0x0 << USICNT0 ); \ -} - -#define SET_USI_TO_READ_DATA( ) \ -{ \ - /* set SDA as input */ \ - DDR_USI &= ~( 1 << PORT_USI_SDA ); \ - /* clear all interrupt flags, except Start Cond */ \ - USISR = \ - ( 0 << USI_START_COND_INT ) | ( 1 << USIOIF ) | \ - ( 1 << USIPF ) | ( 1 << USIDC ) | \ - /* set USI to shift out 8 bits */ \ - ( 0x0 << USICNT0 ); \ -} - -#define USI_RECEIVE_CALLBACK() \ -{ \ - if (usi_onReceiverPtr) \ - { \ - if (usiTwiAmountDataInReceiveBuffer()) \ - { \ - usi_onReceiverPtr(usiTwiAmountDataInReceiveBuffer()); \ - } \ - } \ -} - -#define USI_REQUEST_CALLBACK() \ -{ \ - if(usi_onRequestPtr) usi_onRequestPtr(); \ -} - -/******************************************************************************** - - typedef's - -********************************************************************************/ - -typedef enum -{ - USI_SLAVE_CHECK_ADDRESS = 0x00, - USI_SLAVE_SEND_DATA = 0x01, - USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA = 0x02, - USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA = 0x03, - USI_SLAVE_REQUEST_DATA = 0x04, - USI_SLAVE_GET_DATA_AND_SEND_ACK = 0x05 -} overflowState_t; - - - -/******************************************************************************** - - local variables - -********************************************************************************/ - -static uint8_t slaveAddress; -static uint8_t sleep_enable_bit; -static uint8_t in_transaction; -static volatile overflowState_t overflowState; - - -static uint8_t rxBuf[ TWI_RX_BUFFER_SIZE ]; -static volatile uint8_t rxHead; -static volatile uint8_t rxTail; -static volatile uint8_t rxCount; - -static uint8_t txBuf[ TWI_TX_BUFFER_SIZE ]; -static volatile uint8_t txHead; -static volatile uint8_t txTail; -static volatile uint8_t txCount; - - - -/******************************************************************************** - - local functions - -********************************************************************************/ - -// flushes the TWI buffers - -static void flushTwiBuffers( void ) -{ - rxTail = 0; - rxHead = 0; - rxCount = 0; - txTail = 0; - txHead = 0; - txCount = 0; -} // end flushTwiBuffers - - - -/******************************************************************************** - - public functions - -********************************************************************************/ - -// initialise USI for TWI slave mode - -void usiTwiSlaveInit( uint8_t ownAddress ) -{ - // initialize the TX and RX buffers to empty - flushTwiBuffers( ); - - slaveAddress = ownAddress; - - // In Two Wire mode (USIWM1, USIWM0 = 1X), the slave USI will pull SCL - // low when a start condition is detected or a counter overflow (only - // for USIWM1, USIWM0 = 11). This inserts a wait state. SCL is released - // by the ISRs (USI_START_vect and USI_OVERFLOW_vect). - - // Set SCL and SDA as output - DDR_USI |= ( 1 << PORT_USI_SCL ) | ( 1 << PORT_USI_SDA ); - - // set SCL high - PORT_USI |= ( 1 << PORT_USI_SCL ); - - // set SDA high - PORT_USI |= ( 1 << PORT_USI_SDA ); - - // Set SDA as input - DDR_USI &= ~( 1 << PORT_USI_SDA ); - - USICR = - // enable Start Condition Interrupt - ( 1 << USISIE ) | - // disable Overflow Interrupt - ( 0 << USIOIE ) | - // set USI in Two-wire mode, no USI Counter overflow hold - ( 1 << USIWM1 ) | ( 0 << USIWM0 ) | - // Shift Register Clock Source = external, positive edge - // 4-Bit Counter Source = external, both edges - ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) | - // no toggle clock-port pin - ( 0 << USITC ); - - // clear all interrupt flags and reset overflow counter - - USISR = ( 1 << USI_START_COND_INT ) | ( 1 << USIOIF ) | ( 1 << USIPF ) | ( 1 << USIDC ); - - // The 'in_transaction' variable remembers if the usiTwiSlave driver is in the middle of - // an i2c transaction. Initialize it to zero - in_transaction = 0; - -} // end usiTwiSlaveInit - - -bool usiTwiDataInTransmitBuffer(void) -{ - - // return 0 (false) if the receive buffer is empty - return txCount; - -} // end usiTwiDataInTransmitBuffer - - -// put data in the transmission buffer, wait if buffer is full - -void usiTwiTransmitByte( uint8_t data ) -{ - - // wait for free space in buffer - while ( txCount == TWI_TX_BUFFER_SIZE) ; - - // store data in buffer - txBuf[ txHead ] = data; - txHead = ( txHead + 1 ) & TWI_TX_BUFFER_MASK; - txCount++; - -} // end usiTwiTransmitByte - - -// return a byte from the receive buffer, wait if buffer is empty - -uint8_t usiTwiReceiveByte( void ) -{ - uint8_t rtn_byte; - - // wait for Rx data - while ( !rxCount ); - - rtn_byte = rxBuf [ rxTail ]; - // calculate buffer index - rxTail = ( rxTail + 1 ) & TWI_RX_BUFFER_MASK; - rxCount--; - - // return data from the buffer. - return rtn_byte; - -} // end usiTwiReceiveByte - - -uint8_t usiTwiAmountDataInReceiveBuffer(void) -{ - return rxCount; -} - - -/******************************************************************************** - - USI Start Condition ISR - -********************************************************************************/ - -ISR( USI_START_VECTOR ) -{ - uint8_t usi_pins; - // http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html - - // Notes about ISR. The compiler in the Arduino IDE handles some of the - // basic ISR plumbing (unless the "ISR_NAKED" attribute is applied). - // * The AVR processor resets the SREG.I bit when jumping into an ISR - // * The compiler automatically adds code to save SREG - // * < user's ISR code goes here > - // * The compiler automatically adds code to restore SREG - // * The compiler automatically uses the RETI instruction to return from the ISR. - // The RETI instruction enables interrupts after the return from ISR. - // The compiler behavior can be altered with attributes into the ISR declaration; - // however, the description above is the default. - - // cli() call is not necessary. Processor disables interrupts when - // jumping to an ISR - - // no need to save the SREG. The compiler does this automatically when using the - // ISR construct without modifying attributes. - - if ( !in_transaction ) - { - // remeber the sleep enable bit when entering the ISR - sleep_enable_bit = MCUCR & ( 1 << SE ); - - // clear the sleep enable bit to prevent the CPU from entering sleep mode while executing this ISR. - MCUCR &= ~( 1 << SE ); - } - - // set default starting conditions for new TWI package - overflowState = USI_SLAVE_CHECK_ADDRESS; - - // set SDA as input - DDR_USI &= ~( 1 << PORT_USI_SDA ); - - // the start condition is that the master pulls SDA low. - - // wait for SCL to go low to ensure the Start Condition has completed (the - // start detector will hold SCL low ) - if a Stop Condition arises then leave - // the interrupt to prevent waiting forever - don't use USISR to test for Stop - // Condition as in Application Note AVR312 because the Stop Condition Flag is - // going to be set from the last TWI sequence - - // while SCL is high and SDA is low - while ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) == USI_PINS_SCL ); - - // if SDA line was low at SCL edge, then start condition occurred - if ( !( usi_pins & USI_PINS_SDA ) ) - { - // a Stop Condition did not occur - - // Execute callback if this is a repeated start - if (in_transaction) - { - USI_RECEIVE_CALLBACK(); - } - - USICR = - // keep Start Condition Interrupt enabled to detect RESTART - ( 1 << USISIE ) | - // enable Overflow Interrupt - ( 1 << USIOIE ) | - // set USI in Two-wire mode, hold SCL low on USI Counter overflow - ( 1 << USIWM1 ) | ( 1 << USIWM0 ) | - // Shift Register Clock Source = External, positive edge - // 4-Bit Counter Source = external, both edges - ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) | - // no toggle clock-port pin - ( 0 << USITC ); - - //remember that the USI is in a valid i2c transaction - in_transaction = 1; - - } - else - { - // a Stop Condition did occur - - USICR = - // enable Start Condition Interrupt - ( 1 << USISIE ) | - // disable Overflow Interrupt - ( 0 << USIOIE ) | - // set USI in Two-wire mode, no USI Counter overflow hold - ( 1 << USIWM1 ) | ( 0 << USIWM0 ) | - // Shift Register Clock Source = external, positive edge - // 4-Bit Counter Source = external, both edges - ( 1 << USICS1 ) | ( 0 << USICS0 ) | ( 0 << USICLK ) | - // no toggle clock-port pin - ( 0 << USITC ); - - //no longer in valid i2c transaction - in_transaction = 0; - // restore the sleep enable bit - MCUCR |= sleep_enable_bit; - - } // end if - - USISR = - // clear interrupt flags - resetting the Start Condition Flag will - // release SCL - ( 1 << USI_START_COND_INT ) | ( 1 << USIOIF ) | - ( 1 << USIPF ) |( 1 << USIDC ) | - // set USI to sample 8 bits (count 16 external SCL pin toggles) - ( 0x0 << USICNT0); - - // no need to restore the SREG. The compiler does this automatically when using the - // ISR construct without modifying attributes. - - // The compiler automatically uses an RETI instruction to return when using the - // ISR construct without modifying attributes. - -} // end ISR( USI_START_VECTOR ) - - - -/******************************************************************************** - - USI Overflow ISR - -Handles all the communication. - -Only disabled when waiting for a new Start Condition. - -********************************************************************************/ - -ISR( USI_OVERFLOW_VECTOR ) -{ - uint8_t finished; - uint8_t usi_pins; - - // http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__interrupts.html - - // Notes about ISR. The compiler in the Arduino IDE handles some of the - // basic ISR plumbing. - // * The AVR processor resets the SREG.I bit when jumping into an ISR - // * The compiler automatically adds code to save the SREG - // * < user's ISR code goes here > - // * The compiler automatically adds code to restore the SREG - // * The compiler automatically uses the RETI instruction to return from the ISR. - // The RETI insturction enables interrupts after the return from ISR. - // The compiler behavior can be altered with attributes into the ISR declaration; - // however, the description above is the default. - - // cli() call is not necessary. Processor disables interrupts when - // jumping to an ISR - - // no need to save the SREG. The compiler does this automatically when using the - // ISR construct without modifying attributes. - - // The ISR is only ever entered because the ISR(USI_START_VECTOR) interrupt - // routine ran first. That routine saved the sleep mode and disabled sleep. - - // Most of the time this routine exits, it has setup the USI to shift in/out bits - // and is expected to re-entered because of the USI overflow interrupt. Track whether or - // not the transaction is completely finished. - finished = 0; - - - switch ( overflowState ) - { - - // Address mode: check address and send ACK (and next USI_SLAVE_SEND_DATA) if OK, - // else reset USI - case USI_SLAVE_CHECK_ADDRESS: - if ( ( USIDR == 0 ) || ( ( USIDR >> 1 ) == slaveAddress) ) - { - if ( USIDR & 0x01 ) - { - overflowState = USI_SLAVE_SEND_DATA; - } - else - { - overflowState = USI_SLAVE_REQUEST_DATA; - } // end if - - // ack the start frame - // sets up the USI to pull SDA low and clock one bit (two edges) - SET_USI_TO_SEND_ACK( ); - } - else - { - SET_USI_TO_TWI_START_CONDITION_MODE( ); - finished = 1; - } - break; - - // master-read / slave-send: check reply and goto USI_SLAVE_SEND_DATA if OK, - // else reset USI - case USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA: - // Execute request callback for each byte requested, as this is the intended - // behavior of this library - USI_REQUEST_CALLBACK(); - if ( USIDR ) - { - // if NACK, the master does not want more data - SET_USI_TO_TWI_START_CONDITION_MODE( ); - finished = 1; - break; - } - // from here we just drop straight into USI_SLAVE_SEND_DATA if the - // master sent an ACK - - // copy data from buffer to USIDR and set USI to shift byte - // next USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA - case USI_SLAVE_SEND_DATA: - // Get data from Buffer - if ( txCount ) - { - USIDR = txBuf[ txTail ]; - txTail = ( txTail + 1 ) & TWI_TX_BUFFER_MASK; - txCount--; - - overflowState = USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA; - SET_USI_TO_SEND_DATA( ); - } - else - { - // the buffer is empty - SET_USI_TO_READ_ACK( ); // This might be neccessary sometimes see http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=805227#805227 - SET_USI_TO_TWI_START_CONDITION_MODE( ); - } // end if - break; - - // set USI to sample reply from master - // next USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA - case USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA: - overflowState = USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA; - SET_USI_TO_READ_ACK( ); - break; - - // master-send / slave-receive: set USI to sample data from master, next - // USI_SLAVE_GET_DATA_AND_SEND_ACK - case USI_SLAVE_REQUEST_DATA: - overflowState = USI_SLAVE_GET_DATA_AND_SEND_ACK; - SET_USI_TO_READ_DATA( ); - - // with the SET_USI_TO_READ_DATA() macro call above, the USI has - // been setup to catch the next byte if the master sends one. - // while that's going on, look for a stop condition here which - // is when the SDA line goes high after the SCL line; - - // wait until SCL goes high - while ( ! ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) & USI_PINS_SCL ) ); - - // if SDA line was high at SCL edge, then not a stop condition - if ( usi_pins & USI_PINS_SDA ) - break; - - // wait until SCL goes low or SDA goes high - while ( ( usi_pins = PIN_USI & USI_PINS_SCL_SDA ) == USI_PINS_SCL ); - - // if both SCL and SDA are high, then stop condition occurred - if ( usi_pins == USI_PINS_SCL_SDA ) - { - USI_RECEIVE_CALLBACK(); - SET_USI_TO_TWI_START_CONDITION_MODE( ); - finished = 1; - } - - break; - - // copy data from USIDR and send ACK - // next USI_SLAVE_REQUEST_DATA - case USI_SLAVE_GET_DATA_AND_SEND_ACK: - // put data into buffer - // check buffer size - if ( rxCount < TWI_RX_BUFFER_SIZE ) - { - rxBuf[ rxHead ] = USIDR; - rxHead = ( rxHead + 1 ) & TWI_RX_BUFFER_MASK; - rxCount++; - } else { - // overrun - // drop data - } - // next USI_SLAVE_REQUEST_DATA - overflowState = USI_SLAVE_REQUEST_DATA; - SET_USI_TO_SEND_ACK( ); - break; - - } // end switch - - if (finished) - { - //no longer in valid i2c transaction - in_transaction = 0; - // restore the sleep enable bit - // note that this allows sleep -- it does not cause sleep - MCUCR |= sleep_enable_bit; - } - - // no need to restore the SREG. The compiler does this automatically when using the - // ISR construct without modifying attributes. - - // The compiler automatically uses an RETI instruction to return when using the - // ISR construct without modifying attributes. - -} // end ISR( USI_OVERFLOW_VECTOR ) diff --git a/digital-driver/firmware/TinyWireS/usiTwiSlave.h b/digital-driver/firmware/TinyWireS/usiTwiSlave.h deleted file mode 100644 index 88b9445..0000000 --- a/digital-driver/firmware/TinyWireS/usiTwiSlave.h +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************************** - -Header file for the USI TWI Slave driver. - -Created by Donald R. Blake -donblake at worldnet.att.net - ---------------------------------------------------------------------------------- - -Created from Atmel source files for Application Note AVR312: Using the USI Module -as an I2C slave. - -This program is free software; you can redistribute it and/or modify it under the -terms of the GNU General Public License as published by the Free Software -Foundation; either version 2 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - ---------------------------------------------------------------------------------- - -Change Activity: - - Date Description - ------ ------------- - 15 Mar 2007 Created. - -********************************************************************************/ - - - -#ifndef _USI_TWI_SLAVE_H_ -#define _USI_TWI_SLAVE_H_ - - - -/******************************************************************************** - - includes - -********************************************************************************/ - -#include <stdbool.h> -#include <avr/sleep.h> - - - -/******************************************************************************** - - prototypes - -********************************************************************************/ - -void usiTwiSlaveInit( uint8_t ); -void usiTwiTransmitByte( uint8_t ); -uint8_t usiTwiReceiveByte( void ); -bool usiTwiDataInTransmitBuffer(void); -uint8_t usiTwiAmountDataInReceiveBuffer(void); -// on_XXX handler pointers -void (*usi_onRequestPtr)(void); -void (*usi_onReceiverPtr)(uint8_t); - - -/******************************************************************************** - - driver buffer definitions - -********************************************************************************/ - -// permitted RX buffer sizes: 1, 2, 4, 8, 16, 32, 64, 128 or 256 - -#ifndef TWI_RX_BUFFER_SIZE -#define TWI_RX_BUFFER_SIZE ( 16 ) -#endif -#define TWI_RX_BUFFER_MASK ( TWI_RX_BUFFER_SIZE - 1 ) - -#if ( TWI_RX_BUFFER_SIZE & TWI_RX_BUFFER_MASK ) -# error TWI RX buffer size is not a power of 2 -#endif - -// permitted TX buffer sizes: 1, 2, 4, 8, 16, 32, 64, 128 or 256 - -#ifndef TWI_TX_BUFFER_SIZE -#define TWI_TX_BUFFER_SIZE ( 16 ) -#endif -#define TWI_TX_BUFFER_MASK ( TWI_TX_BUFFER_SIZE - 1 ) - -#if ( TWI_TX_BUFFER_SIZE & TWI_TX_BUFFER_MASK ) -# error TWI TX buffer size is not a power of 2 -#endif - - - -#endif // ifndef _USI_TWI_SLAVE_H_ |