big refactoring and features added
This commit is contained in:
162
App/Protocol/app_uart_protocol.c
Normal file
162
App/Protocol/app_uart_protocol.c
Normal file
@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
68
App/Protocol/app_uart_protocol.h
Normal file
68
App/Protocol/app_uart_protocol.h
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @file app_uart_protocol.h
|
||||
* @brief Table-driven incremental UART packet parser and checksum helpers.
|
||||
*
|
||||
* Architectural note:
|
||||
* The parser is intentionally transport-agnostic. It receives one byte at a
|
||||
* time from the IRQ adapter, reconstructs packets according to a descriptor
|
||||
* table, validates checksums when applicable, and emits fully decoded packet
|
||||
* objects for the application core.
|
||||
*/
|
||||
|
||||
#ifndef APP_UART_PROTOCOL_H
|
||||
#define APP_UART_PROTOCOL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "app_types.h"
|
||||
|
||||
/**
|
||||
* @brief Descriptor describing one supported UART packet shape.
|
||||
*/
|
||||
typedef struct app_packet_descriptor_t {
|
||||
uint16_t header;
|
||||
uint8_t total_bytes;
|
||||
uint8_t payload_words;
|
||||
int8_t checksum_word_index;
|
||||
app_packet_kind_t kind;
|
||||
} app_packet_descriptor_t;
|
||||
|
||||
/**
|
||||
* @brief Parsed UART packet emitted by the protocol layer.
|
||||
*/
|
||||
typedef struct app_packet_t {
|
||||
app_packet_kind_t kind;
|
||||
uint16_t header;
|
||||
uint8_t payload_words;
|
||||
bool checksum_valid;
|
||||
uint16_t words[APP_PROTOCOL_MAX_PAYLOAD_WORDS];
|
||||
} app_packet_t;
|
||||
|
||||
/**
|
||||
* @brief Mutable state of the incremental UART parser.
|
||||
*/
|
||||
typedef struct app_uart_protocol_parser_t {
|
||||
const app_packet_descriptor_t *descriptor;
|
||||
uint16_t partial_header;
|
||||
uint8_t bytes_received;
|
||||
uint8_t buffer[APP_PROTOCOL_MAX_PACKET_BYTES];
|
||||
} app_uart_protocol_parser_t;
|
||||
|
||||
/**
|
||||
* @brief Result returned after feeding one byte into the parser.
|
||||
*/
|
||||
typedef enum app_protocol_feed_result_t {
|
||||
APP_PROTOCOL_FEED_IN_PROGRESS = 0,
|
||||
APP_PROTOCOL_FEED_PACKET_READY,
|
||||
APP_PROTOCOL_FEED_INVALID_HEADER
|
||||
} app_protocol_feed_result_t;
|
||||
|
||||
void app_uart_protocol_init(app_uart_protocol_parser_t *parser);
|
||||
void app_uart_protocol_reset(app_uart_protocol_parser_t *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);
|
||||
uint16_t app_protocol_calculate_checksum(const uint16_t *words, uint16_t word_count);
|
||||
|
||||
#endif /* APP_UART_PROTOCOL_H */
|
||||
Reference in New Issue
Block a user