Buf serializing code

This commit is contained in:
Imbus 2025-07-26 15:36:44 +02:00
parent b0d86c7e2c
commit f8eed345ec
4 changed files with 220 additions and 0 deletions

87
buf/main.c Normal file
View file

@ -0,0 +1,87 @@
#include "buf.h"
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
/*
* Inspired by Vedders bldc code.
*
* I stumbled upon this beautiful solution when reading the motor control firmware from the vesc project.
* It effectively packs/serializes data into a buffer that could easily be sent over, say, uart. The original solution
* also does fp magic in a seemingly portable way.
*
* For the original GPLv3 licensed source, see:
* https://github.com/vedderb/bldc/blob/master/util/buffer.c
*
* For a more permissive MIT licensed source, see:
* https://github.com/waas-rent/vesc_can_sdk/blob/main/vesc_buffer.c
*/
/* This buffer can live anywhere, make sure its long enough to hold your data! */
uint8_t buf[100];
/* Float comparison with error tolerance */
static inline bool float_eq(float a, float b, float epsilon) {
return fabsf(a - b) < epsilon;
}
int main(void) {
/* This index acts as a read/write pointer */
size_t index = 0;
/* Declare and define data to be serialized */
uint8_t uint8bit = 8;
int16_t int16bit = 16;
int32_t int32bit = 32;
float float32bit = 1337.42;
/* When appending the buffer, the index is passed along and incremented accordingly */
buf_append_u8(buf, uint8bit, &index);
assert(index == 1);
buf_append_i16(buf, int16bit, &index);
assert(index == 3);
buf_append_i32(buf, int32bit, &index);
assert(index == 7);
buf_append_f32(buf, float32bit, &index);
assert(index == 11);
/*
* Note that after we're done appending, the index value will hold the
* length of the 'message', so, if you're piping this through uart or some
* other medium, you dont have to send the entire buffer length, just send
* up to the index.
*
* For bonus points for doing it vesc-style, prepend the message with the message type (a
* byte-length enum shared by both sides, for example), as well as a message
* length. You could also use the last two bytes of every message for a
* crc16 checksum for error resilience.
*/
/* Zero the original data */
uint8bit = 0;
int16bit = 0;
int32bit = 0;
float32bit = 0.f;
/* Read from beginning */
index = 0;
/* Re-populate our original data */
uint8bit = buf_read_u8(buf, &index);
assert(index == 1);
int16bit = buf_read_i16(buf, &index);
assert(index == 3);
int32bit = buf_read_i32(buf, &index);
assert(index == 7);
float32bit = buf_read_f32(buf, &index);
assert(index == 11);
/* Assert that it all worked out */
assert(uint8bit == 8);
assert(int16bit == 16);
assert(int32bit == 32);
assert(float_eq(float32bit, 1337.42, 0.01));
printf("All asserts passed!\n");
}