Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #70, increase internal lengths allowed #71

Merged
merged 3 commits into from
Apr 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).


## [1.8.4] - 2024-04-20
- Fix #70, increase length internal buffer.
- add compile time flag **EN_AUTO_WRITE_PROTECT** (thanks to microfoundry)
- improve readability: cnt => count addr => address
- add URL to examples
- minor edits.


## [1.8.3] - 2024-03-28
- Fix #64, compiler warning.
- add **verifyBlock(memoryAddress, buffer, length)**
Expand All @@ -15,7 +23,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- update examples
- update readme.md


## [1.8.2] - 2024-01-02
- updated **uint32_t determineSizeNoWrite()**, kudos to roelandkluit
- minor edits
Expand Down
141 changes: 73 additions & 68 deletions I2C_eeprom.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
//
// FILE: I2C_eeprom.cpp
// AUTHOR: Rob Tillaart
// VERSION: 1.8.3
// VERSION: 1.8.4
// 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


#include "I2C_eeprom.h"
Expand Down Expand Up @@ -60,6 +60,7 @@ bool I2C_eeprom::begin(int8_t writeProtectPin)
_writeProtectPin = writeProtectPin;
if (_writeProtectPin >= 0)
{
_autoWriteProtect = EN_AUTO_WRITE_PROTECT;
pinMode(_writeProtectPin, OUTPUT);
preventWrite();
}
Expand Down Expand Up @@ -131,38 +132,38 @@ uint8_t I2C_eeprom::readByte(const uint16_t memoryAddress)
// returns bytes read.
uint16_t I2C_eeprom::readBlock(const uint16_t memoryAddress, uint8_t * buffer, const uint16_t length)
{
uint16_t addr = memoryAddress;
uint16_t address = memoryAddress;
uint16_t len = length;
uint16_t rv = 0;
uint16_t bytes = 0;
while (len > 0)
{
uint8_t cnt = I2C_BUFFERSIZE;
if (cnt > len) cnt = len;
rv += _ReadBlock(addr, buffer, cnt);
addr += cnt;
buffer += cnt;
len -= cnt;
uint8_t count = I2C_BUFFERSIZE;
if (count > len) count = len;
bytes += _ReadBlock(address, buffer, count);
address += count;
buffer += count;
len -= count;
}
return rv;
return bytes;
}


// returns true or false.
bool I2C_eeprom::verifyBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length)
{
uint16_t addr = memoryAddress;
uint16_t address = memoryAddress;
uint16_t len = length;
while (len > 0)
{
uint8_t cnt = I2C_BUFFERSIZE;
if (cnt > len) cnt = len;
if (_verifyBlock(addr, buffer, cnt) == false)
uint8_t count = I2C_BUFFERSIZE;
if (count > len) count = len;
if (_verifyBlock(address, buffer, count) == false)
{
return false;
}
addr += cnt;
buffer += cnt;
len -= cnt;
address += count;
buffer += count;
len -= count;
}
return true;
}
Expand All @@ -184,25 +185,25 @@ int I2C_eeprom::updateByte(const uint16_t memoryAddress, const uint8_t data)
// returns bytes written.
uint16_t I2C_eeprom::updateBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length)
{
uint16_t addr = memoryAddress;
uint16_t address = memoryAddress;
uint16_t len = length;
uint16_t rv = 0;
uint16_t bytes = 0;
while (len > 0)
{
uint8_t buf[I2C_BUFFERSIZE];
uint8_t cnt = I2C_BUFFERSIZE;
uint8_t count = I2C_BUFFERSIZE;

if (cnt > len) cnt = len;
rv += _ReadBlock(addr, buf, cnt);
if (memcmp(buffer, buf, cnt) != 0)
if (count > len) count = len;
bytes += _ReadBlock(address, buf, count);
if (memcmp(buffer, buf, count) != 0)
{
_pageBlock(addr, buffer, cnt, true);
_pageBlock(address, buffer, count, true);
}
addr += cnt;
buffer += cnt;
len -= cnt;
address += count;
buffer += count;
len -= count;
}
return rv;
return bytes;
}


Expand Down Expand Up @@ -305,12 +306,12 @@ uint32_t I2C_eeprom::determineSize(const bool debug)
uint8_t buf = readByte(size);

// test folding
uint8_t cnt = 0;
uint8_t count = 0;
writeByte(size, pat55);
if (readByte(0) == pat55) cnt++;
if (readByte(0) == pat55) count++;
writeByte(size, patAA);
if (readByte(0) == patAA) cnt++;
folded = (cnt == 2);
if (readByte(0) == patAA) count++;
folded = (count == 2);
if (debug)
{
SPRNH(size, HEX);
Expand All @@ -327,6 +328,7 @@ uint32_t I2C_eeprom::determineSize(const bool debug)
return 0;
}


// new 1.8.1 #61
// updated 1.8.2 #63
//
Expand All @@ -344,7 +346,7 @@ uint32_t I2C_eeprom::determineSizeNoWrite()
if (!isConnected()) return 0;

bool addressSize = _isAddressSizeTwoWords;
_isAddressSizeTwoWords = true; //Otherwise reading large EEPROMS fails
_isAddressSizeTwoWords = true; // Otherwise reading large EEPROMS fails
bool isModifiedFirstSector = false;
bool dataIsDifferent = false;

Expand All @@ -356,8 +358,8 @@ uint32_t I2C_eeprom::determineSizeNoWrite()
{
if (dataIsDifferent || pos == 0)
{
//ignore futher comparison if dataFirstBytes is not the same in buffer
//Ignore first byte
// ignore further comparison if dataFirstBytes is not the same in buffer
// Ignore first byte
}
else if (dataFirstBytes[pos - 1] != dataFirstBytes[pos])
{
Expand All @@ -366,7 +368,7 @@ uint32_t I2C_eeprom::determineSizeNoWrite()

if (dataFirstBytes[pos] != 0xFF && dataFirstBytes[pos] != 0x00)
{
//Default dataFirstBytes value is 0xFF or 0x00
// Default dataFirstBytes value is 0xFF or 0x00
isModifiedFirstSector = true;
}

Expand All @@ -376,31 +378,34 @@ uint32_t I2C_eeprom::determineSizeNoWrite()

if (!isModifiedFirstSector)
{
//Cannot determine diff, at least one of the first bytes within 0 - len [BUFSIZE] needs to be changed.
//to something other than 0x00 and 0xFF
// Cannot determine diff, at least one of the first bytes within 0 - len [BUFSIZE] needs to be changed
// to something other than 0x00 and 0xFF
_isAddressSizeTwoWords = addressSize;
return 1;
}
if (!dataIsDifferent)
{
//Data in first bytes within 0 - len [BUFSIZE] are all the same.
// Data in first bytes within 0 - len [BUFSIZE] are all the same.
_isAddressSizeTwoWords = addressSize;
return 2;
}

//Read from larges to smallest size
// Read from largest to smallest size
for (uint32_t size = 32768; size >= 64; size /= 2)
{
_isAddressSizeTwoWords = (size >= I2C_DEVICESIZE_24LC16); // == 2048

// Try to read last byte of the block, should return length of 0 when fails for single byte devices
// Will return the same dataFirstBytes as initialy read on other devices as the datapointer could not be moved to the requested position
// Try to read last byte of the block, should return length of 0 when fails for single byte devices
// Will return the same dataFirstBytes as initially read on other devices
// as the data pointer could not be moved to the requested position
delay(2);
uint16_t bSize = readBlock(size, dataMatch, BUFSIZE);

if (bSize == BUFSIZE && memcmp(dataFirstBytes, dataMatch, BUFSIZE) != 0)
{
//Read is perfomed just over size (size + BUFSIZE), this will only work for devices with mem > size; therefore return size * 2
// Read is performed just over size (size + BUFSIZE),
// this will only work for devices with mem > size;
// therefore return size * 2
_isAddressSizeTwoWords = addressSize;
return size * 2;
}
Expand Down Expand Up @@ -542,22 +547,22 @@ bool I2C_eeprom::getAutoWriteProtect()
// returns 0 = OK otherwise error
int I2C_eeprom::_pageBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length, const bool incrBuffer)
{
uint16_t addr = memoryAddress;
uint16_t address = memoryAddress;
uint16_t len = length;
while (len > 0)
{
uint8_t bytesUntilPageBoundary = this->_pageSize - addr % this->_pageSize;
uint8_t bytesUntilPageBoundary = this->_pageSize - address % this->_pageSize;

uint8_t cnt = I2C_BUFFERSIZE;
if (cnt > len) cnt = len;
if (cnt > bytesUntilPageBoundary) cnt = bytesUntilPageBoundary;
uint8_t count = I2C_BUFFERSIZE;
if (count > len) count = len;
if (count > bytesUntilPageBoundary) count = bytesUntilPageBoundary;

int rv = _WriteBlock(addr, buffer, cnt);
int rv = _WriteBlock(address, buffer, count);
if (rv != 0) return rv;

addr += cnt;
if (incrBuffer) buffer += cnt;
len -= cnt;
address += count;
if (incrBuffer) buffer += count;
len -= count;
}
return 0;
}
Expand All @@ -574,8 +579,8 @@ void I2C_eeprom::_beginTransmission(const uint16_t memoryAddress)
}
else
{
uint8_t addr = _deviceAddress | ((memoryAddress >> 8) & 0x07);
_wire->beginTransmission(addr);
uint8_t address = _deviceAddress | ((memoryAddress >> 8) & 0x07);
_wire->beginTransmission(address);
}

// Address Low Byte
Expand All @@ -586,7 +591,7 @@ void I2C_eeprom::_beginTransmission(const uint16_t memoryAddress)

// pre: length <= this->_pageSize && length <= I2C_BUFFERSIZE;
// returns 0 = OK otherwise error
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 uint16_t length)
{
_waitEEReady();
if (_autoWriteProtect)
Expand Down Expand Up @@ -624,7 +629,7 @@ int I2C_eeprom::_WriteBlock(const uint16_t memoryAddress, const uint8_t * buffer

// pre: buffer is large enough to hold length bytes
// returns bytes read
uint8_t I2C_eeprom::_ReadBlock(const uint16_t memoryAddress, uint8_t * buffer, const uint8_t length)
uint8_t I2C_eeprom::_ReadBlock(const uint16_t memoryAddress, uint8_t * buffer, const uint16_t length)
{
_waitEEReady();

Expand All @@ -650,22 +655,22 @@ uint8_t I2C_eeprom::_ReadBlock(const uint16_t memoryAddress, uint8_t * buffer, c
}
else
{
uint8_t addr = _deviceAddress | ((memoryAddress >> 8) & 0x07);
readBytes = _wire->requestFrom(addr, length);
uint8_t address = _deviceAddress | ((memoryAddress >> 8) & 0x07);
readBytes = _wire->requestFrom(address, length);
}
yield(); // For OS scheduling
uint8_t cnt = 0;
while (cnt < readBytes)
uint8_t count = 0;
while (count < readBytes)
{
buffer[cnt++] = _wire->read();
buffer[count++] = _wire->read();
}
return readBytes;
}


// compares content of EEPROM with buffer.
// returns true if equal.
bool I2C_eeprom::_verifyBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint8_t length)
bool I2C_eeprom::_verifyBlock(const uint16_t memoryAddress, const uint8_t * buffer, const uint16_t length)
{
_waitEEReady();

Expand All @@ -691,14 +696,14 @@ bool I2C_eeprom::_verifyBlock(const uint16_t memoryAddress, const uint8_t * buff
}
else
{
uint8_t addr = _deviceAddress | ((memoryAddress >> 8) & 0x07);
readBytes = _wire->requestFrom(addr, length);
uint8_t address = _deviceAddress | ((memoryAddress >> 8) & 0x07);
readBytes = _wire->requestFrom(address, length);
}
yield(); // For OS scheduling
uint8_t cnt = 0;
while (cnt < readBytes)
uint8_t count = 0;
while (count < readBytes)
{
if (buffer[cnt++] != _wire->read())
if (buffer[count++] != _wire->read())
{
return false;
}
Expand Down
Loading
Loading