A note from the future: This article is a bit out-dated. Please visit the next entry for the updated entries after you have read this article!

Intro

Inspired a bit my the 'Embed with Elliot' article Going 'Round with Circular Buffers, I decided to make a contribution.  Read the article, it is pretty solid.

After reading the article, I went over to the source code expecting to have a *.h and *.c file that implemented the concepts from the article.  Instead, I found that the concepts from the article were implemented in the same file as the main.c.  Feeling like I had to separate them out and make them somewhat more dynamic, I did a pull of his repository and - more or less - copied his code with a few changes to make the library more portable and more dynamic.

Changes

  • I took the implementation that Elliot created and moved it into its own C and H files in order to make it a bit more friendly for importing into your project.
  • Added one 'slot' to the buffer.  The original implementation would use one less than the actual buffer size, so if your buffer was 16 bytes long, then you could only use 15 slots.
  • Added ability to declare more than one buffer using pass-by-reference functions.
  • Added the ability to change the element width using a header file define.
  • Added checks to ensure that the buffer length is a power of 2 (keeps code executing without EVER using the modulo operation).

Differences in Use

  • You must 'initialize' the buffer using the 'BUF_init()' function.  This was originally taken care of in the declaration.
  • You must now pass the buffer by reference in each function call.
  • You must include 'cbuffer.h' instead of having all of the code copied/pasted at the top.
  • Function calls are slightly different.  Each is prefixed with a 'BUF_', but otherwise very similar.

For anyone who started with the original code and has already copied/pasted and all is working, there is no reason to port.  If you find that you wanted to use a second (or third..., or fourth...) buffer, then you should take the 10 min to convert over.

Example

A quick code sample is in order.

First, the buffer is declared.  There is no reason that this couldn't be declared as a global, but it isn't necessary for this sample.  When using in interrupts, be sure to use 'volatile'!

Next, the buffer is initialized.  Once it is initialized, the buffer is 'empty'.  We can now write to the buffer and read from it.

 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
int main(void) {
    Buffer b;
    BUF_init(&b);
    uint8_t a;

    /* write to the buffer too many times */
    uint8_t i;
    for(i = 0; i < 16; i++){
        BUF_write(&b, i);
    }

    /* read one value */
    BUF_read(&b, &a);

    /* write one value */
    a++;
    BUF_write(&b, a);

    /* read 3 values into a */
    BUF_read(&b, &a);
    BUF_read(&b, &a);
    BUF_read(&b, &a);

    return 0;
}

One key thing to note is that the 'write' passes elements into the buffer by value while the 'read' passes elements out of the buffer by reference.  This is really important to note!

Additionally, I took Elliot's original example and re-worked it mildly to function identically with this cbuffer library instead of the inline code.  It only took a few minutes and it is now its own stand-alone library.  Thank you for your contribution, Elliot!

As always, code can be found on github.

A note from the future: This article is a bit out-dated. Please visit the next entry for the updated entries after you have read this article!



© by Jason R. Jones 2016
My thanks to the Pelican and Python Communities.