52 lines
1.4 KiB
C
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;
|
|
}
|