1.4.2 add updateBlock() (#23)

This commit is contained in:
Rob Tillaart authored and GitHub committed 2021-01-31 16:27:13 +01:00
1 parent 692f1a3004
commit d0f8385bc4
7 files changed
+264 -5

No files matched your search

+26 -1
View File
@@ -1,7 +1,7 @@
//
// FILE: I2C_eeprom.cpp
// AUTHOR: Rob Tillaart
// VERSION: 1.4.1
// VERSION: 1.4.2
// PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al.
// URL: https://github.com/RobTillaart/I2C_EEPROM.git
//
@@ -36,6 +36,7 @@
// See determineSize for all tested.
// 1.4.1 2021-01-28 fixed addressing bug 24LC04/08/16 equivalents from ST e.g. m24c08w
// add Wire1..WireN;
// 1.4.2 2021-01-31 add updateBlock()
#include <I2C_eeprom.h>
@@ -169,6 +170,30 @@ int I2C_eeprom::updateByte(const uint16_t memoryAddress, const uint8_t data)
return writeByte(memoryAddress, data);
}
int I2C_eeprom::updateBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint16_t length)
{
uint16_t addr = memoryAddress;
uint16_t len = length;
uint16_t rv = 0;
while (len > 0)
{
uint8_t buf[I2C_TWIBUFFERSIZE];
uint8_t cnt = I2C_TWIBUFFERSIZE;
if (cnt > len) cnt = len;
rv += _ReadBlock(addr, buf, cnt);
if (memcmp(buffer, buf, cnt) != 0)
{
_pageBlock(addr, buffer, cnt, true);
}
addr += cnt;
buffer += cnt;
len -= cnt;
yield(); // For OS scheduling etc
}
return rv;
}
// returns size in bytes
// returns 0 if not connected
+6 -2
View File
@@ -2,7 +2,7 @@
//
// FILE: I2C_eeprom.h
// AUTHOR: Rob Tillaart
// VERSION: 1.4.1
// VERSION: 1.4.2
// PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al.
// URL: https://github.com/RobTillaart/I2C_EEPROM.git
//
@@ -13,7 +13,7 @@
#include "Wire.h"
#define I2C_EEPROM_VERSION (F("1.4.1"))
#define I2C_EEPROM_VERSION (F("1.4.2"))
#define I2C_DEVICESIZE_24LC512 65536
@@ -76,6 +76,10 @@ public:
// updates a byte at memory address, writes only if there is a new value.
// return 0 if data is same or written OK, error code otherwise.
int updateByte(const uint16_t memoryAddress, const uint8_t value);
// updates a block in memory, writes only if there is a new value.
// only to be used when you expect to write same buffer multiple times.
// test your performance gains!
int updateBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint16_t length);
uint32_t determineSize(const bool debug = false);
+14
View File
@@ -32,6 +32,7 @@ The **I2C_eeprom_cyclic_store** interface is documented [here](README_cyclic_sto
- **int writeByte(uint16_t memoryAddress, uint8_t value)** write a single byte to the specified memory address.
- **int updateByte(uint16_t memoryAddress, uint8_t value)** write a single byte, but only if changed. Returns 0 if value was same or write succeeded.
- **int writeBlock(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)** write a buffer starting at the specified memory address.
- **int updateBlock(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)** write a buffer starting at the specified memory address, but only if changed
- **int setBlock(uint16_t memoryAddress, uint8_t value, uint16_t length)** writes the same byte to length places starting at the specified memory address. Returns 0 if OK.
- **uint8_t readByte(uint16_t memoryAddress)** read a single byte from a given address
- **uint16_t readBlock(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)** read length bytes into buffer starting at specified memory address. Returns the number of bytes read, which should be length.
@@ -69,6 +70,18 @@ Testresults
The function cannot detect smaller than 128 bit EEPROMS.
#### UpdateBlock()
(new since 1.4.2)
The function **updateBlock()** reads the block of data and compares it with the new values to see if it needs rewriting.
As the function reads/writes the data in blocks with a maximum length of **I2C_TWIBUFFERSIZE** (== 30 AVR limitation) it does this comparison in chuncks if the length exceeds this number. The result is that an **updateBlock()** call can result e.g. in 4 reads and only 2 writes under the hood.
If data is changed often between writes, **updateBlock()** is slower than **writeBlock()**.
So you should verify if your sketch can make use of the advantages of **updateBlock()**
## Limitation
The library does not offer multiple EEPROMS as one continuous storage device.
@@ -79,6 +92,7 @@ The library does not offer multiple EEPROMS as one continuous storage device.
- improve error handling, write functions should return bytes written or so.
- what can we do with the print interface? (investigate)
- investigate multi-EEPROM storage,
- investigate smarter strategy for updateBlock() => find first and last changed position would possibly result in less writes.
## Operational
@@ -0,0 +1,77 @@
D:\Rob\WORK\Arduino\libraries\I2C_EEPROM\examples\I2C_eeprom_updateBlock\I2C_eeprom_updateBlock.ino
VERSION: 1.4.1
1
TEST: writeBlock() 32840
TEST: readBlock() 11792
TEST: updateBlock() 44672
2
TEST: writeBlock() 65720
TEST: readBlock() 23588
TEST: updateBlock() 60764
3
TEST: writeBlock() 98544
TEST: readBlock() 35384
TEST: updateBlock() 72628
4
TEST: writeBlock() 131348
TEST: readBlock() 47172
TEST: updateBlock() 84464
5
TEST: writeBlock() 164200
TEST: readBlock() 58976
TEST: updateBlock() 96340
6
TEST: writeBlock() 197068
TEST: readBlock() 70756
TEST: updateBlock() 108236
7
TEST: writeBlock() 229872
TEST: readBlock() 82576
TEST: updateBlock() 120072
8
TEST: writeBlock() 262684
TEST: readBlock() 94352
TEST: updateBlock() 131952
9
TEST: writeBlock() 295568
TEST: readBlock() 106144
TEST: updateBlock() 143808
10
TEST: writeBlock() 328388
TEST: readBlock() 117928
TEST: updateBlock() 155688
TEST: 100x writeBlock()
DUR1: 3284020
00000000 64 63 62 61 60 5F 5E 5D 5C 5B 5A 59 58 57 56 55
00000010 54 53 52 51 50 4F 4E 4D 4C 4B 4A 49 48 47 46 45
00000020 44 43 42 41 40 3F 3E 3D 3C 3B 3A 39 38 37 36 35
00000030 34 33 32 31 30 2F 2E 2D 2C 2B 2A 29 28 27 26 25
00000040 24 23 22 21 20 1F 1E 1D 1C 1B 1A 19 18 17 16 15
00000050 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05
00000060 04 03 02 01
TEST: 100x updateBlock()
DUR2: 1223896
00000000 64 63 62 61 60 5F 5E 5D 5C 5B 5A 59 58 57 56 55
00000010 54 53 52 51 50 4F 4E 4D 4C 4B 4A 49 48 47 46 45
00000020 44 43 42 41 40 3F 3E 3D 3C 3B 3A 39 38 37 36 35
00000030 34 33 32 31 30 2F 2E 2D 2C 2B 2A 29 28 27 26 25
00000040 24 23 22 21 20 1F 1E 1D 1C 1B 1A 19 18 17 16 15
00000050 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05
00000060 04 03 02 01
done...
@@ -0,0 +1,139 @@
//
// FILE: I2C_eeprom_updateBlock.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo I2C_EEPROM library - performance gain updateBlock
//
// uses a 24LC256 (32KB) EEPROM
// as this test writes a lot it might wear out EEPROMs eventually.
//
#include "Wire.h"
#include "I2C_eeprom.h"
I2C_eeprom ee(0x50, I2C_DEVICESIZE_24LC256);
uint32_t start, dur1, dur2;
uint8_t ar[100];
void setup()
{
Serial.begin(115200);
while (!Serial); // wait for SERIAL_OUT port to connect. Needed for Leonardo only
Serial.println(__FILE__);
Serial.print("VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
ee.begin();
if (! ee.isConnected())
{
Serial.println("ERROR: Can't find eeprom\nstopped...");
while (1);
}
for (int i = 0; i < 100; i++) ar[i] = 100 - i;
for (int i = 1; i < 11; i++)
{
test_1(i);
}
test_2();
Serial.println("\ndone...");
}
void loop()
{
}
void test_1(int n)
{
Serial.println(n);
Serial.print("TEST:\twriteBlock()");
delay(10);
ee.setBlock(0, 0, 100); // clear first 100 bytes
start = micros();
for (int i = 0; i < n; i++) ee.writeBlock(0, ar, 100);
dur1 = micros() - start;
Serial.print("\t");
Serial.println(dur1);
delay(10);
Serial.print("TEST:\treadBlock()");
delay(10);
start = micros();
for (int i = 0; i < n; i++) ee.readBlock(0, ar, 100);
dur1 = micros() - start;
Serial.print("\t");
Serial.println(dur1);
delay(10);
Serial.print("TEST:\tupdateBlock()");
delay(10);
ee.setBlock(0, 0, 100); // clear first 100 bytes
start = micros();
for (int i = 0; i < n; i++) ee.updateBlock(0, ar, 100);
dur1 = micros() - start;
Serial.print("\t");
Serial.println(dur1);
delay(10);
Serial.println();
}
void test_2()
{
Serial.println("\nTEST: 100x writeBlock()");
delay(10);
ee.setBlock(0, 0, 100); // clear first 100 bytes
start = micros();
for (int i = 0; i < 100; i++)
{
ee.writeBlock(0, ar, 100);
}
dur1 = micros() - start;
Serial.print("DUR1: ");
Serial.println(dur1);
dump(0, 100);
delay(100);
Serial.println("\nTEST: 100x updateBlock()");
ee.setBlock(0, 0, 100); // clear first 100 bytes
start = micros();
for (int i = 0; i < 100; i++)
{
ee.updateBlock(0, ar, 100);
}
dur2 = micros() - start;
Serial.print("DUR2: ");
Serial.println(dur2);
dump(0, 100);
delay(100);
}
void dump(uint32_t from, uint32_t to)
{
for (uint32_t i = from; i < to; i++) // I2C_DEVICESIZE_24LC512
{
char buffer[24];
if (i % 16 == 0)
{
char buffer[24];
Serial.print('\n');
sprintf(buffer, "%08lX\t", i);
Serial.print(buffer);
}
sprintf(buffer, "%02X\t", ee.readByte(i));
Serial.print(buffer);
}
Serial.println();
}
// -- END OF FILE
+1 -1
View File
@@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/I2C_EEPROM.git"
},
"version":"1.4.1",
"version":"1.4.2",
"frameworks": "arduino",
"platforms": "*"
}
+1 -1
View File
@@ -1,5 +1,5 @@
name=I2C_EEPROM
version=1.4.1
version=1.4.2
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Library for I2C EEPROMS