CPlay/message/message.c
2025-08-24 12:47:13 +02:00

52 lines
1.4 KiB
C

#include "message.h"
#include <assert.h>
uint16_t compute_crc16(const uint8_t *data, uint16_t len);
bool is_type_valid(MessageType t);
/**
* @brief Create a message
*
* Use as: create_message(&m1, UI_VOLTAGE, (MessageData){.voltage = 6.3});
*
* @param m A pointer to the message struct
* @param type The enum type of the message you want to send
* @param data The data corresponding to the message type
*/
void message_create(Message *m, MessageType type, MessageData data) {
m->type = type;
m->data = data;
m->crc = compute_crc16((const uint8_t *)m, offsetof(Message, crc));
}
bool message_validate(const Message *m) {
return is_type_valid(m->type) && m->crc == compute_crc16((const uint8_t *)m, offsetof(Message, crc));
}
// Standard CRC-16-CCITT (poly 0x1021, init 0xFFFF)
uint16_t compute_crc16(const uint8_t *data, uint16_t len) {
uint16_t crc = 0xFFFF;
for (uint16_t i = 0; i < len; i++) {
crc ^= (uint16_t)data[i] << 8;
for (int j = 0; j < 8; j++) {
if (crc & 0x8000)
crc = (crc << 1) ^ 0x1021;
else
crc <<= 1;
}
}
return crc;
}
bool is_type_valid(MessageType t) {
return t >= UI_SPEED_MS && t <= UI_VOLTAGE;
}
int message_tests(void) {
Message m;
message_create(&m, UI_BATTERY, (MessageData){75});
assert(message_validate(&m));
return 0;
}