2. Closed Firmware & 'Over-engineering' I respect the Open Source philosophy, but io_decoder is a professional project that includes dedicated hardware. The 'over-engineering' you see in the HAL driver is actually optimization. While a user-space component can work, a dedicated C component ensures deterministic polling and much lower jitter. If you want a 'professional feel' on the handwheel, those milliseconds matter.
Code:
halcompile --compile io_decoder.c
Compiling realtime io_decoder.c
io_decoder.c: In function ‘usb_thread_function’:
io_decoder.c:1119:60: warning: comparison of integer expressions of different signedness: ‘int’ and ‘long unsigned int’ [-Wsign-compare]
1119 | if (tx_buffer_size > sizeof(io->tx_packet_buffer)) {
| ^
io_decoder.c:1214:80: warning: comparison of integer expressions of different signedness: ‘int’ and ‘uint32_t’ {aka ‘unsigned int’} [-Wsign-compare]
1214 | if (parsed_len == io->usb_rx_payload_len) { //
| ^~
io_decoder.c:1318:31: warning: variable ‘rx_success_delta’ set but not used [-Wunused-but-set-variable]
1318 | float rx_success_delta = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:1316:31: warning: variable ‘tx_success_delta’ set but not used [-Wunused-but-set-variable]
1316 | float tx_success_delta = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:1313:31: warning: variable ‘rx_success’ set but not used [-Wunused-but-set-variable]
1313 | float rx_success = 0;
| ^~~~~~~~~~
io_decoder.c:1311:31: warning: variable ‘tx_success’ set but not used [-Wunused-but-set-variable]
1311 | float tx_success = 0;
| ^~~~~~~~~~
io_decoder.c:805:13: warning: unused variable ‘serial_verify’ [-Wunused-variable]
805 | int serial_verify;
| ^~~~~~~~~~~~~
io_decoder.c:783:21: warning: unused variable ‘old_usb_loop’ [-Wunused-variable]
783 | static long old_usb_loop;
| ^~~~~~~~~~~~
io_decoder.c:776:20: warning: unused variable ‘old_pin_debug2’ [-Wunused-variable]
776 | static int old_pin_debug2 = 0;
| ^~~~~~~~~~~~~~
io_decoder.c:775:20: warning: unused variable ‘old_hand_invalid_received’ [-Wunused-variable]
775 | static int old_hand_invalid_received = 0;
| ^~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:773:20: warning: unused variable ‘old_hand_invalid_send’ [-Wunused-variable]
773 | static int old_hand_invalid_send = 0;
| ^~~~~~~~~~~~~~~~~~~~~
io_decoder.c:771:20: warning: unused variable ‘old_hand_valid_received’ [-Wunused-variable]
771 | static int old_hand_valid_received = 0;
| ^~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:769:20: warning: unused variable ‘old_hand_valid_send’ [-Wunused-variable]
769 | static int old_hand_valid_send = 0;
| ^~~~~~~~~~~~~~~~~~~
io_decoder.c:755:16: warning: variable ‘comm_packet_received_and_validated’ set but not used [-Wunused-but-set-variable]
755 | static int comm_packet_received_and_validated = 0; // Per controllare il loop all'interno di COMMUNICATING
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:754:16: warning: unused variable ‘comm_packet_sent’ [-Wunused-variable]
754 | static int comm_packet_sent = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:751:16: warning: variable ‘error_state_comm_timeout’ set but not used [-Wunused-but-set-variable]
751 | static int error_state_comm_timeout = 0;
| ^~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:750:16: warning: variable ‘error_state_hand_serial_read’ set but not used [-Wunused-but-set-variable]
750 | static int error_state_hand_serial_read = 0;; // Per seriale in handshake errata
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:749:16: warning: variable ‘error_state_payload’ set but not used [-Wunused-but-set-variable]
749 | static int error_state_payload = 0; // Per payload in handshake errato
| ^~~~~~~~~~~~~~~~~~~
io_decoder.c:748:16: warning: variable ‘error_state_firmware_2’ set but not used [-Wunused-but-set-variable]
748 | static int error_state_firmware_2 = 0; // Per valori funzioni dentro il firmware errate
| ^~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:747:16: warning: variable ‘error_state_firmware’ set but not used [-Wunused-but-set-variable]
747 | static int error_state_firmware = 0; // Per firmware errato
| ^~~~~~~~~~~~~~~~~~~~
io_decoder.c:746:16: warning: variable ‘error_state_hand_packet’ set but not used [-Wunused-but-set-variable]
746 | static int error_state_hand_packet = 0; // Per pacchetto di handshake di lunghezza non corrispondente
| ^~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:745:16: warning: variable ‘error_state_serial_configure’ set but not used [-Wunused-but-set-variable]
745 | static int error_state_serial_configure = 0; // Per seriale non configurata
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:743:16: warning: unused variable ‘error_state_dbg_printed’ [-Wunused-variable]
743 | static int error_state_dbg_printed = 0; // Per HAL_STATE_ERROR (primo ingresso)
| ^~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:740:16: warning: unused variable ‘handshake_response_dbg_printed’ [-Wunused-variable]
740 | static int handshake_response_dbg_printed = 0; // Per HAL_STATE_HANDSHAKE_WAIT_RESPONSE
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:739:16: warning: unused variable ‘handshake_init_dbg_printed’ [-Wunused-variable]
739 | static int handshake_init_dbg_printed = 0; // Per HAL_STATE_HANDSHAKE_INIT
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:737:16: warning: unused variable ‘timer_overflow_5’ [-Wunused-variable]
737 | static int timer_overflow_5 = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:735:16: warning: unused variable ‘timer_overflow_3’ [-Wunused-variable]
735 | static int timer_overflow_3 = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:734:16: warning: unused variable ‘timer_overflow_2’ [-Wunused-variable]
734 | static int timer_overflow_2 = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:733:16: warning: unused variable ‘timer_overflow_1’ [-Wunused-variable]
733 | static int timer_overflow_1 = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:732:16: warning: unused variable ‘timer_overflow_0’ [-Wunused-variable]
732 | static int timer_overflow_0 = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:724:17: warning: variable ‘last_read_time_ns’ set but not used [-Wunused-but-set-variable]
724 | static long last_read_time_ns; // Inizializza al tempo corrente
| ^~~~~~~~~~~~~~~~~
io_decoder.c:720:10: warning: unused variable ‘next_handshake_attempt_time_ns’ [-Wunused-variable]
720 | long next_handshake_attempt_time_ns = 0; // Tempo per il prossimo tentativo di handshake
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c: In function ‘npic_in_routine’:
io_decoder.c:1443:72: warning: unused parameter ‘length’ [-Wunused-parameter]
1443 | uint8_t npic_in_routine(hal_io_decoder_t *io, uint8_t* buffer, uint8_t length) {
| ~~~~~~~~^~~~~~
io_decoder.c: In function ‘npic_out_routine’:
io_decoder.c:1494:68: warning: unused parameter ‘length’ [-Wunused-parameter]
1494 | void npic_out_routine(hal_io_decoder_t *io, uint8_t* dato, uint8_t length) {
| ~~~~~~~~^~~~~~
io_decoder.c: In function ‘encoder_routine’:
io_decoder.c:1577:9: warning: unused variable ‘encoder_delta_from_arduino’ [-Wunused-variable]
1577 | int encoder_delta_from_arduino; // Questo sarà il valore decodificato (il "delta")
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c: In function ‘adc_routine’:
io_decoder.c:1770:57: warning: comparison of integer expressions of different signedness: ‘uint32_t’ {aka ‘unsigned int’} and ‘int32_t’ {aka ‘int’} [-Wsign-compare]
1770 | if ((io->adc_raw_joy[i] <= joy_center_plus) && (io->adc_raw_joy[i] >= joy_center_minus)) {
| ^~
io_decoder.c:1770:100: warning: comparison of integer expressions of different signedness: ‘uint32_t’ {aka ‘unsigned int’} and ‘int32_t’ {aka ‘int’} [-Wsign-compare]
1770 | if ((io->adc_raw_joy[i] <= joy_center_plus) && (io->adc_raw_joy[i] >= joy_center_minus)) {
| ^~
io_decoder.c:1778:48: warning: comparison of integer expressions of different signedness: ‘uint32_t’ {aka ‘unsigned int’} and ‘int32_t’ {aka ‘int’} [-Wsign-compare]
1778 | if (io->adc_raw_joy[i] > (joy_center_plus)) {
| ^
io_decoder.c:1784:55: warning: comparison of integer expressions of different signedness: ‘uint32_t’ {aka ‘unsigned int’} and ‘int32_t’ {aka ‘int’} [-Wsign-compare]
1784 | } else if (io->adc_raw_joy[i] < (joy_center_minus)) {
| ^
io_decoder.c:1680:17: warning: unused variable ‘joy_offset’ [-Wunused-variable]
1680 | int32_t joy_offset;
| ^~~~~~~~~~
io_decoder.c:1678:10: warning: unused variable ‘overflow_period_ns’ [-Wunused-variable]
1678 | long overflow_period_ns = 20 * 1000 * 1000; // Periodo di 20ms per resettare l'overflow
| ^~~~~~~~~~~~~~~~~~
io_decoder.c: In function ‘DAC_out_routine’:
io_decoder.c:1874:13: warning: unused variable ‘i’ [-Wunused-variable]
1874 | int i;
| ^
io_decoder.c: In function ‘in_expansion_routine’:
io_decoder.c:1918:13: warning: unused variable ‘current_value’ [-Wunused-variable]
1918 | float_t current_value = 0; // Useremo un int32_t per gestire il valore
| ^~~~~~~~~~~~~
io_decoder.c:1917:13: warning: unused variable ‘bytesWritten’ [-Wunused-variable]
1917 | uint8_t bytesWritten = 0; // Contatore dei byte letti dal buffer
| ^~~~~~~~~~~~
io_decoder.c:1916:13: warning: unused variable ‘i’ [-Wunused-variable]
1916 | int i;
| ^
io_decoder.c:1914:61: warning: unused parameter ‘buffer’ [-Wunused-parameter]
1914 | uint8_t in_expansion_routine(hal_io_decoder_t *io, uint8_t* buffer, uint8_t length) {
| ~~~~~~~~~^~~~~~
io_decoder.c:1914:77: warning: unused parameter ‘length’ [-Wunused-parameter]
1914 | uint8_t in_expansion_routine(hal_io_decoder_t *io, uint8_t* buffer, uint8_t length) {
| ~~~~~~~~^~~~~~
io_decoder.c: In function ‘out_expansion_routine’:
io_decoder.c:1951:13: warning: unused variable ‘current_value’ [-Wunused-variable]
1951 | float_t current_value = 0; // Useremo un int32_t per gestire il valore
| ^~~~~~~~~~~~~
io_decoder.c:1950:13: warning: unused variable ‘bytesWritten’ [-Wunused-variable]
1950 | uint8_t bytesWritten = 0; // Contatore dei byte letti dal buffer
| ^~~~~~~~~~~~
io_decoder.c:1949:13: warning: unused variable ‘i’ [-Wunused-variable]
1949 | int i;
| ^
io_decoder.c:1947:59: warning: unused parameter ‘dato’ [-Wunused-parameter]
1947 | void out_expansion_routine(hal_io_decoder_t *io, uint8_t* dato, uint8_t length) {
| ~~~~~~~~~^~~~
io_decoder.c:1947:73: warning: unused parameter ‘length’ [-Wunused-parameter]
1947 | void out_expansion_routine(hal_io_decoder_t *io, uint8_t* dato, uint8_t length) {
| ~~~~~~~~^~~~~~
io_decoder.c: In function ‘key_simulation_loop’:
io_decoder.c:2032:53: warning: variable ‘suppress_base_key’ set but not used [-Wunused-but-set-variable]
2032 | int suppress_base_key = 0; // 0 = false, 1 = true
| ^~~~~~~~~~~~~~~~~
io_decoder.c:2004:9: warning: unused variable ‘send_status’ [-Wunused-variable]
2004 | int send_status;
| ^~~~~~~~~~~
io_decoder.c:2001:13: warning: unused variable ‘bitValue’ [-Wunused-variable]
2001 | uint8_t bitValue;
| ^~~~~~~~
io_decoder.c: In function ‘calc_io_decoder’:
io_decoder.c:2421:45: warning: unused parameter ‘period’ [-Wunused-parameter]
2421 | static void calc_io_decoder(void *arg, long period) {
| ~~~~~^~~~~~
io_decoder.c: In function ‘rtapi_app_main’:
io_decoder.c:2484:28: warning: unused variable ‘uidev’ [-Wunused-variable]
2484 | struct uinput_user_dev uidev;
| ^~~~~
io_decoder.c:2471:20: warning: unused variable ‘i’ [-Wunused-variable]
2471 | int n, retval, i;
| ^
io_decoder.c: In function ‘npic_in_routine’:
io_decoder.c:1491:1: warning: control reaches end of non-void function [-Wreturn-type]
1491 | }
| ^
io_decoder.c: In function ‘adc_routine’:
io_decoder.c:1870:1: warning: control reaches end of non-void function [-Wreturn-type]
1870 | }
| ^
io_decoder.c: In function ‘in_expansion_routine’:
io_decoder.c:1945:1: warning: control reaches end of non-void function [-Wreturn-type]
1945 | }
| ^
io_decoder.c: At top level:
io_decoder.c:732:16: warning: ‘timer_overflow_0’ defined but not used [-Wunused-variable]
732 | static int timer_overflow_0 = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:733:16: warning: ‘timer_overflow_1’ defined but not used [-Wunused-variable]
733 | static int timer_overflow_1 = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:734:16: warning: ‘timer_overflow_2’ defined but not used [-Wunused-variable]
734 | static int timer_overflow_2 = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:735:16: warning: ‘timer_overflow_3’ defined but not used [-Wunused-variable]
735 | static int timer_overflow_3 = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:737:16: warning: ‘timer_overflow_5’ defined but not used [-Wunused-variable]
737 | static int timer_overflow_5 = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:739:16: warning: ‘handshake_init_dbg_printed’ defined but not used [-Wunused-variable]
739 | static int handshake_init_dbg_printed = 0; // Per HAL_STATE_HANDSHAKE_INIT
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:740:16: warning: ‘handshake_response_dbg_printed’ defined but not used [-Wunused-variable]
740 | static int handshake_response_dbg_printed = 0; // Per HAL_STATE_HANDSHAKE_WAIT_RESPONSE
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:743:16: warning: ‘error_state_dbg_printed’ defined but not used [-Wunused-variable]
743 | static int error_state_dbg_printed = 0; // Per HAL_STATE_ERROR (primo ingresso)
| ^~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:754:16: warning: ‘comm_packet_sent’ defined but not used [-Wunused-variable]
754 | static int comm_packet_sent = 0;
| ^~~~~~~~~~~~~~~~
io_decoder.c:769:20: warning: ‘old_hand_valid_send’ defined but not used [-Wunused-variable]
769 | static int old_hand_valid_send = 0;
| ^~~~~~~~~~~~~~~~~~~
io_decoder.c:771:20: warning: ‘old_hand_valid_received’ defined but not used [-Wunused-variable]
771 | static int old_hand_valid_received = 0;
| ^~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:773:20: warning: ‘old_hand_invalid_send’ defined but not used [-Wunused-variable]
773 | static int old_hand_invalid_send = 0;
| ^~~~~~~~~~~~~~~~~~~~~
io_decoder.c:775:20: warning: ‘old_hand_invalid_received’ defined but not used [-Wunused-variable]
775 | static int old_hand_invalid_received = 0;
| ^~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:776:20: warning: ‘old_pin_debug2’ defined but not used [-Wunused-variable]
776 | static int old_pin_debug2 = 0;
| ^~~~~~~~~~~~~~
io_decoder.c:783:21: warning: ‘old_usb_loop’ defined but not used [-Wunused-variable]
783 | static long old_usb_loop;
| ^~~~~~~~~~~~
io_decoder.c:643:14: warning: ‘format_buffer_for_debug’ defined but not used [-Wunused-function]
643 | static char* format_buffer_for_debug(const unsigned char *buffer, int len) {
| ^~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:148:12: warning: ‘printed_debug’ defined but not used [-Wunused-variable]
148 | static int printed_debug[100] = {0}; //serve a creare uno stop alle scritte di debug
| ^~~~~~~~~~~~~
io_decoder.c: In function ‘usb_thread_function’:
io_decoder.c:1297:28: warning: ‘usb2_current_time_ns’ may be used uninitialized [-Wmaybe-uninitialized]
1297 | usb_jitter_time_ns = usb_current_time_ns - usb2_current_time_ns;
| ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:729:10: note: ‘usb2_current_time_ns’ was declared here
729 | long usb2_current_time_ns;
| ^~~~~~~~~~~~~~~~~~~~
io_decoder.c:1297:28: warning: ‘usb_current_time_ns’ may be used uninitialized [-Wmaybe-uninitialized]
1297 | usb_jitter_time_ns = usb_current_time_ns - usb2_current_time_ns;
| ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:728:10: note: ‘usb_current_time_ns’ was declared here
728 | long usb_current_time_ns;
| ^~~~~~~~~~~~~~~~~~~
io_decoder.c:1308:38: warning: ‘next_parse_error_time_ns’ may be used uninitialized [-Wmaybe-uninitialized]
1308 | if ((current_time_ns - next_parse_error_time_ns) > parse_error_time_ns) {
| ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c:726:10: note: ‘next_parse_error_time_ns’ was declared here
726 | long next_parse_error_time_ns;
| ^~~~~~~~~~~~~~~~~~~~~~~~
io_decoder.c: In function ‘npic_out_routine’:
io_decoder.c:1550:107: warning: ‘freq_conversion’ may be used uninitialized [-Wmaybe-uninitialized]
1550 | if (current_time_ns > (io->out_blink_time_ns[current_bit] + freq_conversion)) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
io_decoder.c:1503:10: note: ‘freq_conversion’ was declared here
1503 | long freq_conversion;
| ^~~~~~~~~~~~~~~
Linking io_decoder.so