diff --git a/libraries/I2C/I2C.cpp b/libraries/I2C/I2C.cpp index 254670138f..20aaf22f14 100644 --- a/libraries/I2C/I2C.cpp +++ b/libraries/I2C/I2C.cpp @@ -1,567 +1,566 @@ -/* - I2C.cpp - I2C library - Copyright (c) 2011 Wayne Truchsess. All right reserved. - Rev 2.0 - September 19th, 2011 - - Added support for timeout function to prevent - and recover from bus lockup (thanks to PaulS - and CrossRoads on the Arduino forum) - - Changed return type for stop() from void to - uint8_t to handle timeOut function - Rev 1.0 - August 8th, 2011 - - This is a modified version of the Arduino Wire/TWI - library. Functions were rewritten to provide more functionality - and also the use of Repeated Start. Some I2C devices will not - function correctly without the use of a Repeated Start. The - initial version of this library only supports the Master. - - - 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 -#include "I2C.h" -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif - - - -uint8_t I2C::bytesAvailable = 0; -uint8_t I2C::bufferIndex = 0; -uint8_t I2C::totalBytes = 0; -uint16_t I2C::timeOutDelay = 0; - -I2C::I2C() -{ -} - - -////////////// Public Methods //////////////////////////////////////// - - - -void I2C::begin() -{ - #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) - // 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 / 100000) - 16) / 2; - // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); -} - -void I2C::end() -{ - TWCR = 0; -} - -void I2C::timeOut(uint16_t _timeOut) -{ - timeOutDelay = _timeOut; -} - -void I2C::setSpeed(boolean _fast) -{ - if(!_fast) - { - TWBR = ((CPU_FREQ / 100000) - 16) / 2; - } - else - { - TWBR = ((CPU_FREQ / 400000) - 16) / 2; - } -} - -void I2C::pullup(boolean activate) -{ - if(activate) - { - #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) - // 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 - } - else - { - #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) - // deactivate internal pull-ups for twi - // as per note from atmega8 manual pg167 - cbi(PORTC, 4); - cbi(PORTC, 5); - #else - // deactivate internal pull-ups for twi - // as per note from atmega128 manual pg204 - cbi(PORTD, 0); - cbi(PORTD, 1); - #endif - } -} - -/////////////carry over from Wire library /////////// - -uint8_t I2C::beginTransmission(uint8_t address) -{ - returnStatusWire = 0; - returnStatus = 0; - returnStatus = start(); - returnStatusWire = returnStatus; - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - returnStatusWire = returnStatus; - return(returnStatus); -} - -uint8_t I2C::beginTransmission(int address) -{ - return(beginTransmission((uint8_t) address)); -} - -uint8_t I2C::send(uint8_t databyte) -{ - if(returnStatusWire) - { - return(returnStatusWire); - } - returnStatus = 0; - returnStatus = sendByte(databyte); - returnStatusWire = returnStatus; - return(returnStatus); -} - -uint8_t I2C::send(int databyte) -{ - return(send((uint8_t) databyte)); -} - -uint8_t I2C::endTransmission() -{ - stop(); - return(returnStatusWire); -} - -uint8_t I2C::requestFrom(int address, int numberBytes) -{ - return(requestFrom((uint8_t) address, (uint8_t) numberBytes)); -} - -uint8_t I2C::requestFrom(uint8_t address, uint8_t numberBytes) -{ - returnStatus = 0; - returnStatus = read(address,numberBytes); - if(!returnStatus) - { - return(numberBytes); - } - return(0); -} - -uint8_t I2C::available() -{ - return(bytesAvailable); -} - -uint8_t I2C::receive() -{ - bufferIndex = totalBytes - bytesAvailable; - if(!bytesAvailable) - { - bufferIndex = 0; - return(0); - } - bytesAvailable--; - return(data[bufferIndex]); -} - - - - - -///////////////////////////////////////////////////// - -uint8_t I2C::write(uint8_t address, uint8_t registerAddress) -{ - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(registerAddress); - if(returnStatus){return(returnStatus);} - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::write(int address, int registerAddress) -{ - return(write((uint8_t) address, (uint8_t) registerAddress)); -} - -uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t databyte) -{ - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(registerAddress); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(databyte); - if(returnStatus){return(returnStatus);} - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::write(int address, int registerAddress, int databyte) -{ - return(write((uint8_t) address, (uint8_t) registerAddress, (uint8_t) databyte)); -} - -uint8_t I2C::write(uint8_t address, uint8_t registerAddress, char *databytes) -{ - uint8_t bufferLength = strlen(databytes); - returnStatus = 0; - returnStatus = write(address, registerAddress, (uint8_t*)databytes, bufferLength); - return(returnStatus); -} - -uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t *databytes, uint8_t numberBytes) -{ - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(registerAddress); - if(returnStatus){return(returnStatus);} - for (uint8_t i = 0; i < numberBytes; i++) - { - returnStatus = sendByte(databytes[i]); - if(returnStatus){return(returnStatus);} - } - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::read(int address, int numberBytes) -{ - return(read((uint8_t) address, (uint8_t) numberBytes)); -} - -uint8_t I2C::read(uint8_t address, uint8_t numberBytes) -{ - bytesAvailable = 0; - bufferIndex = 0; - if(numberBytes == 0){numberBytes++;} - nack = numberBytes - 1; - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_R(address)); - if(returnStatus){return(returnStatus);} - for(uint8_t i = 0; i < numberBytes; i++) - { - if( i == nack ) - { - returnStatus = receiveByte(0); - if(returnStatus != MR_DATA_NACK){return(returnStatus);} - } - else - { - returnStatus = receiveByte(1); - if(returnStatus != MR_DATA_ACK){return(returnStatus);} - } - data[i] = TWDR; - bytesAvailable = i+1; - totalBytes = i+1; - } - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::read(int address, int registerAddress, int numberBytes) -{ - return(read((uint8_t) address, (uint8_t) registerAddress, (uint8_t) numberBytes)); -} - -uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes) -{ - bytesAvailable = 0; - bufferIndex = 0; - if(numberBytes == 0){numberBytes++;} - nack = numberBytes - 1; - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(registerAddress); - if(returnStatus){return(returnStatus);} - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_R(address)); - if(returnStatus){return(returnStatus);} - for(uint8_t i = 0; i < numberBytes; i++) - { - if( i == nack ) - { - returnStatus = receiveByte(0); - if(returnStatus != MR_DATA_NACK){return(returnStatus);} - } - else - { - returnStatus = receiveByte(1); - if(returnStatus != MR_DATA_ACK){return(returnStatus);} - } - data[i] = TWDR; - bytesAvailable = i+1; - totalBytes = i+1; - } - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::read(uint8_t address, uint8_t numberBytes, uint8_t *dataBuffer) -{ - bytesAvailable = 0; - bufferIndex = 0; - if(numberBytes == 0){numberBytes++;} - nack = numberBytes - 1; - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_R(address)); - if(returnStatus){return(returnStatus);} - for(uint8_t i = 0; i < numberBytes; i++) - { - if( i == nack ) - { - returnStatus = receiveByte(0); - if(returnStatus != MR_DATA_NACK){return(returnStatus);} - } - else - { - returnStatus = receiveByte(1); - if(returnStatus != MR_DATA_ACK){return(returnStatus);} - } - dataBuffer[i] = TWDR; - bytesAvailable = i+1; - totalBytes = i+1; - } - returnStatus = stop(); - return(returnStatus); -} - -uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes, uint8_t *dataBuffer) -{ - bytesAvailable = 0; - bufferIndex = 0; - if(numberBytes == 0){numberBytes++;} - nack = numberBytes - 1; - returnStatus = 0; - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_W(address)); - if(returnStatus){return(returnStatus);} - returnStatus = sendByte(registerAddress); - if(returnStatus){return(returnStatus);} - returnStatus = start(); - if(returnStatus){return(returnStatus);} - returnStatus = sendAddress(SLA_R(address)); - if(returnStatus){return(returnStatus);} - for(uint8_t i = 0; i < numberBytes; i++) - { - if( i == nack ) - { - returnStatus = receiveByte(0); - if(returnStatus != MR_DATA_NACK){return(returnStatus);} - } - else - { - returnStatus = receiveByte(1); - if(returnStatus != MR_DATA_ACK){return(returnStatus);} - } - dataBuffer[i] = TWDR; - bytesAvailable = i+1; - totalBytes = i+1; - } - returnStatus = stop(); - return(returnStatus); -} - - -/////////////// Private Methods //////////////////////////////////////// - - -uint8_t I2C::start() -{ - unsigned long startingTime = millis(); - TWCR = (1<= timeOutDelay) - { - lockUp(); - return(1); - } - - } - if ((TWI_STATUS == START) || (TWI_STATUS == REPEATED_START)) - { - return(0); - } - return(TWI_STATUS); -} - -uint8_t I2C::sendAddress(uint8_t i2cAddress) -{ - TWDR = i2cAddress; - unsigned long startingTime = millis(); - TWCR = (1<= timeOutDelay) - { - lockUp(); - return(1); - } - - } - if ((TWI_STATUS == MT_SLA_ACK) || (TWI_STATUS == MR_SLA_ACK)) - { - return(0); - } - return(TWI_STATUS); -} - -uint8_t I2C::sendByte(uint8_t i2cData) -{ - TWDR = i2cData; - unsigned long startingTime = millis(); - TWCR = (1<= timeOutDelay) - { - lockUp(); - return(1); - } - - } - if (TWI_STATUS == MT_DATA_ACK) - { - return(0); - } - return(TWI_STATUS); -} - -uint8_t I2C::receiveByte(boolean ack) -{ - unsigned long startingTime = millis(); - if(ack) - { - TWCR = (1<= timeOutDelay) - { - lockUp(); - return(1); - } - - } - return(TWI_STATUS); -} - -uint8_t I2C::stop() -{ - unsigned long startingTime = millis(); - TWCR = (1<= timeOutDelay) - { - lockUp(); - return(1); - } - - } - return(0); -} - -void I2C::lockUp() -{ - TWCR = 0; //releases SDA and SCL lines to high impedance - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); //reinitialize TWI +/* + I2C.cpp - I2C library + Copyright (c) 2011 Wayne Truchsess. All right reserved. + Rev 2.0 - September 19th, 2011 + - Added support for timeout function to prevent + and recover from bus lockup (thanks to PaulS + and CrossRoads on the Arduino forum) + - Changed return type for stop() from void to + uint8_t to handle timeOut function + Rev 1.0 - August 8th, 2011 + + This is a modified version of the Arduino Wire/TWI + library. Functions were rewritten to provide more functionality + and also the use of Repeated Start. Some I2C devices will not + function correctly without the use of a Repeated Start. The + initial version of this library only supports the Master. + + + 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 +#include "I2C.h" +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + + + +uint8_t I2C::bytesAvailable = 0; +uint8_t I2C::bufferIndex = 0; +uint8_t I2C::totalBytes = 0; +uint16_t I2C::timeOutDelay = 0; + +I2C::I2C() +{ +} + + +////////////// Public Methods //////////////////////////////////////// + + + +void I2C::begin() +{ + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // 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 / 100000) - 16) / 2; + // enable twi module, acks, and twi interrupt + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); +} + +void I2C::end() +{ + TWCR = 0; +} + +void I2C::timeOut(uint16_t _timeOut) +{ + timeOutDelay = _timeOut; +} + +void I2C::setSpeed(boolean _fast) +{ + if(!_fast) + { + TWBR = ((CPU_FREQ / 100000) - 16) / 2; + } + else + { + TWBR = ((CPU_FREQ / 400000) - 16) / 2; + } +} + +void I2C::pullup(boolean activate) +{ + if(activate) + { + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // 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 + } + else + { + #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) + // deactivate internal pull-ups for twi + // as per note from atmega8 manual pg167 + cbi(PORTC, 4); + cbi(PORTC, 5); + #else + // deactivate internal pull-ups for twi + // as per note from atmega128 manual pg204 + cbi(PORTD, 0); + cbi(PORTD, 1); + #endif + } +} + +/////////////carry over from Wire library /////////// + +uint8_t I2C::beginTransmission(uint8_t address) +{ + returnStatusWire = 0; + returnStatus = 0; + returnStatus = start(); + returnStatusWire = returnStatus; + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + returnStatusWire = returnStatus; + return(returnStatus); +} + +uint8_t I2C::beginTransmission(int address) +{ + return(beginTransmission((uint8_t) address)); +} + +uint8_t I2C::send(uint8_t databyte) +{ + if(returnStatusWire) + { + return(returnStatusWire); + } + returnStatus = 0; + returnStatus = sendByte(databyte); + returnStatusWire = returnStatus; + return(returnStatus); +} + +uint8_t I2C::send(int databyte) +{ + return(send((uint8_t) databyte)); +} + +uint8_t I2C::endTransmission() +{ + stop(); + return(returnStatusWire); +} + +uint8_t I2C::requestFrom(int address, int numberBytes) +{ + return(requestFrom((uint8_t) address, (uint8_t) numberBytes)); +} + +uint8_t I2C::requestFrom(uint8_t address, uint8_t numberBytes) +{ + returnStatus = 0; + returnStatus = read(address,numberBytes); + if(!returnStatus) + { + return(numberBytes); + } + return(0); +} + +uint8_t I2C::available() +{ + return(bytesAvailable); +} + +uint8_t I2C::receive() +{ + bufferIndex = totalBytes - bytesAvailable; + if(!bytesAvailable) + { + bufferIndex = 0; + return(0); + } + bytesAvailable--; + return(data[bufferIndex]); +} + + + + + +///////////////////////////////////////////////////// + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress) +{ + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(registerAddress); + if(returnStatus){return(returnStatus);} + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::write(int address, int registerAddress) +{ + return(write((uint8_t) address, (uint8_t) registerAddress)); +} + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t databyte) +{ + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(registerAddress); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(databyte); + if(returnStatus){return(returnStatus);} + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::write(int address, int registerAddress, int databyte) +{ + return(write((uint8_t) address, (uint8_t) registerAddress, (uint8_t) databyte)); +} + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress, char *databytes) +{ + uint8_t bufferLength = strlen(databytes); + returnStatus = 0; + returnStatus = write(address, registerAddress, (uint8_t*)databytes, bufferLength); + return(returnStatus); +} + +uint8_t I2C::write(uint8_t address, uint8_t registerAddress, uint8_t *databytes, uint8_t numberBytes) +{ + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(registerAddress); + if(returnStatus){return(returnStatus);} + for (uint8_t i = 0; i < numberBytes; i++) + { + returnStatus = sendByte(databytes[i]); + if(returnStatus){return(returnStatus);} + } + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::read(int address, int numberBytes) +{ + return(read((uint8_t) address, (uint8_t) numberBytes)); +} + +uint8_t I2C::read(uint8_t address, uint8_t numberBytes) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus){return(returnStatus);} + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + data[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::read(int address, int registerAddress, int numberBytes) +{ + return(read((uint8_t) address, (uint8_t) registerAddress, (uint8_t) numberBytes)); +} + +uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(registerAddress); + if(returnStatus){return(returnStatus);} + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus){return(returnStatus);} + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + data[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::read(uint8_t address, uint8_t numberBytes, uint8_t *dataBuffer) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus){return(returnStatus);} + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + dataBuffer[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + return(returnStatus); +} + +uint8_t I2C::read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes, uint8_t *dataBuffer) +{ + bytesAvailable = 0; + bufferIndex = 0; + if(numberBytes == 0){numberBytes++;} + nack = numberBytes - 1; + returnStatus = 0; + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_W(address)); + if(returnStatus){return(returnStatus);} + returnStatus = sendByte(registerAddress); + if(returnStatus){return(returnStatus);} + returnStatus = start(); + if(returnStatus){return(returnStatus);} + returnStatus = sendAddress(SLA_R(address)); + if(returnStatus){return(returnStatus);} + for(uint8_t i = 0; i < numberBytes; i++) + { + if( i == nack ) + { + returnStatus = receiveByte(0); + if(returnStatus != MR_DATA_NACK){return(returnStatus);} + } + else + { + returnStatus = receiveByte(1); + if(returnStatus != MR_DATA_ACK){return(returnStatus);} + } + dataBuffer[i] = TWDR; + bytesAvailable = i+1; + totalBytes = i+1; + } + returnStatus = stop(); + return(returnStatus); +} + + +/////////////// Private Methods //////////////////////////////////////// + + +uint8_t I2C::start() +{ + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + if ((TWI_STATUS == START) || (TWI_STATUS == REPEATED_START)) + { + return(0); + } + return(TWI_STATUS); +} + +uint8_t I2C::sendAddress(uint8_t i2cAddress) +{ + TWDR = i2cAddress; + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + if ((TWI_STATUS == MT_SLA_ACK) || (TWI_STATUS == MR_SLA_ACK)) + { + return(0); + } + return(TWI_STATUS); +} + +uint8_t I2C::sendByte(uint8_t i2cData) +{ + TWDR = i2cData; + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + if (TWI_STATUS == MT_DATA_ACK) + { + return(0); + } + return(TWI_STATUS); +} + +uint8_t I2C::receiveByte(boolean ack) +{ + unsigned long startingTime = millis(); + if(ack) + { + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + return(TWI_STATUS); +} + +uint8_t I2C::stop() +{ + unsigned long startingTime = millis(); + TWCR = (1<= timeOutDelay) + { + lockUp(); + return(1); + } + + } + return(0); +} + +void I2C::lockUp() +{ + TWCR = 0; //releases SDA and SCL lines to high impedance + TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); //reinitialize TWI _lockup_count++; } uint8_t I2C::lockup_count(void) { return _lockup_count; -} - -SIGNAL(TWI_vect) -{ - switch(TWI_STATUS){ - case 0x20: - case 0x30: - case 0x48: - TWCR = (1< -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif - -#ifndef I2C_h -#define I2C_h - - -#define START 0x08 -#define REPEATED_START 0x10 -#define MT_SLA_ACK 0x18 -#define MT_DATA_ACK 0x28 -#define MR_SLA_ACK 0x40 -#define MR_DATA_ACK 0x50 -#define MR_DATA_NACK 0x58 -#define TWI_STATUS (TWSR & 0xF8) -#define SLA_W(address) (address << 1) -#define SLA_R(address) ((address << 1) + 0x01) -#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) -#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) - -#define MAX_BUFFER_SIZE 32 - - -#ifndef CPU_FREQ -#define CPU_FREQ 16000000L -#endif - - - -class I2C -{ - public: - I2C(); - void begin(); - void end(); - void timeOut(uint16_t); - void setSpeed(boolean); - void pullup(boolean); - ///////carry over from Wire library//////// - uint8_t returnStatusWire; - uint8_t beginTransmission(uint8_t); - uint8_t beginTransmission(int); - uint8_t send(uint8_t); - uint8_t send(int); - uint8_t endTransmission(); - uint8_t requestFrom(uint8_t, uint8_t); - uint8_t requestFrom(int, int); - uint8_t available(); - /////////////////////////////////////////// - uint8_t write(uint8_t, uint8_t); - uint8_t write(int, int); - uint8_t write(uint8_t, uint8_t, uint8_t); - uint8_t write(int, int, int); - uint8_t write(uint8_t, uint8_t, char*); - uint8_t write(uint8_t, uint8_t, uint8_t*, uint8_t); - uint8_t read(uint8_t, uint8_t); - uint8_t read(int, int); - uint8_t read(uint8_t, uint8_t, uint8_t); - uint8_t read(int, int, int); - uint8_t read(uint8_t, uint8_t, uint8_t*); - uint8_t read(uint8_t, uint8_t, uint8_t, uint8_t*); - uint8_t receive(); +/* + I2C.h - I2C library + Copyright (c) 2011 Wayne Truchsess. All right reserved. + Rev 2.0 - September 19th, 2011 + - Added support for timeout function to prevent + and recover from bus lockup (thanks to PaulS + and CrossRoads on the Arduino forum) + - Changed return type for stop() from void to + uint8_t to handle timeOut function + Rev 1.0 - August 8th, 2011 + + This is a modified version of the Arduino Wire/TWI + library. Functions were rewritten to provide more functionality + and also the use of Repeated Start. Some I2C devices will not + function correctly without the use of a Repeated Start. The + initial version of this library only supports the Master. + + + 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 +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#ifndef I2C_h +#define I2C_h + + +#define START 0x08 +#define REPEATED_START 0x10 +#define MT_SLA_ACK 0x18 +#define MT_DATA_ACK 0x28 +#define MR_SLA_ACK 0x40 +#define MR_DATA_ACK 0x50 +#define MR_DATA_NACK 0x58 +#define TWI_STATUS (TWSR & 0xF8) +#define SLA_W(address) (address << 1) +#define SLA_R(address) ((address << 1) + 0x01) +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) + +#define MAX_BUFFER_SIZE 32 + + +#ifndef CPU_FREQ +#define CPU_FREQ 16000000L +#endif + + + +class I2C +{ + public: + I2C(); + void begin(); + void end(); + void timeOut(uint16_t); + void setSpeed(boolean); + void pullup(boolean); + ///////carry over from Wire library//////// + uint8_t returnStatusWire; + uint8_t beginTransmission(uint8_t); + uint8_t beginTransmission(int); + uint8_t send(uint8_t); + uint8_t send(int); + uint8_t endTransmission(); + uint8_t requestFrom(uint8_t, uint8_t); + uint8_t requestFrom(int, int); + uint8_t available(); + /////////////////////////////////////////// + uint8_t write(uint8_t, uint8_t); + uint8_t write(int, int); + uint8_t write(uint8_t, uint8_t, uint8_t); + uint8_t write(int, int, int); + uint8_t write(uint8_t, uint8_t, char*); + uint8_t write(uint8_t, uint8_t, uint8_t*, uint8_t); + uint8_t read(uint8_t, uint8_t); + uint8_t read(int, int); + uint8_t read(uint8_t, uint8_t, uint8_t); + uint8_t read(int, int, int); + uint8_t read(uint8_t, uint8_t, uint8_t*); + uint8_t read(uint8_t, uint8_t, uint8_t, uint8_t*); + uint8_t receive(); uint8_t lockup_count(); - - private: - uint8_t start(); - uint8_t sendAddress(uint8_t); - uint8_t sendByte(uint8_t); - uint8_t receiveByte(boolean); - uint8_t stop(); - void lockUp(); - uint8_t returnStatus; - uint8_t nack; - uint8_t data[MAX_BUFFER_SIZE]; + + private: + uint8_t start(); + uint8_t sendAddress(uint8_t); + uint8_t sendByte(uint8_t); + uint8_t receiveByte(boolean); + uint8_t stop(); + void lockUp(); + uint8_t returnStatus; + uint8_t nack; + uint8_t data[MAX_BUFFER_SIZE]; uint8_t _lockup_count; - static uint8_t bytesAvailable; - static uint8_t bufferIndex; - static uint8_t totalBytes; - static uint16_t timeOutDelay; - -}; - -extern I2C I2c; - -#endif + static uint8_t bytesAvailable; + static uint8_t bufferIndex; + static uint8_t totalBytes; + static uint16_t timeOutDelay; + +}; + +extern I2C I2c; + +#endif