Skip to content

Commit 273cf1a

Browse files
committed
Fixed compiler errors and added readme
1 parent 5c5b8ea commit 273cf1a

File tree

5 files changed

+200
-26
lines changed

5 files changed

+200
-26
lines changed

README.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# ArduinoRingBuffer
2+
3+
This is a simple ring (FIFO) buffer queuing library for embedded platforms, such as Arduino's. This library is based on a previous one I wrote, only now in C++ instead of C. It uses C++'s templating, so weird no more weird pointer casting, and deep copies of objects are supported. It has concurrency protection built in, so feel free to do operations
4+
on the buffer inside of ISR's. All memory is statically allocated at compile time, so no heap memory is used. It can buffer any fixed size object (ints, floats, structs, objects, etc...).
5+
6+
## FAQ's
7+
<dl>
8+
<dt>I only have a C compiler for my platform</dt>
9+
<dd>No worries, try the vanilla C version of the library.</dd>
10+
</dl>
11+
12+
13+
## Use Cases
14+
15+
A ring buffer is used when passing asynchronous io between two threads. In the case of the Arduino, it is very useful for buffering data in an interrupt routine that is later processed in your `void loop()`.
16+
17+
## Supported Platforms
18+
The library currently supports:
19+
- AVR
20+
- ESP8266
21+
- Any other platform (just implement the `RB_ATOMIC_START` and `RB_ATOMIC_END` macros)
22+
23+
## Install
24+
25+
This library is now available in the Arduino Library Manager, directly in the IDE. Go to `Sketch > Include Library > Manage Libraries` and search for `RingBuf`.
26+
27+
To manually install this library, download this file as a zip, and extract the resulting folder into your Arduino Libraries folder. [Installing an Arduino Library] (https://www.arduino.cc/en/Guide/Libraries).
28+
29+
## Examples
30+
31+
Look at the examples folder for several examples.
32+
33+
## Contributing
34+
35+
If you find this Arduino library helpful, click the Star button, and you will make my day.
36+
37+
Feel free to improve this library. Fork it, make your changes, then submit a pull request!
38+
39+
## API
40+
41+
42+
### Constructor
43+
44+
```c++
45+
RingBuf<typename Type, uint16_t MaxElements>();
46+
```
47+
48+
Creates a new RingBuf object that can buffer up to MaxElements of type Type.
49+
50+
51+
## Methods
52+
53+
54+
### add()
55+
56+
```c++
57+
bool add(Type &obj);
58+
```
59+
60+
Append an element to the buffer. Return true on success, false on a full buffer.
61+
62+
### peek()
63+
64+
```c++
65+
Type *peek(uint16_t num);
66+
```
67+
68+
Peek at the num'th element in the buffer. Returns a pointer to the location of the num'th element. If num is out of bounds or the num'th element is empty, a NULL pointer is returned. Note that this gives you direct memory access to the location of the num'th element in the buffer, allowing you to directly edit elements in the buffer. Note that while all of RingBuf's public methods are atomic (including this one), directly using the pointer returned from this method is not safe. If there is a possibility an interrupt could fire and remove/modify the item pointed to by the returned pointer, disable interrupts first with `noInterrupts()`, do whatever you need to do with the pointer, then you can reenable interrupts by calling `interrupts()`.
69+
70+
### pull()
71+
72+
```c++
73+
bool pull(Type *dest);
74+
```
75+
76+
Pull the first element out of the buffer. The first element is copied into the location pointed to by dest. Returns false if the buffer is empty, otherwise returns true on success.
77+
78+
79+
### numElements()
80+
```c++
81+
uint16_t numElements();
82+
```
83+
84+
Returns number of elements in the buffer.
85+
86+
### isFull()
87+
```c++
88+
bool isFull();
89+
```
90+
91+
Returns true if buffer is full, otherwise false.
92+
93+
94+
### isEmpty()
95+
96+
```c++
97+
bool isEmpty();
98+
```
99+
100+
Returns true if buffer is empty, false otherwise.
101+
102+
## License
103+
104+
This library is open-source, and licensed under the [MIT license](http://opensource.org/licenses/MIT). Do whatever you like with it, but contributions are appreciated.

RingBuf.cpp

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,107 @@
1-
#include "RingBuf.h"
1+
//#include "RingBuf.h"
22

33
template <typename Type, uint16_t MaxElements>
44
RingBuf<Type, MaxElements>::RingBuf()
5-
: _buf{ 0 }
5+
//: _buf{ 0 }
66
{
7-
_numElements = 0;
7+
RB_ATOMIC_START
8+
{
9+
_numElements = 0;
810

9-
_head = 0;
11+
_head = 0;
12+
}
13+
RB_ATOMIC_END
1014
}
1115

1216
template <typename Type, uint16_t MaxElements>
1317
bool RingBuf<Type, MaxElements>::add(Type &obj)
1418
{
15-
if (isFull())
16-
return false;
19+
RB_ATOMIC_START
20+
{
21+
if (isFull())
22+
return false;
1723

18-
_buf[_head] = obj;
19-
_head = (_head + 1)%MaxElements;
20-
numElements++;
21-
return true;
24+
_buf[_head] = obj;
25+
_head = (_head + 1)%MaxElements;
26+
_numElements++;
27+
return true;
28+
}
29+
RB_ATOMIC_END
2230
}
2331

2432
template <typename Type, uint16_t MaxElements>
2533
bool RingBuf<Type, MaxElements>::pull(Type *dest)
2634
{
27-
uint16_t tail;
35+
RB_ATOMIC_START
36+
{
37+
uint16_t tail;
2838

29-
if (isEmpty())
30-
return false;
39+
if (isEmpty())
40+
return false;
3141

32-
tail = getTail();
42+
tail = getTail();
3343

34-
*dest = _buf[tail];
35-
numElements--;
36-
return true;
44+
*dest = _buf[tail];
45+
_numElements--;
46+
return true;
47+
}
48+
RB_ATOMIC_END
3749
}
3850

3951
template <typename Type, uint16_t MaxElements>
4052
bool RingBuf<Type, MaxElements>::isFull()
4153
{
42-
return numElements >= MaxElements;
54+
RB_ATOMIC_START
55+
{
56+
return _numElements >= MaxElements;
57+
}
58+
RB_ATOMIC_END
4359
}
4460

4561
template <typename Type, uint16_t MaxElements>
4662
uint16_t RingBuf<Type, MaxElements>::numElements()
4763
{
48-
return numElements;
64+
RB_ATOMIC_START
65+
{
66+
return _numElements;
67+
}
68+
RB_ATOMIC_END
4969
}
5070

5171
template <typename Type, uint16_t MaxElements>
5272
bool RingBuf<Type, MaxElements>::isEmpty()
5373
{
54-
return !numElements;
74+
RB_ATOMIC_START
75+
{
76+
return !_numElements;
77+
}
78+
RB_ATOMIC_END
5579
}
5680

5781
template <typename Type, uint16_t MaxElements>
5882
Type *RingBuf<Type, MaxElements>::peek(uint16_t num)
5983
{
60-
if (num >= numElements)
61-
return NULL;
84+
RB_ATOMIC_START
85+
{
86+
if (num >= _numElements)
87+
return NULL;
6288

63-
return &_buf[(getTail() + num)%MaxElements];
89+
return &_buf[(getTail() + num)%MaxElements];
90+
}
91+
RB_ATOMIC_END
6492
}
6593

94+
// ONLY CALL WHEN SAFE
6695
template <typename Type, uint16_t MaxElements>
6796
uint16_t RingBuf<Type, MaxElements>::getTail()
6897
{
6998
return (_head + (MaxElements - _numElements))%MaxElements;
7099
}
100+
/*
101+
void TemporaryFunction()
102+
{
103+
RingBuf<bool, 1> TempObj;
104+
bool b = true;
105+
TempObj.add(b);
106+
}
107+
*/

RingBuf.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
#ifndef RINGBUG_FIFO_H
2-
#define RINGBUF_FIFO_H
1+
#ifndef EM_RINGBUF_FIFO_CPP_H
2+
#define EM_RINGBUF_FIFO_CPP_H
3+
4+
// TODO fix this
5+
#define NULL (void *)(0)
36

47
#ifdef ARDUINO
58
#include <Arduino.h>
@@ -46,7 +49,6 @@
4649
#endif
4750

4851
template <typename Type, uint16_t MaxElements>
49-
5052
class RingBuf
5153
{
5254
public:
@@ -101,4 +103,6 @@ uint16_t _numElements;
101103
private:
102104

103105
};
106+
107+
#include "RingBuf.cpp"
104108
#endif

a.out

8.59 KB
Binary file not shown.

test.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include <stdio.h>
2+
#include "RingBuf.h"
3+
#include <stdint.h>
4+
#include <stdlib.h>
5+
6+
int main()
7+
{
8+
RingBuf<int, 5> q;
9+
int tmp = 12;
10+
//q.add(tmp);
11+
12+
for (uint16_t i=0; i< 100; i++) {
13+
int tmp = random();
14+
15+
if (q.add(tmp)) {
16+
printf("Added %d\n", tmp);
17+
}
18+
else {
19+
q.pull(&tmp);
20+
break;
21+
}
22+
}
23+
24+
while(!q.isEmpty()) {
25+
int pulled;
26+
q.pull(&pulled);
27+
printf("Got %d\n", pulled);
28+
}
29+
}

0 commit comments

Comments
 (0)