0.5.4 FRAM_I2C

This commit is contained in:
Rob Tillaart 2023-09-07 14:07:49 +02:00
parent 1cf039eb8a
commit 711ddef9d7
8 changed files with 314 additions and 236 deletions

View File

@ -5,13 +5,23 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.5.4] - 2023-09-04
- merge #39 add **read64(), write64()** (kudos to pvogt09)
- merge #40 add **MB85RC64V** info (kudos to pvogt09)
- rewrite **getManufacturerID, getProductID, getSize()**
to handle non existent metadata (See #38)
- update keywords.txt
- update unit test
- improved readability parameter names
- update readme.md
## [0.5.3] - 2023-04-28
- major redo FRAM9 and FRAM11, see #35
- update FRAM32 to match FRAM
- update readme.md.
- minor edits
## [0.5.2] - 2023-04-22
- add **FRAM_ML** class - see FRAM_MULTILANGUAGE.md
- add examples.

View File

@ -1,7 +1,7 @@
//
// FILE: FRAM.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.5.3
// VERSION: 0.5.4
// DATE: 2018-01-24
// PURPOSE: Arduino library for I2C FRAM
// URL: https://github.com/RobTillaart/FRAM_I2C
@ -89,115 +89,130 @@ bool FRAM::isConnected()
}
void FRAM::write8(uint16_t memaddr, uint8_t value)
void FRAM::write8(uint16_t memAddr, uint8_t value)
{
uint8_t val = value;
_writeBlock(memaddr, (uint8_t *)&val, sizeof(uint8_t));
_writeBlock(memAddr, (uint8_t *)&val, sizeof(uint8_t));
}
void FRAM::write16(uint16_t memaddr, uint16_t value)
void FRAM::write16(uint16_t memAddr, uint16_t value)
{
uint16_t val = value;
_writeBlock(memaddr, (uint8_t *)&val, sizeof(uint16_t));
_writeBlock(memAddr, (uint8_t *)&val, sizeof(uint16_t));
}
void FRAM::write32(uint16_t memaddr, uint32_t value)
void FRAM::write32(uint16_t memAddr, uint32_t value)
{
uint32_t val = value;
_writeBlock(memaddr, (uint8_t *)&val, sizeof(uint32_t));
_writeBlock(memAddr, (uint8_t *)&val, sizeof(uint32_t));
}
void FRAM::writeFloat(uint16_t memaddr, float value)
void FRAM::write64(uint16_t memAddr, uint64_t value)
{
uint64_t val = value;
_writeBlock(memAddr, (uint8_t *)&val, sizeof(uint64_t));
}
void FRAM::writeFloat(uint16_t memAddr, float value)
{
float val = value;
_writeBlock(memaddr, (uint8_t *)&val, sizeof(float));
_writeBlock(memAddr, (uint8_t *)&val, sizeof(float));
}
void FRAM::writeDouble(uint16_t memaddr, double value)
void FRAM::writeDouble(uint16_t memAddr, double value)
{
double val = value;
_writeBlock(memaddr, (uint8_t *)&val, sizeof(double));
_writeBlock(memAddr, (uint8_t *)&val, sizeof(double));
}
void FRAM::write(uint16_t memaddr, uint8_t * obj, uint16_t size)
void FRAM::write(uint16_t memAddr, uint8_t * obj, uint16_t size)
{
const int blocksize = 24;
uint8_t * p = obj;
while (size >= blocksize)
{
_writeBlock(memaddr, p, blocksize);
memaddr += blocksize;
_writeBlock(memAddr, p, blocksize);
memAddr += blocksize;
p += blocksize;
size -= blocksize;
}
// remaining
if (size > 0)
{
_writeBlock(memaddr, p, size);
_writeBlock(memAddr, p, size);
}
}
uint8_t FRAM::read8(uint16_t memaddr)
uint8_t FRAM::read8(uint16_t memAddr)
{
uint8_t val;
_readBlock(memaddr, (uint8_t *)&val, sizeof(uint8_t));
_readBlock(memAddr, (uint8_t *)&val, sizeof(uint8_t));
return val;
}
uint16_t FRAM::read16(uint16_t memaddr)
uint16_t FRAM::read16(uint16_t memAddr)
{
uint16_t val;
_readBlock(memaddr, (uint8_t *)&val, sizeof(uint16_t));
_readBlock(memAddr, (uint8_t *)&val, sizeof(uint16_t));
return val;
}
uint32_t FRAM::read32(uint16_t memaddr)
uint32_t FRAM::read32(uint16_t memAddr)
{
uint32_t val;
_readBlock(memaddr, (uint8_t *)&val, sizeof(uint32_t));
_readBlock(memAddr, (uint8_t *)&val, sizeof(uint32_t));
return val;
}
float FRAM::readFloat(uint16_t memaddr)
uint64_t FRAM::read64(uint16_t memAddr)
{
uint64_t val;
_readBlock(memAddr, (uint8_t *)&val, sizeof(uint64_t));
return val;
}
float FRAM::readFloat(uint16_t memAddr)
{
float val;
_readBlock(memaddr, (uint8_t *)&val, sizeof(float));
_readBlock(memAddr, (uint8_t *)&val, sizeof(float));
return val;
}
double FRAM::readDouble(uint16_t memaddr)
double FRAM::readDouble(uint16_t memAddr)
{
double val;
_readBlock(memaddr, (uint8_t *)&val, sizeof(double));
_readBlock(memAddr, (uint8_t *)&val, sizeof(double));
return val;
}
void FRAM::read(uint16_t memaddr, uint8_t * obj, uint16_t size)
void FRAM::read(uint16_t memAddr, uint8_t * obj, uint16_t size)
{
const uint8_t blocksize = 24;
uint8_t * p = obj;
while (size >= blocksize)
{
_readBlock(memaddr, p, blocksize);
memaddr += blocksize;
_readBlock(memAddr, p, blocksize);
memAddr += blocksize;
p += blocksize;
size -= blocksize;
}
// remainder
if (size > 0)
{
_readBlock(memaddr, p, size);
_readBlock(memAddr, p, size);
}
}
@ -205,15 +220,15 @@ void FRAM::read(uint16_t memaddr, uint8_t * obj, uint16_t size)
////////////////////////////////////////////////////////////////////////
int32_t FRAM::readUntil(uint16_t memaddr, char * buf, uint16_t buflen, char separator)
int32_t FRAM::readUntil(uint16_t memAddr, char * buffer, uint16_t bufferLength, char separator)
{
// read and fill the buffer at once.
read(memaddr, (uint8_t *)buf, buflen);
for (uint16_t length = 0; length < buflen; length++)
read(memAddr, (uint8_t *)buffer, bufferLength);
for (uint16_t length = 0; length < bufferLength; length++)
{
if (buf[length] == separator)
if (buffer[length] == separator)
{
buf[length] = 0; // replace separator => \0 EndChar
buffer[length] = 0; // replace separator => \0 EndChar
return length;
}
}
@ -222,15 +237,15 @@ int32_t FRAM::readUntil(uint16_t memaddr, char * buf, uint16_t buflen, char sepa
}
int32_t FRAM::readLine(uint16_t memaddr, char * buf, uint16_t buflen)
int32_t FRAM::readLine(uint16_t memAddr, char * buffer, uint16_t bufferLength)
{
// read and fill the buffer at once.
read(memaddr, (uint8_t *)buf, buflen);
for (uint16_t length = 0; length < buflen-1; length++)
read(memAddr, (uint8_t *)buffer, bufferLength);
for (uint16_t length = 0; length < bufferLength-1; length++)
{
if (buf[length] == '\n')
if (buffer[length] == '\n')
{
buf[length + 1] = 0; // add \0 EndChar after '\n'
buffer[length + 1] = 0; // add \0 EndChar after '\n'
return length + 1;
}
}
@ -259,22 +274,32 @@ bool FRAM::getWriteProtect()
uint16_t FRAM::getManufacturerID()
{
return _getMetaData(0);
uint32_t value = _getMetaData();
return (value >> 12) & 0x0FFF;
}
uint16_t FRAM::getProductID()
{
return _getMetaData(1);
uint32_t value = _getMetaData();
return value & 0x0FFF;
}
// NOTE: returns the size in kiloBYTE
// DENSITY
// Fujitsu data sheet
// 3 => MB85RC64 = 64 Kbit.
// 5 => MB85RC256
// 6 => MB85RC512
// 7 => MB85RC1M
// NOTE: returns the size in kiloBYTE (0 is read error)
uint16_t FRAM::getSize()
{
uint16_t density = _getMetaData(2);
uint16_t size = 0;
if (density > 0) size = (1UL << density);
uint32_t value = _getMetaData();
if (value == 0xFFFFFFFF) return 0;
uint16_t density = (value >> 8) & 0x0F;
uint16_t size = (1UL << density);
_sizeBytes = size * 1024UL;
return size;
}
@ -336,20 +361,18 @@ bool FRAM::wakeup(uint32_t trec)
// FRAM PROTECTED
//
// metadata is packed as [....MMMM][MMMMDDDD][PPPPPPPP]
// metadata is packed as [MMMMMMMM][MMMMDDDD][PPPPPPPP]
// M = manufacturerID
// D = density => memory size = 2^D KB
// P = product ID (together with D)
// P part might be proprietary
uint16_t FRAM::_getMetaData(uint8_t field)
uint32_t FRAM::_getMetaData()
{
if (field > 2) return 0;
_wire->beginTransmission(FRAM_SLAVE_ID_);
_wire->write(_address << 1);
_wire->endTransmission(false);
int x = _wire->requestFrom(FRAM_SLAVE_ID_, (uint8_t)3);
if (x != 3) return -1;
if (x != 3) return 0xFFFFFFFF;
uint32_t value = 0;
value = _wire->read();
@ -358,26 +381,15 @@ uint16_t FRAM::_getMetaData(uint8_t field)
value = value << 8;
value |= _wire->read();
// MANUFACTURER
if (field == 0) return (value >> 12) & 0xFF;
// PRODUCT ID
if (field == 1) return value & 0x0FFF;
// DENSITY
// Fujitsu data sheet
// 3 => MB85RC64 = 64 Kbit.
// 5 => MB85RC256
// 6 => MB85RC512
// 7 => MB85RC1M
if (field == 2) return (value >> 8) & 0x0F;
return 0;
return value;
}
void FRAM::_writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
void FRAM::_writeBlock(uint16_t memAddr, uint8_t * obj, uint8_t size)
{
_wire->beginTransmission(_address);
_wire->write((uint8_t) (memaddr >> 8));
_wire->write((uint8_t) (memaddr & 0xFF));
_wire->write((uint8_t) (memAddr >> 8));
_wire->write((uint8_t) (memAddr & 0xFF));
uint8_t * p = obj;
for (uint8_t i = size; i > 0; i--)
{
@ -387,11 +399,11 @@ void FRAM::_writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
}
void FRAM::_readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
void FRAM::_readBlock(uint16_t memAddr, uint8_t * obj, uint8_t size)
{
_wire->beginTransmission(_address);
_wire->write((uint8_t) (memaddr >> 8));
_wire->write((uint8_t) (memaddr & 0xFF));
_wire->write((uint8_t) (memAddr >> 8));
_wire->write((uint8_t) (memAddr & 0xFF));
_wire->endTransmission();
_wire->requestFrom(_address, size);
uint8_t * p = obj;
@ -412,128 +424,143 @@ FRAM32::FRAM32(TwoWire *wire) : FRAM(wire)
}
void FRAM32::write8(uint32_t memaddr, uint8_t value)
void FRAM32::write8(uint32_t memAddr, uint8_t value)
{
uint8_t val = value;
_writeBlock(memaddr, (uint8_t *)&val, sizeof(uint8_t));
_writeBlock(memAddr, (uint8_t *)&val, sizeof(uint8_t));
}
void FRAM32::write16(uint32_t memaddr, uint16_t value)
void FRAM32::write16(uint32_t memAddr, uint16_t value)
{
uint16_t val = value;
_writeBlock(memaddr, (uint8_t *)&val, sizeof(uint16_t));
_writeBlock(memAddr, (uint8_t *)&val, sizeof(uint16_t));
}
void FRAM32::write32(uint32_t memaddr, uint32_t value)
void FRAM32::write32(uint32_t memAddr, uint32_t value)
{
uint32_t val = value;
_writeBlock(memaddr, (uint8_t *)&val, sizeof(uint32_t));
_writeBlock(memAddr, (uint8_t *)&val, sizeof(uint32_t));
}
void FRAM32::writeFloat(uint32_t memaddr, float value)
void FRAM32::write64(uint32_t memAddr, uint64_t value)
{
uint64_t val = value;
_writeBlock(memAddr, (uint8_t *)&val, sizeof(uint64_t));
}
void FRAM32::writeFloat(uint32_t memAddr, float value)
{
float val = value;
_writeBlock(memaddr, (uint8_t *)&val, sizeof(float));
_writeBlock(memAddr, (uint8_t *)&val, sizeof(float));
}
void FRAM32::writeDouble(uint32_t memaddr, double value)
void FRAM32::writeDouble(uint32_t memAddr, double value)
{
double val = value;
_writeBlock(memaddr, (uint8_t *)&val, sizeof(double));
_writeBlock(memAddr, (uint8_t *)&val, sizeof(double));
}
void FRAM32::write(uint32_t memaddr, uint8_t * obj, uint16_t size)
void FRAM32::write(uint32_t memAddr, uint8_t * obj, uint16_t size)
{
const int blocksize = 24;
uint8_t * p = obj;
while (size >= blocksize)
{
_writeBlock(memaddr, p, blocksize);
memaddr += blocksize;
_writeBlock(memAddr, p, blocksize);
memAddr += blocksize;
p += blocksize;
size -= blocksize;
}
// remaining
if (size > 0)
{
_writeBlock(memaddr, p, size);
_writeBlock(memAddr, p, size);
}
}
uint8_t FRAM32::read8(uint32_t memaddr)
uint8_t FRAM32::read8(uint32_t memAddr)
{
uint8_t val;
_readBlock(memaddr, (uint8_t *)&val, sizeof(uint8_t));
_readBlock(memAddr, (uint8_t *)&val, sizeof(uint8_t));
return val;
}
uint16_t FRAM32::read16(uint32_t memaddr)
uint16_t FRAM32::read16(uint32_t memAddr)
{
uint16_t val;
_readBlock(memaddr, (uint8_t *)&val, sizeof(uint16_t));
_readBlock(memAddr, (uint8_t *)&val, sizeof(uint16_t));
return val;
}
uint32_t FRAM32::read32(uint32_t memaddr)
uint32_t FRAM32::read32(uint32_t memAddr)
{
uint32_t val;
_readBlock(memaddr, (uint8_t *)&val, sizeof(uint32_t));
_readBlock(memAddr, (uint8_t *)&val, sizeof(uint32_t));
return val;
}
float FRAM32::readFloat(uint32_t memaddr)
uint64_t FRAM32::read64(uint32_t memAddr)
{
uint64_t val;
_readBlock(memAddr, (uint8_t *)&val, sizeof(uint64_t));
return val;
}
float FRAM32::readFloat(uint32_t memAddr)
{
float val;
_readBlock(memaddr, (uint8_t *)&val, sizeof(float));
_readBlock(memAddr, (uint8_t *)&val, sizeof(float));
return val;
}
double FRAM32::readDouble(uint32_t memaddr)
double FRAM32::readDouble(uint32_t memAddr)
{
double val;
_readBlock(memaddr, (uint8_t *)&val, sizeof(double));
_readBlock(memAddr, (uint8_t *)&val, sizeof(double));
return val;
}
void FRAM32::read(uint32_t memaddr, uint8_t * obj, uint16_t size)
void FRAM32::read(uint32_t memAddr, uint8_t * obj, uint16_t size)
{
const uint8_t blocksize = 24;
uint8_t * p = obj;
while (size >= blocksize)
{
_readBlock(memaddr, p, blocksize);
memaddr += blocksize;
_readBlock(memAddr, p, blocksize);
memAddr += blocksize;
p += blocksize;
size -= blocksize;
}
// remainder
if (size > 0)
{
_readBlock(memaddr, p, size);
_readBlock(memAddr, p, size);
}
}
int32_t FRAM32::readUntil(uint32_t memaddr, char * buf, uint16_t buflen, char separator)
int32_t FRAM32::readUntil(uint32_t memAddr, char * buffer, uint16_t bufferLength, char separator)
{
// read and fill the buffer at once.
read(memaddr, (uint8_t *)buf, buflen);
for (uint16_t length = 0; length < buflen; length++)
read(memAddr, (uint8_t *)buffer, bufferLength);
for (uint16_t length = 0; length < bufferLength; length++)
{
if (buf[length] == separator)
if (buffer[length] == separator)
{
buf[length] = 0; // replace separator => \0 EndChar
buffer[length] = 0; // replace separator => \0 EndChar
return length;
}
}
@ -542,15 +569,15 @@ int32_t FRAM32::readUntil(uint32_t memaddr, char * buf, uint16_t buflen, char se
}
int32_t FRAM32::readLine(uint32_t memaddr, char * buf, uint16_t buflen)
int32_t FRAM32::readLine(uint32_t memAddr, char * buffer, uint16_t bufferLength)
{
// read and fill the buffer at once.
read(memaddr, (uint8_t *)buf, buflen);
for (uint16_t length = 0; length < buflen-1; length++)
read(memAddr, (uint8_t *)buffer, bufferLength);
for (uint16_t length = 0; length < bufferLength-1; length++)
{
if (buf[length] == '\n')
if (buffer[length] == '\n')
{
buf[length + 1] = 0; // add \0 EndChar after '\n'
buffer[length + 1] = 0; // add \0 EndChar after '\n'
return length + 1;
}
}
@ -559,29 +586,29 @@ int32_t FRAM32::readLine(uint32_t memaddr, char * buf, uint16_t buflen)
}
template <class T> uint32_t FRAM32::writeObject(uint32_t memaddr, T &obj)
template <class T> uint32_t FRAM32::writeObject(uint32_t memAddr, T &obj)
{
write(memaddr, (uint8_t *) &obj, sizeof(obj));
return memaddr + sizeof(obj);
write(memAddr, (uint8_t *) &obj, sizeof(obj));
return memAddr + sizeof(obj);
};
template <class T> uint32_t FRAM32::readObject(uint32_t memaddr, T &obj)
template <class T> uint32_t FRAM32::readObject(uint32_t memAddr, T &obj)
{
read(memaddr, (uint8_t *) &obj, sizeof(obj));
return memaddr + sizeof(obj);
read(memAddr, (uint8_t *) &obj, sizeof(obj));
return memAddr + sizeof(obj);
}
uint32_t FRAM32::clear(uint8_t value)
{
uint8_t buf[16];
for (uint8_t i = 0; i < 16; i++) buf[i] = value;
uint8_t buffer[16];
for (uint8_t i = 0; i < 16; i++) buffer[i] = value;
uint32_t start = 0;
uint32_t end = _sizeBytes;
for (uint32_t addr = start; addr < end; addr += 16)
{
_writeBlock(addr, buf, 16);
_writeBlock(addr, buffer, 16);
}
return end - start;
}
@ -593,14 +620,14 @@ uint32_t FRAM32::clear(uint8_t value)
//
// FRAM32 PROTECTED
//
void FRAM32::_writeBlock(uint32_t memaddr, uint8_t * obj, uint8_t size)
void FRAM32::_writeBlock(uint32_t memAddr, uint8_t * obj, uint8_t size)
{
uint8_t _addr = _address;
if (memaddr & 0x00010000) _addr += 0x01;
if (memAddr & 0x00010000) _addr += 0x01;
_wire->beginTransmission(_addr);
_wire->write((uint8_t) (memaddr >> 8));
_wire->write((uint8_t) (memaddr & 0xFF));
_wire->write((uint8_t) (memAddr >> 8));
_wire->write((uint8_t) (memAddr & 0xFF));
uint8_t * p = obj;
for (uint8_t i = size; i > 0; i--)
{
@ -610,14 +637,14 @@ void FRAM32::_writeBlock(uint32_t memaddr, uint8_t * obj, uint8_t size)
}
void FRAM32::_readBlock(uint32_t memaddr, uint8_t * obj, uint8_t size)
void FRAM32::_readBlock(uint32_t memAddr, uint8_t * obj, uint8_t size)
{
uint8_t _addr = _address;
if (memaddr & 0x00010000) _addr += 0x01;
if (memAddr & 0x00010000) _addr += 0x01;
_wire->beginTransmission(_address);
_wire->write((uint8_t) (memaddr >> 8));
_wire->write((uint8_t) (memaddr & 0xFF));
_wire->write((uint8_t) (memAddr >> 8));
_wire->write((uint8_t) (memAddr & 0xFF));
_wire->endTransmission();
_wire->requestFrom(_addr, size);
uint8_t * p = obj;
@ -669,12 +696,12 @@ uint16_t FRAM11::getSize()
//
// FRAM11 PROTECTED
//
void FRAM11::_writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
void FRAM11::_writeBlock(uint16_t memAddr, uint8_t * obj, uint8_t size)
{
// Device uses Address Pages
uint8_t DeviceAddrWithPageBits = _address | ((memaddr & 0x0700) >> 8);
uint8_t DeviceAddrWithPageBits = _address | ((memAddr & 0x0700) >> 8);
_wire->beginTransmission(DeviceAddrWithPageBits);
_wire->write((uint8_t) (memaddr & 0xFF));
_wire->write((uint8_t) (memAddr & 0xFF));
uint8_t * p = obj;
for (uint8_t i = size; i > 0; i--)
@ -685,12 +712,12 @@ void FRAM11::_writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
}
void FRAM11::_readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
void FRAM11::_readBlock(uint16_t memAddr, uint8_t * obj, uint8_t size)
{
// Device uses Address Pages
uint8_t DeviceAddrWithPageBits = _address | ((memaddr & 0x0700) >> 8);
uint8_t DeviceAddrWithPageBits = _address | ((memAddr & 0x0700) >> 8);
_wire->beginTransmission(DeviceAddrWithPageBits);
_wire->write((uint8_t) (memaddr & 0xFF));
_wire->write((uint8_t) (memAddr & 0xFF));
_wire->endTransmission();
_wire->requestFrom(DeviceAddrWithPageBits, size);
@ -744,12 +771,12 @@ uint16_t FRAM9::getSize()
//
// FRAM9 PROTECTED
//
void FRAM9::_writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
void FRAM9::_writeBlock(uint16_t memAddr, uint8_t * obj, uint8_t size)
{
// Device uses Address Pages
uint8_t DeviceAddrWithPageBits = _address | ((memaddr & 0x0100) >> 8);
uint8_t DeviceAddrWithPageBits = _address | ((memAddr & 0x0100) >> 8);
_wire->beginTransmission(DeviceAddrWithPageBits);
_wire->write((uint8_t) (memaddr & 0xFF));
_wire->write((uint8_t) (memAddr & 0xFF));
uint8_t * p = obj;
for (uint8_t i = size; i > 0; i--)
@ -760,12 +787,12 @@ void FRAM9::_writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
}
void FRAM9::_readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size)
void FRAM9::_readBlock(uint16_t memAddr, uint8_t * obj, uint8_t size)
{
// Device uses Address Pages
uint8_t DeviceAddrWithPageBits = _address | ((memaddr & 0x0100) >> 8);
uint8_t DeviceAddrWithPageBits = _address | ((memAddr & 0x0100) >> 8);
_wire->beginTransmission(DeviceAddrWithPageBits);
_wire->write((uint8_t) (memaddr & 0xFF));
_wire->write((uint8_t) (memAddr & 0xFF));
_wire->endTransmission();
_wire->requestFrom(DeviceAddrWithPageBits, size);

View File

@ -2,7 +2,7 @@
//
// FILE: FRAM.h
// AUTHOR: Rob Tillaart
// VERSION: 0.5.3
// VERSION: 0.5.4
// DATE: 2018-01-24
// PURPOSE: Arduino library for I2C FRAM
// URL: https://github.com/RobTillaart/FRAM_I2C
@ -12,7 +12,7 @@
#include "Wire.h"
#define FRAM_LIB_VERSION (F("0.5.3"))
#define FRAM_LIB_VERSION (F("0.5.4"))
#define FRAM_OK 0
@ -24,6 +24,7 @@
#define FRAM_MB85RC04 512
#define FRAM_MB85RC16 2048
#define FRAM_MB85RC64T 8192
#define FRAM_MB85RC64V 8192
#define FRAM_MB85RC128A 16384
#define FRAM_MB85RC256V 32768
#define FRAM_MB85RC512T 65536
@ -45,54 +46,67 @@ public:
const int8_t writeProtectPin = -1);
bool isConnected();
void write8(uint16_t memaddr, uint8_t value);
void write16(uint16_t memaddr, uint16_t value);
void write32(uint16_t memaddr, uint32_t value);
void writeFloat(uint16_t memaddr, float value);
void writeDouble(uint16_t memaddr, double value);
void write(uint16_t memaddr, uint8_t * obj, uint16_t size);
uint8_t read8(uint16_t memaddr);
uint16_t read16(uint16_t memaddr);
uint32_t read32(uint16_t memaddr);
float readFloat(uint16_t memaddr);
double readDouble(uint16_t memaddr);
void read(uint16_t memaddr, uint8_t * obj, uint16_t size);
// WRITE DATA TYPES
void write8(uint16_t memAddr, uint8_t value);
void write16(uint16_t memAddr, uint16_t value);
void write32(uint16_t memAddr, uint32_t value);
void write64(uint16_t memAddr, uint64_t value);
void writeFloat(uint16_t memAddr, float value);
void writeDouble(uint16_t memAddr, double value);
void write(uint16_t memAddr, uint8_t * obj, uint16_t size);
// fills FRAM with value, default 0.
uint32_t clear(uint8_t value = 0);
// READ DATA TYPES
uint8_t read8(uint16_t memAddr);
uint16_t read16(uint16_t memAddr);
uint32_t read32(uint16_t memAddr);
uint64_t read64(uint16_t memAddr);
float readFloat(uint16_t memAddr);
double readDouble(uint16_t memAddr);
void read(uint16_t memAddr, uint8_t * obj, uint16_t size);
// Experimental 0.5.1
// readUntil returns length 0.. n of the buffer.
// readUntil does NOT include the separator character.
// readUntil returns -1 if data does not fit into buffer,
// => separator not encountered.
int32_t readUntil(uint16_t memaddr, char * buf, uint16_t buflen, char separator);
int32_t readUntil(uint16_t memAddr, char * buffer, uint16_t bufferLength, char separator);
// readLine returns length 0.. n of the buffer.
// readLine does include '\n' as end character.
// readLine returns -1 if data does not fit into buffer.
// buffer needs one place for end char '\0'.
int32_t readLine(uint16_t memaddr, char * buf, uint16_t buflen);
int32_t readLine(uint16_t memAddr, char * buffer, uint16_t bufferLength);
template <class T> uint16_t writeObject(uint16_t memaddr, T &obj)
template <class T> uint16_t writeObject(uint16_t memAddr, T &obj)
{
write(memaddr, (uint8_t *) &obj, sizeof(obj));
return memaddr + sizeof(obj);
write(memAddr, (uint8_t *) &obj, sizeof(obj));
return memAddr + sizeof(obj);
};
template <class T> uint16_t readObject(uint16_t memaddr, T &obj)
template <class T> uint16_t readObject(uint16_t memAddr, T &obj)
{
read(memaddr, (uint8_t *) &obj, sizeof(obj));
return memaddr + sizeof(obj);
read(memAddr, (uint8_t *) &obj, sizeof(obj));
return memAddr + sizeof(obj);
}
// WRITEPROTECT
// works only if pin is defined in begin().
bool setWriteProtect(bool b);
bool getWriteProtect();
// meta info
// MEAT INFO
// may not work for devices with no deviceID register.
// Fujitsu = 0x000A, Ramtron = 0x004
uint16_t getManufacturerID();
// Proprietary
// Proprietary product ID
uint16_t getProductID();
// virtual so derived classes FRAM9/11 use their implementation.
// Returns size in KILO-BYTE (or 0)
// Verify for all manufacturers.
@ -102,10 +116,9 @@ public:
// override when getSize() fails == 0 (see readme.md)
void setSizeBytes(uint32_t value);
// fills FRAM with value, default 0.
uint32_t clear(uint8_t value = 0);
// 0.3.6
// SLEEP - 0.3.6
void sleep();
// trec <= 400us P12
bool wakeup(uint32_t trec = 400);
@ -118,10 +131,10 @@ protected:
int8_t _writeProtectPin = -1;
TwoWire* _wire;
uint16_t _getMetaData(uint8_t id);
uint32_t _getMetaData();
// virtual so derived classes FRAM9/11 use their implementation.
virtual void _writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
virtual void _readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
virtual void _writeBlock(uint16_t memAddr, uint8_t * obj, uint8_t size);
virtual void _readBlock(uint16_t memAddr, uint8_t * obj, uint8_t size);
};
@ -135,35 +148,40 @@ class FRAM32 : public FRAM
public:
FRAM32(TwoWire *wire = &Wire);
void write8(uint32_t memaddr, uint8_t value);
void write16(uint32_t memaddr, uint16_t value);
void write32(uint32_t memaddr, uint32_t value);
void writeFloat(uint32_t memaddr, float value);
void writeDouble(uint32_t memaddr, double value);
void write(uint32_t memaddr, uint8_t * obj, uint16_t size);
void write8(uint32_t memAddr, uint8_t value);
void write16(uint32_t memAddr, uint16_t value);
void write32(uint32_t memAddr, uint32_t value);
void write64(uint32_t memAddr, uint64_t value);
void writeFloat(uint32_t memAddr, float value);
void writeDouble(uint32_t memAddr, double value);
void write(uint32_t memAddr, uint8_t * obj, uint16_t size);
uint8_t read8(uint32_t memAddr);
uint16_t read16(uint32_t memAddr);
uint32_t read32(uint32_t memAddr);
uint64_t read64(uint32_t memAddr);
float readFloat(uint32_t memAddr);
double readDouble(uint32_t memAddr);
void read(uint32_t memAddr, uint8_t * obj, uint16_t size);
uint8_t read8(uint32_t memaddr);
uint16_t read16(uint32_t memaddr);
uint32_t read32(uint32_t memaddr);
float readFloat(uint32_t memaddr);
double readDouble(uint32_t memaddr);
void read(uint32_t memaddr, uint8_t * obj, uint16_t size);
// readUntil returns length 0.. n of the buffer.
// readUntil returns -1 if data does not fit into buffer,
// => separator not encountered.
int32_t readUntil(uint32_t memaddr, char * buf, uint16_t buflen, char separator);
int32_t readUntil(uint32_t memAddr, char * buffer, uint16_t bufferLength, char separator);
// buffer needs one place for end char '\0'.
int32_t readLine(uint32_t memaddr, char * buf, uint16_t buflen);
int32_t readLine(uint32_t memAddr, char * buffer, uint16_t bufferLength);
template <class T> uint32_t writeObject(uint32_t memaddr, T &obj);
template <class T> uint32_t readObject(uint32_t memaddr, T &obj);
template <class T> uint32_t writeObject(uint32_t memAddr, T &obj);
template <class T> uint32_t readObject(uint32_t memAddr, T &obj);
uint32_t clear(uint8_t value = 0); // fills FRAM with value
protected:
void _writeBlock(uint32_t memaddr, uint8_t * obj, uint8_t size);
void _readBlock(uint32_t memaddr, uint8_t * obj, uint8_t size);
void _writeBlock(uint32_t memAddr, uint8_t * obj, uint8_t size);
void _readBlock(uint32_t memAddr, uint8_t * obj, uint8_t size);
};
@ -188,9 +206,10 @@ public:
uint16_t getSize();
protected:
void _writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
void _readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
void _writeBlock(uint16_t memAddr, uint8_t * obj, uint8_t size);
void _readBlock(uint16_t memAddr, uint8_t * obj, uint8_t size);
};
@ -215,9 +234,10 @@ public:
uint16_t getSize();
protected:
void _writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
void _readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
void _writeBlock(uint16_t memAddr, uint8_t * obj, uint8_t size);
void _readBlock(uint16_t memAddr, uint8_t * obj, uint8_t size);
};

View File

@ -2,8 +2,11 @@
[![Arduino CI](https://github.com/RobTillaart/FRAM_I2C/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/FRAM_I2C/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/FRAM_I2C/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/FRAM_I2C/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/FRAM_I2C/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/FRAM_I2C.svg)](https://github.com/RobTillaart/FRAM_I2C/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/FRAM_I2C/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/FRAM_I2C.svg?maxAge=3600)](https://github.com/RobTillaart/FRAM_I2C/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/FRAM_I2C.svg)](https://registry.platformio.org/libraries/robtillaart/FRAM_I2C)
# FRAM_I2C
@ -37,14 +40,15 @@ Types of FRAM that should work with this library:
| MB85RC04 | 512 | Y | no deviceID register | FRAM9 | #35 |
| MB85RC16 | 2 KB | Y | no deviceID register | FRAM11 | #28 |
| MB85RC64T | 8 KB | Y | | FRAM | |
| MB85RC64V | 8 KB | Y | no deviceID register | FRAM | #38 |
| MB85RC128A | 16 KB | N | no deviceID register | FRAM | |
| MB85RC256V | 32 KB | Y | | FRAM | |
| MB85RC512T | 64 KB | Y | | FRAM | |
| MB85RC1MT | 128 KB | Y | | FRAM32 | #19 |
MB85RC128A has no size / deviceID, **clear()** will not work correctly, unless
one calls **setSizeBytes(16 \* 1024)** to set the size manually.
MB85RC128A and MB85RC64V have no size / deviceID, **clear()** will not work correctly, unless
one calls **setSizeBytes(16 \* 1024)** or **setSizeBytes(8 \* 1024)** to set the size manually.
For the FRAM9 and FRAM11 the size problem is solved (hard coded) in their class.
@ -91,23 +95,25 @@ Note the **MB85RC1MT** only uses even addresses.
### Write & read
Support for basic types and two calls for generic objects, use casting if needed.
In the **FRAM32** class these functions have an **uin32_t memaddr**.
In the **FRAM32** class these functions have an **uin32_t memAddr**.
- **void write8(uint16_t memaddr, uint8_t value)** uint8_t
- **void write16(uint16_t memaddr, uint16_t value)** uint16_t
- **void write32(uint16_t memaddr, uint32_t value)** uint32_t
- **void writeFloat(uint16_t memaddr, float value)** float
- **void writeDouble(uint16_t memaddr, double value)** double
- **void write8(uint16_t memAddr, uint8_t value)** uint8_t
- **void write16(uint16_t memAddr, uint16_t value)** uint16_t
- **void write32(uint16_t memAddr, uint32_t value)** uint32_t
- **void write64(uint16_t memAddr, uint64_t value)** uint64_t
- **void writeFloat(uint16_t memAddr, float value)** float
- **void writeDouble(uint16_t memAddr, double value)** double
- For boards that have an 8 byte double.
- **void write(uint16_t memaddr, uint8_t \* obj, uint16_t size)** other types / sizes.
- typical used for structs.
- **uint8_t read8(uint16_t memaddr)**
- **uint16_t read16(uint16_t memaddr)**
- **uint32_t read32(uint16_t memaddr)**
- **float readFloat(uint16_t memaddr)**
- **double readDouble(uint16_t memaddr)**
- **void write(uint16_t memAddr, uint8_t \* obj, uint16_t size)** other types / sizes.
- typical used for structs or text.
- **uint8_t read8(uint16_t memAddr)**
- **uint16_t read16(uint16_t memAddr)**
- **uint32_t read32(uint16_t memAddr)**
- **uint64_t read64(uint16_t memAddr)**
- **float readFloat(uint16_t memAddr)**
- **double readDouble(uint16_t memAddr)**
- For board that have 8 byte double.
- **void read(uint16_t memaddr, uint8_t uint8_t \* obj, uint16_t size)**
- **void read(uint16_t memAddr, uint8_t uint8_t \* obj, uint16_t size)**
- One needs to allocate memory as the function won't.
- **uint32_t clear(uint8_t value = 0)** clears the whole FRAM by writing value to all addresses
- default value is all zero's.
@ -116,26 +122,26 @@ In the **FRAM32** class these functions have an **uin32_t memaddr**.
(Template functions, see issue #13)
- **uint16_t writeObject(uint16_t memaddr, T &obj)** writes an object to memaddr (and following bytes).
- Returns memaddr + sizeof(obj) to get the next address to write to.
- **uint16_t readObject(uint16_t memaddr, T &obj)** reads an object from memaddr and next bytes.
- Returns memaddr + sizeof(obj) to get the next address to read from.
- **uint16_t writeObject(uint16_t memAddr, T &obj)** writes an object to memAddr (and following bytes).
- Returns memAddr + sizeof(obj) to get the next address to write to.
- **uint16_t readObject(uint16_t memAddr, T &obj)** reads an object from memAddr and next bytes.
- Returns memAddr + sizeof(obj) to get the next address to read from.
(Experimental 0.5.1, see issue #30)
- **int32_t readUntil(uint16_t memaddr, char \*buf, uint16_t buflen, char separator)**
Reads FRAM from an address into **buf** until separator is encountered.
- **int32_t readUntil(uint16_t memAddr, char \* buffer, uint16_t bufferLength, char separator)**
Reads FRAM from an address into **buffer** until separator is encountered.
The separator is replaced by an '\0' - end of char array.
**ReadUntil()** returns the length of the buffer.
To get the address of the next "field" one must add ```memaddr += (length + 1)```.
If the separator is not found after **buflen** characters the function returns -1.
To get the address of the next "field" one must add ```memAddr += (length + 1)```.
If the separator is not found after **bufferLength** characters the function returns -1.
However the buffer does contain the data read, which might be useful.
Handle with care as buffer has probably no '\0' end char.
- **int32_t readLine(uint16_t memaddr, char \* buf, uint16_t buflen)**
- **int32_t readLine(uint16_t memAddr, char \* buffer, uint16_t bufferLength)**
Similar to **readUntil()**, reads a line from FRAM including the '\n'.
This '\n' is mandatory as end separator!.
Note: The buffer needs one extra char for the delimiting '\0' end char.
To get the address of the next "field" one must add ```memaddr += length```.
To get the address of the next "field" one must add ```memAddr += length```.
This is an minor but important difference with **readUntil()**.
Note: the returning buffer contains the '\n' so one need to take care when
printing the buffer.
@ -145,10 +151,10 @@ printing the buffer.
**readUntil()** can be used to read lines and/or fields from an FRAM filled with text.
For example logging written with the FRAM_logging.ino example.
Note: if memaddr + buflen >= size of FRAM, memory wrapping may occur.
Note: if memAddr + bufferLength >= size of FRAM, memory wrapping may occur.
The library does not check, so the user should.
Note: internally **readUntil()** reads buflen bytes to fill the buffer.
Note: internally **readUntil()** reads bufferLength bytes to fill the buffer.
Then it searches for the separator.
This is chosen to optimize performance for relative small buffers that are used most.
For large buffers this fetching of the whole buffer will take much time.
@ -178,7 +184,9 @@ These may not work for devices that have no **deviceID** register.
So use with care.
- **uint16_t getManufacturerID()** see table below.
Returns 0x0FFF means **getMetaData()** had a read error.
- **uint16_t getProductID()** idem. Proprietary.
Returns 0x0FFF means **getMetaData()** had a read error.
- **uint16_t getSize()** returns the size in kiloBYTE.
If the FRAM has no device ID register, the size cannot be read.
- FRAM9 will return 0 as it is less than 1 KB. use GetSizeBytes() instead.
@ -187,7 +195,7 @@ If the FRAM has no device ID register, the size cannot be read.
or testing the upper boundary.
- **void setSizeBytes(uint32_t value)** sets the size in bytes for **getSizeBytes()**.
To be used only if **getSize()** cannot determine the size.
As far as known this is for the **MB85RC128A** only.
As far as known this is for the **MB85RC128A** and **MB85RC64V** only.
See also remark in Future section below.
Can also be used to "virtually" reduce the size, e.g. to speed up **clear()**
if the FRAM is used only partial.
@ -195,12 +203,13 @@ if the FRAM is used only partial.
### Manufacturers ID
| Name | ID |
|:----------------------|:-------:|
| Fujitsu | 0x00A |
| Ramtron | 0x004 |
| Name | ID | Notes |
|:-------------------------|:-------:|:--------|
| Fujitsu | 0x00A |
| Ramtron | 0x004 |
| getMetaData read error | 0xFFF | See #38
Additions are welcome.
Additions for manufacturers ID's are welcome.
### Sleep
@ -310,13 +319,7 @@ Use **getSizeBytes()** to get 512.
- a wrapper class?
- fill power usage table (documentation)
- is in data sheet.
- refactor for readability
- improve / add comments where needed.
- memaddr ==> memoryAddress or memAddr (camelCase)
- buf ==> buffer,
- buflen ==> bufferLength / bufferSize
- obj ==> object
- use SDA/SCL as name
- improve comments where needed.
#### Wont
@ -329,6 +332,15 @@ Use **getSizeBytes()** to get 512.
- Print interface? expensive in performance per char..
- see example **FRAM_hexdump.ino**
- remember last written address? why?
- do we need a **write(memaddr, char \* buf)** for completeness?
- do we need a **write(memAddr, char \* buffer)** for completeness?
- it is just a wrapper
## 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,

View File

@ -16,6 +16,7 @@ isConnected KEYWORD2
write8 KEYWORD2
write16 KEYWORD2
write32 KEYWORD2
write64 KEYWORD2
writeFloat KEYWORD2
writeDouble KEYWORD2
write KEYWORD2
@ -23,6 +24,7 @@ write KEYWORD2
read8 KEYWORD2
read16 KEYWORD2
read32 KEYWORD2
read64 KEYWORD2
readFloat KEYWORD2
readDouble KEYWORD2
read KEYWORD2
@ -93,6 +95,7 @@ FRAM_ERROR_CONNECT LITERAL1
FRAM_MB85RC04 LITERAL1
FRAM_MB85RC16 LITERAL1
FRAM_MB85RC64T LITERAL1
FRAM_MB85RC64V LITERAL1
FRAM_MB85RC128A LITERAL1
FRAM_MB85RC256V LITERAL1
FRAM_MB85RC512T LITERAL1

View File

@ -15,9 +15,9 @@
"type": "git",
"url": "https://github.com/RobTillaart/FRAM_I2C.git"
},
"version": "0.5.3",
"version": "0.5.4",
"license": "MIT",
"frameworks": "arduino",
"frameworks": "*",
"platforms": "*",
"headers": "FRAM.h"
}

View File

@ -1,5 +1,5 @@
name=FRAM_I2C
version=0.5.3
version=0.5.4
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for I2C FRAM for persistent storage.

View File

@ -49,6 +49,7 @@ unittest(test_constants)
assertEqual(512, FRAM_MB85RC04 );
assertEqual(2048, FRAM_MB85RC16 );
assertEqual(8192, FRAM_MB85RC64T );
assertEqual(8192, FRAM_MB85RC64V );
assertEqual(16384, FRAM_MB85RC128A);
assertEqual(32768, FRAM_MB85RC256V);
assertEqual(65536, FRAM_MB85RC512T);
@ -84,8 +85,8 @@ unittest(test_constructor)
assertFalse(fram57.getWriteProtect());
fprintf(stderr, "\n all fail as nothing connected\n");
assertEqual(65535, fram50.getManufacturerID());
assertEqual(65535, fram50.getProductID());
assertEqual(0xFFF, fram50.getManufacturerID());
assertEqual(0xFFF, fram50.getProductID());
assertEqual(0, fram50.getSize());
}
@ -100,6 +101,11 @@ unittest(test_getSizeBytes)
fram.setSizeBytes(FRAM_MB85RC256V);
assertEqual(32768, fram.getSizeBytes());
FRAM32 f32;
assertEqual(0, f32.getSizeBytes());
f32.setSizeBytes(FRAM_MB85RC1MT);
assertEqual(131072, f32.getSizeBytes());
FRAM11 f11;
assertEqual(2, f11.getSize());
assertEqual(2048, f11.getSizeBytes());