Circular buffer arduino

tonton81/Circular_Buffer

Use Git or checkout with SVN using the web URL.

Work fast with our official CLI. Learn more.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

This is pretty much an advanced version of a circular buffer that follows the STL naming conventions of std::queue,deque,vector, etc.

It supports multiple circular buffer creations without the use of reallocation, new, or malloc. The system uses a template for the configuration of the buffers for the class.

Both circular buffers and circular arrays all support FIFO, LIFO, and MIXED (FIFO+LIFO); This can lead you to design a priority queue system where front entries for priority items and back entries for least priority.

The library is capable of inserting and reading from both the front and the back of the queue.

The buffer system this library supports is not just for ring buffer usage. There is an even more powerful array system. Both buffer types have advanced feature sets of their own we will talk about.

Methods for circular ring buffer

Methods for circular array buffer

If you ever used queues before, you will notice some similarities. Here is the full list of both buffers combined above since they share quite a few methods but run differently depending on which buffer calls it.

The replace function is special. It searches all your «available» queues and replaces the entry thats found for a match. This is good when your running async code and if the buffer wasnt written yet before the next queue addition, this will replace your queue with the current one rather than adding a duplicate command to the queue. It returns 0 if there was no match. If a match was found, it would be updated and a 1 returned indicating it was updated.

An example is as follows:

That simple line above demonstrates that if no match is found «!_outgoing_queue.replace(buffer,4,1,2,3)», in this case, it’s comparing «buffer» against all your circular arrays in queue. (buffer being the buffer to compare, 4 being it’s size, 1,2,3 being the 3 indices to verify). In this case, I’ll mention byte[1] store the command, byte[2] stores object, byte[3] stores index, 4 and 5 actually contain the value, which is not our concern. So if a buffer command, index, and object all match up, the buffer is replaced with one of updated values (_outgoing_queue.push_back(buffer,4);).

The library has a tracking system for the actual size of your arrays in the circular array raw buffer. When you create a circular array buffer, of lets say, 200 per array in size, the library actually creates 202. This is because the 2 first entries of the array internally are used when you buffer write the length of the array to queue. The length is stored in the first 2 positions of the raw array space. Why 2? When dealing with char or uint8_t or other 8 bit buffers, going beyond 255 byte array indexing wont be possible.

The library supports many types, ones that have been tested are floats, uint8_t, uint16_t, uint32_t, and uint64_t.

Theres 2 ways to construct the buffer of your choice.

ALL YOUR SIZES MUST BE A POWER OF 2 FOR THE FIRST FIELD. IMPORTANT!

If you don’t heed this warning, undefined behaviour will result!

There is a demo in the examples folder, hope you all enjoy it.

Источник

bolderflight/circle_buf

Use Git or checkout with SVN using the web URL.

Work fast with our official CLI. Learn more.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

This library implements a first in, first out circular buffer, methods are provided for writing to and reading from the buffer. This library is compatible with Arduino ARM devices and with CMake build systems. It would also be easy to include with other projects, since it is a header only library consisting of a single file.

Use the Arduino Library Manager to install this library or clone to your Arduino/libraries folder. The library is added as:

An example Arduino executable is located at examples/arduino/circle_buf_example/circle_buf_example.ino. Teensy 3.x, 4.x, and LC devices are used for testing under Arduino and this library should be compatible with other ARM devices. This library is not expected to work on AVR devices.

CMake is used to build this library, which is exported as a library target called circle_buf. The header is added as:

The library can be also be compiled stand-alone using the CMake idiom of creating a build directory and then, from within that directory issuing:

This will build the library, an example executable called circle_buf_example, and an executable for testing using the Google Test framework, called circle_buf_test. The example executable source file is located at examples/cmake/circle_buf_example.cc.

This library is within the namespace bfs

This class implements the circular buffer.

CircleBuf Creates a circular buffer object, of type T with buffer size N.

bool Write(const T val) Writes a single value to the buffer. Note the buffer prevents over-writing data. This method returns true on success or false on failure.

std::size_t Write(T const * const data, const std::size_t len) Writes data into the buffer given a pointer to the data and the number of elements to write. Returns the number of elements written into the buffer. Note that the buffer prevents over-writing data, so the number of elements written may be less than the number of elements to write.

optional T Read() Reads a single value from the buffer using an interface similar to std::optional whether a value was returned or not. The optional return interface is provided by optional-bare. A value would not be returned if the buffer is empty (i.e size = 0).

std::size_t Read(T * const data, std::size_t len) Reads elements from the buffer given a pointer to store the data and the maximum number of elements to read. Returns the number of elements read off the buffer.

std::size_t capacity() Returns the capacity of the circular buffer. This will always be equal to N used during construction.

std::size_t size() Returns the number of elements currently stored in the buffer.

void Clear() Empties the buffer.

Источник

rlogiacco/CircularBuffer

Use Git or checkout with SVN using the web URL.

Work fast with our official CLI. Learn more.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

IMPORTANT

Please, before submitting a support request read carefully this README and check if an answer already exists among previously answered questions: do not abuse of the Github issue tracker.

CircularBuffer

The library itself has an implicit memory consumption of about 0.5Kb: 580 bytes (max) of code and 8 bytes of memory, to my calculations. That does not consider the space used to store the items themselves, obviously.

Declare and initialize

When declaring your buffer you should specify the data type it must handle and the buffer capacity: those two parameters will influence the memory consumed by the buffer.

Please note: the memory usage reported above includes the program memory used by the library code, the heap memory is much less and is comparable to an array of the same size and type of the buffer.

Let’s start making things clear: the library doesn’t support inserting data in the middle of the buffer. You can add data to the buffer either before the first element via an unshift() operation or after the last element via a push() operation. You can keep adding data beyond the buffer maximum capacity, but you’ll lose the least significant information:

  • since unshift() adds to the head, adding beyond capacity causes the element at tail to be overwritten and lost
  • since push() adds to the tail, adding beyond capacity causes the element at head to be overwritten and lost

Both unshift() and push() return true if the addition didn’t cause any information loss, false if an overwrite occurred:

Similarly to data addition, data retrieval can be performed at tail via a pop() operation or from head via an shift() operation: both cause the element being read to be removed from the buffer.

⚠ Reading data beyond the actual buffer size has an undefined behaviour and is user’s responsibility to prevent such boundary violations using the additional operations listed in the next section. The library will behave differently depending on the data type and allocation method, but you can safely assume your program will crash if you don’t watch your steps.

Non-destructive read operations are also available:

  • first() returns the element at head
  • last() returns the element at tail
  • an array-like indexed read operation is also available so you can read any element in the buffer using the [] operator
  • isEmpty() returns true only if no data is stored in the buffer
  • isFull() returns true if no data can be further added to the buffer without causing overwrites/data loss
  • size() returns the number of elements currently stored in the buffer; it should be used in conjunction with the [] operator to avoid boundary violations: the first element index is always 0 (if buffer is not empty), the last element index is always size() — 1
  • available() returns the number of elements that can be added before saturating the buffer
  • capacity() returns the number of elements the buffer can store, for completeness only as it’s user-defined and never changes REMOVED from 1.3.0 replaced by the read-only member variable capacity
  • clear() resets the whole buffer to its initial state (pay attention though, if you had dynamically allocated objects in your buffer, memory used by such object is not released: iterate over the buffer contents and release object accordingly to their allocation method)

Starting from version 1.3.0 the library is capable to automatically detect which data type should be used for the index based on the buffer capacity:

  • if you declare a buffer with a capacity greater than 65535 then your index is going to be an unsigned long
  • unsigned int for buffers with a declared capacity greater than 255
  • otherwise a byte is going to suffice

In addition, you can mix in the same code buffers with small index and buffers with normal index: previously this was not possible.

To obtain the maximum advantage of the optimization above, anytime you need to refer to the buffer index you should use the most appropriate type: this can be easily achieved using the decltype specifier, like in the following example:

If you prefer, you can alias the index type and refer to such alias:

The following applies to versions prior to 1.3.0 only.

By default the library uses unsigned int indexes, allowing for a maximum of 65535 items, but you’ll rarely need such a huge store.

You can switch the library indexes to byte type defining the CIRCULAR_BUFFER_XS macro BEFORE the #include directive: this reduces the memory used by the library itself by only 36 bytes, but allows you to potentially squeeze out much more whenever you perform an indexed access, if you do any, by using the smaller data type.

Please note: this macro switch forces the buffer to use an 8 bits data type as internal index, as such all your buffers will be limited to a maximum capacity of 255 .

The library does help working with interrupts defining the CIRCULAR_BUFFER_INT_SAFE macro switch, which introduces the volatile modifier to the count variable, making the whole library more interrupt friendly at the price of disabling some compiler optimizations. The #define statement needs to be put somewhere before the #include statement:

Please note this does NOT make the library interrupt safe, but it does help its usage in interrupt driven firmwares.

Multiple examples are available in the examples folder of the library:

  • CircularBuffer.ino shows how you can use the library to create a continous averaging of the most recent readings
  • EventLogging.ino focuses on dumping the buffer when it becomes full and printing the buffer contents periodically at the same time
  • Object.ino is meant to demonstrate how to use the buffer to store dynamic structures
  • Queue.ino is a classical example of a queue, or a FIFO data structure
  • Stack.ino on the other end shows how to use the library to represent a LIFO data structure
  • Struct.ino answers to the question can this library store structured data?
  • Interrupts.ino demonstrates the use of the library in interrupt driven code

Reclaim dynamic memory

If you use this library to store dynamically allocated objects, refrain from using the clear() method as that will not perform memory deallocation: you need to iterate over your buffer content and release memory accordingly to the allocation method used, either via delete (if you had used new ) or free (in case of malloc ):

Источник

Adblock
detector