You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.8 KiB
C

// Resource/Inspiration: https://embedjournal.com/implementing-circular-buffer-embedded-c/
/*
Penguin's Circular Buffer -- a simple floating queue designed for low memory usage (mainly for embedded)
This is a ring buffer with limited capabilities. It is meant as a container for moving data.
Normally included features such as checks to see if the buffer is full or empty have been omitted
because this type of buffer is being implemented mainly for sensor data usage. Data is almost never read
individually, and even if it is, it isn't meant to be cleared on read. It is a simple moving buffer that
automatically writes over old data for the purpose of keeping track of the most up to date data.
Notes:
- Initialization is mandatory using p_cb_<type>_init.
- If a circular buffer is not initialized, you will run into a LOT of hard-to-debug problems. Just initialize it.
- By default, all cb types should be defined as disabled. This is to save on size. Enable the ones you want to use.
Behavior:
- Oldest data is overwritten
- popping of data isn't implemented. If this feature is required, use a ring buffer.
Acronyms:
- p: penguin
- pb: penguin buffer
- cb: circular buffer
- uX, where X is bit size: unsigned X bit integer
- iX, where X is bit size: signed X bit integer
Note: I wrote this like 3 years ago or something. I hope it works.
*/
#ifndef _PCIRCULARBUFFER_H_
#define _PCIRCULARBUFFER_H_
#include "p_serial_mgr.h"
#include <stdbool.h>
#include <stdint.h>
#ifdef _DEBUG
#define PC_CB_DEBUG
#endif
// Max size is 65535 (2^16 - 1) so variables can be safely set 16 bits (unsigned)
// If you want to change this, you'll need to change the sizes of all heads and max lengths
#define PB_CB_MAX_BUFFER_SIZE (65535)
typedef enum PB_CB_STATUS
{
PB_CB_GOOD = 0,
PB_CB_BAD = 1,
PB_CB_BAD_BUFFER_SIZE = 2,
PB_CB_NULL_BUFFER = 3,
PB_CB_NULL_CBUFFER = 4
} PB_CB_STATUS;
typedef struct p_cb_u8
{
uint8_t *buffer;
uint16_t head;
uint16_t max_len;
// Signifies the buffer being filled at least once.
// Useful for initializing sensor data
bool b_filled;
// Signifies the buffer being empty
// Useful for knowing if data is being received
bool b_empty;
PB_CB_STATUS (*push)(struct p_cb_u8 *cbuffer, uint8_t value);
PB_CB_STATUS (*empty)(struct p_cb_u8 *cbuffer);
} p_cb_u8;
PB_CB_STATUS p_cb_u8_init(p_cb_u8 *circ_buffer, uint8_t *buff, uint32_t max_length);
typedef struct p_cb_serial_pkt_t
{
serial_pkt_t *buffer;
uint16_t head;
uint16_t max_len;
bool b_filled;
// Signifies the buffer being empty
// Useful for knowing if data is being received
bool b_empty;
PB_CB_STATUS (*push)(struct p_cb_serial_pkt_t *cbuffer, serial_pkt_t value);
PB_CB_STATUS (*empty)(struct p_cb_serial_pkt_t *cbuffer);
} p_cb_serial_pkt_t;
PB_CB_STATUS p_cb_serial_pkt_init(p_cb_serial_pkt_t *inst, serial_pkt_t *buff, uint32_t max_length);
#endif