diff --git a/src/telemetry.c b/src/telemetry.c new file mode 100644 index 0000000..fe6f471 --- /dev/null +++ b/src/telemetry.c @@ -0,0 +1,36 @@ +#include "telemetry.h" + +static uint8_t crc8(const uint8_t *data, size_t length) { + uint8_t crc = 0; + for (size_t i = 0; i < length; ++i) { + crc ^= data[i]; + for (int bit = 0; bit < 8; ++bit) + crc = (uint8_t)((crc & 0x80u) ? (((unsigned)crc << 1) ^ 0x07u) : ((unsigned)crc << 1)); + } + return crc; +} + +frame_result_t decode_frame(const uint8_t *bytes, size_t length, sample_t *sample) { + if (!bytes || !sample || length != 8) return FRAME_SHORT; + if (bytes[0] != 1) return FRAME_VERSION; + if (crc8(bytes, 7) != bytes[7]) return FRAME_CRC; + sample->sequence = (uint16_t)((bytes[1] << 8) | bytes[2]); + sample->temperature_centi = (int16_t)((bytes[3] << 8) | bytes[4]); + sample->voltage_mv = (uint16_t)((bytes[5] << 8) | bytes[6]); + if (sample->temperature_centi < -4000 || sample->temperature_centi > 8500 || + sample->voltage_mv < 9000 || sample->voltage_mv > 16000) return FRAME_RANGE; + return FRAME_OK; +} + +const char *frame_result_name(frame_result_t result) { + switch (result) { + case FRAME_OK: return "accepted"; + case FRAME_SHORT: return "invalid length"; + case FRAME_VERSION: return "unsupported version"; + case FRAME_CRC: return "crc mismatch"; + case FRAME_RANGE: return "sample out of range"; + case FRAME_DUPLICATE: return "duplicate sequence"; + case FRAME_ROLLBACK: return "sequence rollback"; + } + return "unknown"; +}