From 994a567dd84b8ceb349c78868f50752592621419 Mon Sep 17 00:00:00 2001 From: erikkaashoek Date: Thu, 29 Oct 2026 11:28:12 +0100 Subject: [PATCH 1/2] Keep a console request while the lever, touch or listen mode is handled Report: in output mode, with each command sent as soon as the prompt arrives, a command right after "output" or "modulation" (e.g. "level -30" after "output off", or "mode low input" after "output off" twice) got no prompt and was dropped with "Command timeout" after 20 s; the next command worked. Cause: after a direct command the shell set operation_requested = true, which is OP_LEVER. The sweep thread left sweep(), found no command yet, and ui_process() handled that "lever event" and then set operation_requested = OP_NONE. When the shell had parsed the next command in between (shell_function set, OP_CONSOLE set), that clear wiped OP_CONSOLE. A zero span output mode sweep only returns when operation_requested is set, so the command never ran. Caught on hardware with a breakpoint on the clear: operation_requested 0x05 with cmd_level / cmd_mode waiting, every time. - ui_process() clears only the bit it handled, locked, so OP_CONSOLE survives lever and touch handling (a touch, e.g. a remote "touch" from tinySA-App, hit the same clear). - The sweep thread clears OP_CONSOLE together with taking shell_function, which the shell sets together, so a request left by a direct or timed out command does not keep aborting sweeps. - A direct command asks for the sweep restart with OP_CONSOLE instead of a fake lever event. - SI4432_Listen() keeps OP_CONSOLE on entry, so a command ends listen mode instead of being lost the same way. Tested on a ZS405 (HW V0.4.5.1): both reported sequences 15 rounds each without a hang (release firmware: 7 of 7 hung), every reply < 0.5 s. In zero span output mode the sweep thread loop passes once per direct command ("output off/on", "level") and not while idle. Remote touches mixed with commands in output mode: 10 rounds without a hang. Input mode touch menu and sweeping work. Listen mode and the jog lever not tested on hardware. ULTRA +88 bytes, BASIC +84 bytes. Co-Authored-By: Claude Opus 5.5 --- main.c | 7 ++++++- si4432.c | 4 +++- si4468.c | 4 +++- ui.c | 10 ++++++++-- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/main.c b/main.c index fe79846..f31eb18 100644 --- a/main.c +++ b/main.c @@ -268,6 +268,9 @@ static THD_FUNCTION(Thread1, arg) chSysLock(); local_func = shell_function; shell_function = 0; + // The shell sets OP_CONSOLE together with shell_function, a request without a + // command (direct command, timed out command) has done its job: the sweep stopped + operation_requested &= ~OP_CONSOLE; chSysUnlock(); if (local_func) { @@ -3255,7 +3258,9 @@ static void VNAShell_executeLine(char *line) #else if (dirty) { #endif - operation_requested = true; // ensure output is updated + chSysLock(); + operation_requested |= OP_CONSOLE; // ensure output is updated: stop the sweep, not a lever event + chSysUnlock(); if (MODE_OUTPUT(setting.mode)) draw_menu(); // update screen if in output mode and dirty else diff --git a/si4432.c b/si4432.c index f7b8215..2661a02 100644 --- a/si4432.c +++ b/si4432.c @@ -755,7 +755,9 @@ void SI4432_Listen(int s) uint16_t sel = SI_nSEL[SI4432_Sel]; uint8_t max = 0; uint16_t count = 0; - operation_requested = OP_NONE; + chSysLock(); + operation_requested &= ~(OP_LEVER|OP_TOUCH); // keep a console request, its command is waiting + chSysUnlock(); do { uint8_t v; palClearPad(GPIOC, sel); diff --git a/si4468.c b/si4468.c index e7aaf44..fe71385 100644 --- a/si4468.c +++ b/si4468.c @@ -2132,7 +2132,9 @@ void SI4432_Listen(int s) (void) s; uint8_t max = 0; uint16_t count = 0; - operation_requested = OP_NONE; + chSysLock(); + operation_requested &= ~(OP_LEVER|OP_TOUCH); // keep a console request, its command is waiting + chSysUnlock(); // SI4463_WAIT_CTS; // Wait for CTS do { uint8_t v = Si446x_readRSSI(); diff --git a/ui.c b/ui.c index b868827..ae503ad 100644 --- a/ui.c +++ b/ui.c @@ -8687,14 +8687,20 @@ ui_process(void) selection = -1; // hide keyboard mode selection ui_mode_menu(); } + // Clear only the handled request: the shell may have set OP_CONSOLE meanwhile for a + // waiting command, without it an output mode sweep never stops to run that command if ((operation_requested&OP_LEVER) || previous_button_state != button_state) { ui_process_lever(); previous_button_state = button_state; - operation_requested = OP_NONE; + chSysLock(); + operation_requested &= ~OP_LEVER; + chSysUnlock(); } if (operation_requested&OP_TOUCH) { ui_process_touch(); - operation_requested = OP_NONE; + chSysLock(); + operation_requested &= ~OP_TOUCH; + chSysUnlock(); } touch_start_watchdog(); } From 6a0c67cf1eb15a77e8cfd77f8ca4a3b1caaef435 Mon Sep 17 00:00:00 2001 From: erikkaashoek Date: Thu, 29 Oct 2026 11:28:12 +0100 Subject: [PATCH 2/2] Changelog: V1.4266 console command hang in output mode Co-Authored-By: Claude Opus 5.5 --- changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.txt b/changelog.txt index cd50f04..6114a33 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +V1.4266 2026-10-29 For all tinySA models +- Fixed a console command sent right after "output", "modulation" or a touch (e.g. by a script) hanging in output mode until "Command timeout" after 20 s + V1.4263 2026-10-28 For all tinySA Ultra models - PRESET > STORE > STORE 1-4 prefills the name keypad with the name of the active preset (the SD file it was loaded from, else the name it was stored under), so a single ENTER keeps it