diff --git a/examples/eepromTest_Update/eepromTest_Update.ino b/examples/eepromTest_Update/eepromTest_Update.ino new file mode 100644 index 0000000..c45bf88 --- /dev/null +++ b/examples/eepromTest_Update/eepromTest_Update.ino @@ -0,0 +1,84 @@ +// Test extEEPROM library - update() method. +// Damian Wrobel + +#include + +extEEPROM ep(kbits_256, 1, 64); // device size, number of devices, page size + +void test_update() { + Serial.println("\n(0) Test Started"); + + constexpr auto addr = 0; + constexpr int length = (BUFFER_LENGTH * 2) + 13; + + byte writeBuf[length]; + + for (auto i = 0; i < length; i++) { + writeBuf[i] = i; + } + + auto rv = ep.update(addr, writeBuf, length); + if (rv) { + Serial.print("(1) Error updating: "); + Serial.println(rv); + } + + byte readBuf[length]; + for (auto i = 0; i < length; i++) { + readBuf[i] = ~writeBuf[i]; + } + + rv = ep.read(addr, readBuf, length); + if (rv) { + Serial.print("(2) Error reading: "); + Serial.println(rv); + } + + rv = memcmp(writeBuf, readBuf, length); + if (rv) { + Serial.print("(3) Error comparing: "); + Serial.println(rv); + } + + for (auto i = 0; i < length; i++) { + if (i % 2 || i % 3) + writeBuf[i] = i; + } + + rv = ep.update(addr, writeBuf, length); + if (rv) { + Serial.print("(4) Error updating: "); + Serial.println(rv); + } + + rv = ep.read(addr, readBuf, length); + if (rv) { + Serial.print("(5) Error reading: "); + Serial.println(rv); + } + + rv = memcmp(writeBuf, readBuf, length); + if (rv) { + Serial.print("(6) Error comparing: "); + Serial.println(rv); + } + + Serial.println("(7) Test OK"); +} + +void setup(void) { + Serial.begin(115200); + + const auto eepStatus = ep.begin(ep.twiClock100kHz); + if (eepStatus) { + Serial.print("extEEPROM.begin() failed, status = "); + Serial.println(eepStatus); + while (1) + ; + } + + test_update(); +} + +void loop(void) { +} diff --git a/extEEPROM.cpp b/extEEPROM.cpp index 96487a6..5565bba 100644 --- a/extEEPROM.cpp +++ b/extEEPROM.cpp @@ -114,7 +114,7 @@ byte extEEPROM::begin(twiClockFreq_t twiFreq, TwoWire *_comm) //If the I/O would extend past the top of the EEPROM address space, //a status of EEPROM_ADDR_ERR is returned. For I2C errors, the status //from the Arduino Wire library is passed back through to the caller. -byte extEEPROM::write(unsigned long addr, byte *values, unsigned int nBytes) +byte extEEPROM::write(unsigned long addr, const byte *values, unsigned int nBytes) { uint8_t ctrlByte; //control byte (I2C device address & chip/block select bits) uint8_t txStatus = 0; //transmit status @@ -217,13 +217,48 @@ int extEEPROM::read(unsigned long addr) //Update bytes to external EEPROM. //For I2C errors, the status from the Arduino Wire library is passed back through to the caller. -byte extEEPROM::update(unsigned long addr, byte *values, unsigned int nBytes) +byte extEEPROM::update(unsigned long addr, const byte *values, unsigned int nBytes) { - if (nBytes == 1) { - return update(addr, values[0]); + decltype(nBytes) off = 0; + + while (nBytes > 0) { + byte tmpBuf[BUFFER_LENGTH]; + static_assert(BUFFER_LENGTH < UINT8_MAX, "BUFFER_LENGTH value has to fit into uint8_t"); + const uint8_t readBytes = min(nBytes, static_cast(BUFFER_LENGTH)); + const auto currAddress = addr + off; + const auto rv = read(currAddress, tmpBuf, readBytes); + if (rv != 0) + return rv; + + auto startDiff = 0; + + while (startDiff < readBytes) { + if (tmpBuf[startDiff] == values[currAddress + startDiff]) { + startDiff++; + continue; + } + + auto endDiff = startDiff + 1; + + while (endDiff < readBytes) { + if (tmpBuf[endDiff] != values[currAddress + endDiff]) { + endDiff++; + continue; + } + } + + const auto wv = write(currAddress + startDiff, &values[off + startDiff], endDiff - startDiff); + if (wv) + return wv; + + startDiff = endDiff; + } + + off += readBytes; + nBytes -= readBytes; } - return false; + return 0; } //Update a single byte to external EEPROM. diff --git a/extEEPROM.h b/extEEPROM.h index a57598e..67ca19c 100644 --- a/extEEPROM.h +++ b/extEEPROM.h @@ -47,9 +47,12 @@ * 29Mar2013 v2 - Updated to span page boundaries (and therefore also * * device boundaries, assuming an integral number of pages per device) * * 08Jul2014 v3 - Generalized for 2kb - 2Mb EEPROMs. * - * * - * Paolo Paolucci 22-10-2015 v3.2 * - * 09-01-2016 v3.2 Add update function. * + * * + * Paolo Paolucci 22-10-2015 v3.2 * + * 09-01-2016 v3.2 Add update function. * + * * + * Damian Wrobel * + * 29-04-2019 v3.4.2 Implement update() method. * * * * External EEPROM Library by Jack Christensen is licensed under CC BY-SA 4.0, * * http://creativecommons.org/licenses/by-sa/4.0/ * @@ -93,11 +96,11 @@ class extEEPROM // It is ready for every I2C Sercom, by default use the main Wire byte begin(twiClockFreq_t twiFreq = twiClock100kHz, TwoWire *_comm=&Wire); - byte write(unsigned long addr, byte *values, unsigned int nBytes); + byte write(unsigned long addr, const byte *values, unsigned int nBytes); byte write(unsigned long addr, byte value); byte read(unsigned long addr, byte *values, unsigned int nBytes); int read(unsigned long addr); - byte update(unsigned long addr, byte *values, unsigned int nBytes); + byte update(unsigned long addr, const byte *values, unsigned int nBytes); byte update(unsigned long addr, byte value); unsigned long length();