Skip to content

Commit d2a0622

Browse files
authored
Add FRAM based ring buffer class (#24)
* initial version FRAM_RINGBUFFER class * add (object, size) API calls * add persistence interface * update documentation + version number
1 parent a572a68 commit d2a0622

13 files changed

+892
-42
lines changed

.arduino-ci.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
platforms:
2+
rpipico:
3+
board: rp2040:rp2040:rpipico
4+
package: rp2040:rp2040
5+
gcc:
6+
features:
7+
defines:
8+
- ARDUINO_ARCH_RP2040
9+
warnings:
10+
flags:
11+
12+
packages:
13+
rp2040:rp2040:
14+
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
15+
116
compile:
217
# Choosing to run compilation tests on 2 different Arduino platforms
318
platforms:
@@ -8,4 +23,6 @@ compile:
823
- m4
924
- esp32
1025
- esp8266
11-
# - mega2560
26+
# - mega2560
27+
- rpipico
28+

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

77

8+
## [0.4.2] - 2022-10-03
9+
10+
### Added
11+
- FRAM_RINGBUFFER class - see FRAM_RINGBUFFER.md
12+
- build-ci support for RP2040 pico
13+
14+
### Changed
15+
- updated documentation
16+
- moved code from FRAM.h to FRAM.cpp
17+
18+
819
## [0.4.1] - 2022-09-24
920

1021
### Added

FRAM.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// FILE: FRAM.cpp
33
// AUTHOR: Rob Tillaart
4-
// VERSION: 0.4.1
4+
// VERSION: 0.4.2
55
// DATE: 2018-01-24
66
// PURPOSE: Arduino library for I2C FRAM
77
// URL: https://github.com/RobTillaart/FRAM_I2C
@@ -212,6 +212,12 @@ uint16_t FRAM::getSize()
212212
}
213213

214214

215+
uint32_t FRAM::getSizeBytes()
216+
{
217+
return _sizeBytes;
218+
};
219+
220+
215221
// override to be used when getSize() fails == 0
216222
void FRAM::setSizeBytes(uint32_t value)
217223
{
@@ -419,6 +425,20 @@ void FRAM32::read(uint32_t memaddr, uint8_t * obj, uint16_t size)
419425
}
420426

421427

428+
template <class T> uint32_t FRAM32::writeObject(uint32_t memaddr, T &obj)
429+
{
430+
write(memaddr, (uint8_t *) &obj, sizeof(obj));
431+
return memaddr + sizeof(obj);
432+
};
433+
434+
435+
template <class T> uint32_t FRAM32::readObject(uint32_t memaddr, T &obj)
436+
{
437+
read(memaddr, (uint8_t *) &obj, sizeof(obj));
438+
return memaddr + sizeof(obj);
439+
}
440+
441+
422442
uint32_t FRAM32::clear(uint8_t value)
423443
{
424444
uint8_t buf[16];

FRAM.h

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// FILE: FRAM.h
44
// AUTHOR: Rob Tillaart
5-
// VERSION: 0.4.1
5+
// VERSION: 0.4.2
66
// DATE: 2018-01-24
77
// PURPOSE: Arduino library for I2C FRAM
88
// URL: https://github.com/RobTillaart/FRAM_I2C
@@ -13,7 +13,7 @@
1313
#include "Wire.h"
1414

1515

16-
#define FRAM_LIB_VERSION (F("0.4.1"))
16+
#define FRAM_LIB_VERSION (F("0.4.2"))
1717

1818

1919
#define FRAM_OK 0
@@ -75,8 +75,8 @@ class FRAM
7575
uint16_t getManufacturerID(); // Fujitsu = 0x000A
7676
uint16_t getProductID(); // Proprietary
7777
uint16_t getSize(); // Returns size in KILO-BYTE (or 0)
78-
uint32_t getSizeBytes() { return _sizeBytes; }; // Returns size in BYTE
79-
void setSizeBytes(uint32_t value); // override when getSize() fails == 0
78+
uint32_t getSizeBytes(); // Returns size in BYTE
79+
void setSizeBytes(uint32_t value); // override when getSize() fails == 0
8080

8181
uint32_t clear(uint8_t value = 0); // fills FRAM with value
8282

@@ -95,7 +95,6 @@ class FRAM
9595
uint16_t _getMetaData(uint8_t id);
9696
void _writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
9797
void _readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size);
98-
9998
};
10099

101100

@@ -120,16 +119,8 @@ class FRAM32 : public FRAM
120119
uint32_t read32(uint32_t memaddr);
121120
void read(uint32_t memaddr, uint8_t * obj, uint16_t size);
122121

123-
template <class T> uint32_t writeObject(uint32_t memaddr, T &obj)
124-
{
125-
write(memaddr, (uint8_t *) &obj, sizeof(obj));
126-
return memaddr + sizeof(obj);
127-
};
128-
template <class T> uint32_t readObject(uint32_t memaddr, T &obj)
129-
{
130-
read(memaddr, (uint8_t *) &obj, sizeof(obj));
131-
return memaddr + sizeof(obj);
132-
}
122+
template <class T> uint32_t writeObject(uint32_t memaddr, T &obj);
123+
template <class T> uint32_t readObject(uint32_t memaddr, T &obj);
133124

134125
uint32_t clear(uint8_t value = 0); // fills FRAM with value
135126

FRAM_RINGBUFFER.cpp

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
//
2+
// FILE: FRAM_RINGBUFFER.h
3+
// AUTHOR: Rob Tillaart
4+
// DATE: 2022-10-03
5+
// PURPOSE: Arduino library for I2C FRAM based RING BUFFER
6+
// URL: https://github.com/RobTillaart/FRAM_I2C
7+
//
8+
9+
10+
#include "FRAM_RINGBUFFER.h"
11+
12+
13+
FRAM_RINGBUFFER::FRAM_RINGBUFFER()
14+
{
15+
}
16+
17+
18+
uint32_t FRAM_RINGBUFFER::begin(FRAM *fram, uint32_t size, uint32_t start)
19+
{
20+
_fram = fram;
21+
_size = size;
22+
_start = start + 20; // allocate 5 uint32_t for storage.
23+
flush();
24+
_saved = false;
25+
return _start + _size; // first free FRAM location.
26+
}
27+
28+
29+
//////////////////////////////////////////////////////////////////
30+
//
31+
// ADMINISTRATIVE
32+
//
33+
void FRAM_RINGBUFFER::flush()
34+
{
35+
_front = _tail = _start;
36+
_count = 0;
37+
_saved = false;
38+
}
39+
40+
41+
uint32_t FRAM_RINGBUFFER::size()
42+
{
43+
return _size;
44+
}
45+
46+
47+
uint32_t FRAM_RINGBUFFER::count()
48+
{
49+
return _count;
50+
}
51+
52+
53+
bool FRAM_RINGBUFFER::full()
54+
{
55+
return _count == _size;
56+
}
57+
58+
59+
bool FRAM_RINGBUFFER::empty()
60+
{
61+
return _count == 0;
62+
}
63+
64+
65+
uint32_t FRAM_RINGBUFFER::free()
66+
{
67+
return _size - _count;
68+
}
69+
70+
71+
float FRAM_RINGBUFFER::freePercent()
72+
{
73+
return (100.0 * _count) / _size;
74+
}
75+
76+
// DEBUG
77+
// uint32_t FRAM_RINGBUFFER::tail() { return _tail; };
78+
// uint32_t FRAM_RINGBUFFER::front() { return _front; };
79+
80+
81+
//////////////////////////////////////////////////////////////////
82+
//
83+
// BYTE INTERFACE
84+
//
85+
int FRAM_RINGBUFFER::write(uint8_t value)
86+
{
87+
if (full()) return FRAM_RB_ERR_BUF_FULL;
88+
_fram->write8(_front, value);
89+
_saved = false;
90+
_front++;
91+
_count++;
92+
if (_front >= _start + _size) _front = _start;
93+
return 1;
94+
}
95+
96+
97+
int FRAM_RINGBUFFER::read()
98+
{
99+
if (empty()) return FRAM_RB_ERR_BUF_EMPTY;
100+
int value = _fram->read8(_tail);
101+
_saved = false;
102+
_tail++;
103+
_count--;
104+
if (_tail >= _start + _size) _tail = _start;
105+
return value;
106+
}
107+
108+
109+
int FRAM_RINGBUFFER::peek()
110+
{
111+
if (empty()) return FRAM_RB_ERR_BUF_EMPTY;
112+
int value = _fram->read8(_tail);
113+
return value;
114+
}
115+
116+
117+
///////////////////////////////////////////////////
118+
//
119+
// MAKE RINGBUFFER PERSISTENT OVER REBOOTS
120+
//
121+
bool FRAM_RINGBUFFER::isSaved()
122+
{
123+
return _saved;
124+
}
125+
126+
127+
void FRAM_RINGBUFFER::save()
128+
{
129+
uint32_t pos = _start - 20;
130+
if (not _saved)
131+
{
132+
uint32_t checksum = _size + _front + _tail + _count;
133+
_fram->write32(pos + 0, _size );
134+
_fram->write32(pos + 4, _front);
135+
_fram->write32(pos + 8, _tail );
136+
_fram->write32(pos + 12, _count);
137+
_fram->write32(pos + 16, checksum);
138+
_saved = true;
139+
}
140+
}
141+
142+
143+
bool FRAM_RINGBUFFER::load()
144+
{
145+
uint32_t pos = _start - 20;
146+
uint32_t size = _fram->read32(pos + 0);
147+
uint32_t front = _fram->read32(pos + 4);
148+
uint32_t tail = _fram->read32(pos + 8);
149+
uint32_t count = _fram->read32(pos + 12);
150+
uint32_t checksum = _fram->read32(pos + 16);
151+
// checksum test should be enough.
152+
// optional these are possible
153+
// (_start <= _front) && (_front < _start + _size);
154+
// (_start <= _tail) && (_tail < _start + _size);
155+
_saved = (checksum == size + front + tail + count);
156+
if (_saved)
157+
{
158+
_size = size;
159+
_front = front;
160+
_tail = tail;
161+
_count = count;
162+
}
163+
return _saved;
164+
}
165+
166+
167+
void FRAM_RINGBUFFER::wipe()
168+
{
169+
uint32_t pos = _start - 20; // also overwrite metadata
170+
while (pos < _start + _size - 4) // prevent writing adjacent FRAM
171+
{
172+
_fram->write32(pos, 0xFFFFFFFF);
173+
pos += 4;
174+
}
175+
while (pos < _start + _size) // if _size not a multiple of 4.
176+
{
177+
_fram->write8(pos, 0xFF);
178+
pos++;
179+
}
180+
flush(); // reset internal variables too.
181+
}
182+
183+
184+
185+
// -- END OF FILE --
186+

0 commit comments

Comments
 (0)