11#include "si/commands.h"
22
3+ #define COMMAND_TABLE_SIZE 18
4+
35enum {
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
1012struct 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 };
1821static uint8_t command_buffer [SI_BLOCK_SIZE ];
1922static 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
2252static 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
3663static 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
5384void 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
6099uint8_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
65108si_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
70117void 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
83126void si_command_processing_enable ()
@@ -89,4 +132,5 @@ void si_command_processing_enable()
89132void si_command_processing_disable ()
90133{
91134 auto_tx_rx_transition = false;
135+ bus_state = BUS_STATE_UNKNOWN ;
92136}
0 commit comments