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:
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 |
#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;