Files
RadioPhotonic_PCB_software/App/Protocol/app_uart_protocol.c
2026-04-24 16:51:15 +03:00

163 lines
5.6 KiB
C

/**
* @file app_uart_protocol.c
* @brief Table-driven incremental UART packet parser and checksum helpers.
*/
#include "app_uart_protocol.h"
#include <string.h>
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;
}