-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRingBuffer.h
152 lines (122 loc) · 6.9 KB
/
RingBuffer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#pragma once
/*
The MIT License (MIT)
Copyright (c) 2023 Robert E Bridges
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
On a personal note, if you develop an application or product using this library
and make millions of dollars, I'm happy for you!
*/
/*
Code by Robert E Bridges bob@bricomp-uk.com
Revision Date Author Description
1.00 04/05/2023 Robert E Bridges - Initial release
1.10 05/05/2023 Robert E Bridges - Option added to allow ReadNext to change direction.
This library is designed to offer a Ring buffer control aka Roladex.
Although other libraries exist they are usually limited to storing standard numeric
types, eg uint32_t, int etc. With this library you can use any type you wish, create
your own type in a struct and use that. No problem.
The library manages the index into the array/storage structure. It is NOT limited to
storage in an array in memory but could be used to store data in EEPROM, SD card or
any other storage medium.
Note that this library does NOT store any data but manages the returning of an index
into an Array or Data Structure to indicate where to store or retrieve the data.
If you examine the Example "TestRingBuffer" I have used an array of char, just because
it's easy to track the addition of ASCII characters to demonstrate useage.
You start off by defining your storage medium. As I said before it can be used for
any storage medium but for the purposes of describing it's useage I will use arrays
by way of examples.
Then create an instance of the "RingBuffer" passing the Maximum size of the array.
By maximum size I mean maximum index, NOT the storage size i.e. data[ maximumSize].
Ok, that's it we can now start storing data into our "Rolodex" type storage medium.
To add data just use "AddDataToBuffer()". This function returns the index of the array
where the data is to be stored. So useage is buffer[ cBuf.AddDataToBuffe() ] = dataChar.
You can keep on adding data to your hearts content, storing many more items than the
original array could accomodate. Bear in mind that once you have exceeded the size of the
original array that the data will roll over and overwrite the original data. The array index
returned by "AddDataToBuffer()" will always be a legal array location. Think of this like
having completely filled your Rolodex and have to remove a card to add new information.
The library works in a LIFO manner.
Having stored the data you will want to do something with it. Retrieval of the data starts
by using the functions either "ReadFromHead()" or "ReadFromTail()". Head represents the
last entered data and tail represents the first entered data. "ReadFromHead()" and
"ReadFromTail()" both return an index into the array of data. they can be used like:-
Serial.print( buffer[ cBuf.ReadFromHead() ] ); where the data is returned from the array
and printed.
In order to continue retrieving data from the store (array) we now use the function
"ReadNext()". This returns the next array index in the sequence and is used in the
same manner as the previously described functions "ReadFromHead()" and "ReadFromTail()",
those having set the direction for subsequent "ReadNext()"s. As you can imagine it would
be possible to read past head or tail which would give rise to an erroneous condition.
To ensure that this does not happen the boolean variable "BadCommand" is set to true
and the index returned by "ReadNext()" is NOT incremented or decremented, i.e. the
previous value is returned.
Note that as of vs 1.10 ReadNext can have the optional option to change read direction.
ReadNext() returns the next data index in the original set direction whilst ReadNext(true)
changes the direction and returns the previous index.
The boolean variable is reset to false by using either "ReadFromHead() or "ReadFromTail()" again.
In order to help with data management there are two functions which return array information.
these are "MaxBufferSize()", which effectively returns the original maximum array index passed
when the instance of RingBuffer was created, and "currentBufferLength()" which returns the
number of entries into the array. If the system has started to roll over then "currentBufferLength()"
will be the same as "MaxBufferSize()".
Obviously before any data has been added "currentBufferLength()" will be zero.
Should you wish to power down your system but not lose your Ring Buffer database then you can use
the function "SaveRBInfo". First start by saving your ArrayData away then get the RingBuffer
internal data with "RingBuffer::infoType rbData = SaveRBData();" then save that datya away.
To recover your Ring Buffer restore your array data and then read in your cbData and then
use the function "RestoreRBInfo( rbData )" to put the data back. This function attempts to check
the validity of the data and return bool if the data looks legal. If false is returned the data is
not valid and the RingBuffer internal variables will NOT have been updated.
*/
#include "Arduino.h"
class RingBuffer {
public:
enum dirType {
forward,
backward
};
struct infoType {
uint32_t h;
uint32_t t;
uint32_t bS;
uint32_t lRL;
dirType rD;
uint32_t lRP;
uint32_t lAL;
bool c;
};
const char revision[5] = "1.00";
const uint32_t revisionNum = 100;
bool badCommand;
RingBuffer(uint32_t bufferSize);
uint32_t AddDataToBuffer();
uint32_t MaxBufferSize();
uint32_t currentBufferLength();
uint32_t ReadFromTail();
uint32_t ReadFromHead();
uint32_t ReadNext(bool changeDirectionn = false);
infoType SaveRBInfo();
bool RestoreRBInfo(infoType info);
private:
uint32_t head;
uint32_t tail;
uint32_t bufSize;
uint32_t lastReadLocn;
dirType readDirection;
uint32_t lastReadPos;
uint32_t lastArrayLocn;
bool circulating;
};