parent
a6f31599c6
commit
891c07f5fb
@ -1,43 +1,15 @@ |
|||||||
Circular byte buffer |
Buffers |
||||||
==================== |
======= |
||||||
|
|
||||||
**(and other buffers)** |
This is a collection of useful buffer modules for C programs. |
||||||
|
|
||||||
This is a circular buffer implementation, useful mainly for embedded systems (buffer for UART RX/TX queues etc). |
- **circbuf** - generic circular buffer, queue, stack |
||||||
|
- **matcher** - pattern matcher for character streams |
||||||
|
- **meanbuf** - averaging (smoothing) buffer. |
||||||
|
|
||||||
It should be reliable with producent / consumer threads (no race conditions, as no length variable is used). |
*Please see READMEs in the project folders for more details.* |
||||||
|
|
||||||
A Matching buffer, and Averaging buffer are also included—see their header files for instructions. |
|
||||||
|
|
||||||
|
|
||||||
Usage |
|
||||||
----- |
|
||||||
|
|
||||||
```c |
|
||||||
#include <stdint.h> |
|
||||||
#include "circbuf.h" |
|
||||||
|
|
||||||
circbuf_t cb; // buffer instance |
|
||||||
|
|
||||||
void main() |
|
||||||
{ |
|
||||||
char c; |
|
||||||
cbuf_init(&cb, 32); // init the buffer |
|
||||||
|
|
||||||
// now it's ready for use! |
|
||||||
|
|
||||||
cbuf_write(&cb, 'A'); |
|
||||||
|
|
||||||
if (cbuf_read(&cb, &c)) { |
|
||||||
printf("%c", c); |
|
||||||
} |
|
||||||
|
|
||||||
cbuf_deinit(&cb); // free the backing array (in embedded system you don't usually need to, allocate once and keep it) |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
Most functions return a success flag (true - success), so make sure to check the return values. |
|
||||||
|
|
||||||
False is returned on buffer overflow / underflow. See the header file for details. |
|
||||||
|
|
||||||
|
The buffers were developed for embedded microcontrollers (STM32, AVR), |
||||||
|
but can be used anywhere, they are fully portable. |
||||||
|
|
||||||
|
Pull requests to add new buffers or improve the current ones are welcome! |
||||||
|
@ -1,101 +0,0 @@ |
|||||||
#include <stdint.h> |
|
||||||
#include <stdbool.h> |
|
||||||
#include <string.h> |
|
||||||
#include <malloc.h> |
|
||||||
|
|
||||||
#include "circbuf.h" |
|
||||||
|
|
||||||
|
|
||||||
void cbuf_init(circbuf_t *inst, size_t capacity) |
|
||||||
{ |
|
||||||
inst->buf = malloc(capacity); |
|
||||||
inst->cap = capacity; |
|
||||||
|
|
||||||
cbuf_clear(inst); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void cbuf_deinit(circbuf_t *inst) |
|
||||||
{ |
|
||||||
if (inst->buf != NULL) { |
|
||||||
free(inst->buf); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
bool cbuf_full(circbuf_t *inst) |
|
||||||
{ |
|
||||||
return (inst->lr == inst->nw); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
static bool can_read_at(circbuf_t *inst, size_t i) |
|
||||||
{ |
|
||||||
if (inst->lr < inst->nw) { |
|
||||||
return i > inst->lr && i < inst->nw; |
|
||||||
} else { |
|
||||||
// NW < LR
|
|
||||||
return (i < inst->cap && i > inst->lr) || i < inst->nw; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
bool cbuf_empty(circbuf_t *inst) |
|
||||||
{ |
|
||||||
return ((inst->lr + 1) % inst->cap) == inst->nw; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
bool cbuf_write(circbuf_t *inst, uint8_t b) |
|
||||||
{ |
|
||||||
if (cbuf_full(inst)) return false; |
|
||||||
|
|
||||||
inst->buf[inst->nw] = b; |
|
||||||
|
|
||||||
// increment
|
|
||||||
inst->nw++; |
|
||||||
if (inst->nw == inst->cap) inst->nw = 0; |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
bool cbuf_read(circbuf_t *inst, uint8_t *b) |
|
||||||
{ |
|
||||||
if (cbuf_empty(inst)) return false; |
|
||||||
|
|
||||||
// increment
|
|
||||||
inst->lr++; |
|
||||||
if (inst->lr == inst->cap) inst->lr = 0; |
|
||||||
|
|
||||||
*b = inst->buf[inst->lr]; |
|
||||||
|
|
||||||
//zero out the read byte (for debug)
|
|
||||||
inst->buf[inst->lr] = 0; |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
bool cbuf_peek(circbuf_t *inst, size_t nth, uint8_t *b) |
|
||||||
{ |
|
||||||
// check if can read there (can't use modulo, could "wrap")
|
|
||||||
size_t n = inst->lr; |
|
||||||
for (size_t i = 0; i <= nth; i++) { |
|
||||||
// increment N
|
|
||||||
n++; |
|
||||||
if (n == inst->cap) n = 0; |
|
||||||
|
|
||||||
if (!can_read_at(inst, n)) return false; |
|
||||||
} |
|
||||||
|
|
||||||
*b = inst->buf[n]; |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void cbuf_clear(circbuf_t *inst) |
|
||||||
{ |
|
||||||
inst->lr = inst->cap - 1; |
|
||||||
inst->nw = 0; |
|
||||||
} |
|
@ -1,51 +0,0 @@ |
|||||||
#pragma once |
|
||||||
#include <stdint.h> |
|
||||||
#include <stdbool.h> |
|
||||||
#include <stdlib.h> |
|
||||||
|
|
||||||
// Circular Character Buffer implementation
|
|
||||||
|
|
||||||
typedef struct CircularBuffer_struct { |
|
||||||
uint8_t *buf; |
|
||||||
size_t cap; |
|
||||||
size_t lr; // last read pos
|
|
||||||
size_t nw; // next write pos
|
|
||||||
} circbuf_t; |
|
||||||
|
|
||||||
|
|
||||||
/** Init a buffer */ |
|
||||||
void cbuf_init(circbuf_t *inst, size_t capacity); |
|
||||||
|
|
||||||
|
|
||||||
/** Deinit a buffer (free the memory) */ |
|
||||||
void cbuf_deinit(circbuf_t *inst); |
|
||||||
|
|
||||||
|
|
||||||
/** Test for full buffer */ |
|
||||||
bool cbuf_full(circbuf_t *inst); |
|
||||||
|
|
||||||
|
|
||||||
/** Test for empty buffer */ |
|
||||||
bool cbuf_empty(circbuf_t *inst); |
|
||||||
|
|
||||||
|
|
||||||
/** Write a byte to buffer, returns success */ |
|
||||||
bool cbuf_write(circbuf_t *inst, uint8_t b); |
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a byte from the buffer, return susccess. |
|
||||||
* If `b` is NULL, the read byte is discarded. |
|
||||||
*/ |
|
||||||
bool cbuf_read(circbuf_t *inst, uint8_t *b); |
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get n-th byte from the buffer, without removing it. |
|
||||||
* Returns false if offset is invalid (ie. empty buffer). |
|
||||||
*/ |
|
||||||
bool cbuf_peek(circbuf_t *inst, size_t nth, uint8_t *b); |
|
||||||
|
|
||||||
|
|
||||||
/** Remove all data from buffer */ |
|
||||||
void cbuf_clear(circbuf_t *inst); |
|
@ -0,0 +1,51 @@ |
|||||||
|
Circular buffer |
||||||
|
=============== |
||||||
|
|
||||||
|
This is a C implementation of a circular buffer, which can also be used |
||||||
|
as a queue or stack. |
||||||
|
|
||||||
|
Supported operations: `push`, `pop`, `append`. |
||||||
|
|
||||||
|
To achieve thread safety (to some extent) in a producent-consumer situation, |
||||||
|
there is no length variable, only write pointers. |
||||||
|
|
||||||
|
The buffer has a fixed size, values are copied when inserted. The buffer is created using `malloc`. |
||||||
|
If your platform does not support `malloc`, you will have to customize the initialization routine. |
||||||
|
|
||||||
|
Applications |
||||||
|
------------ |
||||||
|
|
||||||
|
- Buffer for USARTs or similar communication interfaces |
||||||
|
- Event queue |
||||||
|
- Object stack |
||||||
|
|
||||||
|
Usage |
||||||
|
----- |
||||||
|
|
||||||
|
```c |
||||||
|
#include <stdint.h> |
||||||
|
#include "circbuf.h" |
||||||
|
|
||||||
|
CircBuf *cb; // buffer instance |
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
cb = cbuf_make(32, sizeof(char)); // create a char buffer of size 32. |
||||||
|
|
||||||
|
// now it's ready for use! |
||||||
|
|
||||||
|
// write functions return true on success: |
||||||
|
cbuf_append(cb, 'A'); // append A (using as a queue) |
||||||
|
cbuf_push(cb, 'B'); // push B (using as a stack) |
||||||
|
|
||||||
|
// read all |
||||||
|
char c; |
||||||
|
while (cbuf_pop(cb, &c)) { |
||||||
|
printf("%c", c); |
||||||
|
} |
||||||
|
|
||||||
|
cbuf_destroy(cb); // free the buffer |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
For details how to use each function, please read the header file. |
@ -0,0 +1,167 @@ |
|||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <string.h> |
||||||
|
#include <malloc.h> |
||||||
|
|
||||||
|
#include "circbuf.h" |
||||||
|
|
||||||
|
// --- Circbuf data structure ----
|
||||||
|
|
||||||
|
/** Offset in void* buffer */ |
||||||
|
#define PV_OFFS(pvBuf, elem_size, index) ((uint8_t*)(pvBuf) + ((elem_size)*(index))) |
||||||
|
|
||||||
|
|
||||||
|
// Instance structure
|
||||||
|
struct circbuf_struct { |
||||||
|
void *buf; |
||||||
|
size_t elem_size; |
||||||
|
size_t cap; |
||||||
|
size_t lr; // last read pos
|
||||||
|
size_t nw; // next write pos
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write data to a CircBuf slot |
||||||
|
* @param cb : circbuf |
||||||
|
* @param index : slot index |
||||||
|
* @param source : data source |
||||||
|
*/ |
||||||
|
static void write_buffer(CircBuf *cb, size_t index, const void *source) |
||||||
|
{ |
||||||
|
memcpy(PV_OFFS(cb->buf, cb->elem_size, index), source, cb->elem_size); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Copy data from a CircBuf slot to a buffer |
||||||
|
* @param cb : circbuf |
||||||
|
* @param index : slot index |
||||||
|
* @param dest : destination buffer |
||||||
|
*/ |
||||||
|
static void read_buffer(const CircBuf *cb, size_t index, void *dest) |
||||||
|
{ |
||||||
|
memcpy(dest, PV_OFFS(cb->buf, cb->elem_size, index), cb->elem_size); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Create a cbuf */ |
||||||
|
CircBuf *cbuf_make(size_t capacity, size_t elem_size) |
||||||
|
{ |
||||||
|
// add one, because one is always unused.
|
||||||
|
capacity++; |
||||||
|
|
||||||
|
// Allocate the structure
|
||||||
|
CircBuf *cb = malloc(sizeof(CircBuf)); |
||||||
|
if (cb == NULL) { |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
// allocate the buffer
|
||||||
|
cb->buf = malloc(capacity * elem_size); |
||||||
|
if (cb->buf == NULL) { |
||||||
|
free(cb); // fail - free structure.
|
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
// set capacity, clear state
|
||||||
|
cb->elem_size = elem_size; |
||||||
|
cb->cap = capacity; |
||||||
|
cbuf_clear(cb); |
||||||
|
|
||||||
|
return cb; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Release cbuf memory */ |
||||||
|
void cbuf_destroy(CircBuf *cb) |
||||||
|
{ |
||||||
|
if (cb != NULL) { |
||||||
|
if (cb->buf != NULL) { |
||||||
|
free(cb->buf); |
||||||
|
} |
||||||
|
|
||||||
|
free(cb); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Check if cbuf is full */ |
||||||
|
bool cbuf_full(const CircBuf *cb) |
||||||
|
{ |
||||||
|
if (cb == NULL) return false; |
||||||
|
|
||||||
|
return (cb->lr == cb->nw); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Check if cbuf is empty */ |
||||||
|
bool cbuf_empty(const CircBuf *cb) |
||||||
|
{ |
||||||
|
if (cb == NULL) return true; |
||||||
|
|
||||||
|
return ((cb->lr + 1) % cb->cap) == cb->nw; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Write a byte to the buffer, if space left */ |
||||||
|
bool cbuf_append(CircBuf *cb, const void *source) |
||||||
|
{ |
||||||
|
if (cb == NULL) return false; |
||||||
|
if (source == NULL) return false; |
||||||
|
if (cbuf_full(cb)) return false; |
||||||
|
|
||||||
|
write_buffer(cb, cb->nw, source); |
||||||
|
|
||||||
|
// increment
|
||||||
|
cb->nw++; |
||||||
|
if (cb->nw == cb->cap) cb->nw = 0; |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Push value to the end, like a stack. */ |
||||||
|
bool cbuf_push(CircBuf *cb, const void *source) |
||||||
|
{ |
||||||
|
if (cb == NULL) return false; |
||||||
|
if (source == NULL) return false; |
||||||
|
if (cbuf_full(cb)) return false; |
||||||
|
|
||||||
|
write_buffer(cb, cb->lr, source); |
||||||
|
|
||||||
|
// move lr back
|
||||||
|
if (cb->lr == 0) { |
||||||
|
cb->lr = cb->cap - 1; // wrap to the end
|
||||||
|
} else { |
||||||
|
cb->lr--; |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Read one byte, if not empty. */ |
||||||
|
bool cbuf_pop(CircBuf *cb, void *dest) |
||||||
|
{ |
||||||
|
if (cb == NULL || dest == NULL) return false; |
||||||
|
if (cbuf_empty(cb)) return false; |
||||||
|
|
||||||
|
// increment
|
||||||
|
cb->lr++; |
||||||
|
if (cb->lr == cb->cap) cb->lr = 0; |
||||||
|
|
||||||
|
read_buffer(cb, cb->lr, dest); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Clear a cbuf */ |
||||||
|
void cbuf_clear(CircBuf *cb) |
||||||
|
{ |
||||||
|
if (cb == NULL) return; |
||||||
|
|
||||||
|
cb->lr = cb->cap - 1; |
||||||
|
cb->nw = 0; |
||||||
|
} |
@ -0,0 +1,93 @@ |
|||||||
|
/**
|
||||||
|
* @file circbuf.h |
||||||
|
* @author Ondřej Hruška, 2016 |
||||||
|
* |
||||||
|
* Circular buffer / queue / stack. |
||||||
|
* Slots are pre-allocated, values are copied into the buffer. |
||||||
|
* |
||||||
|
* The buffer may be used as a stack, event queue or a simple buffer. |
||||||
|
* |
||||||
|
* ------------------------------------- |
||||||
|
* |
||||||
|
* NW LR |
||||||
|
* append -> [][][][] -> pop |
||||||
|
* <- push |
||||||
|
* |
||||||
|
* NW - next write pointer (stack base) |
||||||
|
* LR - last read position (stack top) |
||||||
|
* |
||||||
|
* ------------------------------------- |
||||||
|
* |
||||||
|
* MIT license |
||||||
|
*/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
|
||||||
|
typedef struct circbuf_struct CircBuf; |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a circular buffer. The buffer is malloc'd. |
||||||
|
* @param capacity : buffer capacity |
||||||
|
* @param elem_size : size of one element |
||||||
|
* @return pointer to the buffer instance |
||||||
|
*/ |
||||||
|
CircBuf *cbuf_make(size_t capacity, size_t elem_size); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy a buffer, freeing used memory. |
||||||
|
* |
||||||
|
* @attention |
||||||
|
* If the buffer items have malloc'd members, you have |
||||||
|
* to free them manually to avoid a memory leak. |
||||||
|
* |
||||||
|
* @param cb : buffer |
||||||
|
*/ |
||||||
|
void cbuf_destroy(CircBuf *cb); |
||||||
|
|
||||||
|
|
||||||
|
/** Test for full buffer */ |
||||||
|
bool cbuf_full(const CircBuf *cb); |
||||||
|
|
||||||
|
|
||||||
|
/** Test for empty buffer */ |
||||||
|
bool cbuf_empty(const CircBuf *cb); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Append a value to the buffer (FIFO) |
||||||
|
* @param cb : buffer |
||||||
|
* @param source : pointer to a value (will be copied) |
||||||
|
* @return success |
||||||
|
*/ |
||||||
|
bool cbuf_append(CircBuf *cb, const void *source); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Push a value into the circbuf (LIFO). |
||||||
|
* |
||||||
|
* @param cb : buffer |
||||||
|
* @param source : pointer to a value (will be copied) |
||||||
|
* @return success |
||||||
|
*/ |
||||||
|
bool cbuf_push(CircBuf *cb, const void *source); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read a value from the buffer, return susccess. |
||||||
|
* |
||||||
|
* @param cb : buffer |
||||||
|
* @param dest : read destionation. If NULL, value is discarded. |
||||||
|
* @return success |
||||||
|
*/ |
||||||
|
bool cbuf_pop(CircBuf *cb, void *dest); |
||||||
|
|
||||||
|
|
||||||
|
/** @brief Remove all data from buffer */ |
||||||
|
void cbuf_clear(CircBuf *cb); |
@ -1,21 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include <stdint.h> |
|
||||||
#include <stdbool.h> |
|
||||||
#include <stdlib.h> |
|
||||||
|
|
||||||
typedef struct { |
|
||||||
const char *pattern; |
|
||||||
size_t cursor; |
|
||||||
} matcher_t; |
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Consume an incoming character. |
|
||||||
* If this char was the last char of the pattern, returns true and rewinds. |
|
||||||
* |
|
||||||
* If the char is not in the pattern, resets match state. |
|
||||||
* |
|
||||||
* @returns true if the char concluded the expected pattern. |
|
||||||
*/ |
|
||||||
bool matcher_test(matcher_t * mb, uint8_t b); |
|
@ -0,0 +1,14 @@ |
|||||||
|
Character stream pattern matcher |
||||||
|
================================ |
||||||
|
|
||||||
|
Matcher can be used for detecting a pattern in a stream of characters. |
||||||
|
With each incoming character, call `matcher_test()`. |
||||||
|
|
||||||
|
It will return true if the character completed a match. |
||||||
|
|
||||||
|
Applications |
||||||
|
------------ |
||||||
|
|
||||||
|
This buffer was designed for parsing responses to AT commands from ESP8266. |
||||||
|
|
||||||
|
It can be used for any similar purpose. |
@ -0,0 +1,39 @@ |
|||||||
|
/**
|
||||||
|
* @file matcher.h |
||||||
|
* @author Ondřej Hruška, 2016 |
||||||
|
* |
||||||
|
* String matching utility. |
||||||
|
*
|
||||||
|
* Matcher can be used for detecting a pattern in a stream of characters. |
||||||
|
* With each incoming character, call matcher_test().
|
||||||
|
*
|
||||||
|
* It will return true if the character completed a match. |
||||||
|
*
|
||||||
|
* MIT license |
||||||
|
*/ |
||||||
|
|
||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
typedef struct { |
||||||
|
const char *pattern; |
||||||
|
size_t cursor; |
||||||
|
} matcher_t; |
||||||
|
|
||||||
|
|
||||||
|
/** reset match progress */ |
||||||
|
void matcher_reset(matcher_t *m); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consume an incoming character. |
||||||
|
* If this char was the last char of the pattern, returns true and resets matcher. |
||||||
|
* |
||||||
|
* If the char is not in the pattern, resets matcher. |
||||||
|
* |
||||||
|
* @returns true if the char concluded the expected pattern. |
||||||
|
*/ |
||||||
|
bool matcher_test(matcher_t * mb, uint8_t b); |
@ -1,21 +0,0 @@ |
|||||||
#pragma once |
|
||||||
#include <stdlib.h> |
|
||||||
#include <stdint.h> |
|
||||||
|
|
||||||
|
|
||||||
typedef struct { |
|
||||||
float * buf; // buffer (allocated at init)
|
|
||||||
size_t cap; // capacity
|
|
||||||
size_t nw; // next write index
|
|
||||||
float mean; // updated on write
|
|
||||||
} meanbuf_t; |
|
||||||
|
|
||||||
|
|
||||||
/** Init a buffer */ |
|
||||||
void meanbuf_init(meanbuf_t *mb, size_t size); |
|
||||||
|
|
||||||
/** Deinit a buffer (free buffer array) */ |
|
||||||
void meanbuf_deinit(meanbuf_t *mb); |
|
||||||
|
|
||||||
/** Add a value to the buffer. Returns current mean. */ |
|
||||||
float meanbuf_add(meanbuf_t *mb, float f); |
|
@ -0,0 +1,11 @@ |
|||||||
|
Averaging float buffer |
||||||
|
====================== |
||||||
|
|
||||||
|
*(You can adjust it to use doubles, if you prefer.)* |
||||||
|
|
||||||
|
The `meanbuf_create()` function allocates a buffer. |
||||||
|
|
||||||
|
You can then call `meanbuf_add()` to add a new value into the buffer (and remove the oldest). |
||||||
|
This function returns the current average value. |
||||||
|
|
||||||
|
This buffer can be used for **signal smoothing** (such as from an analogue sensor). |
@ -0,0 +1,31 @@ |
|||||||
|
/**
|
||||||
|
* @file meanbuf.h |
||||||
|
* @author Ondřej Hruška, 2016 |
||||||
|
* |
||||||
|
* Averaging float buffer. (You can adjust it to use doubles, if you prefer.) |
||||||
|
*
|
||||||
|
* The meanbuf_create() function allocates a buffer. |
||||||
|
*
|
||||||
|
* You can then call meanbuf_add() to add a new value into the buffer (and remove the oldest). |
||||||
|
* This function returns the current average value. |
||||||
|
*
|
||||||
|
* This buffer can be used for signal smoothing (such as from an analogue sensor). |
||||||
|
* |
||||||
|
* MIT license |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
#pragma once |
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
typedef struct meanbuf_struct MeanBuf; |
||||||
|
|
||||||
|
/** Init a buffer */ |
||||||
|
MeanBuf *meanbuf_create(size_t size); |
||||||
|
|
||||||
|
/** Deinit a buffer (free buffer array) */ |
||||||
|
void meanbuf_destroy(MeanBuf *mb); |
||||||
|
|
||||||
|
/** Add a value to the buffer. Returns current mean. */ |
||||||
|
float meanbuf_add(MeanBuf *mb, float f); |
Loading…
Reference in new issue