fix #83, update readme.md (#85)

- fix #83, update readme.md (thanks to TonyRiddiough)
- add calculatePageSize(deviceSize) to replace getPageSize(deviceSize) prep.
- update GitHub actions
- minor update examples
- minor edits
This commit is contained in:
Rob Tillaart
2025-09-01 10:05:59 +02:00
committed by GitHub
parent 86228c599f
commit 86a5017fa9
23 changed files with 169 additions and 81 deletions
+2 -2
View File
@@ -6,8 +6,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: arduino/arduino-lint-action@v1
- uses: actions/checkout@v5
- uses: arduino/arduino-lint-action@v2
with:
library-manager: update
compliance: strict
+1 -1
View File
@@ -8,7 +8,7 @@ jobs:
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
+3 -1
View File
@@ -5,13 +5,15 @@ on:
paths:
- '**.json'
pull_request:
paths:
- '**.json'
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: json-syntax-check
uses: limitusus/json-syntax-check@v2
with:
+7 -1
View File
@@ -6,10 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [1.9.4] - 2025-08-27
- fix #83, update readme.md (thanks to TonyRiddiough)
- add calculatePageSize(deviceSize) to replace getPageSize(deviceSize) prep.
- update GitHub actions
- minor update examples
- minor edits
## [1.9.3] - 2025-08-01
- update readme.md
## [1.9.2] - 2024-11-25
- fix #79, wrong default in constructor - kudos to ekinohito
+11 -4
View File
@@ -45,7 +45,7 @@ I2C_eeprom::I2C_eeprom(const uint8_t deviceAddress, const uint32_t deviceSize, T
{
_deviceAddress = deviceAddress;
_deviceSize = setDeviceSize(deviceSize);
_pageSize = getPageSize(_deviceSize);
_pageSize = calculatePageSize(_deviceSize);
_wire = wire;
// Chips 16 Kbit (2048 Bytes) or smaller only have one-word addresses.
@@ -433,7 +433,7 @@ uint8_t I2C_eeprom::getPageSize()
}
uint8_t I2C_eeprom::getPageSize(uint32_t deviceSize)
uint8_t I2C_eeprom::calculatePageSize(uint32_t deviceSize)
{
// determine page size from device size
// based on Microchip 24LCXX data sheets.
@@ -441,8 +441,15 @@ uint8_t I2C_eeprom::getPageSize(uint32_t deviceSize)
if (deviceSize <= I2C_DEVICESIZE_24LC16) return 16;
if (deviceSize <= I2C_DEVICESIZE_24LC64) return 32;
if (deviceSize <= I2C_DEVICESIZE_24LC256) return 64;
// I2C_DEVICESIZE_24LC512
return 128;
if (deviceSize <= I2C_DEVICESIZE_24LC512) return 128;
// Error.
return 0;
}
uint8_t I2C_eeprom::getPageSize(uint32_t deviceSize)
{
return calculatePageSize(deviceSize);
}
+8 -6
View File
@@ -2,7 +2,7 @@
//
// FILE: I2C_eeprom.h
// AUTHOR: Rob Tillaart
// VERSION: 1.9.3
// VERSION: 1.9.4
// PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al.
// URL: https://github.com/RobTillaart/I2C_EEPROM
@@ -11,7 +11,7 @@
#include "Wire.h"
#define I2C_EEPROM_VERSION (F("1.9.3"))
#define I2C_EEPROM_VERSION (F("1.9.4"))
#define I2C_DEVICESIZE_24LC512 65536
#define I2C_DEVICESIZE_24LC256 32768
@@ -74,17 +74,17 @@ public:
* It will try to guess page size and address word size based on the size of the device.
*
* @param deviceAddress Byte address of the device.
* @param deviceSize Max size in bytes of the device (divide your device size in Kbits by 8)
* @param deviceSize Max size in bytes of the device (divide your device size in Kbits by 8 to get Kbytes)
* @param wire Select alternative Wire interface
*/
I2C_eeprom(const uint8_t deviceAddress, const uint32_t deviceSize, TwoWire *wire = &Wire);
// use default I2C pins.
bool begin(int8_t writeProtectPin = -1);
bool isConnected();
uint8_t getAddress();
// user is responsible that address is in range of the EEPROM used.
// writes a byte to memoryAddress
// returns I2C status, 0 = OK
int writeByte(const uint16_t memoryAddress, const uint8_t value);
@@ -123,11 +123,13 @@ public:
// Meta data functions
uint32_t determineSize(const bool debug = false);
uint32_t determineSizeNoWrite();
uint32_t getDeviceSize();
uint8_t getPageSize();
uint8_t calculatePageSize(uint32_t deviceSize);
[[deprecated("Use calculatePageSize(deviceSize) instead.")]]
uint8_t getPageSize(uint32_t deviceSize);
uint32_t determineSizeNoWrite();
uint32_t determineSize(const bool debug = false);
uint32_t getLastWrite();
+1
View File
@@ -5,6 +5,7 @@
// VERSION: 1.0.0
// PURPOSE: Supplemental utility class for I2C_EEPROM library
//
// URL: https://github.com/RobTillaart/I2C_EEPROM
#include <I2C_eeprom.h>
+75 -34
View File
@@ -17,34 +17,42 @@ Arduino Library for external I2C EEPROM - 24LC512, 24LC256, 24LC64/32/16/08/04/0
## Description
This library is to access the external I2C EEPROM up to 64KB (= 512 Kbit) in size.
MicroChip 24LC512, 24LC256, 24LC64, 24LC32, 24LC16, 24LC08, 24LC04, 24LC02, 24LC01 and equivalents.
This library is used to access an external I2C EEPROM up to 64KB (= 512 Kbit) in size.
The MicroChip 24LC512, 24LC256, 24LC64, 24LC32, 24LC16, 24LC08, 24LC04, 24LC02, 24LC01
and equivalents are tested and working.
Also confirmed working M24512-W, M24512-R, M24512-DF (See #68).
Not supported is the identification page functions.
Not supported are the identification page functions.
The **I2C_eeprom_cyclic_store** interface is documented [here](README_cyclic_store.md)
**Warning**
The user is responsible to verify the used memoryAddress (range) exists in the used EEPROM. (read / write / verify functions).
The library does not check this. If the address is larger than the EEPROM size,
the address used will probably be memoryAddress % deviceSize.
### RP2040
There are at least two boards modules for the RP2040 that use a different Wire libraries.
There are at least two boards modules for the RP2040 that use different Wire libraries.
One from "Earle F. Philhower" and an "MBED" one. See issues #53 and #55 for details.
In 1.7.3 defines are checked to select between these two and as far as tested this seems
to solve the issue #53 while being backwards compatible.
If a better solution is found, it will be implemented.
### Breaking change
### Breaking change 1.9.0
Version 1.9.0 fixed a memory leak in **verifyBlock()**.
### Breaking change 1.8.0
Version 1.8.0 introduced a breaking change.
You cannot set the pins in **begin()** any more.
This reduces the dependency of processor dependent Wire implementations.
You cannot set the I2C pins in **begin()** any more.
This reduces the dependency of processor dependent Wire (I2C) implementations.
The user has to call **Wire.begin()** and can optionally set the Wire pins
before calling **I2C_eeprom.begin()**.
(if the board supports this), before calling **I2C_eeprom.begin()**.
### Related
@@ -56,6 +64,8 @@ before calling **I2C_eeprom.begin()**.
## Schematic
Verify the datasheet for your specific EEPROM.
```cpp
+---U---+
A0 | 1 8 | VCC = 1.7V to 5.5V
@@ -70,7 +80,7 @@ before calling **I2C_eeprom.begin()**.
I2C address = 0x50 .. 0x57 depending on three address lines (A0, A1, A2).
Read the datasheet, section device addressing.
Read the datasheet of your specific EEPROM, section device addressing.
### I2C multiplexing
@@ -91,7 +101,6 @@ too if they are behind the multiplexer.
- https://github.com/RobTillaart/TCA9548
## Interface
```cpp
@@ -101,22 +110,46 @@ too if they are behind the multiplexer.
The interface is kept quite identical to the I2C_24LC1025 library.
https://github.com/RobTillaart/I2C_24LC1025
Most important difference is 32 bit memory addresses.
Most important difference is that the latter uses 32 bit memory addresses.
### Constructor
- **I2C_eeprom(uint8_t deviceAddress, TwoWire \*wire = &Wire)** constructor,
optional Wire interface.
- **I2C_eeprom(uint8_t deviceAddress, TwoWire \*wire = &Wire)** constructor, to set the
device address and optional Wire interface. The deviceSize == I2C_DEVICESIZE_24LC256 (32KB)
is used as it is the most often used I2C_EEPROM size.
Be aware that if you use other sized EEPROMs you have to use the next constructor,
and name the deviceSize explicitly, otherwise errors might occur.
- **I2C_eeprom(uint8_t deviceAddress, uint32_t deviceSize, TwoWire \*wire = &Wire)**
constructor, with optional Wire interface.
- **bool begin(uint8_t writeProtectPin = -1)** initializes the I2C bus with the default pins.
Furthermore it checks if the deviceAddress is available on the I2C bus.
Returns true if deviceAddress is found on the bus, false otherwise.
Optionally one can set the **WP** writeProtect pin. (see section below).
constructor, idem as above, furthermore the deviceSize can be any of the defines in the
table below or its number equivalent.
The Wire interface is optional, default Wire.
- **bool begin(uint8_t writeProtectPin = -1)** Optionally one can set the **WP**
writeProtect pin. (see section below).
If the **WP** pin is defined, the default behaviour will be to **not** allow writing.
- **bool isConnected()** test to see if deviceAddress is found on the bus.
Furthermore it checks if the deviceAddress given in the constructor is available
on the defined I2C bus.
Returns true if deviceAddress is found on the I2C bus, false otherwise.
- **bool isConnected()** returns true if the address given in the constructor is
available on the defined I2C bus.
- **uint8_t getAddress()** returns deviceAddress set in the constructor.
Convenience.
Defined device sizes for constructor, more details see below.
| Define | bytes | Notes |
|:-------------------------|--------:|:--------|
| I2C_DEVICESIZE_24LC512 | 65536 |
| I2C_DEVICESIZE_24LC256 | 32768 | most used
| I2C_DEVICESIZE_24LC128 | 16384 |
| I2C_DEVICESIZE_24LC64 | 8192 |
| I2C_DEVICESIZE_24LC32 | 4096 |
| I2C_DEVICESIZE_24LC16 | 2048 |
| I2C_DEVICESIZE_24LC08 | 1024 |
| I2C_DEVICESIZE_24LC04 | 512 |
| I2C_DEVICESIZE_24LC02 | 256 |
| I2C_DEVICESIZE_24LC01 | 128 |
### Write functions
@@ -134,8 +167,11 @@ Returns I2C status, 0 = OK.
### Update functions
Using update instead of write functions does not write if the value is the same.
The price is an extra read() call, but if there is no change the gain is performance.
- **int updateByte(uint16_t memoryAddress, uint8_t value)** write a single byte,
but only if changed.
but only if the value has changed.
Returns 0 if value was same or write succeeded.
- **uint16_t updateBlock(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
write a buffer starting at the specified memory address, but only if changed.
@@ -148,6 +184,7 @@ Returns bytes actually written <= length.
- **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.
The user is responsible that the used buffer can hold length bytes.
### Verify functions
@@ -155,6 +192,7 @@ Returns the number of bytes read, which should be length.
Since 1.6.0. - experimental, needs extensive testing.
Same as write and update functions above. Returns true if successful, false indicates an error.
The user is responsible that the used buffer can hold length bytes.
- **bool writeByteVerify(uint16_t memoryAddress, uint8_t value)**
- **bool writeBlockVerify(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
@@ -162,15 +200,17 @@ Same as write and update functions above. Returns true if successful, false indi
- **bool updateByteVerify(uint16_t memoryAddress, uint8_t value)**
- **bool updateBlockVerify(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
- **bool verifyBlock(uint16_t memoryAddress, uint8_t \* buffer, uint16_t length)**
Returns true is buffer equals memoryAddres for length bytes.
Returns true is buffer equals memoryAddress for length bytes.
### Other
- **uint32_t getDeviceSize()** idem
- **uint8_t getPageSize()** idem
- **uint8_t getPageSize(uint32_t deviceSize)** idem
- **uint32_t getLastWrite()** idem
- **uint32_t getDeviceSize()** returns the current set deviceSize.
- **uint8_t getPageSize()** returns the current set pageSize.
- **uint8_t calculatePageSize(uint32_t deviceSize)** calculates the pageSize of a device
with deviceSize. Note it does not set the pageSize!
- **uint8_t getPageSize(uint32_t deviceSize)** deprecated, wrapper around calculatePageSize().
- **uint32_t getLastWrite()** returns timestamp in millis since start of program.
- **uint32_t determineSizeNoWrite()** function that determines the size of the EEPROM
by detecting when a selected memory address is not readable. (new in 1.8.1).
- **uint32_t determineSize(bool debug = false)**
@@ -178,7 +218,6 @@ function that determines the size of the EEPROM by detecting when a memory addre
is folded upon memory address 0.
It is based upon the observation that memory wraps around.
The debug flag prints some output to Serial.
**Warning**: this function has changed (again) in 1.4.0
Test results **determineSize()**
@@ -216,7 +255,7 @@ The function **updateBlock()** reads the block of data and compares it with the
As the function reads/writes the data in blocks with a maximum length of **I2C_TWIBUFFERSIZE**
(== 30 AVR limitation; 128 for ESP32)
It does this comparison in chunks if the length exceeds this number.
It does this comparison in chunks if the length exceeds the length of the I2C buffer.
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()**.
@@ -280,11 +319,12 @@ The library does not offer multiple EEPROMS as one continuous storage device.
#### Should
- investigate multi-EEPROM storage
- wrapper class?
- improve error handling,
- write functions should return bytes written or so.
- make deviceSize explicit in examples?
- investigate multi-EEPROM storage ==> wrapper class!
- improve error handling
- address range check in begin
- write functions should return bytes written (like Print() does)
now they return I2C status... => error / status.
- remove uint8_t getPageSize(uint32_t deviceSize) in 0.2.0. now deprecated.
#### Could
@@ -292,7 +332,8 @@ The library does not offer multiple EEPROMS as one continuous storage device.
=> find first and last changed position could possibly result in less writes.
- can **setBlock()** use strategies from **updateBlock()**
- **pageBlock()**: incrBuffer is an implementation name, not a functional name.
- replace defines with const uint8_t / const uint16_t to force type checking?
- sync order .h file and readme.md.
#### Wont
@@ -30,7 +30,12 @@ I2C_eeprom_cyclic_store<SampleData> cs;
void setup()
{
Serial.begin(115200);
while(!Serial);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println();
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
Wire.begin();
@@ -45,9 +50,9 @@ void setup()
sprintf(data.message, "Initialized to %x", data.counter);
cs.write(data);
}
}
void loop()
{
Serial.println(data.message);
@@ -18,9 +18,11 @@ void setup()
{
Serial.begin(115200);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println();
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
Wire.begin();
@@ -58,7 +60,7 @@ void setup()
}
Serial.print("PAGE: ");
uint8_t pageSize = ee.getPageSize(size);
uint8_t pageSize = ee.calculatePageSize(size);
Serial.print(pageSize);
Serial.println(" bytes.");
@@ -18,9 +18,11 @@ void setup()
{
Serial.begin(115200);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println();
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
Wire.begin();
@@ -66,7 +68,7 @@ void setup()
}
Serial.print("PAGE: ");
uint8_t pageSize = ee.getPageSize(size);
uint8_t pageSize = ee.calculatePageSize(size);
Serial.print(pageSize);
Serial.println(" bytes.");
@@ -18,9 +18,11 @@ void setup()
{
Serial.begin(115200);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println();
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
Wire.begin();
@@ -6,7 +6,6 @@
//
// uses a 24LC256 (32KB) EEPROM
// as this test writes a lot it might wear out EEPROMs eventually.
//
#include "Wire.h"
@@ -29,9 +28,11 @@ void setup()
{
Serial.begin(115200);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println();
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
Wire.begin();
+4 -3
View File
@@ -18,8 +18,7 @@
// #define SERIAL_OUT SerialUSB
I2C_eeprom ee(0x50);
// I2C_eeprom ee(0x50, I2C_DEVICESIZE_24LC256);
I2C_eeprom ee(0x50, I2C_DEVICESIZE_24LC256);
uint32_t start, diff, totals = 0;
@@ -28,9 +27,11 @@ void setup()
{
SERIAL_OUT.begin(115200);
while (!SERIAL_OUT); // wait for SERIAL_OUT port to connect. Needed for Leonardo only
SERIAL_OUT.println();
SERIAL_OUT.println(__FILE__);
SERIAL_OUT.print("I2C_EEPROM_VERSION: ");
SERIAL_OUT.println(I2C_EEPROM_VERSION);
SERIAL_OUT.println();
Wire.begin();
@@ -200,7 +201,7 @@ void setup()
SERIAL_OUT.println(totals);
totals = 0;
// does it go well?
// did it go well?
SERIAL_OUT.println(xx);
SERIAL_OUT.println("\tDone...");
@@ -18,9 +18,11 @@ void setup()
{
Serial.begin(115200);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println();
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
Wire.begin();
@@ -140,7 +142,7 @@ void test()
Serial.println(totals);
totals = 0;
// does it go well?
// did it go well?
Serial.println(xx);
}
@@ -20,9 +20,11 @@ void setup()
{
Serial.begin(115200);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println();
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
Wire.begin();
@@ -23,9 +23,11 @@ void setup()
{
Serial.begin(115200);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println();
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
Wire.begin();
@@ -21,9 +21,11 @@ void setup()
{
Serial.begin(115200);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println();
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
Wire.begin();
@@ -20,9 +20,11 @@ void setup()
{
Serial.begin(115200);
while (!Serial); // wait for Serial port to connect. Needed for Leonardo only
Serial.println();
Serial.println(__FILE__);
Serial.print("I2C_EEPROM_VERSION: ");
Serial.println(I2C_EEPROM_VERSION);
Serial.println();
Wire.begin();
@@ -96,5 +98,4 @@ void disrupt(uint8_t location)
}
// -- END OF FILE --
@@ -1,12 +1,13 @@
//
// FILE: I2C_small_eeprom_test.ino
// AUTHOR: Tyler Freeman
// VERSION: 0.1.1
// VERSION: 0.1.2
// PURPOSE: show/test I2C_EEPROM library with small EEPROMS
// URL: https://github.com/RobTillaart/I2C_EEPROM
// HISTORY
// 0.1.0 2014-05-xx initial version
// 0.1.1 2020-07-14 fix #1 compile for ESP; fix author
// 0.1.2 2025-08-27 add print filename and version number of library
#include <Wire.h>
@@ -102,6 +103,11 @@ void setup()
{
SERIAL_DEBUG.begin(57600);
while (!SERIAL_DEBUG); // wait for SERIAL_DEBUG port to connect. Needed for Leonardo only
SERIAL_DEBUG.println();
SERIAL_DEBUG.println(__FILE__);
SERIAL_DEBUG.print("I2C_EEPROM_VERSION: ");
SERIAL_DEBUG.println(I2C_EEPROM_VERSION);
SERIAL_DEBUG.println();
SERIAL_DEBUG.println("IT IS BEGINNING");
SERIAL_DEBUG.println("WAIT FOR IT");
+1
View File
@@ -34,6 +34,7 @@ determineSize KEYWORD2
determineSizeNoWrite KEYWORD2
getDeviceSize KEYWORD2
getPageSize KEYWORD2
calculatePageSize KEYWORD2
getLastWrite KEYWORD2
setDeviceSize KEYWORD2
+1 -1
View File
@@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/I2C_EEPROM.git"
},
"version": "1.9.3",
"version": "1.9.4",
"license": "MIT",
"frameworks": "*",
"platforms": "*",
+1 -1
View File
@@ -1,5 +1,5 @@
name=I2C_EEPROM
version=1.9.3
version=1.9.4
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Library for I2C EEPROMS