Useful Code Snippet: AVR and C++11

16 June 2013

Despite what a lot of people say about the Arduino crowd and using C++ on a microcontroller, I like it.  Sometimes it incurs a performance or code-size overhead, but I’m not often approaching the RAM or Flash limits of an Atmega 328, or especially an Atmega 2560.  When appropriate features are used, C++ results in more readable code.  Lately, I’ve branched into using templates with some AVR Code.  Here’s a super useful snippet for creating a quick ringbuffer:

#ifndef AVR_RING_BUFFER_H
#define AVR_RING_BUFFER_H

#ifdef ARDUINO
#include <Arduino.h>
#endif

template <typename T, size_t size> class AVRRingBuffer
{
public:
    AVRRingBuffer();

    bool isEmpty() const;
    bool isFull() const;
    int count() const;

    T get();
    int put(const T i);
private:
    unsigned int _size = size+1;
    T _data[size+1];
    int _head = 0;
    int _tail = 0;
    int _count = 0;
};

template<typename T, size_t size>
AVRRingBuffer<T, size>::AVRRingBuffer()
{
}

template<typename T, size_t size>
bool AVRRingBuffer<T, size>::isEmpty() const
{
    return _head == _tail;
}

template<typename T, size_t size>
bool AVRRingBuffer<T, size>::isFull() const
{
    return (_tail + 1) % _size == _head;
}

template<typename T, size_t size>
int AVRRingBuffer<T, size>::count() const
{
    return _count;
}

template<typename T, size_t size>
T AVRRingBuffer<T, size>::get()
{
    if(!isEmpty())
    {
        _count--;
        T rv = _data[_head];
        _head = (_head + 1) % _size;
        return rv;
    } else {
        return T();
    }

}

template<typename T, size_t size>
int AVRRingBuffer<T, size>::put(const T i)
{
    _data[_tail] = i;
    _tail = (_tail + 1) % _size;
    if(_tail == _head)
    {
        _head = (_head + 1) % _size;
        return 1;
    } else {
        _count++;
        return 0;
    }
}

#endif

No malloc or new to be seen here.  As long as equality operators and copy constructors are sorted, it should work with arbitrary types (although I’ve only tested it with built-ins and simple structs).

C++11 also allows you to typedef templates, like this:typedef AVRRingBuffer<char, 25> SerialBuffer;