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