commit cb8ce335843517f833efbb8e95f010344d568b24 Author: adragott Date: Thu Oct 31 04:19:19 2019 -0500 init diff --git a/CircularBuffer/.vscode/launch.json b/CircularBuffer/.vscode/launch.json new file mode 100644 index 0000000..4bb622a --- /dev/null +++ b/CircularBuffer/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "gcc.exe build and debug active file", + "type": "cppdbg", + "request": "launch", + "program": "${fileDirname}\\${fileBasenameNoExtension}.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "C:\\msys64\\mingw64\\bin\\gdb.exe", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "gcc.exe build active file" + } + ] +} \ No newline at end of file diff --git a/CircularBuffer/CB-README.md b/CircularBuffer/CB-README.md new file mode 100644 index 0000000..e69de29 diff --git a/CircularBuffer/Makefile b/CircularBuffer/Makefile new file mode 100644 index 0000000..51f0d99 --- /dev/null +++ b/CircularBuffer/Makefile @@ -0,0 +1,43 @@ +CC=gcc +CFLAGS=-std=c99 -Wall -Wextra + +#-Werror -Wshadow -Wdouble-promotion \ + -Wformat=2 -Wformat-truncation -fno-common -fstack-usage -Wconversion -Os \ + -Werror=unused-function + +BIN=./bin +SRC=./src +INC=./inc +TEST=./test +EXAMPLE_DIR=./example +TESTER_OBJS=$(BIN)/PCircularBuffer.o $(BIN)/test.o +EXAMPLE_OBJS=$(BIN)/PCircularBuffer.o $(BIN)/simple_circular_buffer_example.o + +TESTER=$(BIN)/tester +EXAMPLE=$(BIN)/simple_circular_buffer_example + +$(TESTER): $(TESTER_OBJS) + $(CC) $(CFLAGS) -o $@ $(TESTER_OBJS) + +$(EXAMPLE): $(EXAMPLE_OBJS) + $(CC) $(CFLAGS) -o $@ $(EXAMPLE_OBJS) + +$(BIN)/PCircularBuffer.o: $(SRC)/PCircularBuffer.c $(INC)/PCircularBuffer.h + $(CC) -c $(CFLAGS) -I$(INC) $(SRC)/PCircularBuffer.c -o $(BIN)/PCircularBuffer.o + +$(BIN)/test.o: $(TEST)/test.c + $(CC) -c $(CFLAGS) -I$(INC) $(TEST)/test.c -o $(BIN)/test.o + +$(BIN)/simple_circular_buffer_example.o: $(EXAMPLE_DIR)/simple_circular_buffer_example.c + $(CC) -c $(CFLAGS) -I$(INC) $(EXAMPLE_DIR)/simple_circular_buffer_example.c -o $(BIN)/simple_circular_buffer_example.o + +all: $(TESTER) $(EXAMPLE) + +clean: + rm -rf $(BIN)/* + +test: $(TESTER) + $(TESTER) + +example: $(EXAMPLE) + $(EXAMPLE) \ No newline at end of file diff --git a/CircularBuffer/bin/PCircularBuffer.o b/CircularBuffer/bin/PCircularBuffer.o new file mode 100644 index 0000000..182cbea Binary files /dev/null and b/CircularBuffer/bin/PCircularBuffer.o differ diff --git a/CircularBuffer/bin/test.o b/CircularBuffer/bin/test.o new file mode 100644 index 0000000..f9b2165 Binary files /dev/null and b/CircularBuffer/bin/test.o differ diff --git a/CircularBuffer/bin/tester.exe b/CircularBuffer/bin/tester.exe new file mode 100644 index 0000000..9c0c97c Binary files /dev/null and b/CircularBuffer/bin/tester.exe differ diff --git a/CircularBuffer/example/simple_circular_buffer_example.c b/CircularBuffer/example/simple_circular_buffer_example.c new file mode 100644 index 0000000..6f431b8 --- /dev/null +++ b/CircularBuffer/example/simple_circular_buffer_example.c @@ -0,0 +1,41 @@ +/* + (WORK IN PROGRESS) + Penguin's Circular Buffer Example -- Turning a noisy bell curve into a less noisy bell curve + + Here's an example of using the circular buffer library for sensor data: + + Let's say I have a sensor that gives me temperature at 1khz (using ideals so it is exactly 1khz) + If this sensor was only giving me raw analog data, I might want to do some processing on these values + so that I can make sure the values are as clean as possible. The more samples we have, the closer we are to the actual value. + The faster we gather samples, the closer we get to representing our data in realtime. + + Using the sample rate, I can decide on a sampling window (in seconds) and an OSR (Oversampling Rate). The larger the buffer size, the more memory I need, so + it is useful to find a happy medium between a large buffer and clean values. + + A sampling window is the window of time in which we can accept values for an average value. Depending on your application, + a sampling window may need to be extremely small or maybe not so small. A rocket going extremely fast using + some sensor for real time controls will want an extremely small sampling window as well as a lot of measurements for + both clean, near noiseless data and as close to realtime data as possible. + + The sampling windows is usually an engineering requirement given that can match the sampling rate of the sensor with the following: + sampling window (in seconds) = 1 / frequency + Here, the OSR is simply 1. + + So at 1khz sample rate, let's say I decide I only need a 0.125 second sample window and I want to clean up some noisy data. + We can now use this equation: + OSR = frequency * sample window (in seconds) + + All of these have ignored real world slowdowns like the time it takes to do math on lower end hardware, interrupts slightly delaying the math, etc + Without wanting to do some hard analysis on whatever hardware we're using, I usually take my frequency and half it to ensure timing requirements are met, like so: + + OSR = frequency / 2 * sample window + + Please note: In applications that require real real-time data, this is not a good way of doing things. + +*/ + +int main() +{ + + return 0; +} \ No newline at end of file diff --git a/CircularBuffer/inc/PCircularBuffer.h b/CircularBuffer/inc/PCircularBuffer.h new file mode 100644 index 0000000..8eab357 --- /dev/null +++ b/CircularBuffer/inc/PCircularBuffer.h @@ -0,0 +1,202 @@ +// 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 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__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 +*/ + +#ifndef _PCIRCULARBUFFER_H_ +#define _PCIRCULARBUFFER_H_ + +#include +#include +// comment this out for release builds +#define PB_CB_DEBUG + +// Making these PB_EN/DIS rather than just ENABLE/DISABLE because +// some enable/disable definition might already exist that is +// inversely active (enabled = 0, disable = 1) +// this way our en/dis definitions are explicit +#ifndef PB_ENABLE + #define PB_ENABLE (1) +#endif + +#ifndef PB_DISABLE + #define PB_DISABLE (0) +#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) + +// Config +// Disable or Enable types needed here +// We can save code size this way +// While there are better ways to do this, this is the most accessible for anyone imo +#define PB_CB_FLOAT PB_ENABLE +#define PB_CB_DOUBLE PB_ENABLE +#define PB_CB_U8 PB_ENABLE +#define PB_CB_U16 PB_ENABLE +#define PB_CB_U32 PB_ENABLE +#define PB_CB_U64 PB_ENABLE +#define PB_CB_I8 PB_DISABLE +#define PB_CB_I16 PB_DISABLE +#define PB_CB_I32 PB_DISABLE +#define PB_CB_I64 PB_DISABLE + +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; + + +#if PB_CB_U8 +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); +#endif + +#if PB_CB_U16 +typedef struct p_cb_u16 +{ + uint16_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_u16* cbuffer, uint16_t value); + PB_CB_STATUS (*empty)(struct p_cb_u16* cbuffer); +}p_cb_u16; + +PB_CB_STATUS p_cb_u16_init(p_cb_u16* circ_buffer, uint16_t* buff, uint32_t max_length); +#endif + +#if PB_CB_U32 +typedef struct p_cb_u32 +{ + uint32_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_u32* cbuffer, uint32_t value); + PB_CB_STATUS (*empty)(struct p_cb_u32* cbuffer); +}p_cb_u32; + +PB_CB_STATUS p_cb_u32_init(p_cb_u32* circ_buffer, uint32_t* buff, uint32_t max_length); +#endif + + +#if PB_CB_U64 +typedef struct p_cb_u64 +{ + uint64_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_u64* cbuffer, uint64_t value); + PB_CB_STATUS (*empty)(struct p_cb_u64* cbuffer); +}p_cb_u64; + +PB_CB_STATUS p_cb_u64_init(p_cb_u64* circ_buffer, uint64_t* buff, uint32_t max_length); +#endif + +#if PB_CB_FLOAT +typedef struct p_cb_float +{ + float* 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_float* cbuffer, float value); + PB_CB_STATUS (*empty)(struct p_cb_float* cbuffer); +}p_cb_float; + +PB_CB_STATUS p_cb_float_init(p_cb_float* circ_buffer, float* buff, uint32_t max_length); +#endif + +#if PB_CB_DOUBLE +typedef struct p_cb_double +{ + double* 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_double* cbuffer, double value); + PB_CB_STATUS (*empty)(struct p_cb_double* cbuffer); +}p_cb_double; + +PB_CB_STATUS p_cb_double_init(p_cb_double* circ_buffer, double* buff, uint32_t max_length); +#endif + + + + +#endif \ No newline at end of file diff --git a/CircularBuffer/src/PCircularBuffer.c b/CircularBuffer/src/PCircularBuffer.c new file mode 100644 index 0000000..9303571 --- /dev/null +++ b/CircularBuffer/src/PCircularBuffer.c @@ -0,0 +1,427 @@ +#include + +// Error handler used for debugging only +#ifdef PB_CB_DEBUG +#include +static void handle_status(const char* func, PB_CB_STATUS status_code) +{ + if(status_code != PB_CB_GOOD) + { + printf("%s failed: error code: %d\r\n", func, status_code); + } +} +#endif + +// Circular Buffer Prototypes -- uint8_t +#if PB_CB_U8 +static PB_CB_STATUS p_cb_u8_push(p_cb_double* cbuffer, uint8_t value); +static PB_CB_STATUS p_cb_u8_empty(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_u8_is_full(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_u8_is_empty(p_cb_double* cbuffer); +#endif + +// Circular Buffer Prototypes -- uint16_t +#if PB_CB_U16 +static PB_CB_STATUS p_cb_u16_push(p_cb_double* cbuffer, uint16_t value); +static PB_CB_STATUS p_cb_u16_empty(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_u16_is_full(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_u16_is_empty(p_cb_double* cbuffer); +#endif + +// Circular Buffer Prototypes -- uint32_t +#if PB_CB_U32 +static PB_CB_STATUS p_cb_u32_push(p_cb_double* cbuffer, uint32_t value); +static PB_CB_STATUS p_cb_u32_empty(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_u32_is_full(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_u32_is_empty(p_cb_double* cbuffer); +#endif + +// Circular Buffer Prototypes -- uint64_t +#if PB_CB_U64 +static PB_CB_STATUS p_cb_u64_push(p_cb_double* cbuffer, uint64_t value); +static PB_CB_STATUS p_cb_u64_empty(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_u64_is_full(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_u64_is_empty(p_cb_double* cbuffer); +#endif + +// Circular Buffer Prototypes -- int8_t +#if PB_CB_I8 +static PB_CB_STATUS p_cb_i8_push(p_cb_double* cbuffer, int8_t value); +static PB_CB_STATUS p_cb_i8_empty(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_i8_is_full(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_i8_is_empty(p_cb_double* cbuffer); +#endif + +// Circular Buffer Prototypes -- int16_t +#if PB_CB_I16 +static PB_CB_STATUS p_cb_i16_push(p_cb_double* cbuffer, int16_t value); +static PB_CB_STATUS p_cb_i16_empty(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_i16_is_full(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_i16_is_empty(p_cb_double* cbuffer); +#endif + +// Circular Buffer Prototypes -- int32_t +#if PB_CB_I32 +static PB_CB_STATUS p_cb_i32_push(p_cb_double* cbuffer, int32_t value); +static PB_CB_STATUS p_cb_i32_empty(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_i32_is_full(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_i32_is_empty(p_cb_double* cbuffer); +#endif + +// Circular Buffer Prototypes -- int64_t +#if PB_CB_I64 +static PB_CB_STATUS p_cb_i64_push(p_cb_double* cbuffer, int64_t value); +static PB_CB_STATUS p_cb_i64_empty(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_i64_is_full(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_i64_is_empty(p_cb_double* cbuffer); +#endif + +// Circular Buffer Prototypes -- Float +#if PB_CB_FLOAT +static PB_CB_STATUS p_cb_float_push(p_cb_double* cbuffer, float value); +static PB_CB_STATUS p_cb_float_empty(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_float_is_full(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_float_is_empty(p_cb_double* cbuffer); +#endif + +// Circular Buffer Prototypes -- Double +#if PB_CB_DOUBLE +static PB_CB_STATUS p_cb_double_push(p_cb_double* cbuffer, double value); +static PB_CB_STATUS p_cb_double_empty(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_double_is_full(p_cb_double* cbuffer); +static PB_CB_STATUS p_cb_double_is_empty(p_cb_double* cbuffer); +#endif + +// Circular Buffer Definitions -- uint8_t +#if PB_CB_U8 +PB_CB_STATUS p_cb_u8_init(p_cb_u8* circ_buffer, uint8_t* buff, uint32_t max_length) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + do + { + // Make sure the buffer isn't bad (null) + if(!buff) + { + ret = PB_CB_NULL_BUFFER; + break; + } + + // Make sure the max buffer is a useable size + if(max_length > PB_CB_MAX_BUFFER_SIZE || max_length <= 0) + { + ret = PB_CB_BAD_BUFFER_SIZE; + break; + } + } while (0); + + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} + +PB_CB_STATUS p_cb_u8_push(p_cb_double* cbuffer, uint8_t value) +{ + +} +PB_CB_STATUS p_cb_u8_empty(p_cb_double* cbuffer) +{ + +} +#endif +// Circular Buffer Definitions -- uint16_t +#if PB_CB_U16 +PB_CB_STATUS p_cb_u16_init(p_cb_u16* circ_buffer, uint16_t* buff, uint32_t max_length) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + do + { + // Make sure the buffer isn't bad (null) + if(!buff) + { + ret = PB_CB_NULL_BUFFER; + break; + } + + // Make sure the max buffer is a useable size + if(max_length > PB_CB_MAX_BUFFER_SIZE || max_length <= 0) + { + ret = PB_CB_BAD_BUFFER_SIZE; + break; + } + } while (0); + + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +PB_CB_STATUS p_cb_u16_push(p_cb_double* cbuffer, uint16_t value) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +PB_CB_STATUS p_cb_u16_empty(p_cb_double* cbuffer) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +#endif + +// Circular Buffer Definitions -- uint32_t +#if PB_CB_U32 +PB_CB_STATUS p_cb_u32_init(p_cb_u32* circ_buffer, uint32_t* buff, uint32_t max_length) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + do + { + // Make sure the buffer isn't bad (null) + if(!buff) + { + ret = PB_CB_NULL_BUFFER; + break; + } + + // Make sure the max buffer is a useable size + if(max_length > PB_CB_MAX_BUFFER_SIZE || max_length <= 0) + { + ret = PB_CB_BAD_BUFFER_SIZE; + break; + } + } while (0); + + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +PB_CB_STATUS p_cb_u32_push(p_cb_double* cbuffer, uint32_t value) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +PB_CB_STATUS p_cb_u32_empty(p_cb_double* cbuffer) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +#endif + +// Circular Buffer Definitions -- uint64_t +#if PB_CB_U64 +PB_CB_STATUS p_cb_u64_init(p_cb_u64* circ_buffer, uint64_t* buff, uint32_t max_length) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + do + { + // Make sure the buffer isn't bad (null) + if(!buff) + { + ret = PB_CB_NULL_BUFFER; + break; + } + + // Make sure the max buffer is a useable size + if(max_length > PB_CB_MAX_BUFFER_SIZE || max_length <= 0) + { + ret = PB_CB_BAD_BUFFER_SIZE; + break; + } + } while (0); + + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +PB_CB_STATUS p_cb_u64_push(p_cb_double* cbuffer, uint64_t value) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +PB_CB_STATUS p_cb_u64_empty(p_cb_double* cbuffer) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +#endif + +#if PB_CB_FLOAT +PB_CB_STATUS p_cb_float_init(p_cb_float* circ_buffer, float* buff, uint32_t max_length) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + do + { + // Make sure the buffer isn't bad (null) + if(!buff) + { + ret = PB_CB_NULL_BUFFER; + break; + } + + // Make sure the max buffer is a useable size + if(max_length > PB_CB_MAX_BUFFER_SIZE || max_length <= 0) + { + ret = PB_CB_BAD_BUFFER_SIZE; + break; + } + } while (0); + + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +PB_CB_STATUS p_cb_float_push(p_cb_double* cbuffer, float value) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +PB_CB_STATUS p_cb_float_empty(p_cb_double* cbuffer) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +#endif + +// Circular Buffer Definitions -- double +#if PB_CB_DOUBLE +PB_CB_STATUS p_cb_double_init(p_cb_double* circ_buffer, double* buff, uint32_t max_length) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + do + { + // Make sure the buffer isn't bad (null) + if(!buff) + { + ret = PB_CB_NULL_BUFFER; + break; + } + + // Make sure the max buffer is a useable size + if(max_length > PB_CB_MAX_BUFFER_SIZE || max_length <= 0) + { + ret = PB_CB_BAD_BUFFER_SIZE; + break; + } + circ_buffer->max_len = max_length; + circ_buffer->push = p_cb_double_push; + circ_buffer->empty = p_cb_double_empty; + circ_buffer->empty(circ_buffer); + } while (0); + + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + + return ret; +} + +PB_CB_STATUS p_cb_double_push(p_cb_double* cbuffer, double value) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + + if(!cbuffer) + { + ret = PB_CB_NULL_CBUFFER; + } + else + { + cbuffer->buffer[cbuffer->head] = value; + cbuffer->head = (cbuffer->head + 1) % cbuffer->max_len; + printf("head: %d\r\n", cbuffer->max_len); + } + + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +PB_CB_STATUS p_cb_double_empty(p_cb_double* cbuffer) +{ + PB_CB_STATUS ret = PB_CB_GOOD; + + do + { + if(!cbuffer) + { + ret = PB_CB_NULL_CBUFFER; + break; + } + + if(!cbuffer->buffer) + { + ret = PB_CB_NULL_BUFFER; + break; + } + for(int ind = 0; ind < cbuffer->max_len; ind++) + { + cbuffer->buffer[ind] = 0.0; + } + cbuffer->head = 0; + cbuffer->b_empty = true; + cbuffer->b_filled = false; + } while (0); + + // Debugging + #ifdef PB_CB_DEBUG + handle_status(__func__, ret); + #endif + + return ret; +} +#endif diff --git a/CircularBuffer/test/test.c b/CircularBuffer/test/test.c new file mode 100644 index 0000000..e2ab91e --- /dev/null +++ b/CircularBuffer/test/test.c @@ -0,0 +1,21 @@ +#include +#include +int main() +{ + const uint16_t maxlength = 16; + double my_buffer[maxlength]; + p_cb_double data; + for(int ind = 0; ind < 2; ind++) + { + for(int x = 0; x < 16; x++) + { + printf("[%02d] Before: %02lf\t", x, data.buffer[x]); + data.push(&data, (double)x); + printf("[%02d] After: %02lf\r\n", x, data.buffer[x]); + } + } + + int x = 5; + printf("%d\r\n", x); + return 0; +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..263e790 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# PenguinBuffer