Skip to content

Commit

Permalink
add WP writeProtect support (#58)
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
RobTillaart authored Sep 8, 2023
1 parent a13ec20 commit e7c5075
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 22 deletions.
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
85 changes: 78 additions & 7 deletions I2C_eeprom.cpp
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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))
Expand All @@ -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))
{
Expand All @@ -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();
}

Expand Down Expand Up @@ -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;
}


////////////////////////////////////////////////////////////////////
//
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
22 changes: 18 additions & 4 deletions I2C_eeprom.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand Down Expand Up @@ -63,10 +63,10 @@ class I2C_eeprom
// 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();


Expand Down Expand Up @@ -127,13 +127,24 @@ class I2C_eeprom
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
uint32_t _deviceSize = 0;
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;
Expand All @@ -154,6 +165,9 @@ class I2C_eeprom

bool _debug = false;

int8_t _writeProtectPin = -1;
bool _autoWriteProtect = false;

UNIT_TEST_FRIEND;
};

Expand Down
62 changes: 55 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.


Expand Down Expand Up @@ -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)

Expand All @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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,

7 changes: 7 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions library.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -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
Expand Down

0 comments on commit e7c5075

Please sign in to comment.