Skip to content

Commit 311c6a0

Browse files
committed
Added numElements() method and added examples
1 parent dc627ab commit 311c6a0

5 files changed

Lines changed: 211 additions & 9 deletions

File tree

README.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
# ArduinoRingBuffer
22

3-
This is a simple ring buffer library for the Arduino. It is written in vanilla C, and can easily be modified to work with other platforms simply be removing the `#include "Arduino.h" `.
4-
5-
6-
I have heard about object orinted progrming in pure C, and I decided to give it a shot with this library. Using C structs and function pointers, one creates a RingBuf object that is complete with its own methods and attributes.
3+
This is a simple ring buffer library for the Arduino. It is written in vanilla C, and can easily be modified to work with other platforms simply be removing the `#include "Arduino.h" `. It can buffer any fixed size object (ints, floats, structs, etc...).
74

85

6+
I have heard about object oriented programing in pure C, and I decided to give it a shot with this library. Using C structs and function pointers, the library creates RingBuf objects that are complete with their own methods and attributes. Note that every method (except constructor), takes a `RingBuf *self` pointer. This is the equivalent of the `this` pointer in C++, but the C++ compiler automatically passes it behind the scenes. For this library, you must manually pass this as the first argument.
97

108
## Use Cases
119

1210
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()`.
1311

12+
## Examples
13+
14+
Look at the examples folder for several examples.
15+
1416
## API
1517

1618

@@ -20,7 +22,7 @@ A ring buffer is used when passing asynchronous io between two threads. In the c
2022
RingBuf *RingBuf_new(int size, int len);
2123
```
2224

23-
Creates a new RingBuf object of len elements that are size bytes each. A poetinter to the new RingBuf object is returned on success. On failure (lack of memory), a null pointer is returned.
25+
Creates a new RingBuf object of len elements that are size bytes each. A pointer to the new RingBuf object is returned on success. On failure (lack of memory), a null pointer is returned.
2426
This would be the equivalent of `new RingBuf(int size, int len)` in C++.
2527

2628
### Deconstructor
@@ -58,6 +60,12 @@ void *pull(RingBuf *self, void *object);
5860

5961
Pull the first element out of the buffer. The first element is copied into the location pointed to by object. Returns a NULL pointer if the buffer is empty, otherwise returns object.
6062

63+
### numElements()
64+
```
65+
unsigned int numElements(RingBuf *self);
66+
```
67+
68+
Returns number of elements in buffer.
6169

6270
### isFull()
6371
```

RingBuf.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
2-
RingBuf.c - Library for implementing a simple Ring Buffer on Arduino boards.
3-
Created by D. Aaron Wisner, December 10, 2015.
2+
RingBuf.c - Library for implementing a simple Ring Buffer on Arduino boards.
3+
Created by D. Aaron Wisner (daw268@cornell.edu)
4+
January 17, 2015.
45
Released into the public domain.
56
*/
67
#include "RingBuf.h"
@@ -38,6 +39,7 @@ int RingBuf_init(RingBuf *self, int size, int len)
3839
self->isFull = &RingBufIsFull;
3940
self->isEmpty = &RingBufIsEmpty;
4041
self->add = &RingBufAdd;
42+
self->numElements = &RingBufNumElements;
4143
self->peek = &RingBufPeek;
4244
self->pull = &RingBufPull;
4345
return 0;
@@ -117,6 +119,12 @@ void *RingBufPull(RingBuf *self, void *object)
117119
return object;
118120
}
119121

122+
// Returns number of elemnts in buffer
123+
unsigned int RingBufNumElements(RingBuf *self)
124+
{
125+
return self->elements;
126+
}
127+
120128
// Returns true if buffer is full
121129
bool RingBufIsFull(RingBuf *self)
122130
{

RingBuf.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
2-
RingBuf.h - Library for implementing a simple Ring Buffer on Arduino boards.
3-
Created by D. Aaron Wisner, December 10, 2015.
2+
RingBuf.h - Library for implementing a simple Ring Buffer on Arduino boards.
3+
Created by D. Aaron Wisner (daw268@cornell.edu)
4+
January 17, 2015.
45
Released into the public domain.
56
*/
67
#ifndef RingBuf_h
@@ -27,6 +28,8 @@ typedef struct RingBuf
2728
bool (*isFull) (RingBuf*);
2829
// Returns true if empty
2930
bool (*isEmpty) (RingBuf*);
31+
// Returns number of elemnts in buffer
32+
unsigned int (*numElements)(RingBuf*);
3033
// Add Event, Returns index where added in buffer, -1 on full buffer
3134
int (*add) (RingBuf*, void*);
3235
// Returns pointer to nth element, NULL when nth element is empty
@@ -53,6 +56,7 @@ void *RingBufPeek(RingBuf *self, unsigned int num);
5356
void *RingBufPull(RingBuf *self, void *object);
5457
bool RingBufIsFull(RingBuf *self);
5558
bool RingBufIsEmpty(RingBuf *self);
59+
unsigned int RingBufNumElements(RingBuf *self);
5660

5761
#ifdef __cplusplus
5862
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
RingBufExample.ino - A basic demo of adding a struct, then removing one
3+
Created by D. Aaron Wisner (daw268@cornell.edu)
4+
January 17, 2015.
5+
Released into the public domain.
6+
*/
7+
8+
#include <RingBuf.h>
9+
10+
struct mystruct
11+
{
12+
int index;
13+
char randomstring[10];
14+
unsigned int mycrap;
15+
unsigned long long timestamp;
16+
};
17+
18+
// Create a RinBuf object designed to hold a 20 of mystructs
19+
RingBuf *my_buf = RingBuf_new(sizeof(struct mystruct), 20);
20+
21+
22+
void setup() {
23+
Serial.begin(9600);
24+
// Check if null pointer
25+
if (!my_buf)
26+
{
27+
Serial.println("Not enough memory");
28+
while (1);
29+
}
30+
31+
// Create element I want to add
32+
struct mystruct bar, foo;
33+
34+
// Zero both of them out
35+
memset(&bar, 0, sizeof(struct mystruct));
36+
memset(&foo, 0, sizeof(struct mystruct));
37+
38+
bar.index = 1;
39+
bar.timestamp = millis();
40+
41+
// Copy bar into the ring_buf
42+
my_buf->add(my_buf, &bar);
43+
44+
// Pull first element out of buffer (should be same as bar) into foo
45+
my_buf->pull(my_buf, &foo);
46+
47+
// Prove that foo is the same as bar
48+
if (!memcmp(&bar, &foo, sizeof(struct mystruct)))
49+
{
50+
Serial.println("As expected, foo is a copy of bar");
51+
}
52+
53+
// Delete RingBuf object
54+
RingBuf_delete(my_buf);
55+
my_buf = NULL;
56+
57+
}
58+
59+
60+
61+
void loop() {
62+
// put your main code here, to run repeatedly:
63+
64+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
RingBufInterruptsExample.ino - Interrupt example, to demonstrate the power of a ring buffer with asynchronous io
3+
Created by D. Aaron Wisner (daw268@cornell.edu)
4+
January 17, 2015.
5+
Released into the public domain.
6+
7+
Trigger an interrupt by toggling EVENT_PIN, this will push an Event struct into the buffer
8+
Print the contents of the buffer by sending anything over Serial Monitor
9+
*/
10+
#include <RingBuf.h>
11+
12+
// MUST BE AN INTTERUPT COMPATIBLE PIN
13+
#define EVENT_PIN 3
14+
15+
struct Event
16+
{
17+
int index;
18+
unsigned char pinState;
19+
unsigned long timestamp;
20+
};
21+
22+
// Declare as volatile, since modofied in ISR
23+
volatile unsigned int index = 0;
24+
25+
// Create a RinBuf object designed to hold a 20 Event structs
26+
RingBuf *buf = RingBuf_new(sizeof(struct Event), 20);
27+
28+
29+
void setup() {
30+
Serial.begin(9600);
31+
32+
// Check if null pointer
33+
if (!buf)
34+
{
35+
Serial.println("Not enough memory");
36+
while (1);
37+
}
38+
39+
// Attach the interrupt service routine
40+
attachInterrupt(digitalPinToInterrupt(EVENT_PIN), isr_event, CHANGE);
41+
42+
43+
Serial.println("Toggle the pin state of pin EVENT_PIN, to fire an interrupt");
44+
Serial.println("Send anything over serial to dump the contents of the buffer");
45+
Serial.println();
46+
}
47+
48+
void loop() {
49+
// Print the number of elements
50+
Serial.print("There are: ");
51+
Serial.print(buf->numElements(buf));
52+
Serial.println(" elements in the ring buffer");
53+
54+
// Check if empty
55+
if (buf->isEmpty(buf))
56+
{
57+
Serial.println("The ring buffer is currently empty");
58+
}
59+
else if (buf->isFull(buf))
60+
{
61+
Serial.println("The ring buffer is currently full");
62+
}
63+
64+
// If any message sent through serial monitor, dump buffer
65+
if (Serial.available() > 0)
66+
{
67+
// Print contents of buffer
68+
print_buf_contents();
69+
70+
//empty serial buffer
71+
while (Serial.read() > 0);
72+
}
73+
74+
Serial.println();
75+
76+
delay(2000);
77+
}
78+
79+
80+
// This interrupt serve routine function is called whenever an interrupt fires on EVENT_PIN
81+
// An Event Struct will be appened to the buffer
82+
void isr_event()
83+
{
84+
struct Event e;
85+
e.index = index++;
86+
e.pinState = digitalRead(EVENT_PIN);
87+
e.timestamp = millis();
88+
// Add it to the buffer
89+
buf->add(buf, &e);
90+
}
91+
92+
// Print the buffer's contents then empty it
93+
void print_buf_contents()
94+
{
95+
struct Event e;
96+
97+
Serial.println("\n______Dumping contents of ring buffer_______");
98+
99+
// Keep looping until pull() returns NULL
100+
while (buf->pull(buf, &e))
101+
{
102+
//
103+
Serial.print("Event index: ");
104+
Serial.println(e.index);
105+
106+
Serial.print("Pin state: ");
107+
Serial.println(e.pinState);
108+
109+
Serial.print("Timestamp (ms): ");
110+
Serial.println(e.timestamp);
111+
112+
Serial.println();
113+
}
114+
115+
Serial.println("______Done dumping contents_______");
116+
117+
}
118+

0 commit comments

Comments
 (0)