Files
templates/c/set-protocol/src/tms2812.c

79 lines
2.4 KiB
C

#include "tms2812.h"
#include <stdint.h>
#include <string.h>
#include "set_crc.h"
static void put_le32(uint8_t *output, uint32_t value)
{
output[0] = (uint8_t)value;
output[1] = (uint8_t)(value >> 8);
output[2] = (uint8_t)(value >> 16);
output[3] = (uint8_t)(value >> 24);
}
uint16_t tms2812_crc16(const uint8_t *data, size_t size)
{
return set_crc16_modbus(data, size);
}
size_t tms2812_build_upload_request(
uint8_t controller, uint32_t word_address, uint32_t byte_count,
uint8_t *output, size_t output_size)
{
uint16_t crc;
if ((output == NULL) || (output_size < TMS2812_UPLOAD_REQUEST_SIZE) ||
(byte_count == 0U)) return 0U;
output[0] = controller;
output[1] = TMS2812_CMD_UPLOAD;
put_le32(&output[2], word_address);
put_le32(&output[6], byte_count);
crc = tms2812_crc16(output, 10U);
output[10] = (uint8_t)crc;
output[11] = (uint8_t)(crc >> 8);
return TMS2812_UPLOAD_REQUEST_SIZE;
}
size_t tms2812_expected_upload_response_size(uint32_t byte_count)
{
if (byte_count == 0U ||
(uint64_t)byte_count + TMS2812_UPLOAD_RESPONSE_OVERHEAD > SIZE_MAX) {
return 0U;
}
return (size_t)byte_count + TMS2812_UPLOAD_RESPONSE_OVERHEAD;
}
int tms2812_validate_upload_response(
const uint8_t *data, size_t size, uint8_t controller,
uint32_t byte_count)
{
size_t expected = tms2812_expected_upload_response_size(byte_count);
size_t crc_offset;
uint16_t expected_crc;
uint16_t actual_crc;
if (data == NULL) return TMS2812_ERROR_ARGUMENT;
if (expected == 0U) return TMS2812_ERROR_RANGE;
if (size != expected) return TMS2812_ERROR_LENGTH;
if ((data[0] != controller) || (data[1] != TMS2812_CMD_UPLOAD))
return TMS2812_ERROR_HEADER;
crc_offset = (size_t)byte_count + 2U;
expected_crc = tms2812_crc16(data, crc_offset);
actual_crc = (uint16_t)(data[crc_offset] |
((uint16_t)data[crc_offset + 1U] << 8));
return actual_crc == expected_crc ? TMS2812_OK : TMS2812_ERROR_CRC;
}
int tms2812_decode_upload_response(
const uint8_t *data, size_t size, uint8_t controller,
uint32_t byte_count, uint8_t *output, size_t output_size)
{
int status = tms2812_validate_upload_response(
data, size, controller, byte_count);
if (status != TMS2812_OK) return status;
if ((output == NULL) || (output_size < byte_count))
return TMS2812_ERROR_CAPACITY;
memcpy(output, &data[2], byte_count);
return TMS2812_OK;
}