diff --git a/CircularBuffer/.clang-format b/CircularBuffer/.clang-format new file mode 100644 index 0000000..e4537cc --- /dev/null +++ b/CircularBuffer/.clang-format @@ -0,0 +1,178 @@ +--- +Language: Cpp +# BasedOnStyle: Microsoft +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: false + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 1000 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: true +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Always +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/CircularBuffer/.vscode/launch.json b/CircularBuffer/.vscode/launch.json index 4bb622a..9e41c87 100644 --- a/CircularBuffer/.vscode/launch.json +++ b/CircularBuffer/.vscode/launch.json @@ -1,29 +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" - } - ] +{ + // 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/examples/simple_circular_buffer_example.c b/CircularBuffer/examples/simple_circular_buffer_example.c index 5a602ff..a3a04a7 100644 --- a/CircularBuffer/examples/simple_circular_buffer_example.c +++ b/CircularBuffer/examples/simple_circular_buffer_example.c @@ -1,42 +1,42 @@ -/* - (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. - -*/ - -#include -int main() -{ - - return 0; +/* + (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. + +*/ + +#include +int main() +{ + + return 0; } \ No newline at end of file diff --git a/CircularBuffer/inc/PCircularBuffer.h b/CircularBuffer/inc/PCircularBuffer.h index 5031d9a..1301201 100644 --- a/CircularBuffer/inc/PCircularBuffer.h +++ b/CircularBuffer/inc/PCircularBuffer.h @@ -1,203 +1,198 @@ -// 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__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_DISABLE -#define PB_CB_DOUBLE PB_ENABLE -#define PB_CB_U8 PB_DISABLE -#define PB_CB_U16 PB_DISABLE -#define PB_CB_U32 PB_DISABLE -#define PB_CB_U64 PB_DISABLE -#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 +// 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__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_DISABLE +#define PB_CB_DOUBLE PB_ENABLE +#define PB_CB_U8 PB_DISABLE +#define PB_CB_U16 PB_DISABLE +#define PB_CB_U32 PB_DISABLE +#define PB_CB_U64 PB_DISABLE +#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 diff --git a/CircularBuffer/src/PCircularBuffer.c b/CircularBuffer/src/PCircularBuffer.c index 213f7b8..6e9ea78 100644 --- a/CircularBuffer/src/PCircularBuffer.c +++ b/CircularBuffer/src/PCircularBuffer.c @@ -3,407 +3,446 @@ // Error handler used for debugging only #ifdef PB_CB_DEBUG #include -static void handle_status(const char* func, PB_CB_STATUS status_code) +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); - } + 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_push(p_cb_double *cbuffer, uint8_t value); +static PB_CB_STATUS p_cb_u8_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_push(p_cb_double *cbuffer, uint16_t value); +static PB_CB_STATUS p_cb_u16_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_push(p_cb_double *cbuffer, uint32_t value); +static PB_CB_STATUS p_cb_u32_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_push(p_cb_double *cbuffer, uint64_t value); +static PB_CB_STATUS p_cb_u64_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); +#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); #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_push(p_cb_double *cbuffer, int16_t value); +static PB_CB_STATUS p_cb_i16_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_push(p_cb_double *cbuffer, int32_t value); +static PB_CB_STATUS p_cb_i32_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_push(p_cb_double *cbuffer, int64_t value); +static PB_CB_STATUS p_cb_i64_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_push(p_cb_double *cbuffer, float value); +static PB_CB_STATUS p_cb_float_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_push(p_cb_double *cbuffer, double value); +static PB_CB_STATUS p_cb_double_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 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 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_push(p_cb_double *cbuffer, uint8_t 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; + } + +// Debugging +#ifdef PB_CB_DEBUG + handle_status(__func__, ret); +#endif + return ret; } -PB_CB_STATUS p_cb_u8_empty(p_cb_double* cbuffer) +PB_CB_STATUS p_cb_u8_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; + } + memset(cbuffer->buffer, 0, cbuffer->max_len); + 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 // 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 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 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 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 + PB_CB_STATUS ret = PB_CB_GOOD; +// Debugging +#ifdef PB_CB_DEBUG + handle_status(__func__, ret); +#endif - return ret; + return ret; } -PB_CB_STATUS p_cb_u16_empty(p_cb_double* cbuffer) +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 + PB_CB_STATUS ret = PB_CB_GOOD; +// Debugging +#ifdef PB_CB_DEBUG + handle_status(__func__, ret); +#endif - return ret; + 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 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 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 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 + PB_CB_STATUS ret = PB_CB_GOOD; +// Debugging +#ifdef PB_CB_DEBUG + handle_status(__func__, ret); +#endif - return ret; + return ret; } -PB_CB_STATUS p_cb_u32_empty(p_cb_double* cbuffer) +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 + PB_CB_STATUS ret = PB_CB_GOOD; +// Debugging +#ifdef PB_CB_DEBUG + handle_status(__func__, ret); +#endif - return ret; + 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 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 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 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 + PB_CB_STATUS ret = PB_CB_GOOD; +// Debugging +#ifdef PB_CB_DEBUG + handle_status(__func__, ret); +#endif - return ret; + return ret; } -PB_CB_STATUS p_cb_u64_empty(p_cb_double* cbuffer) +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 + PB_CB_STATUS ret = PB_CB_GOOD; +// Debugging +#ifdef PB_CB_DEBUG + handle_status(__func__, ret); +#endif - return ret; + 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 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 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 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 + PB_CB_STATUS ret = PB_CB_GOOD; +// Debugging +#ifdef PB_CB_DEBUG + handle_status(__func__, ret); +#endif - return ret; + return ret; } -PB_CB_STATUS p_cb_float_empty(p_cb_double* cbuffer) +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 + PB_CB_STATUS ret = PB_CB_GOOD; +// Debugging +#ifdef PB_CB_DEBUG + handle_status(__func__, ret); +#endif - return ret; + 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 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->buffer = buff; - circ_buffer->max_len = (uint16_t)max_length; - circ_buffer->head = 0; - 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 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->buffer = buff; + circ_buffer->max_len = (uint16_t)max_length; + circ_buffer->head = 0; + 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 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; - } - - // Debugging - #ifdef PB_CB_DEBUG - handle_status(__func__, ret); - #endif - - return ret; + 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; + } + +// 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 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; + 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; + } + memset(cbuffer->buffer, 0, sizeof(double) * cbuffer->max_len); + 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 index 7029975..d1cd3b9 100644 --- a/CircularBuffer/test/test.c +++ b/CircularBuffer/test/test.c @@ -1,26 +1,26 @@ -#include -#include -int main() -{ - const uint16_t maxlength = 16; - double my_buffer[maxlength]; - p_cb_double data; - p_cb_double_init(&data, my_buffer, 16); - - for(int x = 0; x < 32; x++) - { - if( x < 16) - { - printf("[%02d] Before: %02lf\t", x, data.buffer[x]); - data.push(&data, (double)x); - printf("[%02d] After: %02lf\r\n", x, data.buffer[x]); - } - else - { - printf("[%02d] Before: %02lf\t", x - 16, data.buffer[x - 16]); - data.push(&data, (double)x); - printf("[%02d] After: %02lf\r\n", x - 16, data.buffer[x - 16]); - } - } - return 0; +#include +#include +int main() +{ + const uint16_t maxlength = 16; + double my_buffer[maxlength]; + p_cb_double data; + p_cb_double_init(&data, my_buffer, 16); + + for(int x = 0; x < 32; x++) + { + if( x < 16) + { + printf("[%02d] Before: %02lf\t", x, data.buffer[x]); + data.push(&data, (double)x); + printf("[%02d] After: %02lf\r\n", x, data.buffer[x]); + } + else + { + printf("[%02d] Before: %02lf\t", x - 16, data.buffer[x - 16]); + data.push(&data, (double)x); + printf("[%02d] After: %02lf\r\n", x - 16, data.buffer[x - 16]); + } + } + return 0; } \ No newline at end of file