diff --git a/lib/I2Cdevlib/I2Cdev.cpp b/lib/I2Cdevlib/I2Cdev.cpp index 21d4e1887..892274ba0 100644 --- a/lib/I2Cdevlib/I2Cdev.cpp +++ b/lib/I2Cdevlib/I2Cdev.cpp @@ -3,6 +3,9 @@ // 2013-06-05 by Jeff Rowberg // // Changelog: +// 2021-09-28 - allow custom Wire object as transaction function argument +// 2020-01-20 - hardija : complete support for Teensy 3.x +// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 // 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications // 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) // 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire @@ -44,11 +47,8 @@ THE SOFTWARE. */ #include "I2Cdev.h" -#if defined(ESP32) - #define BUFFER_LENGTH 32 -#endif -#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE #ifdef I2CDEV_IMPLEMENTATION_WARNINGS #if ARDUINO < 100 @@ -103,9 +103,9 @@ I2Cdev::I2Cdev() { * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout) { +int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout, void *wireObj) { uint8_t b; - uint8_t count = readByte(devAddr, regAddr, &b, timeout); + uint8_t count = readByte(devAddr, regAddr, &b, timeout, wireObj); *data = b & (1 << bitNum); return count; } @@ -118,9 +118,9 @@ int8_t I2Cdev::readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout) { +int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout, void *wireObj) { uint16_t b; - uint8_t count = readWord(devAddr, regAddr, &b, timeout); + uint8_t count = readWord(devAddr, regAddr, &b, timeout, wireObj); *data = b & (1 << bitNum); return count; } @@ -134,14 +134,14 @@ int8_t I2Cdev::readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout) { +int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { // 01101001 read byte // 76543210 bit numbers // xxx args: bitStart=4, length=3 // 010 masked // -> 010 shifted uint8_t count, b; - if ((count = readByte(devAddr, regAddr, &b, timeout)) != 0) { + if ((count = readByte(devAddr, regAddr, &b, timeout, wireObj)) != 0) { uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); b &= mask; b >>= (bitStart - length + 1); @@ -159,7 +159,7 @@ int8_t I2Cdev::readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (1 = success, 0 = failure, -1 = timeout) */ -int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout) { +int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { // 1101011001101001 read byte // fedcba9876543210 bit numbers // xxx args: bitStart=12, length=3 @@ -167,7 +167,7 @@ int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uin // -> 010 shifted uint8_t count; uint16_t w; - if ((count = readWord(devAddr, regAddr, &w, timeout)) != 0) { + if ((count = readWord(devAddr, regAddr, &w, timeout, wireObj)) != 0) { uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); w &= mask; w >>= (bitStart - length + 1); @@ -183,8 +183,8 @@ int8_t I2Cdev::readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uin * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout) { - return readBytes(devAddr, regAddr, 1, data, timeout); +int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout, void *wireObj) { + return readBytes(devAddr, regAddr, 1, data, timeout, wireObj); } /** Read single word from a 16-bit device register. @@ -194,8 +194,8 @@ int8_t I2Cdev::readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_ * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Status of read operation (true = success) */ -int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout) { - return readWords(devAddr, regAddr, 1, data, timeout); +int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout, void *wireObj) { + return readWords(devAddr, regAddr, 1, data, timeout, wireObj); } /** Read multiple bytes from an 8-bit device register. @@ -206,7 +206,7 @@ int8_t I2Cdev::readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Number of bytes read (-1 indicates failure) */ -int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout) { +int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -220,71 +220,73 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 int8_t count = 0; uint32_t t1 = millis(); - #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) + #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += _min(length, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.send(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)_min(length - k, BUFFER_LENGTH)); + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->send(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = Wire.receive(); + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->receive(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); #endif } - Wire.endTransmission(); + useWire->endTransmission(); } #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library // Adds standardized write() and read() stream methods instead of send() and receive() // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += _min(length, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)_min(length - k, BUFFER_LENGTH)); - - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = Wire.read(); + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); #endif } - - Wire.endTransmission(); + + useWire->endTransmission(); } #elif (ARDUINO > 100) // Arduino v1.0.1+, Wire library // Adds official support for repeated start condition, yay! // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += _min(length, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)_min(length - k, BUFFER_LENGTH)); - - for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { - data[count] = Wire.read(); + for (int k = 0; k < length; k += min((int)length, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom((uint8_t)devAddr, (uint8_t)min((int)length - k, I2CDEVLIB_WIRE_BUFFER_LENGTH)); + + for (; useWire->available() && (timeout == 0 || millis() - t1 < timeout); count++) { + data[count] = useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -326,7 +328,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 * @param timeout Optional read timeout in milliseconds (0 to disable, leave off to use default class value in I2Cdev::readTimeout) * @return Number of words read (-1 indicates failure) */ -int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout) { +int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -340,29 +342,31 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 int8_t count = 0; uint32_t t1 = millis(); - #if (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE) +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; #if (ARDUINO < 100) // Arduino v00xx (before v1.0), Wire library // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += _min(length * 2, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.send(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes - + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->send(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + bool msb = true; // starts with MSB, then LSB - for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { // first byte is bits 15-8 (MSb=15) - data[count] = Wire.receive() << 8; + data[count] = useWire->receive() << 8; } else { // second byte is bits 7-0 (LSb=0) - data[count] |= Wire.receive(); + data[count] |= useWire->receive(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -372,30 +376,30 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 msb = !msb; } - Wire.endTransmission(); + useWire->endTransmission(); } #elif (ARDUINO == 100) // Arduino v1.0.0, Wire library // Adds standardized write() and read() stream methods instead of send() and receive() - + // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += _min(length * 2, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes - + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + bool msb = true; // starts with MSB, then LSB - for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { // first byte is bits 15-8 (MSb=15) - data[count] = Wire.read() << 8; + data[count] = useWire->read() << 8; } else { // second byte is bits 7-0 (LSb=0) - data[count] |= Wire.read(); + data[count] |= useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -404,31 +408,31 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - Wire.endTransmission(); + + useWire->endTransmission(); } #elif (ARDUINO > 100) // Arduino v1.0.1+, Wire library // Adds official support for repeated start condition, yay! // I2C/TWI subsystem uses internal buffer that breaks with large data requests - // so if user requests more than BUFFER_LENGTH bytes, we have to do it in + // so if user requests more than I2CDEVLIB_WIRE_BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += _min(length * 2, BUFFER_LENGTH)) { - Wire.beginTransmission(devAddr); - Wire.write(regAddr); - Wire.endTransmission(); - Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes - + for (uint8_t k = 0; k < length * 2; k += min(length * 2, I2CDEVLIB_WIRE_BUFFER_LENGTH)) { + useWire->beginTransmission(devAddr); + useWire->write(regAddr); + useWire->endTransmission(); + useWire->beginTransmission(devAddr); + useWire->requestFrom(devAddr, (uint8_t)(length * 2)); // length=words, this wants bytes + bool msb = true; // starts with MSB, then LSB - for (; Wire.available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { + for (; useWire->available() && count < length && (timeout == 0 || millis() - t1 < timeout);) { if (msb) { // first byte is bits 15-8 (MSb=15) - data[count] = Wire.read() << 8; + data[count] = useWire->read() << 8; } else { // second byte is bits 7-0 (LSb=0) - data[count] |= Wire.read(); + data[count] |= useWire->read(); #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[count], HEX); if (count + 1 < length) Serial.print(" "); @@ -437,8 +441,8 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 } msb = !msb; } - - Wire.endTransmission(); + + useWire->endTransmission(); } #endif @@ -446,8 +450,8 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // Fastwire library // no loop required for fastwire - uint16_t intermediate[(uint8_t)length]; - uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, (uint8_t *)intermediate, (uint8_t)(length * 2)); + uint8_t intermediate[(uint8_t)length*2]; + uint8_t status = Fastwire::readBuf(devAddr << 1, regAddr, intermediate, (uint8_t)(length * 2)); if (status == 0) { count = length; // success for (uint8_t i = 0; i < length; i++) { @@ -466,7 +470,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 Serial.print(count, DEC); Serial.println(" read)."); #endif - + return count; } @@ -477,11 +481,11 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 * @param value New bit value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data) { +bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data, void *wireObj) { uint8_t b; - readByte(devAddr, regAddr, &b); + readByte(devAddr, regAddr, &b, I2Cdev::readTimeout, wireObj); b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum)); - return writeByte(devAddr, regAddr, b); + return writeByte(devAddr, regAddr, b, wireObj); } /** write a single bit in a 16-bit device register. @@ -491,11 +495,11 @@ bool I2Cdev::writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t * @param value New bit value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data) { +bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data, void *wireObj) { uint16_t w; - readWord(devAddr, regAddr, &w); + readWord(devAddr, regAddr, &w, I2Cdev::readTimeout, wireObj); w = (data != 0) ? (w | (1 << bitNum)) : (w & ~(1 << bitNum)); - return writeWord(devAddr, regAddr, w); + return writeWord(devAddr, regAddr, w, wireObj); } /** Write multiple bits in an 8-bit device register. @@ -506,7 +510,7 @@ bool I2Cdev::writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_ * @param data Right-aligned value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data) { +bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data, void *wireObj) { // 010 value to write // 76543210 bit numbers // xxx args: bitStart=4, length=3 @@ -515,13 +519,13 @@ bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8 // 10100011 original & ~mask // 10101011 masked | value uint8_t b; - if (readByte(devAddr, regAddr, &b) != 0) { + if (readByte(devAddr, regAddr, &b, I2Cdev::readTimeout, wireObj) != 0) { uint8_t mask = ((1 << length) - 1) << (bitStart - length + 1); data <<= (bitStart - length + 1); // shift data into correct position data &= mask; // zero all non-important bits in data b &= ~(mask); // zero all important bits in existing byte b |= data; // combine data with existing byte - return writeByte(devAddr, regAddr, b); + return writeByte(devAddr, regAddr, b, wireObj); } else { return false; } @@ -535,7 +539,7 @@ bool I2Cdev::writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8 * @param data Right-aligned value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data) { +bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data, void *wireObj) { // 010 value to write // fedcba9876543210 bit numbers // xxx args: bitStart=12, length=3 @@ -544,13 +548,13 @@ bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint // 1010001110010110 original & ~mask // 1010101110010110 masked | value uint16_t w; - if (readWord(devAddr, regAddr, &w) != 0) { + if (readWord(devAddr, regAddr, &w, I2Cdev::readTimeout, wireObj) != 0) { uint16_t mask = ((1 << length) - 1) << (bitStart - length + 1); data <<= (bitStart - length + 1); // shift data into correct position data &= mask; // zero all non-important bits in data w &= ~(mask); // zero all important bits in existing word w |= data; // combine data with existing word - return writeWord(devAddr, regAddr, w); + return writeWord(devAddr, regAddr, w, wireObj); } else { return false; } @@ -562,8 +566,8 @@ bool I2Cdev::writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint * @param data New byte value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { - return writeBytes(devAddr, regAddr, 1, &data); +bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wireObj) { + return writeBytes(devAddr, regAddr, 1, &data, wireObj); } /** Write single word to a 16-bit device register. @@ -572,8 +576,8 @@ bool I2Cdev::writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data) { * @param data New word value to write * @return Status of operation (true = success) */ -bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { - return writeWords(devAddr, regAddr, 1, &data); +bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wireObj) { + return writeWords(devAddr, regAddr, 1, &data, wireObj); } /** Write multiple bytes to an 8-bit device register. @@ -583,7 +587,7 @@ bool I2Cdev::writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data) { * @param data Buffer to copy new data from * @return Status of operation (true = success) */ -bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data) { +bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t* data, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -594,12 +598,20 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ Serial.print("..."); #endif uint8_t status = 0; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; +#endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.beginTransmission(devAddr); - Wire.send((uint8_t) regAddr); // send address - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - Wire.beginTransmission(devAddr); - Wire.write((uint8_t) regAddr); // send address + useWire->beginTransmission(devAddr); + useWire->send((uint8_t) regAddr); // send address + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + useWire->beginTransmission(devAddr); + useWire->write((uint8_t) regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::beginTransmission(devAddr); Fastwire::write(regAddr); @@ -610,17 +622,21 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ if (i + 1 < length) Serial.print(" "); #endif #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.send((uint8_t) data[i]); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - Wire.write((uint8_t) data[i]); + useWire->send((uint8_t) data[i]); + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + useWire->write((uint8_t) data[i]); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t) data[i]); #endif } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.endTransmission(); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - status = Wire.endTransmission(); + useWire->endTransmission(); + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + status = useWire->endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); @@ -638,7 +654,7 @@ bool I2Cdev::writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_ * @param data Buffer to copy new data from * @return Status of operation (true = success) */ -bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data) { +bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t* data, void *wireObj) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print("I2C (0x"); Serial.print(devAddr, HEX); @@ -649,37 +665,49 @@ bool I2Cdev::writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16 Serial.print("..."); #endif uint8_t status = 0; + +#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + TwoWire *useWire = &Wire; + if (wireObj) useWire = (TwoWire *)wireObj; +#endif + #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.beginTransmission(devAddr); - Wire.send(regAddr); // send address - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - Wire.beginTransmission(devAddr); - Wire.write(regAddr); // send address + useWire->beginTransmission(devAddr); + useWire->send(regAddr); // send address + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + useWire->beginTransmission(devAddr); + useWire->write(regAddr); // send address #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::beginTransmission(devAddr); Fastwire::write(regAddr); #endif - for (uint8_t i = 0; i < length * 2; i++) { + for (uint8_t i = 0; i < length; i++) { #ifdef I2CDEV_SERIAL_DEBUG Serial.print(data[i], HEX); if (i + 1 < length) Serial.print(" "); #endif #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.send((uint8_t)(data[i] >> 8)); // send MSB - Wire.send((uint8_t)data[i++]); // send LSB - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - Wire.write((uint8_t)(data[i] >> 8)); // send MSB - Wire.write((uint8_t)data[i++]); // send LSB + useWire->send((uint8_t)(data[i] >> 8)); // send MSB + useWire->send((uint8_t)data[i]); // send LSB + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + useWire->write((uint8_t)(data[i] >> 8)); // send MSB + useWire->write((uint8_t)data[i]); // send LSB #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::write((uint8_t)(data[i] >> 8)); // send MSB - status = Fastwire::write((uint8_t)data[i++]); // send LSB + status = Fastwire::write((uint8_t)data[i]); // send LSB if (status != 0) break; #endif } #if ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO < 100) || I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE) - Wire.endTransmission(); - #elif (I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) - status = Wire.endTransmission(); + useWire->endTransmission(); + #elif ((I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE && ARDUINO >= 100) \ + || (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE && ARDUINO >= 100) \ + || I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE) + status = useWire->endTransmission(); #elif (I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE) Fastwire::stop(); //status = Fastwire::endTransmission(); @@ -739,15 +767,15 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; #endif TWSR = 0; // no prescaler => prescaler = 1 - TWBR = ((16000L / khz) - 16) / 2; // change the I2C clock rate + TWBR = F_CPU / 2000 / khz - 8; // change the I2C clock rate TWCR = 1 << TWEN; // enable twi module, no interrupt } // added by Jeff Rowberg 2013-05-07: // Arduino Wire-style "beginTransmission" function // (takes 7-bit device address like the Wire method, NOT 8-bit: 0x68, not 0xD0/0xD1) - uint8_t Fastwire::beginTransmission(uint8_t device) { - uint8_t twst, retry; + byte Fastwire::beginTransmission(byte device) { + byte twst, retry; retry = 2; do { TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO) | (1 << TWSTA); @@ -766,8 +794,8 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; return 0; } - uint8_t Fastwire::writeBuf(uint8_t device, uint8_t address, uint8_t *data, uint8_t num) { - uint8_t twst, retry; + byte Fastwire::writeBuf(byte device, byte address, byte *data, byte num) { + byte twst, retry; retry = 2; do { @@ -793,7 +821,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; twst = TWSR & 0xF8; if (twst != TW_MT_DATA_ACK) return 6; - for (uint8_t i = 0; i < num; i++) { + for (byte i = 0; i < num; i++) { //Serial.print(data[i], HEX); //Serial.print(" "); TWDR = data[i]; // send data to the previously addressed device @@ -807,8 +835,8 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; return 0; } - uint8_t Fastwire::write(uint8_t value) { - uint8_t twst; + byte Fastwire::write(byte value) { + byte twst; //Serial.println(value, HEX); TWDR = value; // send data TWCR = (1 << TWINT) | (1 << TWEN); @@ -818,8 +846,8 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; return 0; } - uint8_t Fastwire::readBuf(uint8_t device, uint8_t address, uint8_t *data, uint8_t num) { - uint8_t twst, retry; + byte Fastwire::readBuf(byte device, byte address, byte *data, byte num) { + byte twst, retry; retry = 2; do { @@ -885,7 +913,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; TWCR = 0; } - uint8_t Fastwire::stop() { + byte Fastwire::stop() { TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); if (!waitInt()) return 1; return 0; @@ -899,50 +927,50 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; /* call this version 1.0 - + Offhand, the only funky part that I can think of is in nbrequestFrom, where the buffer length and index are set *before* the data is actually read. The problem is that these are variables local to the TwoWire object, and by the time we actually have read the - data, and know what the length actually is, we have no simple access to the object's + data, and know what the length actually is, we have no simple access to the object's variables. The actual bytes read *is* given to the callback function, though. - + The ISR code for a slave receiver is commented out. I don't have that setup, and can't verify it at this time. Save it for 2.0! - - The handling of the read and write processes here is much like in the demo sketch code: + + The handling of the read and write processes here is much like in the demo sketch code: the process is broken down into sequential functions, where each registers the next as a callback, essentially. - - For example, for the Read process, twi_read00 just returns if TWI is not yet in a + + For example, for the Read process, twi_read00 just returns if TWI is not yet in a ready state. When there's another interrupt, and the interface *is* ready, then it sets up the read, starts it, and registers twi_read01 as the function to call after the *next* interrupt. twi_read01, then, just returns if the interface is still in a "reading" state. When the reading is done, it copies the information to the buffer, - cleans up, and calls the user-requested callback function with the actual number of + cleans up, and calls the user-requested callback function with the actual number of bytes read. - + The writing is similar. - + Questions, comments and problems can go to Gene@Telobot.com. - + Thumbs Up! Gene Knight - + */ - + uint8_t TwoWire::rxBuffer[NBWIRE_BUFFER_LENGTH]; uint8_t TwoWire::rxBufferIndex = 0; uint8_t TwoWire::rxBufferLength = 0; - + uint8_t TwoWire::txAddress = 0; uint8_t TwoWire::txBuffer[NBWIRE_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); - + static volatile uint8_t twi_transmitting; static volatile uint8_t twi_state; static uint8_t twi_slarw; @@ -957,7 +985,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; static volatile uint8_t twi_Done; void (*twi_cbendTransmissionDone)(int); void (*twi_cbreadFromDone)(int); - + void twi_init() { // initialize state twi_state = TWI_READY; @@ -979,7 +1007,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2; // bitrate register // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA); /* TWEN - TWI Enable Bit TWIE - TWI Interrupt Enable @@ -988,7 +1016,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; TWSTA - TWI Start Condition */ } - + typedef struct { uint8_t address; uint8_t* data; @@ -1000,7 +1028,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; twi_Write_Vars *ptwv = 0; static void (*fNextInterruptFunction)(void) = 0; - void twi_Finish(uint8_t bRetVal) { + void twi_Finish(byte bRetVal) { if (ptwv) { free(ptwv); ptwv = 0; @@ -1009,13 +1037,13 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; twi_Return_Value = bRetVal; fNextInterruptFunction = 0; } - + uint8_t twii_WaitForDone(uint16_t timeout) { uint32_t endMillis = millis() + timeout; while (!twi_Done && (timeout == 0 || millis() < endMillis)) continue; return twi_Return_Value; } - + void twii_SetState(uint8_t ucState) { twi_state = ucState; } @@ -1048,7 +1076,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; } void twii_SetStart() { - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTA); } void twi_write01() { @@ -1065,8 +1093,8 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; if (twi_cbendTransmissionDone) return twi_cbendTransmissionDone(twi_Return_Value); return; } - - + + void twi_write00() { if (TWI_READY != twi_state) return; // blocking test if (TWI_BUFFER_LENGTH < ptwv -> length) { @@ -1083,7 +1111,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; fNextInterruptFunction = twi_write01; // next routine return twi_write01(); } - + void twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) { uint8_t i; ptwv = (twi_Write_Vars *)malloc(sizeof(twi_Write_Vars)); @@ -1103,7 +1131,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; if (twi_cbreadFromDone) return twi_cbreadFromDone(twi_Return_Value); return; } - + void twi_read00() { if (TWI_READY != twi_state) return; // blocking test if (TWI_BUFFER_LENGTH < ptwv -> length) twi_Finish(0); // error return @@ -1131,34 +1159,34 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; 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); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (1 << TWEA); } else { - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT); } } - + void twi_stop(void) { // send stop condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); - + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWSTO); + // wait for stop condition to be exectued on bus // TWINT is not set after a stop condition! - while (TWCR & _BV(TWSTO)) { + while (TWCR & (1 << TWSTO)) { continue; } - + // update twi state twi_state = TWI_READY; } void twi_releaseBus(void) { // release bus - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); - + TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWEA) | (1 << TWINT); + // update twi state twi_state = TWI_READY; } - + SIGNAL(TWI_vect) { switch (TW_STATUS) { // All Master @@ -1168,7 +1196,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; 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 @@ -1196,7 +1224,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; twi_error = TW_MT_ARB_LOST; twi_releaseBus(); break; - + // Master Receiver case TW_MR_DATA_ACK: // data received, ack sent // put byte into buffer @@ -1294,7 +1322,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; twi_txBufferLength = 1; twi_txBuffer[0] = 0x00; } - + // transmit first byte from buffer, fall through case TW_ST_DATA_ACK: // byte sent, ack returned @@ -1332,26 +1360,26 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; } TwoWire::TwoWire() { } - + void TwoWire::begin(void) { rxBufferIndex = 0; rxBufferLength = 0; - + txBufferIndex = 0; txBufferLength = 0; twi_init(); } - + void TwoWire::beginTransmission(uint8_t address) { //beginTransmission((uint8_t)address); // indicate that we are transmitting twi_transmitting = 1; - + // set address of targeted slave txAddress = address; - + // reset tx buffer iterator vars txBufferIndex = 0; txBufferLength = 0; @@ -1378,7 +1406,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; twi_writeTo(txAddress, txBuffer, txBufferLength, 1); return; } - + void TwoWire::send(uint8_t data) { if (twi_transmitting) { // in master transmitter mode @@ -1399,21 +1427,21 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; //twi_transmit(&data, 1); } } - + 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; } - + uint8_t TwoWire::requestFrom(uint8_t address, int quantity, uint16_t timeout) { // clamp to buffer length if (quantity > NBWIRE_BUFFER_LENGTH) { @@ -1428,10 +1456,10 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; // set rx buffer iterator vars rxBufferIndex = 0; rxBufferLength = read; - + return read; } - + void TwoWire::nbrequestFrom(uint8_t address, int quantity, void (*function)(int)) { // clamp to buffer length if (quantity > NBWIRE_BUFFER_LENGTH) { diff --git a/lib/I2Cdevlib/I2Cdev.h b/lib/I2Cdevlib/I2Cdev.h index 007281de6..5b59c56ff 100644 --- a/lib/I2Cdevlib/I2Cdev.h +++ b/lib/I2Cdevlib/I2Cdev.h @@ -3,6 +3,8 @@ // 2013-06-05 by Jeff Rowberg // // Changelog: +// 2021-09-28 - allow custom Wire object as transaction function argument +// 2020-01-20 - hardija : complete support for Teensy 3.x // 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1 // 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications // 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan) @@ -47,11 +49,18 @@ THE SOFTWARE. #ifndef _I2CDEV_H_ #define _I2CDEV_H_ +// ----------------------------------------------------------------------------- +// Enable deprecated pgmspace typedefs in avr-libc +// ----------------------------------------------------------------------------- +#define __PROG_TYPES_COMPAT__ + // ----------------------------------------------------------------------------- // I2C interface implementation setting // ----------------------------------------------------------------------------- #ifndef I2CDEV_IMPLEMENTATION #define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE +//#define I2CDEV_IMPLEMENTATION I2CDEV_TEENSY_3X_WIRE +//#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_SBWIRE //#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE #endif // I2CDEV_IMPLEMENTATION @@ -67,6 +76,8 @@ THE SOFTWARE. // ^^^ NBWire implementation is still buggy w/some interrupts! #define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project #define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at https://github.com/DSSCircuits/I2C-Master-Library +#define I2CDEV_BUILTIN_SBWIRE 5 // I2C object from Shuning (Steve) Bian's SBWire Library at https://github.com/freespace/SBWire +#define I2CDEV_TEENSY_3X_WIRE 6 // Teensy 3.x support using i2c_t3 library // ----------------------------------------------------------------------------- // Arduino-style "Serial.print" debug constant (uncomment to enable) @@ -82,16 +93,38 @@ THE SOFTWARE. #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_TEENSY_3X_WIRE + #include + #endif #if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY #include #endif + #if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_SBWIRE + #include "SBWire.h" + #endif #endif #ifdef SPARK - #include + #include "application.h" #define ARDUINO 101 + #define BUFFER_LENGTH 32 #endif +#ifndef I2CDEVLIB_WIRE_BUFFER_LENGTH + #if defined(I2C_BUFFER_LENGTH) + // Arduino ESP32 core Wire uses this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH I2C_BUFFER_LENGTH + #elif defined(BUFFER_LENGTH) + // Arduino AVR core Wire and many others use this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH BUFFER_LENGTH + #elif defined(SERIAL_BUFFER_SIZE) + // Arduino SAMD core Wire uses this + #define I2CDEVLIB_WIRE_BUFFER_LENGTH SERIAL_BUFFER_SIZE + #else + // should be a safe fallback, though possibly inefficient + #define I2CDEVLIB_WIRE_BUFFER_LENGTH 32 + #endif +#endif // 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];") #define I2CDEV_DEFAULT_READ_TIMEOUT 1000 @@ -100,23 +133,23 @@ class I2Cdev { public: I2Cdev(); - static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout); - static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout); + static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); + static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout, void *wireObj=0); - static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data); - static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data); - static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data); - static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data); - static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data); - static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data); - static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data); - static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data); + static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data, void *wireObj=0); + static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data, void *wireObj=0); + static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data, void *wireObj=0); + static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data, void *wireObj=0); + static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data, void *wireObj=0); + static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data, void *wireObj=0); + static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, void *wireObj=0); + static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, void *wireObj=0); static uint16_t readTimeout; }; @@ -156,12 +189,12 @@ class I2Cdev { public: static void setup(int khz, boolean pullup); - static uint8_t beginTransmission(uint8_t device); - static uint8_t write(uint8_t value); - static uint8_t writeBuf(uint8_t device, uint8_t address, uint8_t *data, uint8_t num); - static uint8_t readBuf(uint8_t device, uint8_t address, uint8_t *data, uint8_t num); + static byte beginTransmission(byte device); + static byte write(byte value); + static byte writeBuf(byte device, byte address, byte *data, byte num); + static byte readBuf(byte device, byte address, byte *data, byte num); static void reset(); - static uint8_t stop(); + static byte stop(); }; #endif @@ -229,7 +262,7 @@ class I2Cdev { /* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */ - #define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3)) + #define TW_STATUS_MASK ((1 << TWS7)|(1 << TWS6)|(1 << TWS5)|(1 << TWS4)|(1 << TWS3)) #define TW_STATUS (TWSR & TW_STATUS_MASK) #define TW_START 0x08 #define TW_REP_START 0x10 @@ -264,11 +297,11 @@ class I2Cdev { //#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr)) #ifndef sbi // set bit - #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) + #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= (1 << bit)) #endif // sbi #ifndef cbi // clear bit - #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) + #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~(1 << bit)) #endif // cbi extern TwoWire Wire; diff --git a/lib/I2Cdevlib/library.json b/lib/I2Cdevlib/library.json index e974a9ab3..5c5eab8fb 100644 --- a/lib/I2Cdevlib/library.json +++ b/lib/I2Cdevlib/library.json @@ -9,10 +9,10 @@ "url": "https://github.com/jrowberg/i2cdevlib.git" }, "frameworks": "arduino", - "platforms": "atmelavr", - "dependencies": [ - { - "name": "Wire" - } + "platforms": "*", + "dependencies": [ + { + "name": "Wire" + } ] } diff --git a/src/ESPEasy_common.h b/src/ESPEasy_common.h index 9f112a49b..4aaa84f5f 100644 --- a/src/ESPEasy_common.h +++ b/src/ESPEasy_common.h @@ -75,7 +75,7 @@ namespace std - #include "core_version.h" + #include #define NODE_TYPE_ID NODE_TYPE_ID_ESP_EASYM_STD #define FILE_CONFIG "config.dat" #define FILE_SECURITY "security.dat" @@ -95,13 +95,13 @@ namespace std #ifndef LWIP_OPEN_SRC #define LWIP_OPEN_SRC #endif - #include "lwip/opt.h" - #include "lwip/udp.h" - #include "lwip/igmp.h" - #include "include/UdpContext.h" - #include "limits.h" + #include + #include + #include + #include + #include extern "C" { - #include "user_interface.h" + #include } #define SMALLEST_OTA_IMAGE 276848 // smallest known 2-step OTA image diff --git a/src/_N001_Email.ino b/src/_N001_Email.ino index 5ad734bc9..a15491f48 100644 --- a/src/_N001_Email.ino +++ b/src/_N001_Email.ino @@ -22,9 +22,10 @@ #include "src/Helpers/StringParser.h" #include "src/Helpers/_CPlugin_Helper.h" // safeReadStringUntil +// Forward declaration +boolean NPlugin_001_send(const NotificationSettingsStruct& notificationsettings, const String& aSub, String& aMesg); // The message body is included in event->String1 - boolean NPlugin_001(NPlugin::Function function, struct EventStruct *event, String& string) { boolean success = false; diff --git a/src/src/Commands/Diagnostic.cpp b/src/src/Commands/Diagnostic.cpp index f20afbee9..dff3c072c 100644 --- a/src/src/Commands/Diagnostic.cpp +++ b/src/src/Commands/Diagnostic.cpp @@ -1,13 +1,5 @@ #include "../Commands/Diagnostic.h" -/* - #include "Common.h" - #include "../../ESPEasy_common.h" - - #include "../DataStructs/ESPEasy_EventStruct.h" - */ - - #include "../Commands/Common.h" diff --git a/src/src/Commands/Networks.cpp b/src/src/Commands/Networks.cpp index 04b0d96eb..7aba7004a 100644 --- a/src/src/Commands/Networks.cpp +++ b/src/src/Commands/Networks.cpp @@ -7,7 +7,7 @@ #ifdef HAS_ETHERNET -#include "ETH.h" +#include #endif String Command_AccessInfo_Ls(struct EventStruct *event, const char* Line) diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index 4a6dec83c..19181a53f 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -1415,7 +1415,7 @@ To create/register a plugin, you have to : #define USES_P096 // eInk (Needs lib_deps = Adafruit GFX Library, LOLIN_EPD ) #endif #ifndef USES_P098 - #define USES_P098 // ESPEasy-NOW Receiver +// #define USES_P098 // ESPEasy-NOW Receiver #endif #ifndef USES_P099 #define USES_P099 // XPT2046 Touchscreen diff --git a/src/src/DataStructs/EventStructCommandWrapper.h b/src/src/DataStructs/EventStructCommandWrapper.h index ef3cd5c31..86ae05fc6 100644 --- a/src/src/DataStructs/EventStructCommandWrapper.h +++ b/src/src/DataStructs/EventStructCommandWrapper.h @@ -2,7 +2,7 @@ #define DATASTRUCTS_EVENTSTRUCTCOMMANDWRAPPER_H #include -#include "ESPEasy_EventStruct.h" +#include "../DataStructs/ESPEasy_EventStruct.h" struct EventStructCommandWrapper { EventStructCommandWrapper() : id(0) {} diff --git a/src/src/DataStructs/RTC_cache_handler_struct.h b/src/src/DataStructs/RTC_cache_handler_struct.h index 9717e6522..9984011c6 100644 --- a/src/src/DataStructs/RTC_cache_handler_struct.h +++ b/src/src/DataStructs/RTC_cache_handler_struct.h @@ -2,7 +2,7 @@ #define DATASTRUCTS_RTC_CACHE_HANDLER_STRUCT_H -#include "RTCCacheStruct.h" +#include "../DataStructs/RTCCacheStruct.h" #include "../../ESPEasy_common.h" diff --git a/src/src/ESPEasyCore/ESPEasyWiFiEvent.cpp b/src/src/ESPEasyCore/ESPEasyWiFiEvent.cpp index 8691ab139..81f18d2c8 100644 --- a/src/src/ESPEasyCore/ESPEasyWiFiEvent.cpp +++ b/src/src/ESPEasyCore/ESPEasyWiFiEvent.cpp @@ -1,7 +1,7 @@ -#include "ESPEasyWiFiEvent.h" +#include "../ESPEasyCore/ESPEasyWiFiEvent.h" #ifdef HAS_ETHERNET -#include "ETH.h" +#include #endif #include "../DataStructs/RTCStruct.h" diff --git a/src/src/Globals/I2Cdev.cpp b/src/src/Globals/I2Cdev.cpp index 5c2f05c38..f4062267a 100644 --- a/src/src/Globals/I2Cdev.cpp +++ b/src/src/Globals/I2Cdev.cpp @@ -1,4 +1,4 @@ -#include "I2Cdev.h" +#include "../Globals/I2Cdev.h" I2Cdev i2cdev; diff --git a/src/src/Helpers/DeepSleep.cpp b/src/src/Helpers/DeepSleep.cpp index 2a90f1393..8ac9284de 100644 --- a/src/src/Helpers/DeepSleep.cpp +++ b/src/src/Helpers/DeepSleep.cpp @@ -141,7 +141,7 @@ void deepSleepStart(int dsdelay) if (Settings.UseAlternativeDeepSleep()) { // See: https://github.com/esp8266/Arduino/issues/6318#issuecomment-711389479 - #include "c_types.h" + #include // system_phy_set_powerup_option: // 1 = RF initialization only calibrate VDD33 and Tx power which will take about 18 ms // 2 = RF initialization only calibrate VDD33 which will take about 2 ms diff --git a/src/src/Helpers/FS_Helper.h b/src/src/Helpers/FS_Helper.h index 26d8755f7..e1d9b335c 100644 --- a/src/src/Helpers/FS_Helper.h +++ b/src/src/Helpers/FS_Helper.h @@ -11,7 +11,7 @@ #define FS_NO_GLOBALS #if defined(ESP8266) extern "C" { - #include "spi_flash.h" + #include } #ifdef CORE_POST_2_6_0 extern "C" uint32_t _FS_start; diff --git a/src/src/Helpers/Memory.cpp b/src/src/Helpers/Memory.cpp index 7a19779b4..822c0474c 100644 --- a/src/src/Helpers/Memory.cpp +++ b/src/src/Helpers/Memory.cpp @@ -3,7 +3,7 @@ #ifdef ESP8266 extern "C" { -#include "user_interface.h" +#include } #endif diff --git a/src/src/Helpers/Networking.cpp b/src/src/Helpers/Networking.cpp index be78d1979..fa39960f0 100644 --- a/src/src/Helpers/Networking.cpp +++ b/src/src/Helpers/Networking.cpp @@ -60,7 +60,7 @@ void etharp_gratuitous_r(struct netif *netif) { # include # endif // ifdef ESP8266 # ifdef ESP32 -# include "HTTPClient.h" +# include # endif // ifdef ESP32 #endif // USE_SETTINGS_ARCHIVE diff --git a/src/src/Helpers/StringProvider.cpp b/src/src/Helpers/StringProvider.cpp index 46e76a6ea..6fad04b86 100644 --- a/src/src/Helpers/StringProvider.cpp +++ b/src/src/Helpers/StringProvider.cpp @@ -1,7 +1,7 @@ #include "../Helpers/StringProvider.h" #ifdef HAS_ETHERNET -# include "ETH.h" +# include #endif // ifdef HAS_ETHERNET #include "../../ESPEasy-Globals.h" diff --git a/src/src/Helpers/_CPlugin_Helper.cpp b/src/src/Helpers/_CPlugin_Helper.cpp index ee6315b2c..42b47a4fa 100644 --- a/src/src/Helpers/_CPlugin_Helper.cpp +++ b/src/src/Helpers/_CPlugin_Helper.cpp @@ -36,7 +36,7 @@ # include #endif // ifdef ESP8266 #ifdef ESP32 -# include "HTTPClient.h" +# include #endif // ifdef ESP32 bool safeReadStringUntil(Stream & input, diff --git a/src/src/WebServer/ConfigPage.cpp b/src/src/WebServer/ConfigPage.cpp index 0dd2d4f3e..59bf65c8b 100644 --- a/src/src/WebServer/ConfigPage.cpp +++ b/src/src/WebServer/ConfigPage.cpp @@ -23,6 +23,8 @@ +#include "../DataStructs/MAC_address.h" + // ******************************************************************************** // Web Interface config page // ********************************************************************************