0.4.2 FRAM_I2C

This commit is contained in:
rob tillaart 2022-10-16 19:09:32 +02:00
parent 09b05e5efe
commit 89bf078d48
13 changed files with 892 additions and 42 deletions

View File

@ -1,3 +1,18 @@
platforms:
rpipico:
board: rp2040:rp2040:rpipico
package: rp2040:rp2040
gcc:
features:
defines:
- ARDUINO_ARCH_RP2040
warnings:
flags:
packages:
rp2040:rp2040:
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
@ -8,4 +23,6 @@ compile:
- m4
- esp32
- esp8266
# - mega2560
# - mega2560
- rpipico

View File

@ -5,6 +5,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.4.2] - 2022-10-03
### Added
- FRAM_RINGBUFFER class - see FRAM_RINGBUFFER.md
- build-ci support for RP2040 pico
### Changed
- updated documentation
- moved code from FRAM.h to FRAM.cpp
## [0.4.1] - 2022-09-24
### Added

View File

@ -1,7 +1,7 @@
//
// FILE: FRAM.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.4.1
// VERSION: 0.4.2
// DATE: 2018-01-24
// PURPOSE: Arduino library for I2C FRAM
// URL: https://github.com/RobTillaart/FRAM_I2C
@ -212,6 +212,12 @@ uint16_t FRAM::getSize()
}
uint32_t FRAM::getSizeBytes()
{
return _sizeBytes;
};
// override to be used when getSize() fails == 0
void FRAM::setSizeBytes(uint32_t value)
{
@ -419,6 +425,20 @@ void FRAM32::read(uint32_t memaddr, uint8_t * obj, uint16_t size)
}
template <class T> uint32_t FRAM32::writeObject(uint32_t memaddr, T &obj)
{
write(memaddr, (uint8_t *) &obj, sizeof(obj));
return memaddr + sizeof(obj);
};
template <class T> uint32_t FRAM32::readObject(uint32_t memaddr, T &obj)
{
read(memaddr, (uint8_t *) &obj, sizeof(obj));
return memaddr + sizeof(obj);
}
uint32_t FRAM32::clear(uint8_t value)
{
uint8_t buf[16];

View File

@ -2,7 +2,7 @@
//
// FILE: FRAM.h
// AUTHOR: Rob Tillaart
// VERSION: 0.4.1
// VERSION: 0.4.2
// DATE: 2018-01-24
// PURPOSE: Arduino library for I2C FRAM
// URL: https://github.com/RobTillaart/FRAM_I2C
@ -13,7 +13,7 @@
#include "Wire.h"
#define FRAM_LIB_VERSION (F("0.4.1"))
#define FRAM_LIB_VERSION (F("0.4.2"))
#define FRAM_OK 0
@ -75,8 +75,8 @@ public:
uint16_t getManufacturerID(); // Fujitsu = 0x000A
uint16_t getProductID(); // Proprietary
uint16_t getSize(); // Returns size in KILO-BYTE (or 0)
uint32_t getSizeBytes() { return _sizeBytes; }; // Returns size in BYTE
void setSizeBytes(uint32_t value); // override when getSize() fails == 0
uint32_t getSizeBytes(); // Returns size in BYTE
void setSizeBytes(uint32_t value); // override when getSize() fails == 0
uint32_t clear(uint8_t value = 0); // fills FRAM with value
@ -95,7 +95,6 @@ protected:
uint16_t _getMetaData(uint8_t id);
void _writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
void _readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
};
@ -120,16 +119,8 @@ public:
uint32_t read32(uint32_t memaddr);
void read(uint32_t memaddr, uint8_t * obj, uint16_t size);
template <class T> uint32_t writeObject(uint32_t memaddr, T &obj)
{
write(memaddr, (uint8_t *) &obj, sizeof(obj));
return memaddr + sizeof(obj);
};
template <class T> uint32_t readObject(uint32_t memaddr, T &obj)
{
read(memaddr, (uint8_t *) &obj, sizeof(obj));
return memaddr + sizeof(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

View File

@ -0,0 +1,186 @@
//
// FILE: FRAM_RINGBUFFER.h
// AUTHOR: Rob Tillaart
// DATE: 2022-10-03
// PURPOSE: Arduino library for I2C FRAM based RING BUFFER
// URL: https://github.com/RobTillaart/FRAM_I2C
//
#include "FRAM_RINGBUFFER.h"
FRAM_RINGBUFFER::FRAM_RINGBUFFER()
{
}
uint32_t FRAM_RINGBUFFER::begin(FRAM *fram, uint32_t size, uint32_t start)
{
_fram = fram;
_size = size;
_start = start + 20; // allocate 5 uint32_t for storage.
flush();
_saved = false;
return _start + _size; // first free FRAM location.
}
//////////////////////////////////////////////////////////////////
//
// ADMINISTRATIVE
//
void FRAM_RINGBUFFER::flush()
{
_front = _tail = _start;
_count = 0;
_saved = false;
}
uint32_t FRAM_RINGBUFFER::size()
{
return _size;
}
uint32_t FRAM_RINGBUFFER::count()
{
return _count;
}
bool FRAM_RINGBUFFER::full()
{
return _count == _size;
}
bool FRAM_RINGBUFFER::empty()
{
return _count == 0;
}
uint32_t FRAM_RINGBUFFER::free()
{
return _size - _count;
}
float FRAM_RINGBUFFER::freePercent()
{
return (100.0 * _count) / _size;
}
// DEBUG
// uint32_t FRAM_RINGBUFFER::tail() { return _tail; };
// uint32_t FRAM_RINGBUFFER::front() { return _front; };
//////////////////////////////////////////////////////////////////
//
// BYTE INTERFACE
//
int FRAM_RINGBUFFER::write(uint8_t value)
{
if (full()) return FRAM_RB_ERR_BUF_FULL;
_fram->write8(_front, value);
_saved = false;
_front++;
_count++;
if (_front >= _start + _size) _front = _start;
return 1;
}
int FRAM_RINGBUFFER::read()
{
if (empty()) return FRAM_RB_ERR_BUF_EMPTY;
int value = _fram->read8(_tail);
_saved = false;
_tail++;
_count--;
if (_tail >= _start + _size) _tail = _start;
return value;
}
int FRAM_RINGBUFFER::peek()
{
if (empty()) return FRAM_RB_ERR_BUF_EMPTY;
int value = _fram->read8(_tail);
return value;
}
///////////////////////////////////////////////////
//
// MAKE RINGBUFFER PERSISTENT OVER REBOOTS
//
bool FRAM_RINGBUFFER::isSaved()
{
return _saved;
}
void FRAM_RINGBUFFER::save()
{
uint32_t pos = _start - 20;
if (not _saved)
{
uint32_t checksum = _size + _front + _tail + _count;
_fram->write32(pos + 0, _size );
_fram->write32(pos + 4, _front);
_fram->write32(pos + 8, _tail );
_fram->write32(pos + 12, _count);
_fram->write32(pos + 16, checksum);
_saved = true;
}
}
bool FRAM_RINGBUFFER::load()
{
uint32_t pos = _start - 20;
uint32_t size = _fram->read32(pos + 0);
uint32_t front = _fram->read32(pos + 4);
uint32_t tail = _fram->read32(pos + 8);
uint32_t count = _fram->read32(pos + 12);
uint32_t checksum = _fram->read32(pos + 16);
// checksum test should be enough.
// optional these are possible
// (_start <= _front) && (_front < _start + _size);
// (_start <= _tail) && (_tail < _start + _size);
_saved = (checksum == size + front + tail + count);
if (_saved)
{
_size = size;
_front = front;
_tail = tail;
_count = count;
}
return _saved;
}
void FRAM_RINGBUFFER::wipe()
{
uint32_t pos = _start - 20; // also overwrite metadata
while (pos < _start + _size - 4) // prevent writing adjacent FRAM
{
_fram->write32(pos, 0xFFFFFFFF);
pos += 4;
}
while (pos < _start + _size) // if _size not a multiple of 4.
{
_fram->write8(pos, 0xFF);
pos++;
}
flush(); // reset internal variables too.
}
// -- END OF FILE --

View File

@ -0,0 +1,154 @@
#pragma once
//
// FILE: FRAM_RINGBUFFER.h
// AUTHOR: Rob Tillaart
// DATE: 2022-10-03
// PURPOSE: Arduino library for I2C FRAM based ring buffer
// URL: https://github.com/RobTillaart/FRAM_I2C
//
#include "FRAM.h" // https://github.com/RobTillaart/FRAM_I2C
// ERROR CODES
#define FRAM_RB_OK 0
#define FRAM_RB_ERR_BUF_FULL -1
#define FRAM_RB_ERR_BUF_EMPTY -2
#define FRAM_RB_ERR_BUF_NO_ROOM -21 // (almost) full
#define FRAM_RB_ERR_BUF_NO_DATA -22 // (almost) empty
class FRAM_RINGBUFFER
{
public:
//////////////////////////////////////////////////////////////////
//
// CONSTRUCTOR + BEGIN
//
FRAM_RINGBUFFER();
// fram = pointer to FRAM object
// size in bytes
// memAddr in bytes where ring buffer starts
// returns uint32_t == first free (next) FRAM location.
uint32_t begin(FRAM *fram, uint32_t size, uint32_t memAddr);
//////////////////////////////////////////////////////////////////
//
// ADMINISTRATIVE
//
void flush();
uint32_t size();
uint32_t count();
uint32_t free();
float freePercent();
bool full();
bool empty();
// DEBUG
// uint32_t tail() { return _tail; };
// uint32_t front() { return _front; };
//////////////////////////////////////////////////////////////////
//
// BYTE INTERFACE
//
// returns bytes written.
// - FRAM_RB_ERR_BUF_FULL indicates full buffer.
int write(uint8_t value);
// returns value read
// - FRAM_RB_ERR_BUF_EMPTY indicates empty buffer.
int read();
// returns value read
// - FRAM_RB_ERR_BUF_EMPTY indicates empty buffer.
int peek();
//////////////////////////////////////////////////////////////////
//
// OBJECT INTERFACE
//
// returns bytes written.
// - FRAM_RB_ERR_BUF_NO_ROOM indicates (almost) full buffer
// ==> object does not fit.
template <class T> int write(T &obj)
{
uint8_t objectSize = sizeof(obj);
if ((_size - _count) < objectSize) return FRAM_RB_ERR_BUF_NO_ROOM;
uint8_t * p = (uint8_t *)&obj;
for (uint8_t i = 0; i < objectSize; i++)
{
write(*p++);
}
_saved = false;
return objectSize;
};
// returns bytes read.
// - FRAM_RB_ERR_BUF_NO_DATA indicates (almost) empty buffer
// ==> Too few bytes to read object.
template <class T> int read(T &obj)
{
uint8_t objectSize = sizeof(obj);
if (_count < objectSize) return FRAM_RB_ERR_BUF_NO_DATA;
uint8_t * p = (uint8_t *)&obj;
for (uint8_t i = 0; i < objectSize; i++)
{
*p++ = read();
}
_saved = false;
return objectSize;
};
// returns bytes read.
// - FRAM_RB_ERR_BUF_NO_DATA indicates (almost) empty buffer
// ==> Too few bytes to read object.
template <class T> int peek(T &obj)
{
uint8_t objectSize = sizeof(obj);
if (_count < objectSize) return FRAM_RB_ERR_BUF_NO_DATA;
bool prevSaved = _saved; // remember saved state
uint32_t previousTail = _tail; // remember _tail 'pointer'
int n = read(obj);
_tail = previousTail; // restore _tail 'pointer'
_saved = prevSaved; // restore _saved
_count += n;
return n;
};
///////////////////////////////////////////////////
//
// MAKE RINGBUFFER PERSISTENT OVER REBOOTS
//
bool isSaved();
// stores the internal variables + checksum.
// if you need constant persistency,
// call save() after every read() write() flush()
void save();
// retrieves the internal variables + verify checksum.
// returns false if checksum fails ==> data inconsistent (no load)
bool load();
// removes all data from ring buffer by overwriting the FRAM.
void wipe();
private:
uint32_t _count = 0; // optimization == front - tail (+ size)
uint32_t _size = 0;
uint32_t _start = 0;
uint32_t _front = _start;
uint32_t _tail = _start;
FRAM * _fram;
bool _saved = false;
};
// -- END OF FILE --

View File

@ -0,0 +1,144 @@
[![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)
[![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)
# FRAM_RINGBUFFER
Library for FRAM_RINGBUFFER to be used with the FRAM_I2C library.
## Description
FRAM_RINGBUFFER is a class that uses an FRAM object to implement
a ring buffer that can be made persistent over reboots.
The ring buffer can hold any size objects, but the user is responsible
to manage the contents.
This means it can hold objects of different sizes, but the user should
add this size and/or type info into the object, or preceding every object.
The FRAM_RINGBUFFER is build upon the FRAM_I2C library so it is not
expected to work with other FRAM libraries.
Types of FRAM that should work with this library:
| TYPE | SIZE | TESTED |
|:----------:|-------:|:------:|
| MB85RC04 | 512 | |
| MB85RC16 | 2 KB | |
| MB85RC64T | 8 KB | |
| MB85RC128A | 16 KB | |
| MB85RC256V | 32 KB | Y |
| MB85RC512T | 64 KB | |
| MB85RC1MT | 128 KB | |
Please let me know if you have verified one that is not in the list.
#### Version
As the FRAM_RINGBUFFER is strongly connected to FRAM_I2C
it has no separate version number.
## Interface
### Admin
- **FRAM_RINGBUFFER()** Constructor.
- **uint32_t begin(FRAM \*fram, uint32_t size, uint32_t memAddr)** initializes
the ring buffer.
- size is in bytes.
- memAddr is start memory address where ring buffer starts.
- returns uint32_t == first free (next) FRAM location.
- **void flush()** resets the internal administration.
- Note: flush() does not wipe the content from FRAM.
- **uint32_t size()** returns size.
- **uint32_t count()** returns count == bytes used.
- **uint32_t free()** returns the number of bytes free.
- **float freePercent()** returns the number of bytes free as percentage.
- **bool full()** returns true if the ring buffer has no free bytes left.
- **bool empty()** returns true if the ring buffer has no data in it.
### read / write (bytes)
- **int write(uint8_t value)** writes a byte to the ring buffer.
- returns the number of bytes written (1) or **FRAM_RB_ERR_BUF_FULL**
- **int read()** returns a byte from the ring buffer.
- returns **FRAM_RB_ERR_BUF_EMPTY** in case of an empty buffer.
- **int peek()** returns the next byte that would be read().
- returns **FRAM_RB_ERR_BUF_EMPTY** in case of an empty buffer.
### read / write (objects)
- **template <class T> int write(T &obj)** writes an object to the ring buffer.
- returns the number of bytes written or **FRAM_RB_ERR_BUF_NO_ROOM**
- see example how to use.
- **template <class T> int read(T &obj)** returns an object from the ring buffer.
- returns bytes read or **FRAM_RB_ERR_BUF_NO_DATA** if the buffer has less
bytes than the object requested.
- **template <class T> int peek(T &obj)** returns the next object in the ring buffer.
- returns bytes read or **FRAM_RB_ERR_BUF_NO_DATA** if the buffer has less
bytes than the object requested.
### persistency
- **bool isSaved()** returns true if the administration of the ring buffer
is written to FRAM.
- **void save()** stores the internal administration + checksum to FRAM.
- **bool load()** retrieves the internal administration + checksum from FRAM.
- returns true if checksum matches the stored variables. Only then the
variables of the ring buffer will be updated.
- **void wipe()** removes all data from ring buffer by overwriting the FRAM.
### Error codes
| value | description | Notes |
|:-------:|:-------------------------|:--------|
| 0 | FRAM_RB_OK |
| -1 | FRAM_RB_ERR_BUF_FULL |
| -2 | FRAM_RB_ERR_BUF_EMPTY |
| -21 | FRAM_RB_ERR_BUF_NO_ROOM | (almost) full
| -22 | FRAM_RB_ERR_BUF_NO_DATA | (almost) empty
## Operational
See examples.
## Future
### high
- elaborate FRAM_RINGBUFFER documentation
- add bool flag to **load(bool overrule = false)** to overrule the checksum verification.
- default false.
- add bool flag to **wipe(bool all = true)** to overwrite all or the
administration part only.
### medium
- example for a ring-buffer with different size objects
- struct with size and type info.
- preceding every object with type + size - 1..4 bytes
- add debugging tooling
- add object count?
### low
- create a RING_BUFFER class that can work with any type of storage.
- SD card, EEPROM etc.
### wont

View File

@ -14,10 +14,10 @@ Arduino library for I2C FRAM.
## Description
FRAM is a library to read from and write to (over I2C) an FRAM module.
The library has (since 0.4.0) two classes **FRAM** and **FRAM32**.
The library has (since 0.4.0) two classes **FRAM** and **FRAM32**.
The first is for the 16 bit devices and the latter for the 32 bit devices.
Currently only the **MB85RC1MT** is known to be 32 bit.
**FRAM32** can also address 16 bit devices although there is some overhead in footprint.
Currently only the **MB85RC1MT** is known to be 32 bit.
**FRAM32** can also address 16 bit devices although there is some overhead in footprint.
FRAM stands for Ferroelectric RAM - https://en.wikipedia.org/wiki/Ferroelectric_RAM
@ -44,7 +44,7 @@ Types of FRAM that should work with this library:
- Not all types of FRAM are tested. Please let me know if you have verified one that is not in the list.
- If there is no deviceID **getSize()** will not work correctly.
- Address = 0x50 (default) .. 0x57, depends on the lines A0..A2.
- **MB85RC1MT** uses even addresses only as it uses the next odd one internally. So 0x50 uses 0x51 internally for the upper 64 KB block.
- **MB85RC1MT** uses even addresses only as it uses the next odd one internally. So 0x50 uses 0x51 internally for the upper 64 KB block.
This latter will not be shown on an I2C scanner (to be tested).
@ -54,16 +54,18 @@ This latter will not be shown on an I2C scanner (to be tested).
### Constructor
- **FRAM(TwoWire \*wire = &Wire)** Constructor with optional Wire interface.
- **FRAM32(TwoWire \*wire = &Wire)** Constructor with optional Wire interface, specific for **MB85RC1MT** type of device.
- **FRAM32(TwoWire \*wire = &Wire)** Constructor with optional Wire interface,
specific for **MB85RC1MT** type of device.
- **int begin(uint8_t address = 0x50, int8_t writeProtectPin = -1)** address and writeProtectPin is optional.
Note the **MB85RC1MT** only uses even addresses.
Note the **MB85RC1MT** only uses even addresses.
- **int begin(int sda, int scl, uint8_t address = 0x50, int8_t writeProtectPin = -1)** idem for ESP32 a.o.
- **bool isConnected()** checks if the address is visible on the I2C bus.
### Write & read
Support for basic types and 2 calls for generic object, use casting if needed. In the **FRAM32** class these functions have an **uin32_t memaddr**.
Support for basic types and 2 calls for generic object, use casting if needed.
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
@ -76,21 +78,21 @@ Support for basic types and 2 calls for generic object, use casting if needed. I
One needs to allocate memory as the function won't.
(0.3.4 added template functions, see issue #13 )
- **uint16_t writeObject(uint16_t memaddr, T &obj)** writes an object to memaddr (and following bytes).
- **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.
- **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.
(0.3.5 added)
- **uint32_t clear(uint8_t value = 0)** clears the whole FRAM by writing value to all addresses - default zero's.
Returns the number of bytes written..
Returns the number of bytes written.
### Miscellaneous
- **bool setWriteProtect(bool b)** make the FRAM write-protected by pulling line HIGH / LOW.
Returns true if a writeProtectPin was defined.
Otherwise the FRAM cannot be write protected.
Otherwise the FRAM cannot be write protected.
Note the pin should be defined in **begin()**.
- **bool getWriteProtect()** get current write protect status.
- **uint16_t getManufacturerID()** idem. Fujitsu = 0x00A.
@ -102,19 +104,19 @@ Convenience wrapper, useful for iterating over the whole memory,
or testing the upper boundary.
- **void setSizeBytes(uint32_t value)** sets size in bytes for **getSizeBytes()**.
To be used only if **getSize()** cannot determine the size.
See also remark in Future section below.
See also remark in Future section below.
### Sleep
(0.3.6 added - experimental)
- **void sleep()** puts the FRAM in sleep mode so it uses less power.
Still needs a power test for 2 types of FRAM.
- **void sleep()** puts the FRAM in sleep mode so it uses less power.
Still needs a power test for several types of FRAM.
- **bool wakeup(uint32_t trec = 400)** tries to wake up the device with a default recovery time of 400 microseconds.
Returns true if connected after the call.
According to the data sheets there are only three FRAM devices support the sleep command.
So use with care.
So use with care.
| TYPE | SIZE | SLEEP (datasheet)| CURRENT | CONFIRMED | NOTES |
|:----------:|-------:|:----------------:|:---------:|:---------:|:--------|
@ -131,7 +133,7 @@ _current with \* are from datasheet_
### Current
Indicative power usage in uA in three modi (if supported).
Indicative power usage in uA in three modi (if supported).
| TYPE | SIZE | STANDBY | WRITE | SLEEP | NOTES |
@ -142,14 +144,21 @@ Indicative power usage in uA in three modi (if supported).
| MB85RC128A | 16 KB | | | - | |
| MB85RC256V | 32 KB | 10.22 uA | 93.48 uA | - | |
| MB85RC512T | 64 KB | | | 4.0 uA | |
| MB85RC1MT | 128 KB | 11.7 uA | 46-721 uA | 3.6 uA | See #17 |
| MB85RC1MT | 128 KB | 11.7 uA | 46-721 uA | 3.6 uA | See #17 |
_TODO: fill the table_
## Operational
See examples
See examples
## FRAM_RINGBUFFER
Since version 0.4.2 a separate class **FRAM_RINGBUFFER** is added.= to this repo.
Its interface is pretty straightforward and described in FRAM_RINGBUFFER.md.
The FRAM_ringbuffer.ino examples shows how the class can be used.
## Future
@ -161,7 +170,6 @@ _TODO: fill the table_
- now it is responsibility user.
- do we want/need this?
### medium
- **write()** and **writeBlock()** might write beyond the end of FRAM
@ -170,8 +178,6 @@ _TODO: fill the table_
- error flag ?
- extend examples
- FRAM for multi language string storage
- FRAM as linear buffer for a slow stream?
- FRAM as ring buffer
- FRAM logging, unequal length strings.
- FRAM (8x) concatenated as one continuous memory.

View File

@ -0,0 +1,128 @@
//
// FILE: FRAM_ringbuffer.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo FRAM_RINGBUFFER class.
// URL: https://github.com/RobTillaart/FRAM_I2C
// experimental code
#include "FRAM.h"
#include "FRAM_RINGBUFFER.h"
FRAM fram;
uint32_t sizeInBytes = 0;
FRAM_RINGBUFFER fb;
// demo struct
struct GPSBuffer {
float lat;
float lon;
float speed;
float alt;
} gps_data;
///////////////////////////////////////////////////////////
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("FRAM_LIB_VERSION: ");
Serial.println(FRAM_LIB_VERSION);
Wire.begin();
int rv = fram.begin(0x50);
if (rv != 0)
{
Serial.print("INIT ERROR: ");
Serial.println(rv);
}
// get size in bytes
sizeInBytes = fram.getSize() * 1024;
// clear FRAM
for (uint32_t addr = 0; addr < sizeInBytes; addr++)
{
fram.write8(addr, 0x00);
}
// initialize the ring buffer.
fb.begin(&fram, 1600, 0);
// clear the ring buffer.
fb.flush();
if (fb.load() == false)
{
Serial.println("FB.LOAD() ERROR: ");
}
// dump initial state.
dump();
// add some bytes.
for (int i = 0; i < 10; i++)
{
fb.write('A' + i); // write ABCDEFGHIJ
}
Serial.print("PEEK:\t");
Serial.println(fb.peek());
dump();
// read some bytes.
for (int i = 0; i < 3; i++)
{
fb.read();
}
Serial.print("PEEK:\t");
Serial.println(fb.peek());
dump();
fb.flush();
for (int i = 0; i < 10; i++)
{
fb.write(gps_data);
}
dump();
fb.flush();
float f = 3.14159265;
for (int i = 0; i < 10; i++)
{
fb.write(f);
}
dump();
}
void loop()
{
}
void dump()
{
Serial.print("\n");
Serial.print("SIZE:\t");
Serial.println(fb.size());
Serial.print("COUNT:\t");
Serial.println(fb.count());
Serial.print("FULL:\t");
Serial.println(fb.full());
Serial.print("EMPTY:\t");
Serial.println(fb.empty());
Serial.print("FREE:\t");
Serial.println(fb.free());
Serial.print("percent:\t");
Serial.println(fb.freePercent(), 1);
}
// -- END OF FILE --

View File

@ -0,0 +1,162 @@
//
// FILE: FRAM_ringbuffer_II.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo FRAM_RINGBUFFER class.
// URL: https://github.com/RobTillaart/FRAM_I2C
// experimental code / playground with 2 ringbuffers
#include "FRAM.h"
#include "FRAM_RINGBUFFER.h"
FRAM fram;
uint32_t sizeInBytes = 0;
FRAM_RINGBUFFER fb;
FRAM_RINGBUFFER fb2;
// demo struct
struct record
{
uint32_t time;
float value;
} data;
///////////////////////////////////////////////////////////
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("FRAM_LIB_VERSION: ");
Serial.println(FRAM_LIB_VERSION);
Wire.begin();
Wire.setClock(400000);
int rv = fram.begin(0x50);
if (rv != 0)
{
Serial.print("INIT ERROR: ");
Serial.println(rv);
}
// get size in bytes
sizeInBytes = fram.getSize() * 1024;
Serial.print("FRAMSIZE:\t");
Serial.println(sizeInBytes);
// clear FRAM optional
// for (uint32_t addr = 0; addr < sizeInBytes; addr += 4)
// {
// fram.write32(addr, 0);
// }
// initialize the two ring buffers.
uint32_t nextAddr = fb.begin(&fram, 80, 0);
nextAddr = fb2.begin(&fram, 80, nextAddr);
Serial.print("NEXTADDR:\t");
Serial.println(nextAddr);
// if you want to start VERY clean...
// fb.wipe();
// fb2.wipe();
if (fb.load() == false)
{
Serial.println("FB.LOAD() FAILED.");
// clear the ring buffer when it could not be loaded from FRAM.
fb.flush();
// only the first 10 will fit.
for (int i = 0; i < 15; i++)
{
data.time = millis();
data.value = sin(data.time / 1024.0);
int rv = fb.write(data);
Serial.print(data.time);
Serial.print("\t");
Serial.print(data.value, 4);
Serial.print("\t");
Serial.println(rv);
delay(100);
}
// make it persistent.
fb.save();
}
while (!fb.empty())
{
fb.read(data);
Serial.print("buf 1");
Serial.print("\t");
Serial.print(data.time);
Serial.print("\t");
Serial.println(data.value, 4);
data.value *= 2;
fb2.write(data);
}
while (!fb2.empty())
{
fb2.read(data);
Serial.print("buf 2");
Serial.print("\t");
Serial.print(data.time);
Serial.print("\t");
Serial.println(data.value, 4);
}
}
void loop()
{
}
///////////////////////////////////////////////////////
void dump()
{
Serial.print("\n");
Serial.print("SIZE:\t");
Serial.println(fb.size());
Serial.print("COUNT:\t");
Serial.println(fb.count());
Serial.print("FULL:\t");
Serial.println(fb.full());
Serial.print("EMPTY:\t");
Serial.println(fb.empty());
Serial.print("FREE:\t");
Serial.println(fb.free());
Serial.print("percent:\t");
Serial.println(fb.freePercent(), 1);
}
void dump2()
{
Serial.print("\n");
Serial.print("SIZE:\t");
Serial.println(fb2.size());
Serial.print("COUNT:\t");
Serial.println(fb2.count());
Serial.print("FULL:\t");
Serial.println(fb2.full());
Serial.print("EMPTY:\t");
Serial.println(fb2.empty());
Serial.print("FREE:\t");
Serial.println(fb2.free());
Serial.print("percent:\t");
Serial.println(fb2.freePercent(), 1);
}
// -- END OF FILE --

View File

@ -3,6 +3,7 @@
# Data types (KEYWORD1)
FRAM KEYWORD1
FRAM32 KEYWORD1
FRAM_RINGBUFFER KEYWORD1
# Methods and Functions (KEYWORD2)
@ -36,6 +37,27 @@ sleep KEYWORD2
wakeup KEYWORD2
# Methods and Functions FRAM_RINGBUFFER
begin KEYWORD2
flush KEYWORD2
size KEYWORD2
count KEYWORD2
free KEYWORD2
freePercent KEYWORD2
full KEYWORD2
empty KEYWORD2
write KEYWORD2
read KEYWORD2
peek KEYWORD2
isSaved KEYWORD2
save KEYWORD2
load KEYWORD2
wipe KEYWORD2
# Constants (LITERAL1)
FRAM_LIB_VERSION LITERAL1
FRAM_OK LITERAL1
@ -51,3 +73,12 @@ FRAM_MB85RC256V LITERAL1
FRAM_MB85RC512T LITERAL1
FRAM_MB85RC1MT LITERAL1
# constants FRAM_RINGBUFFER
FRAM_RB_OK LITERAL1
FRAM_RB_ERR_BUF_FULL LITERAL1
FRAM_RB_ERR_BUF_EMPTY LITERAL1
FRAM_RB_ERR_BUF_NO_ROOM LITERAL1
FRAM_RB_ERR_BUF_NO_DATA LITERAL1

View File

@ -1,7 +1,7 @@
{
"name": "FRAM_I2C",
"keywords": "FRAM, storage",
"description": "Library for FRAM for Arduino.",
"description": "Library for FRAM for Arduino. Includes an experimental FRAM_RINGBUFFER class (since 0.4.2)",
"authors":
[
{
@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/FRAM_I2C.git"
},
"version": "0.4.1",
"version": "0.4.2",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,9 +1,9 @@
name=FRAM_I2C
version=0.4.1
version=0.4.2
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for I2C FRAM.
paragraph=
paragraph=Includes an experimental FRAM_RINGBUFFER class.
category=Data Storage
url=https://github.com/RobTillaart/FRAM_I2C.git
architectures=*