GY-63_MS5611/libraries/FRAM_I2C/FRAM_RINGBUFFER.cpp

187 lines
3.4 KiB
C++
Raw Normal View History

2022-10-16 13:09:32 -04:00
//
// 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 --