/** * @file app_uart_protocol.c * @brief Table-driven incremental UART packet parser and checksum helpers. */ #include "app_uart_protocol.h" #include static const app_packet_descriptor_t g_packet_descriptors[] = { {APP_PACKET_HEADER_WORK_CONFIG, APP_PACKET_BYTES_WORK_CONFIG, APP_PACKET_WORDS_WORK_CONFIG, 13, APP_PACKET_KIND_WORK_CONFIG}, {APP_PACKET_HEADER_DEFAULTS, 2u, 0u, -1, APP_PACKET_KIND_DEFAULTS}, {APP_PACKET_HEADER_TX_CURRENT, 2u, 0u, -1, APP_PACKET_KIND_TX_CURRENT}, {APP_PACKET_HEADER_QUERY_STATE, 2u, 0u, -1, APP_PACKET_KIND_QUERY_STATE}, {APP_PACKET_HEADER_PROFILE_SAVE_CONTROL, APP_PACKET_BYTES_PROFILE_SAVE_CONTROL, APP_PACKET_WORDS_PROFILE_SAVE_CONTROL, 13, APP_PACKET_KIND_PROFILE_SAVE_CONTROL}, {APP_PACKET_HEADER_AD9102_CONTROL, APP_PACKET_BYTES_SHORT_CONTROL, APP_PACKET_WORDS_SHORT_CONTROL, 3, APP_PACKET_KIND_AD9102_CONTROL}, {APP_PACKET_HEADER_AD9833_CONTROL, APP_PACKET_BYTES_SHORT_CONTROL, APP_PACKET_WORDS_SHORT_CONTROL, 3, APP_PACKET_KIND_AD9833_CONTROL}, {APP_PACKET_HEADER_DS1809_CONTROL, APP_PACKET_BYTES_SHORT_CONTROL, APP_PACKET_WORDS_SHORT_CONTROL, 3, APP_PACKET_KIND_DS1809_CONTROL}, {APP_PACKET_HEADER_STM32_DAC_CONTROL, APP_PACKET_BYTES_SHORT_CONTROL, APP_PACKET_WORDS_SHORT_CONTROL, 3, APP_PACKET_KIND_STM32_DAC_CONTROL}, {APP_PACKET_HEADER_AD9102_WAVE_CONTROL, APP_PACKET_BYTES_SHORT_CONTROL, APP_PACKET_WORDS_SHORT_CONTROL, 3, APP_PACKET_KIND_AD9102_WAVE_CONTROL}, {APP_PACKET_HEADER_AD9102_WAVE_DATA, APP_PACKET_BYTES_AD9102_WAVE_DATA, APP_PACKET_WORDS_AD9102_WAVE_DATA, 13, APP_PACKET_KIND_AD9102_WAVE_DATA}, {APP_PACKET_HEADER_PROFILE_SAVE_DATA, APP_PACKET_BYTES_PROFILE_SAVE_DATA, APP_PACKET_WORDS_PROFILE_SAVE_DATA, 13, APP_PACKET_KIND_PROFILE_SAVE_DATA} }; static const app_packet_descriptor_t *app_uart_protocol_find_descriptor(uint16_t header) { size_t index; for (index = 0u; index < (sizeof(g_packet_descriptors) / sizeof(g_packet_descriptors[0])); ++index) { if (g_packet_descriptors[index].header == header) { return &g_packet_descriptors[index]; } } return NULL; } uint16_t app_protocol_calculate_checksum(const uint16_t *words, uint16_t word_count) { uint16_t checksum; uint16_t index; if ((words == NULL) || (word_count == 0u)) { return 0u; } checksum = words[0]; for (index = 1u; index < word_count; ++index) { checksum ^= words[index]; } return checksum; } void app_uart_protocol_init(app_uart_protocol_parser_t *parser) { if (parser != NULL) { memset(parser, 0, sizeof(*parser)); } } void app_uart_protocol_reset(app_uart_protocol_parser_t *parser) { app_uart_protocol_init(parser); } app_protocol_feed_result_t app_uart_protocol_feed_byte(app_uart_protocol_parser_t *parser, uint8_t byte, app_packet_t *out_packet) { uint8_t word_index; if ((parser == NULL) || (out_packet == NULL)) { return APP_PROTOCOL_FEED_IN_PROGRESS; } if (parser->bytes_received == 0u) { parser->buffer[0] = byte; parser->partial_header = byte; parser->bytes_received = 1u; return APP_PROTOCOL_FEED_IN_PROGRESS; } if (parser->bytes_received == 1u) { parser->buffer[1] = byte; parser->partial_header = (uint16_t)(parser->partial_header | ((uint16_t)byte << 8)); parser->descriptor = app_uart_protocol_find_descriptor(parser->partial_header); if (parser->descriptor == NULL) { app_uart_protocol_reset(parser); return APP_PROTOCOL_FEED_INVALID_HEADER; } parser->bytes_received = 2u; if (parser->descriptor->total_bytes == 2u) { memset(out_packet, 0, sizeof(*out_packet)); out_packet->kind = parser->descriptor->kind; out_packet->header = parser->descriptor->header; out_packet->checksum_valid = true; app_uart_protocol_reset(parser); return APP_PROTOCOL_FEED_PACKET_READY; } return APP_PROTOCOL_FEED_IN_PROGRESS; } if (parser->descriptor == NULL) { app_uart_protocol_reset(parser); return APP_PROTOCOL_FEED_INVALID_HEADER; } if (parser->bytes_received >= parser->descriptor->total_bytes) { app_uart_protocol_reset(parser); return APP_PROTOCOL_FEED_INVALID_HEADER; } parser->buffer[parser->bytes_received] = byte; ++parser->bytes_received; if (parser->bytes_received < parser->descriptor->total_bytes) { return APP_PROTOCOL_FEED_IN_PROGRESS; } memset(out_packet, 0, sizeof(*out_packet)); out_packet->kind = parser->descriptor->kind; out_packet->header = parser->descriptor->header; out_packet->payload_words = parser->descriptor->payload_words; for (word_index = 0u; word_index < parser->descriptor->payload_words; ++word_index) { uint8_t byte_offset = (uint8_t)(2u + (word_index * 2u)); out_packet->words[word_index] = (uint16_t)(parser->buffer[byte_offset] | ((uint16_t)parser->buffer[byte_offset + 1u] << 8)); } if (parser->descriptor->checksum_word_index >= 0) { uint8_t checksum_index = (uint8_t)parser->descriptor->checksum_word_index; out_packet->checksum_valid = app_protocol_calculate_checksum(out_packet->words, checksum_index) == out_packet->words[checksum_index]; } else { out_packet->checksum_valid = true; } app_uart_protocol_reset(parser); return APP_PROTOCOL_FEED_PACKET_READY; }