mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
155 lines
3.9 KiB
C
155 lines
3.9 KiB
C
|
#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 --
|
||
|
|