diff --git a/libraries/I2C/BitBangI2C.cpp b/libraries/I2C/BitBangI2C.cpp index 00f959fa..862e31c6 100644 --- a/libraries/I2C/BitBangI2C.cpp +++ b/libraries/I2C/BitBangI2C.cpp @@ -29,11 +29,13 @@ * * This class implements the I2C master protocol on any arbitrary pair * of data and clock pins. It is not restricted to pre-defined pins as - * is the case for the standard \c Wire library. + * is the case for WireI2C. * * This implementation only implements the master side of the protocol. * It assumes that there is a single bus master, no arbitration, and * no clock stretching. + * + * \sa I2CMaster, WireI2C */ #define i2cDelay() delayMicroseconds(5) diff --git a/libraries/I2C/I2CMaster.cpp b/libraries/I2C/I2CMaster.cpp index 8b6dbf8d..9259cbc9 100644 --- a/libraries/I2C/I2CMaster.cpp +++ b/libraries/I2C/I2CMaster.cpp @@ -26,7 +26,7 @@ * \class I2CMaster I2CMaster.h * \brief Abstract base class for I2C master implementations. * - * \sa I2CMaster + * \sa BitBangI2C, WireI2C */ /** diff --git a/libraries/I2C/WireI2C.cpp b/libraries/I2C/WireI2C.cpp new file mode 100644 index 00000000..0ba4a21a --- /dev/null +++ b/libraries/I2C/WireI2C.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2012 Southern Storm Software, Pty Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "WireI2C.h" +#include + +namespace wireI2C { +// XXX: Apparently Arduino libraries cannot directly include each other, +// so we need to work around that by directly pulling in the twi code. +// We hide it in its own namespace just in case the application uses +// Wire directly. Take advantage of the include path to find the +// system-installed twi library. +#include "../../../../libraries/Wire/utility/twi.c" +}; + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define SDA_PIN 20 +#define SCL_PIN 21 +#else +#define SDA_PIN A4 +#define SCL_PIN A5 +#endif + +/** + * \class WireI2C WireI2C.h + * \brief Implementation of an I2C master using the Arduino two-wire interface. + * + * This class implements the I2C master protocol on pre-defined DATA and + * CLOCK pins (A4 and A5 on most boards, D20 and D21 for Arduino Mega). + * For other non-standard pins, use the BitBangI2C class instead. + * + * This implementation only implements the master side of the protocol. + * Use the standard Arduino Wire library for slave I2C implementations. + * + * \sa I2CMaster, BitBangI2C + */ + +/** + * \brief Constructs a new I2C bus master using the Arduino two-wire interface. + * + * If \a useInternalPullups is true (the default) then internal pullups + * will be enabled on the DATA and CLOCK pins. If \a useInternalPullups + * is false, then the external circuit will need to provide pullup resistors. + */ +WireI2C::WireI2C(bool useInternalPullups) + : slaveAddr(0xFF) + , buflen(0) + , bufposn(0) +{ + pinMode(SDA_PIN, INPUT); + pinMode(SCL_PIN, INPUT); + if (useInternalPullups) { + digitalWrite(SDA_PIN, HIGH); + digitalWrite(SCL_PIN, HIGH); + } + wireI2C::twi_init(); +} + +unsigned int WireI2C::maxTransferSize() const +{ + return sizeof(buffer); +} + +void WireI2C::startWrite(unsigned int address) +{ + slaveAddr = (uint8_t)address; + buflen = 0; +} + +void WireI2C::write(uint8_t value) +{ + if (buflen < sizeof(buffer)) + buffer[buflen++] = value; +} + +bool WireI2C::endWrite() +{ + uint8_t result = wireI2C::twi_writeTo(slaveAddr, buffer, buflen, 1); + slaveAddr = 0xFF; + return result == 0; +} + +bool WireI2C::startRead(unsigned int address, unsigned int count) +{ + if (slaveAddr != 0xFF) { + // There is a write operation open, so flush it first. + if (!endWrite()) + return false; + } + if (count > sizeof(buffer)) + count = sizeof(buffer); + bufposn = 0; + buflen = wireI2C::twi_readFrom((uint8_t)address, buffer, (uint8_t)count); + return true; +} + +unsigned int WireI2C::available() +{ + return buflen - bufposn; +} + +uint8_t WireI2C::read() +{ + if (bufposn < buflen) + return buffer[bufposn++]; + else + return 0; +} diff --git a/libraries/I2C/WireI2C.h b/libraries/I2C/WireI2C.h new file mode 100644 index 00000000..33bdb60e --- /dev/null +++ b/libraries/I2C/WireI2C.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 Southern Storm Software, Pty Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef WireI2C_h +#define WireI2C_h + +#include "I2CMaster.h" + +class WireI2C : public I2CMaster { +public: + explicit WireI2C(bool useInternalPullups = true); + + unsigned int maxTransferSize() const; + + void startWrite(unsigned int address); + void write(uint8_t value); + bool endWrite(); + + bool startRead(unsigned int address, unsigned int count); + unsigned int available(); + uint8_t read(); + +private: + uint8_t slaveAddr; + uint8_t buffer[32]; + uint8_t buflen; + uint8_t bufposn; +}; + +#endif