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/).
## [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
- fix #55 ==> redo fix #53
- add test to detect **MBED** and **RP2040**
- adjust **I2C_BUFFERSIZE** for RP2040 to 128.
- update readme.md
## [1.7.2] - 2023-05-02
- fix #53 support RP2040 (kudos to jotamachuca)
- move code from .h to .cpp

View File

@ -1,7 +1,7 @@
//
// FILE: I2C_eeprom.cpp
// AUTHOR: Rob Tillaart
// VERSION: 1.7.3
// VERSION: 1.7.4
// PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al.
// 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)
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 ((sda < 255) && (scl < 255))
@ -67,12 +67,18 @@ bool I2C_eeprom::begin(uint8_t sda, uint8_t scl)
_wire->begin();
}
_lastWrite = 0;
_writeProtectPin = writeProtectPin;
if (_writeProtectPin >= 0)
{
pinMode(_writeProtectPin, OUTPUT);
preventWrite();
}
return isConnected();
}
#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))
{
@ -81,17 +87,29 @@ bool I2C_eeprom::begin(uint8_t sda, uint8_t scl)
_wire->begin();
}
_lastWrite = 0;
_writeProtectPin = writeProtectPin;
if (_writeProtectPin >= 0)
{
pinMode(_writeProtectPin, OUTPUT);
preventWrite();
}
return isConnected();
}
#endif
bool I2C_eeprom::begin()
bool I2C_eeprom::begin(int8_t writeProtectPin)
{
// if (_wire == 0) Serial.println("zero"); // test #48
_wire->begin();
_lastWrite = 0;
_writeProtectPin = writeProtectPin;
if (_writeProtectPin >= 0)
{
pinMode(_writeProtectPin, OUTPUT);
preventWrite();
}
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)
{
_waitEEReady();
if (_autoWriteProtect)
{
digitalWrite(_writeProtectPin, LOW);
}
this->_beginTransmission(memoryAddress);
_wire->write(buffer, length);
int rv = _wire->endTransmission();
if (_autoWriteProtect)
{
digitalWrite(_writeProtectPin, HIGH);
}
_lastWrite = micros();
yield(); // For OS scheduling
@ -529,9 +598,11 @@ void I2C_eeprom::_waitEEReady()
uint32_t waitTime = I2C_WRITEDELAY + _extraTWR * 1000UL;
while ((micros() - _lastWrite) <= waitTime)
{
_wire->beginTransmission(_deviceAddress);
int x = _wire->endTransmission();
if (x == 0) return;
if (isConnected()) return;
// TODO remove pre 1.7.4 code
// _wire->beginTransmission(_deviceAddress);
// int x = _wire->endTransmission();
// if (x == 0) return;
yield(); // For OS scheduling
}
return;

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
name=I2C_EEPROM
version=1.7.3
version=1.7.4
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
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-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)
[![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)
[![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
@ -67,13 +71,17 @@ Most important difference is 32 bit memory addresses.
optional Wire interface.
- **I2C_eeprom(uint8_t deviceAddress, uint32_t deviceSize, TwoWire \*wire = &Wire)**
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.
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.
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).
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.
@ -162,7 +170,7 @@ returns set size == 128, 256, ... 32768, 65536
returns set size == 8, 16, 32, 64, 128.
#### UpdateBlock()
### UpdateBlock()
(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()**
#### ExtraWriteCycleTime (experimental)
### ExtraWriteCycleTime (experimental)
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
@ -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.
### 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
The library does not offer multiple EEPROMS as one continuous storage device.
@ -220,10 +258,20 @@ See examples
- investigate smarter strategy for **updateBlock()**
=> find first and last changed position could possibly result in less writes.
- can **setBlock()** use strategies from **updateBlock()**
- **\_waitEEReady();** can return bool and could use isConnected() internally.
- added value?
#### Wont
- investigate the print interface?
- circular buffer? (see FRAM library)
- 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,