Skip to content

Commit

Permalink
Add FRAM based ring buffer class (#24)
Browse files Browse the repository at this point in the history
* initial version FRAM_RINGBUFFER class
* add (object, size) API calls
* add persistence interface
* update documentation + version number
  • Loading branch information
RobTillaart authored Oct 16, 2022
1 parent a572a68 commit d2a0622
Show file tree
Hide file tree
Showing 13 changed files with 892 additions and 42 deletions.
19 changes: 18 additions & 1 deletion .arduino-ci.yml
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -8,4 +23,6 @@ compile:
- m4
- esp32
- esp8266
# - mega2560
# - mega2560
- rpipico

11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 21 additions & 1 deletion FRAM.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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];
Expand Down
21 changes: 6 additions & 15 deletions FRAM.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -75,8 +75,8 @@ class FRAM
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

Expand All @@ -95,7 +95,6 @@ class FRAM
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);

};


Expand All @@ -120,16 +119,8 @@ class FRAM32 : public FRAM
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

Expand Down
186 changes: 186 additions & 0 deletions FRAM_RINGBUFFER.cpp
Original file line number Diff line number Diff line change
@@ -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 --

Loading

0 comments on commit d2a0622

Please # to comment.