#include "message.h" #include 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; }