library - Wire
This commit is contained in:
		
							parent
							
								
									7592bb1f2f
								
							
						
					
					
						commit
						363d7c505f
					
				| @ -0,0 +1,303 @@ | ||||
| /*
 | ||||
|   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 | ||||
|   | ||||
|   Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts | ||||
| */ | ||||
| 
 | ||||
| extern "C" { | ||||
|   #include <stdlib.h> | ||||
|   #include <string.h> | ||||
|   #include <inttypes.h> | ||||
|   #include "twi.h" | ||||
| } | ||||
| 
 | ||||
| #include "Wire.h" | ||||
| 
 | ||||
| // Initialize Class Variables //////////////////////////////////////////////////
 | ||||
| 
 | ||||
| uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; | ||||
| uint8_t TwoWire::rxBufferIndex = 0; | ||||
| uint8_t TwoWire::rxBufferLength = 0; | ||||
| 
 | ||||
| uint8_t TwoWire::txAddress = 0; | ||||
| uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; | ||||
| 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) | ||||
| { | ||||
|   rxBufferIndex = 0; | ||||
|   rxBufferLength = 0; | ||||
| 
 | ||||
|   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::setClock(uint32_t frequency) | ||||
| { | ||||
|   TWBR = ((F_CPU / frequency) - 16) / 2; | ||||
| } | ||||
| 
 | ||||
| uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) | ||||
| { | ||||
|   // clamp to buffer length
 | ||||
|   if(quantity > BUFFER_LENGTH){ | ||||
|     quantity = BUFFER_LENGTH; | ||||
|   } | ||||
|   // perform blocking read into buffer
 | ||||
|   uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop); | ||||
|   // set rx buffer iterator vars
 | ||||
|   rxBufferIndex = 0; | ||||
|   rxBufferLength = read; | ||||
| 
 | ||||
|   return read; | ||||
| } | ||||
| 
 | ||||
| uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) | ||||
| { | ||||
|   return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); | ||||
| } | ||||
| 
 | ||||
| uint8_t TwoWire::requestFrom(int address, int quantity) | ||||
| { | ||||
|   return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); | ||||
| } | ||||
| 
 | ||||
| uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) | ||||
| { | ||||
|   return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| //	Originally, 'endTransmission' was an f(void) function.
 | ||||
| //	It has been modified to take one parameter indicating
 | ||||
| //	whether or not a STOP should be performed on the bus.
 | ||||
| //	Calling endTransmission(false) allows a sketch to 
 | ||||
| //	perform a repeated start. 
 | ||||
| //
 | ||||
| //	WARNING: Nothing in the library keeps track of whether
 | ||||
| //	the bus tenure has been properly ended with a STOP. It
 | ||||
| //	is very possible to leave the bus in a hung state if
 | ||||
| //	no call to endTransmission(true) is made. Some I2C
 | ||||
| //	devices will behave oddly if they do not see a STOP.
 | ||||
| //
 | ||||
| uint8_t TwoWire::endTransmission(uint8_t sendStop) | ||||
| { | ||||
|   // transmit buffer (blocking)
 | ||||
|   int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop); | ||||
|   // reset tx buffer iterator vars
 | ||||
|   txBufferIndex = 0; | ||||
|   txBufferLength = 0; | ||||
|   // indicate that we are done transmitting
 | ||||
|   transmitting = 0; | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| //	This provides backwards compatibility with the original
 | ||||
| //	definition, and expected behaviour, of endTransmission
 | ||||
| //
 | ||||
| uint8_t TwoWire::endTransmission(void) | ||||
| { | ||||
|   return endTransmission(true); | ||||
| } | ||||
| 
 | ||||
| // must be called in:
 | ||||
| // slave tx event callback
 | ||||
| // or after beginTransmission(address)
 | ||||
| size_t TwoWire::write(uint8_t data) | ||||
| { | ||||
|   if(transmitting){ | ||||
|   // in master transmitter mode
 | ||||
|     // don't bother if buffer is full
 | ||||
|     if(txBufferLength >= BUFFER_LENGTH){ | ||||
|       setWriteError(); | ||||
|       return 0; | ||||
|     } | ||||
|     // 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); | ||||
|   } | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| // must be called in:
 | ||||
| // slave tx event callback
 | ||||
| // or after beginTransmission(address)
 | ||||
| size_t TwoWire::write(const uint8_t *data, size_t quantity) | ||||
| { | ||||
|   if(transmitting){ | ||||
|   // in master transmitter mode
 | ||||
|     for(size_t i = 0; i < quantity; ++i){ | ||||
|       write(data[i]); | ||||
|     } | ||||
|   }else{ | ||||
|   // in slave send mode
 | ||||
|     // reply to master
 | ||||
|     twi_transmit(data, quantity); | ||||
|   } | ||||
|   return quantity; | ||||
| } | ||||
| 
 | ||||
| // must be called in:
 | ||||
| // slave rx event callback
 | ||||
| // or after requestFrom(address, numBytes)
 | ||||
| int TwoWire::available(void) | ||||
| { | ||||
|   return rxBufferLength - rxBufferIndex; | ||||
| } | ||||
| 
 | ||||
| // must be called in:
 | ||||
| // slave rx event callback
 | ||||
| // or after requestFrom(address, numBytes)
 | ||||
| int TwoWire::read(void) | ||||
| { | ||||
|   int value = -1; | ||||
|    | ||||
|   // get each successive byte on each call
 | ||||
|   if(rxBufferIndex < rxBufferLength){ | ||||
|     value = rxBuffer[rxBufferIndex]; | ||||
|     ++rxBufferIndex; | ||||
|   } | ||||
| 
 | ||||
|   return value; | ||||
| } | ||||
| 
 | ||||
| // must be called in:
 | ||||
| // slave rx event callback
 | ||||
| // or after requestFrom(address, numBytes)
 | ||||
| int TwoWire::peek(void) | ||||
| { | ||||
|   int value = -1; | ||||
|    | ||||
|   if(rxBufferIndex < rxBufferLength){ | ||||
|     value = rxBuffer[rxBufferIndex]; | ||||
|   } | ||||
| 
 | ||||
|   return value; | ||||
| } | ||||
| 
 | ||||
| void TwoWire::flush(void) | ||||
| { | ||||
|   // XXX: to be implemented.
 | ||||
| } | ||||
| 
 | ||||
| // 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(); | ||||
| 
 | ||||
| @ -0,0 +1,80 @@ | ||||
| /*
 | ||||
|   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 | ||||
| 
 | ||||
|   Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts | ||||
| */ | ||||
| 
 | ||||
| #ifndef TwoWire_h | ||||
| #define TwoWire_h | ||||
| 
 | ||||
| #include <inttypes.h> | ||||
| #include "Stream.h" | ||||
| 
 | ||||
| #define BUFFER_LENGTH 32 | ||||
| 
 | ||||
| class TwoWire : public Stream | ||||
| { | ||||
|   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 setClock(uint32_t); | ||||
|     void beginTransmission(uint8_t); | ||||
|     void beginTransmission(int); | ||||
|     uint8_t endTransmission(void); | ||||
|     uint8_t endTransmission(uint8_t); | ||||
|     uint8_t requestFrom(uint8_t, uint8_t); | ||||
|     uint8_t requestFrom(uint8_t, uint8_t, uint8_t); | ||||
|     uint8_t requestFrom(int, int); | ||||
|     uint8_t requestFrom(int, int, int); | ||||
|     virtual size_t write(uint8_t); | ||||
|     virtual size_t write(const uint8_t *, size_t); | ||||
|     virtual int available(void); | ||||
|     virtual int read(void); | ||||
|     virtual int peek(void); | ||||
|     virtual void flush(void); | ||||
|     void onReceive( void (*)(int) ); | ||||
|     void onRequest( void (*)(void) ); | ||||
| 
 | ||||
|     inline size_t write(unsigned long n) { return write((uint8_t)n); } | ||||
|     inline size_t write(long n) { return write((uint8_t)n); } | ||||
|     inline size_t write(unsigned int n) { return write((uint8_t)n); } | ||||
|     inline size_t write(int n) { return write((uint8_t)n); } | ||||
|     using Print::write; | ||||
| }; | ||||
| 
 | ||||
| extern TwoWire Wire; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| @ -0,0 +1,87 @@ | ||||
| // 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
 | ||||
| 
 | ||||
| // This example code is in the public domain.
 | ||||
| 
 | ||||
| 
 | ||||
| #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.write(byte(0x00));      // sets register pointer to the command register (0x00)
 | ||||
|   Wire.write(byte(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.write(byte(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.read();  // receive high byte (overwrites previous reading)
 | ||||
|     reading = reading << 8;    // shift high byte to be high 8 bits
 | ||||
|     reading |= Wire.read(); // 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.write(byte(0x00)); | ||||
|   Wire.write(byte(0xA0)); | ||||
|   Wire.endTransmission(); | ||||
| 
 | ||||
|   Wire.beginTransmission(oldAddress); | ||||
|   Wire.write(byte(0x00)); | ||||
|   Wire.write(byte(0xAA)); | ||||
|   Wire.endTransmission(); | ||||
| 
 | ||||
|   Wire.beginTransmission(oldAddress); | ||||
|   Wire.write(byte(0x00)); | ||||
|   Wire.write(byte(0xA5)); | ||||
|   Wire.endTransmission(); | ||||
| 
 | ||||
|   Wire.beginTransmission(oldAddress); | ||||
|   Wire.write(byte(0x00)); | ||||
|   Wire.write(newAddress); | ||||
|   Wire.endTransmission(); | ||||
| } | ||||
| 
 | ||||
| */ | ||||
| @ -0,0 +1,39 @@ | ||||
| // 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
 | ||||
| 
 | ||||
| // This example code is in the public domain.
 | ||||
| 
 | ||||
| // This example code is in the public domain.
 | ||||
| 
 | ||||
| 
 | ||||
| #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.write(byte(0x00));            // sends instruction byte
 | ||||
|   Wire.write(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); | ||||
| } | ||||
| 
 | ||||
| @ -0,0 +1,32 @@ | ||||
| // 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
 | ||||
| 
 | ||||
| // This example code is in the public domain.
 | ||||
| 
 | ||||
| 
 | ||||
| #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.read(); // receive a byte as character
 | ||||
|     Serial.print(c);         // print the character
 | ||||
|   } | ||||
| 
 | ||||
|   delay(500); | ||||
| } | ||||
| @ -0,0 +1,31 @@ | ||||
| // 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
 | ||||
| 
 | ||||
| // This example code is in the public domain.
 | ||||
| 
 | ||||
| 
 | ||||
| #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.write("x is ");        // sends five bytes
 | ||||
|   Wire.write(x);              // sends one byte
 | ||||
|   Wire.endTransmission();    // stop transmitting
 | ||||
| 
 | ||||
|   x++; | ||||
|   delay(500); | ||||
| } | ||||
| @ -0,0 +1,38 @@ | ||||
| // 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
 | ||||
| 
 | ||||
| // This example code is in the public domain.
 | ||||
| 
 | ||||
| 
 | ||||
| #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.read(); // receive byte as a character
 | ||||
|     Serial.print(c);         // print the character
 | ||||
|   } | ||||
|   int x = Wire.read();    // receive byte as an integer
 | ||||
|   Serial.println(x);         // print the integer
 | ||||
| } | ||||
| @ -0,0 +1,32 @@ | ||||
| // 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
 | ||||
| 
 | ||||
| // This example code is in the public domain.
 | ||||
| 
 | ||||
| 
 | ||||
| #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.write("hello "); // respond with message of 6 bytes
 | ||||
|   // as expected by master
 | ||||
| } | ||||
| @ -0,0 +1,32 @@ | ||||
| ####################################### | ||||
| # Syntax Coloring Map For Wire | ||||
| ####################################### | ||||
| 
 | ||||
| ####################################### | ||||
| # Datatypes (KEYWORD1) | ||||
| ####################################### | ||||
| 
 | ||||
| ####################################### | ||||
| # Methods and Functions (KEYWORD2) | ||||
| ####################################### | ||||
| 
 | ||||
| begin	KEYWORD2 | ||||
| setClock	KEYWORD2 | ||||
| beginTransmission	KEYWORD2 | ||||
| endTransmission	KEYWORD2 | ||||
| requestFrom	KEYWORD2 | ||||
| send	KEYWORD2 | ||||
| receive	KEYWORD2 | ||||
| onReceive	KEYWORD2 | ||||
| onRequest	KEYWORD2 | ||||
| 
 | ||||
| ####################################### | ||||
| # Instances (KEYWORD2) | ||||
| ####################################### | ||||
| 
 | ||||
| Wire	KEYWORD2 | ||||
| 
 | ||||
| ####################################### | ||||
| # Constants (LITERAL1) | ||||
| ####################################### | ||||
| 
 | ||||
| @ -0,0 +1,8 @@ | ||||
| name=Wire | ||||
| version=1.0 | ||||
| author=Arduino | ||||
| maintainer=Arduino <info@arduino.cc> | ||||
| sentence=Allows the communication between devices or sensors connected via Two Wire Interface Bus. For all Arduino boards, BUT Arduino DUE.  | ||||
| paragraph= | ||||
| url=http://arduino.cc/en/Reference/Wire | ||||
| architectures=avr | ||||
| @ -0,0 +1,527 @@ | ||||
| /*
 | ||||
|   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 | ||||
| 
 | ||||
|   Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts | ||||
| */ | ||||
| 
 | ||||
| #include <math.h> | ||||
| #include <stdlib.h> | ||||
| #include <inttypes.h> | ||||
| #include <avr/io.h> | ||||
| #include <avr/interrupt.h> | ||||
| #include <compat/twi.h> | ||||
| #include "Arduino.h" // for digitalWrite | ||||
| 
 | ||||
| #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 "pins_arduino.h" | ||||
| #include "twi.h" | ||||
| 
 | ||||
| static volatile uint8_t twi_state; | ||||
| static volatile uint8_t twi_slarw; | ||||
| static volatile uint8_t twi_sendStop;			// should the transaction end with a stop
 | ||||
| static volatile uint8_t twi_inRepStart;			// in the middle of a repeated start
 | ||||
| 
 | ||||
| static void (*twi_onSlaveTransmit)(void); | ||||
| static void (*twi_onSlaveReceive)(uint8_t*, int); | ||||
| 
 | ||||
| static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; | ||||
| static volatile uint8_t twi_masterBufferIndex; | ||||
| static volatile uint8_t twi_masterBufferLength; | ||||
| 
 | ||||
| static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; | ||||
| static volatile uint8_t twi_txBufferIndex; | ||||
| static volatile uint8_t twi_txBufferLength; | ||||
| 
 | ||||
| static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; | ||||
| static volatile uint8_t twi_rxBufferIndex; | ||||
| 
 | ||||
| static volatile uint8_t twi_error; | ||||
| 
 | ||||
| /* 
 | ||||
|  * 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; | ||||
|   twi_sendStop = true;		// default value
 | ||||
|   twi_inRepStart = false; | ||||
|    | ||||
|   // activate internal pullups for twi.
 | ||||
|   digitalWrite(SDA, 1); | ||||
|   digitalWrite(SCL, 1); | ||||
| 
 | ||||
|   // initialize twi prescaler and bit rate
 | ||||
|   cbi(TWSR, TWPS0); | ||||
|   cbi(TWSR, TWPS1); | ||||
|   TWBR = ((F_CPU / 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); | ||||
| } | ||||
| 
 | ||||
| /* 
 | ||||
|  * 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 | ||||
|  *          sendStop: Boolean indicating whether to send a stop at the end | ||||
|  * Output   number of bytes read | ||||
|  */ | ||||
| uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) | ||||
| { | ||||
|   uint8_t i; | ||||
| 
 | ||||
|   // ensure data will fit into buffer
 | ||||
|   if(TWI_BUFFER_LENGTH < length){ | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   // wait until twi is ready, become master receiver
 | ||||
|   while(TWI_READY != twi_state){ | ||||
|     continue; | ||||
|   } | ||||
|   twi_state = TWI_MRX; | ||||
|   twi_sendStop = sendStop; | ||||
|   // reset error state (0xFF.. no error occured)
 | ||||
|   twi_error = 0xFF; | ||||
| 
 | ||||
|   // initialize buffer iteration vars
 | ||||
|   twi_masterBufferIndex = 0; | ||||
|   twi_masterBufferLength = length-1;  // This is not intuitive, read on...
 | ||||
|   // On receive, the previously configured ACK/NACK setting is transmitted in
 | ||||
|   // response to the received byte before the interrupt is signalled. 
 | ||||
|   // Therefor we must actually set NACK when the _next_ to last byte is
 | ||||
|   // received, causing that NACK to be sent in response to receiving the last
 | ||||
|   // expected byte of data.
 | ||||
| 
 | ||||
|   // build sla+w, slave device address + w bit
 | ||||
|   twi_slarw = TW_READ; | ||||
|   twi_slarw |= address << 1; | ||||
| 
 | ||||
|   if (true == twi_inRepStart) { | ||||
|     // if we're in the repeated start state, then we've already sent the start,
 | ||||
|     // (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
 | ||||
|     // We need to remove ourselves from the repeated start state before we enable interrupts,
 | ||||
|     // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
 | ||||
|     // up. Also, don't enable the START interrupt. There may be one pending from the 
 | ||||
|     // repeated start that we sent outselves, and that would really confuse things.
 | ||||
|     twi_inRepStart = false;			// remember, we're dealing with an ASYNC ISR
 | ||||
|     TWDR = twi_slarw; | ||||
|     TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE);	// enable INTs, but not START
 | ||||
|   } | ||||
|   else | ||||
|     // 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; | ||||
|   } | ||||
| 
 | ||||
|   if (twi_masterBufferIndex < length) | ||||
|     length = twi_masterBufferIndex; | ||||
| 
 | ||||
|   // copy twi buffer to data
 | ||||
|   for(i = 0; i < length; ++i){ | ||||
|     data[i] = twi_masterBuffer[i]; | ||||
|   } | ||||
| 	 | ||||
|   return length; | ||||
| } | ||||
| 
 | ||||
| /* 
 | ||||
|  * 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 | ||||
|  *          sendStop: boolean indicating whether or not to send a stop at the end | ||||
|  * Output   0 .. success | ||||
|  *          1 .. length to long for buffer | ||||
|  *          2 .. address send, NACK received | ||||
|  *          3 .. data send, NACK received | ||||
|  *          4 .. other twi error (lost bus arbitration, bus error, ..) | ||||
|  */ | ||||
| uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) | ||||
| { | ||||
|   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; | ||||
|   twi_sendStop = sendStop; | ||||
|   // reset error state (0xFF.. no error occured)
 | ||||
|   twi_error = 0xFF; | ||||
| 
 | ||||
|   // 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; | ||||
|    | ||||
|   // if we're in a repeated start, then we've already sent the START
 | ||||
|   // in the ISR. Don't do it again.
 | ||||
|   //
 | ||||
|   if (true == twi_inRepStart) { | ||||
|     // if we're in the repeated start state, then we've already sent the start,
 | ||||
|     // (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
 | ||||
|     // We need to remove ourselves from the repeated start state before we enable interrupts,
 | ||||
|     // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
 | ||||
|     // up. Also, don't enable the START interrupt. There may be one pending from the 
 | ||||
|     // repeated start that we sent outselves, and that would really confuse things.
 | ||||
|     twi_inRepStart = false;			// remember, we're dealing with an ASYNC ISR
 | ||||
|     TWDR = twi_slarw;				 | ||||
|     TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE);	// enable INTs, but not START
 | ||||
|   } | ||||
|   else | ||||
|     // send start condition
 | ||||
|     TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA);	// enable INTs
 | ||||
| 
 | ||||
|   // wait for write operation to complete
 | ||||
|   while(wait && (TWI_MTX == twi_state)){ | ||||
|     continue; | ||||
|   } | ||||
|    | ||||
|   if (twi_error == 0xFF) | ||||
|     return 0;	// success
 | ||||
|   else if (twi_error == TW_MT_SLA_NACK) | ||||
|     return 2;	// error: address send, nack received
 | ||||
|   else if (twi_error == TW_MT_DATA_NACK) | ||||
|     return 3;	// error: data send, nack received
 | ||||
|   else | ||||
|     return 4;	// other twi error
 | ||||
| } | ||||
| 
 | ||||
| /* 
 | ||||
|  * 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(const 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; | ||||
| } | ||||
| 
 | ||||
| ISR(TWI_vect) | ||||
| { | ||||
|   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{ | ||||
| 	if (twi_sendStop) | ||||
|           twi_stop(); | ||||
| 	else { | ||||
| 	  twi_inRepStart = true;	// we're gonna send the START
 | ||||
| 	  // don't enable the interrupt. We'll generate the start, but we 
 | ||||
| 	  // avoid handling the interrupt until we're in the next transaction,
 | ||||
| 	  // at the point where we would normally issue the start.
 | ||||
| 	  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; | ||||
| 	  twi_state = TWI_READY; | ||||
| 	} | ||||
|       } | ||||
|       break; | ||||
|     case TW_MT_SLA_NACK:  // address sent, nack received
 | ||||
|       twi_error = TW_MT_SLA_NACK; | ||||
|       twi_stop(); | ||||
|       break; | ||||
|     case TW_MT_DATA_NACK: // data sent, nack received
 | ||||
|       twi_error = TW_MT_DATA_NACK; | ||||
|       twi_stop(); | ||||
|       break; | ||||
|     case TW_MT_ARB_LOST: // lost bus arbitration
 | ||||
|       twi_error = TW_MT_ARB_LOST; | ||||
|       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; | ||||
| 	if (twi_sendStop) | ||||
|           twi_stop(); | ||||
| 	else { | ||||
| 	  twi_inRepStart = true;	// we're gonna send the START
 | ||||
| 	  // don't enable the interrupt. We'll generate the start, but we 
 | ||||
| 	  // avoid handling the interrupt until we're in the next transaction,
 | ||||
| 	  // at the point where we would normally issue the start.
 | ||||
| 	  TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; | ||||
| 	  twi_state = TWI_READY; | ||||
| 	}     | ||||
| 	break; | ||||
|     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'; | ||||
|       } | ||||
|       // sends ack and stops interface for clock stretching
 | ||||
|       twi_stop(); | ||||
|       // callback to user defined callback
 | ||||
|       twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); | ||||
|       // since we submit rx buffer to "wire" library, we can reset it
 | ||||
|       twi_rxBufferIndex = 0; | ||||
|       // ack future responses and leave slave receiver state
 | ||||
|       twi_releaseBus(); | ||||
|       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_error = TW_BUS_ERROR; | ||||
|       twi_stop(); | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -0,0 +1,53 @@ | ||||
| /*
 | ||||
|   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 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); | ||||
|   uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); | ||||
|   uint8_t twi_transmit(const 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 | ||||
| 
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user