1.7.4 I2C_EEPROM

This commit is contained in:
Rob Tillaart 2023-09-08 11:35:43 +02:00
parent 711ddef9d7
commit 4b4a52c7f3
7 changed files with 174 additions and 22 deletions

View File

@ -6,13 +6,25 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/). and this project adheres to [Semantic Versioning](http://semver.org/).
## [1.7.4] - 2023-09-06
- solve #57 add support for WriteProtectPin
- add writeProtectPin as optional parameter in **begin()**
- add **bool hasWriteProtectPin()**
- add **void allowWrite()**
- add **void preventWrite()**
- add **void setAutoWriteProtect(bool b)**
- add **bool getAutoWriteProtect()**
- optimized **waitEEReady()**
- update keywords.txt
- update readme.md
## [1.7.3] - 2023-05-10 ## [1.7.3] - 2023-05-10
- fix #55 ==> redo fix #53 - fix #55 ==> redo fix #53
- add test to detect **MBED** and **RP2040** - add test to detect **MBED** and **RP2040**
- adjust **I2C_BUFFERSIZE** for RP2040 to 128. - adjust **I2C_BUFFERSIZE** for RP2040 to 128.
- update readme.md - update readme.md
## [1.7.2] - 2023-05-02 ## [1.7.2] - 2023-05-02
- fix #53 support RP2040 (kudos to jotamachuca) - fix #53 support RP2040 (kudos to jotamachuca)
- move code from .h to .cpp - move code from .h to .cpp

View File

@ -1,7 +1,7 @@
// //
// FILE: I2C_eeprom.cpp // FILE: I2C_eeprom.cpp
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 1.7.3 // VERSION: 1.7.4
// PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al. // PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al.
// URL: https://github.com/RobTillaart/I2C_EEPROM.git // URL: https://github.com/RobTillaart/I2C_EEPROM.git
@ -55,7 +55,7 @@ I2C_eeprom::I2C_eeprom(const uint8_t deviceAddress, const uint32_t deviceSize, T
#if defined(ESP8266) || defined(ESP32) #if defined(ESP8266) || defined(ESP32)
bool I2C_eeprom::begin(uint8_t sda, uint8_t scl) bool I2C_eeprom::begin(uint8_t sda, uint8_t scl, int8_t writeProtectPin)
{ {
// if (_wire == 0) Serial.println("zero"); // test #48 // if (_wire == 0) Serial.println("zero"); // test #48
if ((sda < 255) && (scl < 255)) if ((sda < 255) && (scl < 255))
@ -67,12 +67,18 @@ bool I2C_eeprom::begin(uint8_t sda, uint8_t scl)
_wire->begin(); _wire->begin();
} }
_lastWrite = 0; _lastWrite = 0;
_writeProtectPin = writeProtectPin;
if (_writeProtectPin >= 0)
{
pinMode(_writeProtectPin, OUTPUT);
preventWrite();
}
return isConnected(); return isConnected();
} }
#elif defined(ARDUINO_ARCH_RP2040) && !defined(__MBED__) #elif defined(ARDUINO_ARCH_RP2040) && !defined(__MBED__)
bool I2C_eeprom::begin(uint8_t sda, uint8_t scl) bool I2C_eeprom::begin(uint8_t sda, uint8_t scl, int8_t writeProtectPin)
{ {
if ((sda < 255) && (scl < 255)) if ((sda < 255) && (scl < 255))
{ {
@ -81,17 +87,29 @@ bool I2C_eeprom::begin(uint8_t sda, uint8_t scl)
_wire->begin(); _wire->begin();
} }
_lastWrite = 0; _lastWrite = 0;
_writeProtectPin = writeProtectPin;
if (_writeProtectPin >= 0)
{
pinMode(_writeProtectPin, OUTPUT);
preventWrite();
}
return isConnected(); return isConnected();
} }
#endif #endif
bool I2C_eeprom::begin() bool I2C_eeprom::begin(int8_t writeProtectPin)
{ {
// if (_wire == 0) Serial.println("zero"); // test #48 // if (_wire == 0) Serial.println("zero"); // test #48
_wire->begin(); _wire->begin();
_lastWrite = 0; _lastWrite = 0;
_writeProtectPin = writeProtectPin;
if (_writeProtectPin >= 0)
{
pinMode(_writeProtectPin, OUTPUT);
preventWrite();
}
return isConnected(); return isConnected();
} }
@ -399,6 +417,47 @@ uint8_t I2C_eeprom::getExtraWriteCycleTime()
} }
//
// WRITEPROTECT
//
bool I2C_eeprom::hasWriteProtectPin()
{
return (_writeProtectPin >= 0);
}
void I2C_eeprom::allowWrite()
{
if (hasWriteProtectPin())
{
digitalWrite(_writeProtectPin, LOW);
}
}
void I2C_eeprom::preventWrite()
{
if (hasWriteProtectPin())
{
digitalWrite(_writeProtectPin, HIGH);
}
}
void I2C_eeprom::setAutoWriteProtect(bool b)
{
if (hasWriteProtectPin())
{
_autoWriteProtect = b;
}
}
bool I2C_eeprom::getAutoWriteProtect()
{
return _autoWriteProtect;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// //
@ -457,10 +516,20 @@ void I2C_eeprom::_beginTransmission(const uint16_t memoryAddress)
int I2C_eeprom::_WriteBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint8_t length) int I2C_eeprom::_WriteBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint8_t length)
{ {
_waitEEReady(); _waitEEReady();
if (_autoWriteProtect)
{
digitalWrite(_writeProtectPin, LOW);
}
this->_beginTransmission(memoryAddress); this->_beginTransmission(memoryAddress);
_wire->write(buffer, length); _wire->write(buffer, length);
int rv = _wire->endTransmission(); int rv = _wire->endTransmission();
if (_autoWriteProtect)
{
digitalWrite(_writeProtectPin, HIGH);
}
_lastWrite = micros(); _lastWrite = micros();
yield(); // For OS scheduling yield(); // For OS scheduling
@ -529,9 +598,11 @@ void I2C_eeprom::_waitEEReady()
uint32_t waitTime = I2C_WRITEDELAY + _extraTWR * 1000UL; uint32_t waitTime = I2C_WRITEDELAY + _extraTWR * 1000UL;
while ((micros() - _lastWrite) <= waitTime) while ((micros() - _lastWrite) <= waitTime)
{ {
_wire->beginTransmission(_deviceAddress); if (isConnected()) return;
int x = _wire->endTransmission(); // TODO remove pre 1.7.4 code
if (x == 0) return; // _wire->beginTransmission(_deviceAddress);
// int x = _wire->endTransmission();
// if (x == 0) return;
yield(); // For OS scheduling yield(); // For OS scheduling
} }
return; return;

View File

@ -2,7 +2,7 @@
// //
// FILE: I2C_eeprom.h // FILE: I2C_eeprom.h
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 1.7.3 // VERSION: 1.7.4
// PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al. // PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al.
// URL: https://github.com/RobTillaart/I2C_EEPROM.git // URL: https://github.com/RobTillaart/I2C_EEPROM.git
@ -11,7 +11,7 @@
#include "Wire.h" #include "Wire.h"
#define I2C_EEPROM_VERSION (F("1.7.3")) #define I2C_EEPROM_VERSION (F("1.7.4"))
#define I2C_DEVICESIZE_24LC512 65536 #define I2C_DEVICESIZE_24LC512 65536
@ -63,10 +63,10 @@ public:
// MBED test ==> see #55, #53 // MBED test ==> see #55, #53
#if defined(ESP8266) || defined(ESP32) || (defined(ARDUINO_ARCH_RP2040) && !defined(__MBED__)) #if defined(ESP8266) || defined(ESP32) || (defined(ARDUINO_ARCH_RP2040) && !defined(__MBED__))
// set the I2C pins explicitly (overrule) // set the I2C pins explicitly (overrule)
bool begin(uint8_t sda, uint8_t scl); bool begin(uint8_t sda, uint8_t scl, int8_t writeProtectPin = -1);
#endif #endif
// use default I2C pins. // use default I2C pins.
bool begin(); bool begin(int8_t writeProtectPin = -1);
bool isConnected(); bool isConnected();
@ -127,6 +127,16 @@ public:
uint8_t getExtraWriteCycleTime(); uint8_t getExtraWriteCycleTime();
// WRITEPROTECT
// works only if WP pin is defined in begin().
// see readme.md
inline bool hasWriteProtectPin();
void allowWrite();
void preventWrite();
void setAutoWriteProtect(bool b);
bool getAutoWriteProtect();
private: private:
uint8_t _deviceAddress; uint8_t _deviceAddress;
uint32_t _lastWrite = 0; // for waitEEReady uint32_t _lastWrite = 0; // for waitEEReady
@ -134,6 +144,7 @@ private:
uint8_t _pageSize = 0; uint8_t _pageSize = 0;
uint8_t _extraTWR = 0; // milliseconds uint8_t _extraTWR = 0; // milliseconds
// 24LC32..24LC512 use two bytes for memory address // 24LC32..24LC512 use two bytes for memory address
// 24LC01..24LC16 use one-byte addresses + part of device address // 24LC01..24LC16 use one-byte addresses + part of device address
bool _isAddressSizeTwoWords; bool _isAddressSizeTwoWords;
@ -154,6 +165,9 @@ private:
bool _debug = false; bool _debug = false;
int8_t _writeProtectPin = -1;
bool _autoWriteProtect = false;
UNIT_TEST_FRIEND; UNIT_TEST_FRIEND;
}; };

View File

@ -37,6 +37,13 @@ getLastWrite KEYWORD2
setExtraWriteCycleTime KEYWORD2 setExtraWriteCycleTime KEYWORD2
getExtraWriteCycleTime KEYWORD2 getExtraWriteCycleTime KEYWORD2
hasWriteProtectPin KEYWORD2
allowWrite KEYWORD2
preventWrite KEYWORD2
setAutoWriteProtect KEYWORD2
getAutoWriteProtect KEYWORD2
# I2C_eeprom_cyclic_store # I2C_eeprom_cyclic_store
format KEYWORD2 format KEYWORD2
read KEYWORD2 read KEYWORD2

View File

@ -15,9 +15,9 @@
"type": "git", "type": "git",
"url": "https://github.com/RobTillaart/I2C_EEPROM.git" "url": "https://github.com/RobTillaart/I2C_EEPROM.git"
}, },
"version": "1.7.3", "version": "1.7.4",
"license": "MIT", "license": "MIT",
"frameworks": "arduino", "frameworks": "*",
"platforms": "*", "platforms": "*",
"headers": "I2C_eeprom.h" "headers": "I2C_eeprom.h"
} }

View File

@ -1,5 +1,5 @@
name=I2C_EEPROM name=I2C_EEPROM
version=1.7.3 version=1.7.4
author=Rob Tillaart <rob.tillaart@gmail.com> author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com> maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Library for I2C EEPROMS sentence=Library for I2C EEPROMS

View File

@ -2,8 +2,12 @@
[![Arduino CI](https://github.com/RobTillaart/I2C_EEPROM/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) [![Arduino CI](https://github.com/RobTillaart/I2C_EEPROM/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/I2C_EEPROM/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/I2C_EEPROM/actions/workflows/arduino-lint.yml) [![Arduino-lint](https://github.com/RobTillaart/I2C_EEPROM/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/I2C_EEPROM/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/I2C_EEPROM/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/I2C_EEPROM/actions/workflows/jsoncheck.yml) [![JSON check](https://github.com/RobTillaart/I2C_EEPROM/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/I2C_EEPROM/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/I2C_EEPROM.svg)](https://github.com/RobTillaart/I2C_EEPROM/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/I2C_EEPROM/blob/master/LICENSE) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/I2C_EEPROM/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/I2C_EEPROM.svg?maxAge=3600)](https://github.com/RobTillaart/I2C_EEPROM/releases) [![GitHub release](https://img.shields.io/github/release/RobTillaart/I2C_EEPROM.svg?maxAge=3600)](https://github.com/RobTillaart/I2C_EEPROM/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/I2C_EEPROM.svg)](https://registry.platformio.org/libraries/robtillaart/I2C_EEPROM)
# I2C_EEPROM # I2C_EEPROM
@ -67,13 +71,17 @@ Most important difference is 32 bit memory addresses.
optional Wire interface. optional Wire interface.
- **I2C_eeprom(uint8_t deviceAddress, uint32_t deviceSize, TwoWire \*wire = &Wire)** - **I2C_eeprom(uint8_t deviceAddress, uint32_t deviceSize, TwoWire \*wire = &Wire)**
constructor, with optional Wire interface. constructor, with optional Wire interface.
- **bool begin()** initializes the I2C bus with the default pins. - **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. Furthermore it checks if the deviceAddress is available on the I2C bus.
Returns true if deviceAddress is found on the bus, false otherwise. Returns true if deviceAddress is found on the bus, false otherwise.
- **bool begin(uint8_t sda, uint8_t scl)** for ESP32 / ESP8266 / RP2040 and alike. Optionally one can set the **WP** writeProtect pin. (see section below).
If the **WP** pin is defined the default will be to **not** allow writing.
- **bool begin(uint8_t sda, uint8_t scl, uint8_t writeProtectPin = -1)** for ESP32 / ESP8266 / RP2040 and alike.
Initializes the I2C bus with the specified pins, thereby overruling the default pins. Initializes the I2C bus with the specified pins, thereby overruling the default pins.
Furthermore it checks if the deviceAddress is available on the I2C bus. Furthermore it checks if the deviceAddress is available on the I2C bus.
Returns true if deviceAddress is found on the bus, false otherwise. Returns true if deviceAddress is found on the bus, false otherwise.
Optionally one can set the **WP** writeProtect pin. (see section below).
If the **WP** pin is defined the default will be to **not** allow writing.
- **bool isConnected()** test to see if deviceAddress is found on the bus. - **bool isConnected()** test to see if deviceAddress is found on the bus.
@ -162,7 +170,7 @@ returns set size == 128, 256, ... 32768, 65536
returns set size == 8, 16, 32, 64, 128. returns set size == 8, 16, 32, 64, 128.
#### UpdateBlock() ### UpdateBlock()
(new since 1.4.2) (new since 1.4.2)
@ -177,7 +185,7 @@ If data is changed often between writes, **updateBlock()** is slower than **writ
So you should verify if your sketch can make use of the advantages of **updateBlock()** So you should verify if your sketch can make use of the advantages of **updateBlock()**
#### ExtraWriteCycleTime (experimental) ### ExtraWriteCycleTime (experimental)
To improve support older I2C EEPROMs e.g. IS24C16 two functions were To improve support older I2C EEPROMs e.g. IS24C16 two functions were
added to increase the waiting time before a read and/or write as some added to increase the waiting time before a read and/or write as some
@ -191,6 +199,36 @@ Since 1.7.2 it is also possible to adjust the **I2C_WRITEDELAY** in the .h file
or overrule the define on the command line. or overrule the define on the command line.
### WriteProtectPin WP (experimental)
(since 1.7.4)
The library can control the **WP** = WriteProtect pin of the EEPROM.
To do this one should connect a GPIO pin of the MCU to the **WP** pin of the EEPROM.
Furthermore the **WP** should be defined as a parameter in **begin()**.
If the **WP** pin is defined the default will be to **not** allow writing.
The user has to enable writing either by manual or automatic control.
In the automatic mode the library only allows writing to the EEPROM when it
actually writes to the EEPROM.
So it keeps the EEPROM in a read only mode as much as possible.
This prevents accidental writes due to (noisy) signals on the I2C bus. (#57)
Status
- **bool hasWriteProtectPin()** returns true if **WP** has been set.
Automatic control
- **void setAutoWriteProtect(bool b)** if set to true, the library enables writing
only when the EEPROM is actually written. This setting **overrules** the manual control.
If **setAutoWriteProtect()** is set to false (== default) the manual control is leading.
- **bool getAutoWriteProtect()** get current setting.
Manual control
- **void allowWrite()** allows writing by setting **WP** to LOW.
- **void preventWrite()** disables writing by setting **WP** to HIGH.
## Limitation ## Limitation
The library does not offer multiple EEPROMS as one continuous storage device. The library does not offer multiple EEPROMS as one continuous storage device.
@ -220,10 +258,20 @@ See examples
- investigate smarter strategy for **updateBlock()** - investigate smarter strategy for **updateBlock()**
=> find first and last changed position could possibly result in less writes. => find first and last changed position could possibly result in less writes.
- can **setBlock()** use strategies from **updateBlock()** - can **setBlock()** use strategies from **updateBlock()**
- **\_waitEEReady();** can return bool and could use isConnected() internally.
- added value?
#### Wont
- investigate the print interface? - investigate the print interface?
- circular buffer? (see FRAM library) - circular buffer? (see FRAM library)
- dump function? - dump function?
#### Wont
## Support
If you appreciate my libraries, you can support the development and maintenance.
Improve the quality of the libraries by providing issues and Pull Requests, or
donate through PayPal or GitHub sponsors.
Thank you,