diff options
| author | David A. Mellis <d.mellis@arduino.cc> | 2007-10-06 13:02:43 +0000 | 
|---|---|---|
| committer | David A. Mellis <d.mellis@arduino.cc> | 2007-10-06 13:02:43 +0000 | 
| commit | 179fcdbda432ff33a921a70994087b08b2a79caa (patch) | |
| tree | db62b71d303b5b13876773552451406b13cc66cf /core/libraries/Wire | |
Moving things around - creating the hardware directory and sticking all the avr code, etc. in there.
Diffstat (limited to 'core/libraries/Wire')
| -rwxr-xr-x | core/libraries/Wire/Wire.cpp | 262 | ||||
| -rwxr-xr-x | core/libraries/Wire/Wire.h | 67 | ||||
| -rwxr-xr-x | core/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.pde | 84 | ||||
| -rw-r--r-- | core/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.pde | 34 | ||||
| -rw-r--r-- | core/libraries/Wire/examples/master_reader/master_reader.pde | 29 | ||||
| -rw-r--r-- | core/libraries/Wire/examples/master_writer/master_writer.pde | 28 | ||||
| -rw-r--r-- | core/libraries/Wire/examples/slave_receiver/slave_receiver.pde | 35 | ||||
| -rw-r--r-- | core/libraries/Wire/examples/slave_sender/slave_sender.pde | 29 | ||||
| -rw-r--r-- | core/libraries/Wire/keywords.txt | 31 | ||||
| -rw-r--r-- | core/libraries/Wire/utility/twi.c | 449 | ||||
| -rwxr-xr-x | core/libraries/Wire/utility/twi.h | 57 | 
11 files changed, 1105 insertions, 0 deletions
| diff --git a/core/libraries/Wire/Wire.cpp b/core/libraries/Wire/Wire.cpp new file mode 100755 index 0000000..73369b3 --- /dev/null +++ b/core/libraries/Wire/Wire.cpp @@ -0,0 +1,262 @@ +/* +  TwoWire.cpp - TWI/I2C library for Wiring & Arduino +  Copyright (c) 2006 Nicholas Zambetti.  All right reserved. + +  This library is free software; you can redistribute it and/or +  modify it under the terms of the GNU Lesser General Public +  License as published by the Free Software Foundation; either +  version 2.1 of the License, or (at your option) any later version. + +  This library 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 +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with this library; if not, write to the Free Software +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +*/ + +extern "C" { +  #include <stdlib.h> +  #include <string.h> +  #include <inttypes.h> +  #include "twi.h" +} + +#include "Wire.h" + +// Initialize Class Variables ////////////////////////////////////////////////// + +uint8_t* TwoWire::rxBuffer = 0; +uint8_t TwoWire::rxBufferIndex = 0; +uint8_t TwoWire::rxBufferLength = 0; + +uint8_t TwoWire::txAddress = 0; +uint8_t* TwoWire::txBuffer = 0; +uint8_t TwoWire::txBufferIndex = 0; +uint8_t TwoWire::txBufferLength = 0; + +uint8_t TwoWire::transmitting = 0; +void (*TwoWire::user_onRequest)(void); +void (*TwoWire::user_onReceive)(int); + +// Constructors //////////////////////////////////////////////////////////////// + +TwoWire::TwoWire() +{ +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void TwoWire::begin(void) +{ +  // init buffer for reads +  rxBuffer = (uint8_t*) calloc(BUFFER_LENGTH, sizeof(uint8_t)); +  rxBufferIndex = 0; +  rxBufferLength = 0; + +  // init buffer for writes +  txBuffer = (uint8_t*) calloc(BUFFER_LENGTH, sizeof(uint8_t)); +  txBufferIndex = 0; +  txBufferLength = 0; + +  twi_init(); +} + +void TwoWire::begin(uint8_t address) +{ +  twi_setAddress(address); +  twi_attachSlaveTxEvent(onRequestService); +  twi_attachSlaveRxEvent(onReceiveService); +  begin(); +} + +void TwoWire::begin(int address) +{ +  begin((uint8_t)address); +} + +void TwoWire::requestFrom(uint8_t address, uint8_t quantity) +{ +  // clamp to buffer length +  if(quantity > BUFFER_LENGTH){ +    quantity = BUFFER_LENGTH; +  } +  // perform blocking read into buffer +  twi_readFrom(address, rxBuffer, quantity); +  // set rx buffer iterator vars +  rxBufferIndex = 0; +  rxBufferLength = quantity; +} + +void TwoWire::requestFrom(int address, int quantity) +{ +  requestFrom((uint8_t)address, (uint8_t)quantity); +} + +void TwoWire::beginTransmission(uint8_t address) +{ +  // indicate that we are transmitting +  transmitting = 1; +  // set address of targeted slave +  txAddress = address; +  // reset tx buffer iterator vars +  txBufferIndex = 0; +  txBufferLength = 0; +} + +void TwoWire::beginTransmission(int address) +{ +  beginTransmission((uint8_t)address); +} + +void TwoWire::endTransmission(void) +{ +  // transmit buffer (blocking) +  twi_writeTo(txAddress, txBuffer, txBufferLength, 1); +  // reset tx buffer iterator vars +  txBufferIndex = 0; +  txBufferLength = 0; +  // indicate that we are done transmitting +  transmitting = 0; +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +void TwoWire::send(uint8_t data) +{ +  if(transmitting){ +  // in master transmitter mode +    // don't bother if buffer is full +    if(txBufferLength >= BUFFER_LENGTH){ +      return; +    } +    // put byte in tx buffer +    txBuffer[txBufferIndex] = data; +    ++txBufferIndex; +    // update amount in buffer    +    txBufferLength = txBufferIndex; +  }else{ +  // in slave send mode +    // reply to master +    twi_transmit(&data, 1); +  } +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +void TwoWire::send(uint8_t* data, uint8_t quantity) +{ +  if(transmitting){ +  // in master transmitter mode +    for(uint8_t i = 0; i < quantity; ++i){ +      send(data[i]); +    } +  }else{ +  // in slave send mode +    // reply to master +    twi_transmit(data, quantity); +  } +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +void TwoWire::send(char* data) +{ +  send((uint8_t*)data, strlen(data)); +} + +// must be called in: +// slave tx event callback +// or after beginTransmission(address) +void TwoWire::send(int data) +{ +  send((uint8_t)data); +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +uint8_t TwoWire::available(void) +{ +  return rxBufferLength - rxBufferIndex; +} + +// must be called in: +// slave rx event callback +// or after requestFrom(address, numBytes) +uint8_t TwoWire::receive(void) +{ +  // default to returning null char +  // for people using with char strings +  uint8_t value = '\0'; +   +  // get each successive byte on each call +  if(rxBufferIndex < rxBufferLength){ +    value = rxBuffer[rxBufferIndex]; +    ++rxBufferIndex; +  } + +  return value; +} + +// behind the scenes function that is called when data is received +void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) +{ +  // don't bother if user hasn't registered a callback +  if(!user_onReceive){ +    return; +  } +  // don't bother if rx buffer is in use by a master requestFrom() op +  // i know this drops data, but it allows for slight stupidity +  // meaning, they may not have read all the master requestFrom() data yet +  if(rxBufferIndex < rxBufferLength){ +    return; +  } +  // copy twi rx buffer into local read buffer +  // this enables new reads to happen in parallel +  for(uint8_t i = 0; i < numBytes; ++i){ +    rxBuffer[i] = inBytes[i];     +  } +  // set rx iterator vars +  rxBufferIndex = 0; +  rxBufferLength = numBytes; +  // alert user program +  user_onReceive(numBytes); +} + +// behind the scenes function that is called when data is requested +void TwoWire::onRequestService(void) +{ +  // don't bother if user hasn't registered a callback +  if(!user_onRequest){ +    return; +  } +  // reset tx buffer iterator vars +  // !!! this will kill any pending pre-master sendTo() activity +  txBufferIndex = 0; +  txBufferLength = 0; +  // alert user program +  user_onRequest(); +} + +// sets function called on slave write +void TwoWire::onReceive( void (*function)(int) ) +{ +  user_onReceive = function; +} + +// sets function called on slave read +void TwoWire::onRequest( void (*function)(void) ) +{ +  user_onRequest = function; +} + +// Preinstantiate Objects ////////////////////////////////////////////////////// + +TwoWire Wire = TwoWire(); + diff --git a/core/libraries/Wire/Wire.h b/core/libraries/Wire/Wire.h new file mode 100755 index 0000000..9c91b9b --- /dev/null +++ b/core/libraries/Wire/Wire.h @@ -0,0 +1,67 @@ +/* +  TwoWire.h - TWI/I2C library for Arduino & Wiring +  Copyright (c) 2006 Nicholas Zambetti.  All right reserved. + +  This library is free software; you can redistribute it and/or +  modify it under the terms of the GNU Lesser General Public +  License as published by the Free Software Foundation; either +  version 2.1 of the License, or (at your option) any later version. + +  This library 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 +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with this library; if not, write to the Free Software +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +*/ + +#ifndef TwoWire_h +#define TwoWire_h + +#include <inttypes.h> + +#define BUFFER_LENGTH 32 + +class TwoWire +{ +  private: +    static uint8_t* rxBuffer; +    static uint8_t rxBufferIndex; +    static uint8_t rxBufferLength; + +    static uint8_t txAddress; +    static uint8_t* txBuffer; +    static uint8_t txBufferIndex; +    static uint8_t txBufferLength; + +    static uint8_t transmitting; +    static void (*user_onRequest)(void); +    static void (*user_onReceive)(int); +    static void onRequestService(void); +    static void onReceiveService(uint8_t*, int); +  public: +    TwoWire(); +    void begin(); +    void begin(uint8_t); +    void begin(int); +    void beginTransmission(uint8_t); +    void beginTransmission(int); +    void endTransmission(void); +    void requestFrom(uint8_t, uint8_t); +    void requestFrom(int, int); +    void send(uint8_t); +    void send(uint8_t*, uint8_t); +    void send(int); +    void send(char*); +    uint8_t available(void); +    uint8_t receive(void); +    void onReceive( void (*)(int) ); +    void onRequest( void (*)(void) ); +}; + +extern TwoWire Wire; + +#endif + diff --git a/core/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.pde b/core/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.pde new file mode 100755 index 0000000..c89b0f0 --- /dev/null +++ b/core/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.pde @@ -0,0 +1,84 @@ +// I2C SRF10 or SRF08 Devantech Ultrasonic Ranger Finder  +// by Nicholas Zambetti <http://www.zambetti.com> +// and James Tichenor <http://www.jamestichenor.net>  + +// Demonstrates use of the Wire library reading data from the  +// Devantech Utrasonic Rangers SFR08 and SFR10 + +// Created 29 April 2006 + +#include <Wire.h> + +void setup() +{ +  Wire.begin();                // join i2c bus (address optional for master) +  Serial.begin(9600);          // start serial communication at 9600bps +} + +int reading = 0; + +void loop() +{ +  // step 1: instruct sensor to read echoes +  Wire.beginTransmission(112); // transmit to device #112 (0x70) +                               // the address specified in the datasheet is 224 (0xE0) +                               // but i2c adressing uses the high 7 bits so it's 112 +  Wire.send(0x00);             // sets register pointer to the command register (0x00)   +  Wire.send(0x50);             // command sensor to measure in "inches" (0x50)  +                               // use 0x51 for centimeters +                               // use 0x52 for ping microseconds +  Wire.endTransmission();      // stop transmitting + +  // step 2: wait for readings to happen +  delay(70);                   // datasheet suggests at least 65 milliseconds + +  // step 3: instruct sensor to return a particular echo reading +  Wire.beginTransmission(112); // transmit to device #112 +  Wire.send(0x02);             // sets register pointer to echo #1 register (0x02) +  Wire.endTransmission();      // stop transmitting + +  // step 4: request reading from sensor +  Wire.requestFrom(112, 2);    // request 2 bytes from slave device #112 + +  // step 5: receive reading from sensor +  if(2 <= Wire.available())    // if two bytes were received +  { +    reading = Wire.receive();  // receive high byte (overwrites previous reading) +    reading = reading << 8;    // shift high byte to be high 8 bits +    reading |= Wire.receive(); // receive low byte as lower 8 bits +    Serial.println(reading);   // print the reading +  } + +  delay(250);                  // wait a bit since people have to read the output :) +} + + +/* + +// The following code changes the address of a Devantech Ultrasonic Range Finder (SRF10 or SRF08) +// usage: changeAddress(0x70, 0xE6); + +void changeAddress(byte oldAddress, byte newAddress) +{ +  Wire.beginTransmission(oldAddress); +  Wire.send(0x00); +  Wire.send(0xA0); +  Wire.endTransmission(); + +  Wire.beginTransmission(oldAddress); +  Wire.send(0x00); +  Wire.send(0xAA); +  Wire.endTransmission(); + +  Wire.beginTransmission(oldAddress); +  Wire.send(0x00); +  Wire.send(0xA5); +  Wire.endTransmission(); + +  Wire.beginTransmission(oldAddress); +  Wire.send(0x00); +  Wire.send(newAddress); +  Wire.endTransmission(); +} + +*/ diff --git a/core/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.pde b/core/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.pde new file mode 100644 index 0000000..35ee5d6 --- /dev/null +++ b/core/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.pde @@ -0,0 +1,34 @@ +// I2C Digital Potentiometer +// by Nicholas Zambetti <http://www.zambetti.com> +// and Shawn Bonkowski <http://people.interaction-ivrea.it/s.bonkowski/> + +// Demonstrates use of the Wire library +// Controls AD5171 digital potentiometer via I2C/TWI + +// Created 31 March 2006 + +#include <Wire.h> + +void setup() +{ +  Wire.begin(); // join i2c bus (address optional for master) +} + +byte val = 0; + +void loop() +{ +  Wire.beginTransmission(44); // transmit to device #44 (0x2c) +                              // device address is specified in datasheet +  Wire.send(0x00);            // sends instruction byte   +  Wire.send(val);             // sends potentiometer value byte   +  Wire.endTransmission();     // stop transmitting + +  val++;        // increment value +  if(val == 64) // if reached 64th position (max) +  { +    val = 0;    // start over from lowest value +  } +  delay(500); +} + diff --git a/core/libraries/Wire/examples/master_reader/master_reader.pde b/core/libraries/Wire/examples/master_reader/master_reader.pde new file mode 100644 index 0000000..1b139de --- /dev/null +++ b/core/libraries/Wire/examples/master_reader/master_reader.pde @@ -0,0 +1,29 @@ +// Wire Master Reader +// by Nicholas Zambetti <http://www.zambetti.com> + +// Demonstrates use of the Wire library +// Reads data from an I2C/TWI slave device +// Refer to the "Wire Slave Sender" example for use with this + +// Created 29 March 2006 + +#include <Wire.h> + +void setup() +{ +  Wire.begin();        // join i2c bus (address optional for master) +  Serial.begin(9600);  // start serial for output +} + +void loop() +{ +  Wire.requestFrom(2, 6);    // request 6 bytes from slave device #2 + +  while(Wire.available())    // slave may send less than requested +  {  +    char c = Wire.receive(); // receive a byte as character +    Serial.print(c);         // print the character +  } + +  delay(500); +} diff --git a/core/libraries/Wire/examples/master_writer/master_writer.pde b/core/libraries/Wire/examples/master_writer/master_writer.pde new file mode 100644 index 0000000..d0ff9fa --- /dev/null +++ b/core/libraries/Wire/examples/master_writer/master_writer.pde @@ -0,0 +1,28 @@ +// Wire Master Writer +// by Nicholas Zambetti <http://www.zambetti.com> + +// Demonstrates use of the Wire library +// Writes data to an I2C/TWI slave device +// Refer to the "Wire Slave Receiver" example for use with this + +// Created 29 March 2006 + +#include <Wire.h> + +void setup() +{ +  Wire.begin(); // join i2c bus (address optional for master) +} + +byte x = 0; + +void loop() +{ +  Wire.beginTransmission(4); // transmit to device #4 +  Wire.send("x is ");        // sends five bytes +  Wire.send(x);              // sends one byte   +  Wire.endTransmission();    // stop transmitting + +  x++; +  delay(500); +} diff --git a/core/libraries/Wire/examples/slave_receiver/slave_receiver.pde b/core/libraries/Wire/examples/slave_receiver/slave_receiver.pde new file mode 100644 index 0000000..53c86b5 --- /dev/null +++ b/core/libraries/Wire/examples/slave_receiver/slave_receiver.pde @@ -0,0 +1,35 @@ +// Wire Slave Receiver +// by Nicholas Zambetti <http://www.zambetti.com> + +// Demonstrates use of the Wire library +// Receives data as an I2C/TWI slave device +// Refer to the "Wire Master Writer" example for use with this + +// Created 29 March 2006 + +#include <Wire.h> + +void setup() +{ +  Wire.begin(4);                // join i2c bus with address #4 +  Wire.onReceive(receiveEvent); // register event +  Serial.begin(9600);           // start serial for output +} + +void loop() +{ +  delay(100); +} + +// function that executes whenever data is received from master +// this function is registered as an event, see setup() +void receiveEvent(int howMany) +{ +  while(1 < Wire.available()) // loop through all but the last +  { +    char c = Wire.receive(); // receive byte as a character +    Serial.print(c);         // print the character +  } +  int x = Wire.receive();    // receive byte as an integer +  Serial.println(x);         // print the integer +} diff --git a/core/libraries/Wire/examples/slave_sender/slave_sender.pde b/core/libraries/Wire/examples/slave_sender/slave_sender.pde new file mode 100644 index 0000000..f500644 --- /dev/null +++ b/core/libraries/Wire/examples/slave_sender/slave_sender.pde @@ -0,0 +1,29 @@ +// Wire Slave Sender +// by Nicholas Zambetti <http://www.zambetti.com> + +// Demonstrates use of the Wire library +// Sends data as an I2C/TWI slave device +// Refer to the "Wire Master Reader" example for use with this + +// Created 29 March 2006 + +#include <Wire.h> + +void setup() +{ +  Wire.begin(2);                // join i2c bus with address #2 +  Wire.onRequest(requestEvent); // register event +} + +void loop() +{ +  delay(100); +} + +// function that executes whenever data is requested by master +// this function is registered as an event, see setup() +void requestEvent() +{ +  Wire.send("hello "); // respond with message of 6 bytes +                       // as expected by master +} diff --git a/core/libraries/Wire/keywords.txt b/core/libraries/Wire/keywords.txt new file mode 100644 index 0000000..12f129b --- /dev/null +++ b/core/libraries/Wire/keywords.txt @@ -0,0 +1,31 @@ +####################################### +# Syntax Coloring Map For Wire +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin	KEYWORD2 +beginTransmission	KEYWORD2 +endTransmission	KEYWORD2 +requestFrom	KEYWORD2 +send	KEYWORD2 +receive	KEYWORD2 +onReceive	KEYWORD2 +onRequest	KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +Wire	KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/core/libraries/Wire/utility/twi.c b/core/libraries/Wire/utility/twi.c new file mode 100644 index 0000000..2235b0b --- /dev/null +++ b/core/libraries/Wire/utility/twi.c @@ -0,0 +1,449 @@ +/* +  twi.c - TWI/I2C library for Wiring & Arduino +  Copyright (c) 2006 Nicholas Zambetti.  All right reserved. + +  This library is free software; you can redistribute it and/or +  modify it under the terms of the GNU Lesser General Public +  License as published by the Free Software Foundation; either +  version 2.1 of the License, or (at your option) any later version. + +  This library 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 +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with this library; if not, write to the Free Software +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +*/ + +#include <math.h> +#include <stdlib.h> +#include <inttypes.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/signal.h> +#include <compat/twi.h> + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif + +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +#include "twi.h" + +static volatile uint8_t twi_state; +static uint8_t twi_slarw; + +static void (*twi_onSlaveTransmit)(void); +static void (*twi_onSlaveReceive)(uint8_t*, int); + +static uint8_t* twi_masterBuffer; +static volatile uint8_t twi_masterBufferIndex; +static uint8_t twi_masterBufferLength; + +static uint8_t* twi_txBuffer; +static volatile uint8_t twi_txBufferIndex; +static volatile uint8_t twi_txBufferLength; + +static uint8_t* twi_rxBuffer; +static volatile uint8_t twi_rxBufferIndex; + +/*  + * Function twi_init + * Desc     readys twi pins and sets twi bitrate + * Input    none + * Output   none + */ +void twi_init(void) +{ +  // initialize state +  twi_state = TWI_READY; + +  #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) +    // activate internal pull-ups for twi +    // as per note from atmega8 manual pg167 +    sbi(PORTC, 4); +    sbi(PORTC, 5); +  #else +    // activate internal pull-ups for twi +    // as per note from atmega128 manual pg204 +    sbi(PORTD, 0); +    sbi(PORTD, 1); +  #endif + +  // initialize twi prescaler and bit rate +  cbi(TWSR, TWPS0); +  cbi(TWSR, TWPS1); +  TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; + +  /* twi bit rate formula from atmega128 manual pg 204 +  SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) +  note: TWBR should be 10 or higher for master mode +  It is 72 for a 16mhz Wiring board with 100kHz TWI */ + +  // enable twi module, acks, and twi interrupt +	TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); +	 +	// allocate buffers +  twi_masterBuffer = (uint8_t*) calloc(TWI_BUFFER_LENGTH, sizeof(uint8_t)); +  twi_txBuffer = (uint8_t*) calloc(TWI_BUFFER_LENGTH, sizeof(uint8_t)); +  twi_rxBuffer = (uint8_t*) calloc(TWI_BUFFER_LENGTH, sizeof(uint8_t)); +} + +/*  + * Function twi_slaveInit + * Desc     sets slave address and enables interrupt + * Input    none + * Output   none + */ +void twi_setAddress(uint8_t address) +{ +  // set twi slave address (skip over TWGCE bit) +  TWAR = address << 1; +} + +/*  + * Function twi_readFrom + * Desc     attempts to become twi bus master and read a + *          series of bytes from a device on the bus + * Input    address: 7bit i2c device address + *          data: pointer to byte array + *          length: number of bytes to read into array + * Output   byte: 0 ok, 1 length too long for buffer + */ +uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) +{ +  uint8_t i; + +  // ensure data will fit into buffer +  if(TWI_BUFFER_LENGTH < length){ +    return 1; +  } + +  // wait until twi is ready, become master receiver +  while(TWI_READY != twi_state){ +    continue; +  } +  twi_state = TWI_MRX; + +  // initialize buffer iteration vars +  twi_masterBufferIndex = 0; +  twi_masterBufferLength = length; + +  // build sla+w, slave device address + w bit +  twi_slarw = TW_READ; +	twi_slarw |= address << 1; + +  // send start condition +	TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + +	// wait for read operation to complete +	while(TWI_MRX == twi_state){ +	  continue; +	} + +  // copy twi buffer to data +  for(i = 0; i < length; ++i){ +    data[i] = twi_masterBuffer[i]; +  } +	 +	return 0; +} + +/*  + * Function twi_writeTo + * Desc     attempts to become twi bus master and write a + *          series of bytes to a device on the bus + * Input    address: 7bit i2c device address + *          data: pointer to byte array + *          length: number of bytes in array + *          wait: boolean indicating to wait for write or not + * Output   byte: 0 ok, 1 length too long for buffer + */ +uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) +{ +  uint8_t i; + +  // ensure data will fit into buffer +  if(TWI_BUFFER_LENGTH < length){ +    return 1; +  } + +  // wait until twi is ready, become master transmitter +  while(TWI_READY != twi_state){ +    continue; +  } +  twi_state = TWI_MTX; + +  // initialize buffer iteration vars +  twi_masterBufferIndex = 0; +  twi_masterBufferLength = length; +   +  // copy data to twi buffer +  for(i = 0; i < length; ++i){ +    twi_masterBuffer[i] = data[i]; +  } +   +  // build sla+w, slave device address + w bit +  twi_slarw = TW_WRITE; +	twi_slarw |= address << 1; +   +  // send start condition +	TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + +	// wait for write operation to complete +	while(wait && (TWI_MTX == twi_state)){ +	  continue; +	} +	 +	return 0; +} + +/*  + * Function twi_transmit + * Desc     fills slave tx buffer with data + *          must be called in slave tx event callback + * Input    data: pointer to byte array + *          length: number of bytes in array + * Output   1 length too long for buffer + *          2 not slave transmitter + *          0 ok + */ +uint8_t twi_transmit(uint8_t* data, uint8_t length) +{ +  uint8_t i; + +  // ensure data will fit into buffer +  if(TWI_BUFFER_LENGTH < length){ +    return 1; +  } +   +  // ensure we are currently a slave transmitter +  if(TWI_STX != twi_state){ +    return 2; +  } +   +  // set length and copy data into tx buffer +  twi_txBufferLength = length; +  for(i = 0; i < length; ++i){ +    twi_txBuffer[i] = data[i]; +  } +   +  return 0; +} + +/*  + * Function twi_attachSlaveRxEvent + * Desc     sets function called before a slave read operation + * Input    function: callback function to use + * Output   none + */ +void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) +{ +  twi_onSlaveReceive = function; +} + +/*  + * Function twi_attachSlaveTxEvent + * Desc     sets function called before a slave write operation + * Input    function: callback function to use + * Output   none + */ +void twi_attachSlaveTxEvent( void (*function)(void) ) +{ +  twi_onSlaveTransmit = function; +} + +/*  + * Function twi_reply + * Desc     sends byte or readys receive line + * Input    ack: byte indicating to ack or to nack + * Output   none + */ +void twi_reply(uint8_t ack) +{ +	// transmit master read ready signal, with or without ack +	if(ack){ +	  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); +  }else{ +	  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); +  } +} + +/*  + * Function twi_stop + * Desc     relinquishes bus master status + * Input    none + * Output   none + */ +void twi_stop(void) +{ +  // send stop condition +  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); + +  // wait for stop condition to be exectued on bus +  // TWINT is not set after a stop condition! +  while(TWCR & _BV(TWSTO)){ +    continue; +  } + +  // update twi state +  twi_state = TWI_READY; +} + +/*  + * Function twi_releaseBus + * Desc     releases bus control + * Input    none + * Output   none + */ +void twi_releaseBus(void) +{ +  // release bus +  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); + +  // update twi state +  twi_state = TWI_READY; +} + +SIGNAL(SIG_2WIRE_SERIAL) +{ +  switch(TW_STATUS){ +    // All Master +    case TW_START:     // sent start condition +    case TW_REP_START: // sent repeated start condition +      // copy device address and r/w bit to output register and ack +      TWDR = twi_slarw; +      twi_reply(1); +      break; + +    // Master Transmitter +    case TW_MT_SLA_ACK:  // slave receiver acked address +    case TW_MT_DATA_ACK: // slave receiver acked data +      // if there is data to send, send it, otherwise stop  +      if(twi_masterBufferIndex < twi_masterBufferLength){ +        // copy data to output register and ack +        TWDR = twi_masterBuffer[twi_masterBufferIndex++]; +        twi_reply(1); +      }else{ +        twi_stop(); +      } +      break; +    case TW_MT_SLA_NACK:  // address sent, nack received +    case TW_MT_DATA_NACK: // data sent, nack received +      twi_stop(); +      break; +    case TW_MT_ARB_LOST: // lost bus arbitration +      twi_releaseBus(); +      break; + +    // Master Receiver +    case TW_MR_DATA_ACK: // data received, ack sent +      // put byte into buffer +      twi_masterBuffer[twi_masterBufferIndex++] = TWDR; +    case TW_MR_SLA_ACK:  // address sent, ack received +      // ack if more bytes are expected, otherwise nack +      if(twi_masterBufferIndex < twi_masterBufferLength){ +        twi_reply(1); +      }else{ +        twi_reply(0); +      } +      break; +    case TW_MR_DATA_NACK: // data received, nack sent +      // put final byte into buffer +      twi_masterBuffer[twi_masterBufferIndex++] = TWDR; +    case TW_MR_SLA_NACK: // address sent, nack received +      twi_stop(); +      break; +    // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case + +    // Slave Receiver +    case TW_SR_SLA_ACK:   // addressed, returned ack +    case TW_SR_GCALL_ACK: // addressed generally, returned ack +    case TW_SR_ARB_LOST_SLA_ACK:   // lost arbitration, returned ack +    case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack +      // enter slave receiver mode +      twi_state = TWI_SRX; +      // indicate that rx buffer can be overwritten and ack +      twi_rxBufferIndex = 0; +      twi_reply(1); +      break; +    case TW_SR_DATA_ACK:       // data received, returned ack +    case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack +      // if there is still room in the rx buffer +      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ +        // put byte in buffer and ack +        twi_rxBuffer[twi_rxBufferIndex++] = TWDR; +        twi_reply(1); +      }else{ +        // otherwise nack +        twi_reply(0); +      } +      break; +    case TW_SR_STOP: // stop or repeated start condition received +      // put a null char after data if there's room +      if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ +        twi_rxBuffer[twi_rxBufferIndex] = '\0'; +      } +      // callback to user defined callback +      twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); +      // ack future responses +      twi_reply(1); +      // leave slave receiver state +      twi_state = TWI_READY; +      break; +    case TW_SR_DATA_NACK:       // data received, returned nack +    case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack +      // nack back at master +      twi_reply(0); +      break; +     +    // Slave Transmitter +    case TW_ST_SLA_ACK:          // addressed, returned ack +    case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack +      // enter slave transmitter mode +      twi_state = TWI_STX; +      // ready the tx buffer index for iteration +      twi_txBufferIndex = 0; +      // set tx buffer length to be zero, to verify if user changes it +      twi_txBufferLength = 0; +      // request for txBuffer to be filled and length to be set +      // note: user must call twi_transmit(bytes, length) to do this +      twi_onSlaveTransmit(); +      // if they didn't change buffer & length, initialize it +      if(0 == twi_txBufferLength){ +        twi_txBufferLength = 1; +        twi_txBuffer[0] = 0x00; +      } +      // transmit first byte from buffer, fall +    case TW_ST_DATA_ACK: // byte sent, ack returned +      // copy data to output register +      TWDR = twi_txBuffer[twi_txBufferIndex++]; +      // if there is more to send, ack, otherwise nack +      if(twi_txBufferIndex < twi_txBufferLength){ +        twi_reply(1); +      }else{ +        twi_reply(0); +      } +      break; +    case TW_ST_DATA_NACK: // received nack, we are done  +    case TW_ST_LAST_DATA: // received ack, but we are done already! +      // ack future responses +      twi_reply(1); +      // leave slave receiver state +      twi_state = TWI_READY; +      break; + +    // All +    case TW_NO_INFO:   // no state information +      break; +    case TW_BUS_ERROR: // bus error, illegal stop/start +      twi_stop(); +      break; +  } +} + diff --git a/core/libraries/Wire/utility/twi.h b/core/libraries/Wire/utility/twi.h new file mode 100755 index 0000000..7ccbf5c --- /dev/null +++ b/core/libraries/Wire/utility/twi.h @@ -0,0 +1,57 @@ +/* +  twi.h - TWI/I2C library for Wiring & Arduino +  Copyright (c) 2006 Nicholas Zambetti.  All right reserved. + +  This library is free software; you can redistribute it and/or +  modify it under the terms of the GNU Lesser General Public +  License as published by the Free Software Foundation; either +  version 2.1 of the License, or (at your option) any later version. + +  This library 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 +  Lesser General Public License for more details. + +  You should have received a copy of the GNU Lesser General Public +  License along with this library; if not, write to the Free Software +  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +*/ + +#ifndef twi_h
 +#define twi_h
 + +  #include <inttypes.h> + +  //#define ATMEGA8 + +  #ifndef CPU_FREQ
 +  #define CPU_FREQ 16000000L +  #endif + +  #ifndef TWI_FREQ
 +  #define TWI_FREQ 100000L +  #endif + +  #ifndef TWI_BUFFER_LENGTH +  #define TWI_BUFFER_LENGTH 32 +  #endif + +  #define TWI_READY 0 +  #define TWI_MRX   1 +  #define TWI_MTX   2 +  #define TWI_SRX   3 +  #define TWI_STX   4 +   +  void twi_init(void); +  void twi_setAddress(uint8_t); +  uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t); +  uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t); +  uint8_t twi_transmit(uint8_t*, uint8_t); +  void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); +  void twi_attachSlaveTxEvent( void (*)(void) ); +  void twi_reply(uint8_t); +  void twi_stop(void); +  void twi_releaseBus(void);
 +
 +#endif + | 
