Skip to content

Commit aa63707

Browse files
committed
libsi: Reduce memory usage in command_table
1 parent 457090a commit aa63707

File tree

1 file changed

+74
-30
lines changed

1 file changed

+74
-30
lines changed

firmware/libsi/src/commands.c

Lines changed: 74 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,126 @@
11
#include "si/commands.h"
22

3+
#define COMMAND_TABLE_SIZE 18
4+
35
enum {
4-
COMMAND_STATE_IDLE,
5-
COMMAND_STATE_RX,
6-
COMMAND_STATE_TX,
7-
COMMAND_STATE_ERROR,
6+
BUS_STATE_UNKNOWN = 0,
7+
BUS_STATE_IDLE,
8+
BUS_STATE_BUSY,
9+
BUS_STATE_ERROR,
810
};
911

1012
struct command_entry {
13+
uint8_t command;
1114
uint8_t length;
1215
si_command_handler_fn handler;
1316
void *context;
1417
};
1518

16-
static uint8_t command_state = COMMAND_STATE_IDLE;
17-
static struct command_entry command_table[256] = {0};
19+
static uint8_t bus_state = BUS_STATE_UNKNOWN;
20+
static struct command_entry command_table[COMMAND_TABLE_SIZE] = {0};
1821
static uint8_t command_buffer[SI_BLOCK_SIZE];
1922
static bool auto_tx_rx_transition = false;
2023

24+
// Vaguely context-aware hash function
25+
static inline uint8_t hash_command(uint8_t command)
26+
{
27+
// Reserve hash slots for universal commands
28+
if (command == 0x00)
29+
return 0;
30+
if (command == 0xFF)
31+
return 1;
32+
33+
// Hash all other commands to remaining slots
34+
return (command % (COMMAND_TABLE_SIZE - 2)) + 2;
35+
}
36+
37+
// Find a command entry by command id
38+
static struct command_entry *find_command(uint8_t command)
39+
{
40+
uint8_t index = hash_command(command);
41+
42+
while (command_table[index].handler != NULL) {
43+
if (command_table[index].command == command) {
44+
return &command_table[index];
45+
}
46+
index = (index + 1) % COMMAND_TABLE_SIZE;
47+
}
48+
return NULL;
49+
}
50+
2151
// Command handler TX completion callback
2252
static void on_tx_complete(int result)
2353
{
24-
if (result == 0) {
25-
command_state = COMMAND_STATE_IDLE;
54+
// Update bus state based on result
55+
bus_state = (result < 0) ? BUS_STATE_ERROR : BUS_STATE_IDLE;
2656

27-
// Check if we need to transition back to RX mode
28-
if (auto_tx_rx_transition)
29-
si_command_process();
30-
} else {
31-
command_state = COMMAND_STATE_ERROR;
32-
}
57+
// Transition back to RX mode if auto transition is enabled
58+
if (auto_tx_rx_transition)
59+
si_command_process();
3360
}
3461

3562
// Command handler RX completion callback
3663
static void on_rx_complete(int result)
3764
{
3865
if (result == 0) {
3966
// Look up the command in the table
40-
struct command_entry *command = &command_table[command_buffer[0]];
41-
if (command->handler) {
67+
struct command_entry *command = find_command(command_buffer[0]);
68+
if (command && command->handler) {
4269
// Call the command handler
43-
command_state = COMMAND_STATE_TX;
70+
bus_state = BUS_STATE_BUSY;
4471
command->handler(command_buffer, on_tx_complete, command->context);
4572
return;
4673
}
4774
}
4875

4976
// Error during command read or handler not found
50-
command_state = COMMAND_STATE_ERROR;
77+
bus_state = BUS_STATE_ERROR;
78+
79+
// Transition back to RX mode if auto transition is enabled
80+
if (auto_tx_rx_transition)
81+
si_command_process();
5182
}
5283

5384
void si_command_register(uint8_t command, uint8_t length, si_command_handler_fn handler, void *context)
5485
{
55-
command_table[command].length = length;
56-
command_table[command].handler = handler;
57-
command_table[command].context = context;
86+
uint8_t index = hash_command(command);
87+
88+
// Linear probing for collision resolution
89+
while (command_table[index].handler != NULL && command_table[index].command != command) {
90+
index = (index + 1) % COMMAND_TABLE_SIZE;
91+
}
92+
93+
command_table[index].command = command;
94+
command_table[index].length = length;
95+
command_table[index].handler = handler;
96+
command_table[index].context = context;
5897
}
5998

6099
uint8_t si_command_get_length(uint8_t command)
61100
{
62-
return command_table[command].length;
101+
struct command_entry *entry = find_command(command);
102+
if (entry == NULL)
103+
return 0;
104+
105+
return entry->length;
63106
}
64107

65108
si_command_handler_fn si_command_get_handler(uint8_t command)
66109
{
67-
return command_table[command].handler;
110+
struct command_entry *entry = find_command(command);
111+
if (entry == NULL)
112+
return NULL;
113+
114+
return entry->handler;
68115
}
69116

70117
void si_command_process()
71118
{
72-
if (command_state == COMMAND_STATE_ERROR) {
119+
if (bus_state != BUS_STATE_IDLE)
73120
si_await_bus_idle();
74-
command_state = COMMAND_STATE_IDLE;
75-
}
76121

77-
if (command_state == COMMAND_STATE_IDLE) {
78-
command_state = COMMAND_STATE_RX;
79-
si_read_command(command_buffer, on_rx_complete);
80-
}
122+
bus_state = BUS_STATE_BUSY;
123+
si_read_command(command_buffer, on_rx_complete);
81124
}
82125

83126
void si_command_processing_enable()
@@ -89,4 +132,5 @@ void si_command_processing_enable()
89132
void si_command_processing_disable()
90133
{
91134
auto_tx_rx_transition = false;
135+
bus_state = BUS_STATE_UNKNOWN;
92136
}

0 commit comments

Comments
 (0)