Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/modules/uart/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
idf_component_register(
SRCS
"src/uart_task.c"
"src/addr_map.c"
"src/ssm1.c"

INCLUDE_DIRS "include"

REQUIRES
core

PRIV_REQUIRES
freertos
drivers
)
41 changes: 16 additions & 25 deletions src/modules/uart/src/ssm1.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ void ssm1_get_read_command(struct read_ctx *ctx, uint8_t *cmd)
memcpy(cmd, read_command, sizeof(read_command));
}

void ssm1_get_stop_command(struct read_ctx *ctx, uint8_t *cmd)
{
const uint8_t stop_command[4] = {
0x12, GET_MSB(ctx->addr), GET_LSB(ctx->addr), 0x00
};
memcpy(cmd, stop_command, sizeof(stop_command));
}

void ssm1_get_clear_command(struct read_ctx *ctx, uint8_t *cmd)
{
const uint8_t clear_command[4] = {
Expand All @@ -46,25 +54,11 @@ size_t ssm1_parser_feed(struct ssm1_parser *p,
switch (p->state)
{
case P_WAIT:
if (b == 0xFF) {
p->state = P_MAYBE_ROMID_FE;
} else {
p->tmp_msb = b;
p->state = P_READ_LSB;
}
p->state = (b == 0xFF) ? P_MAYBE_ROMID_FE : P_READ_LSB;
break;

case P_MAYBE_ROMID_FE:
if (b == 0xFE) {
p->state = P_ROMID_SKIP;
} else if (b == 0xFF) {
// Keep waiting for 0xFE
} else {
// Fallback to read frame
p->tmp_msb = 0xFF;
p->tmp_lsb = b;
p->state = P_READ_DATA;
}
p->state = (b == 0xFE) ? P_ROMID_SKIP : P_READ_DATA;
break;

case P_ROMID_SKIP:
Expand All @@ -74,26 +68,23 @@ size_t ssm1_parser_feed(struct ssm1_parser *p,

case P_ROMID_BYTES:
p->rom_buf[p->rom_index++] = b;
if (p->rom_index >= 3) {
if (out_count < out_cap) {
struct parsed_msg *m = &out_msgs[out_count++];
m->type = MSG_TYPE_ROMID;
memcpy(m->u.rom.romid, p->rom_buf, 3);
}
if (p->rom_index == 3)
{
out_msgs->type = MSG_TYPE_ROMID;
memcpy(out_msgs->u.rom.romid, p->rom_buf, 3);
p->state = P_WAIT;
}
break;

case P_READ_LSB:
p->tmp_lsb = b;
p->state = P_READ_DATA;
break;

case P_READ_DATA:
if (out_count < out_cap) {
if (out_count < out_cap)
{
struct parsed_msg *m = &out_msgs[out_count++];
m->type = MSG_TYPE_READ;
m->u.read.addr = ((uint16_t)p->tmp_msb << 8) | p->tmp_lsb;
m->u.read.value = b;
}
p->state = P_WAIT;
Expand Down
21 changes: 18 additions & 3 deletions src/modules/uart/src/ssm1.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include "fsm_states.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

typedef enum
Expand Down Expand Up @@ -45,14 +44,30 @@ struct parsed_msg
{
msg_type_e type;
union {
struct { uint8_t romid[3]; } rom; // MSG_TYPE_ROMID
struct { uint16_t addr; uint8_t value; } read; // MSG_TYPE_READ
struct { uint8_t romid[3]; } rom; // MSG_TYPE_ROMID
struct { uint8_t value; } read; // MSG_TYPE_READ
} u;
};

void ssm1_get_romid_command(struct romid_ctx *ctx, uint8_t *cmd);
void ssm1_get_read_command(struct read_ctx *ctx, uint8_t *cmd);
void ssm1_get_stop_command(struct read_ctx *ctx, uint8_t *cmd);
void ssm1_get_clear_command(struct read_ctx *ctx, uint8_t *cmd);

/**
* @brief Feed UART bytes into the SSM1 parser state machine.
*
* The parser maintains internal state between calls, allowing
* partial frames, stream data, or chunked input.
*
* @param p Pointer to the parser state machine.
* @param buf Pointer to the input byte buffer.
* @param len Num of bytes available in @p buf.
* @param out_msgs Array parsed messages is written to.
* @param out_cap Num of messages @p out_msgs can hold.
*
* @return Num of parsed messages written to @p out_msgs.
*/
size_t ssm1_parser_feed(struct ssm1_parser *p,
const uint8_t *buf,
size_t len,
Expand Down
76 changes: 43 additions & 33 deletions src/modules/uart/src/uart_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
#include "ssm1.h"
#include "addr_map.h"
#include "log.h"
#include "defines.h"
#include "uart_data.h"
#include "uart.h"
#include <string.h>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include <freertos/task.h>
Expand All @@ -21,62 +19,74 @@ static QueueHandle_t uart_data_queue = NULL;

static void uart_task(void *parameters)
{
uint8_t rxbuf[128];
uint8_t cmd[4];
uint8_t rxbuf[256] = {0};
uint8_t cmd[4] = {0};

struct ssm1_parser parser = {0};
struct romid_ctx romctx = {0};
struct read_ctx rctx = {0};

struct uart_data out = {0};
struct parsed_msg msgs[32] = {0};

TickType_t last_romid_send = 0;
bool romid_received = false;
bool init_romid = false;
uint32_t new_state = 0;

for (;;)
{
// Retry ROMID until received
if (!romid_received &&
(xTaskGetTickCount() - last_romid_send) > pdMS_TO_TICKS(100))
if (!init_romid)
{
xQueueSend(uart_data_queue, &out, 0);
init_romid = true;
ssm1_get_romid_command(&romctx, cmd);
}

TickType_t now = xTaskGetTickCount();
if (!romid_received &&
(now - last_romid_send) > pdMS_TO_TICKS(1000))
{
send_bytes(cmd, 4);
last_romid_send = xTaskGetTickCount();
last_romid_send = now;
}

int len = uart_read_from_isr(rxbuf, sizeof(rxbuf), 5);
int len = uart_read_from_isr(rxbuf, sizeof(rxbuf), 1);
if (len > 0)
{
struct parsed_msg msgs[8];
size_t count = ssm1_parser_feed(&parser, rxbuf, len, msgs, 8);
size_t count = ssm1_parser_feed(&parser, rxbuf, len, msgs, 32);

for (size_t i = 0; i < count; i++)
// Check first message for ROM ID
if (msgs[0].type == MSG_TYPE_ROMID)
{
struct parsed_msg *m = &msgs[i];
romid_received = true;
rctx.addr = 0;
ssm1_get_stop_command(&rctx, cmd);
send_bytes(cmd, 4);

out.state = STATE_ROMID;
out.romid[0] = msgs[0].u.rom.romid[0];
out.romid[1] = msgs[0].u.rom.romid[1];
out.romid[2] = msgs[0].u.rom.romid[2];
xQueueSend(uart_data_queue, &out, 0);
}

if (m->type == MSG_TYPE_ROMID)
{
romid_received = true;

struct uart_data out = {0};
out.state = STATE_ROMID;
memcpy(out.romid, m->u.rom.romid, 3);
xQueueSend(uart_data_queue, &out, 0);
}
else if (m->type == MSG_TYPE_READ)
{
struct uart_data out = {0};
out.state = rctx.state;
out.value = m->u.read.value;
xQueueSend(uart_data_queue, &out, 0);

ssm1_get_read_command(&rctx, cmd);
send_bytes(cmd, 4);
}
// Process remaining messages (skip if ROM ID)
for (size_t i = 0; i < count; ++i)
{
struct parsed_msg *m = &msgs[i];
if (m->type == MSG_TYPE_ROMID) { continue; }
out.state = rctx.state;
out.value = m->u.read.value;
xQueueSend(uart_data_queue, &out, 0);
}
}

uint32_t new_state;
if (xTaskNotifyWait(0, 0xFFFFFFFF, &new_state, 0) == pdPASS)
{
ssm1_get_stop_command(&rctx, cmd);
send_bytes(cmd, 4);

rctx.state = (fsm_state_e)new_state;
rctx.addr = lookup_addr(rctx.state);

Expand Down