diff --git a/Adafruit_I2CDevice.cpp b/Adafruit_I2CDevice.cpp index 91724d6..b1db3ea 100644 --- a/Adafruit_I2CDevice.cpp +++ b/Adafruit_I2CDevice.cpp @@ -77,19 +77,10 @@ bool Adafruit_I2CDevice::detected(void) { bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop, const uint8_t *prefix_buffer, size_t prefix_len) { - if ((len + prefix_len) > maxBufferSize()) { - // currently not guaranteed to work if more than 32 bytes! - // we will need to find out if some platforms have larger - // I2C buffer sizes :/ -#ifdef DEBUG_SERIAL - DEBUG_SERIAL.println(F("\tI2CDevice could not write such a large buffer")); -#endif - return false; - } - _wire->beginTransmission(_addr); // Write the prefix data (usually an address) + // This is required to be less than _maxBufferSize, so no need to chunkify if ((prefix_len != 0) && (prefix_buffer != NULL)) { if (_wire->write(prefix_buffer, prefix_len) != prefix_len) { #ifdef DEBUG_SERIAL @@ -99,14 +90,32 @@ bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop, } } - // Write the data itself - if (_wire->write(buffer, len) != len) { + // Write the data itself, chunkify if needed + size_t bufferSize = maxBufferSize(); + if (bufferSize > len) { + // can just write + if (_wire->write(buffer, len) != len) { #ifdef DEBUG_SERIAL - DEBUG_SERIAL.println(F("\tI2CDevice failed to write")); + DEBUG_SERIAL.println(F("\tI2CDevice failed to write")); #endif - return false; + return false; + } + } else { + // must chunkify + size_t pos = 0; + uint8_t write_buffer[bufferSize]; + while (pos < len) { + size_t write_len = len - pos > bufferSize ? bufferSize : len - pos; + for (size_t i = 0; i < write_len; i++) + write_buffer[i] = buffer[pos++]; + if (_wire->write(write_buffer, write_len) != write_len) { +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println(F("\tI2CDevice failed to write")); +#endif + return false; + } + } } - #ifdef DEBUG_SERIAL DEBUG_SERIAL.print(F("\tI2CWRITE @ 0x")); @@ -137,7 +146,7 @@ bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop, if (_wire->endTransmission(stop) == 0) { #ifdef DEBUG_SERIAL - // DEBUG_SERIAL.println("Sent!"); + DEBUG_SERIAL.println("Sent!"); #endif return true; } else { @@ -157,16 +166,27 @@ bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop, * @return True if read was successful, otherwise false. */ bool Adafruit_I2CDevice::read(uint8_t *buffer, size_t len, bool stop) { - if (len > maxBufferSize()) { - // currently not guaranteed to work if more than 32 bytes! - // we will need to find out if some platforms have larger - // I2C buffer sizes :/ -#ifdef DEBUG_SERIAL - DEBUG_SERIAL.println(F("\tI2CDevice could not read such a large buffer")); -#endif - return false; + size_t bufferSize = maxBufferSize(); + if (bufferSize > len) { + // can just read + return _read(buffer, len, stop); + } else { + // must chunkify + size_t pos = 0; + uint8_t read_buffer[bufferSize]; + while (pos < len) { + size_t read_len = len - pos > bufferSize ? bufferSize : len - pos; + if (!_read(read_buffer, read_len, false)) { + return false; + } + for (size_t i = 0; i < read_len; i++) + buffer[pos++] = read_buffer[i]; + } + return true; } +} +bool Adafruit_I2CDevice::_read(uint8_t *buffer, size_t len, bool stop) { #if defined(TinyWireM_h) size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len); #else diff --git a/Adafruit_I2CDevice.h b/Adafruit_I2CDevice.h index 28468ea..d47714f 100644 --- a/Adafruit_I2CDevice.h +++ b/Adafruit_I2CDevice.h @@ -28,6 +28,7 @@ private: TwoWire *_wire; bool _begun; size_t _maxBufferSize; + bool _read(uint8_t *buffer, size_t len, bool stop); }; #endif // Adafruit_I2CDevice_h diff --git a/library.properties b/library.properties index b6c1ac7..6845034 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Adafruit BusIO -version=1.8.3 +version=1.9.0 author=Adafruit maintainer=Adafruit sentence=This is a library for abstracting away UART, I2C and SPI interfacing