Can you trace the calls?
I have a long standing suspicion that the vertical position controls are slow because somewhere internally they're converting them into multiple SCPI commands. Is it possible to confirm that?
I see calls in disassembler.
I will give an example of how the simplest command for obtaining the channel bandwidth is produced. (SYSTEM:BW?)
In the firmware there is a huge table (more than 1000 elements) for all SCPI commands. The main handler parses the command to separate components, finds the desired element in the table, and calls the subroutine. Up to this point everything has been done normally.
First subroutine:
LXI_SYSTEM_BW_Ack ; DATA XREF: P4_rw:402086C4o
P4_rw:4030F3F4 STMFD SP!, {R4,LR} ; Store Block to Memory
P4_rw:4030F3F8 MOV R4, #0 ; Rd = Op2
P4_rw:4030F3FC BL LXI_SYSTEM_BW_Ack_ ; Branch with Link
P4_rw:4030F400 MOVS R4, R0 ; Rd = Op2
P4_rw:4030F404 CMP R4, #0 ; Set cond. codes on Op1 - Op2
P4_rw:4030F408 BEQ loc_4030F414 ; Branch
P4_rw:4030F40C ADDS R4, R4, #0xB0000 ; Rd = Op1 + Op2
P4_rw:4030F410 B loc_4030F418 ; Branch
P4_rw:4030F414 ; ---------------------------------------------------------------------------
P4_rw:4030F414
P4_rw:4030F414 loc_4030F414 ; CODE XREF: LXI_SYSTEM_BW_Ack+14j
P4_rw:4030F414 BL LXI_SetBackAnswerFlags ; Branch with Link
P4_rw:4030F418
P4_rw:4030F418 loc_4030F418 ; CODE XREF: LXI_SYSTEM_BW_Ack+1Cj
P4_rw:4030F418 MOVS R0, R4 ; Rd = Op2
P4_rw:4030F41C LDMFD SP!, {R4,PC} ; Load Block from Memory
Second subroutinr:
P4_rw:402E1344 LXI_SYSTEM_BW_Ack_ ; CODE XREF: LXI_SYSTEM_BW_Ack+8p
P4_rw:402E1344
P4_rw:402E1344 BWCode = -0xB0
P4_rw:402E1344
P4_rw:402E1344 STMFD SP!, {R4,LR} ; Store Block to Memory
P4_rw:402E1348 SUB SP, SP, #0xB0 ; Rd = Op1 - Op2
P4_rw:402E134C MOV R4, #0 ; Rd = Op2
P4_rw:402E1350 MOVS R0, SP ; Target
P4_rw:402E1354 LDR R1, =dword_4000DE68 ; Source
P4_rw:402E1358 MOV R2, #0xB0 ; '-' ; Len
P4_rw:402E135C BL memcpy ; Branch with Link
P4_rw:402E1360 ;--
P4_rw:402E1360 MOVS R2, SP ; Buffer
P4_rw:402E1364 MOV R1, #6 ; Id
P4_rw:402E1368 LDR R0, =aConfig_16 ; OptCONFIG
P4_rw:402E136C BL GetSettings ; Branch with Link
P4_rw:402E1370 ;--
P4_rw:402E1370 LDR R0, [SP,#0xB8+BWCode] ; Load from Memory
P4_rw:402E1374 MOVS R4, R0 ; Rd = Op2
P4_rw:402E1378 MOVS R1, R4 ; Rd = Op2
P4_rw:402E137C ADR R0, aU_3 ; "%u"
P4_rw:402E1380 BL LXI_PrinfOut ; Branch with Link
P4_rw:402E1384 ADD SP, SP, #0xB0 ; Rd = Op1 + Op2
P4_rw:402E1388 LDMFD SP!, {R4,PC} ; Load Block from Memory
Here you can see a call to the GetSettings with three parameters: the module name (char []), the request code to the module, and the query format descriptor. The specified subroutine searches for the desired module (by direct search through the table via strcmp!!!), creates a special block of query, puts it in the queue for processing and and falls asleep.
The system thread periodically looks at the request queue and calls the desired subroutine (each module also has the ID and subprogram matching tables, the search for them is also linear). Here's a subroutine for BW:
P4_rw:402521F8 Cfg_GetMaxFreq ; DATA XREF: P6_rw:40601EC0o
P4_rw:402521F8
P4_rw:402521F8 var_18 = -0x18
P4_rw:402521F8
P4_rw:402521F8 STMFD SP!, {R4-R6,LR} ; Store Block to Memory
P4_rw:402521FC SUB SP, SP, #8 ; Rd = Op1 - Op2
P4_rw:40252200 MOVS R4, R0 ; Rd = Op2
P4_rw:40252204 MOVS R5, R1 ; Rd = Op2
P4_rw:40252208 MOVS R6, R2 ; Rd = Op2
P4_rw:4025220C BL RetMaxFreqX ; Branch with Link
P4_rw:40252210 CMP R0, #100 ; Set cond. codes on Op1 - Op2
P4_rw:40252214 BNE loc_40252220 ; Branch
P4_rw:40252218 MOV R4, #100 ; Rd = Op2
P4_rw:4025221C B loc_40252224 ; Branch
P4_rw:40252220 ; ---------------------------------------------------------------------------
P4_rw:40252220
P4_rw:40252220 loc_40252220 ; CODE XREF: Cfg_GetMaxFreq+1Cj
P4_rw:40252220 MOV R4, #70 ; Rd = Op2
P4_rw:40252224
P4_rw:40252224 loc_40252224 ; CODE XREF: Cfg_GetMaxFreq+24j
P4_rw:40252224 MOVS R0, R6 ; Dsc
P4_rw:40252228 BL InitStrParamDescr ; Branch with Link
P4_rw:4025222C MOV R0, #0 ; Rd = Op2
P4_rw:40252230 STR R0, [SP,#0x18+var_18] ; Store to Memory
P4_rw:40252234 MOV R3, #0 ; Rd = Op2
P4_rw:40252238 MOV R2, #1 ; Rd = Op2
P4_rw:4025223C MOVS R1, R4 ; Index
P4_rw:40252240 MOVS R0, R6 ; int
P4_rw:40252244 BL RetValFmt_02 ; Branch with Link
P4_rw:40252248 LDMFD SP!, {R0,R1,R4-R6,PC} ; Load Block from Memory
P4_rw:400F5F00 RetMaxFreqX ; CODE XREF: Cfg_GetMaxFreq+14p
P4_rw:400F5F00 ; ConfigMaxFreq2Operate+14p
P4_rw:400F5F00 ; ConfigMaxFreq2Operate:No70Mhzp
P4_rw:400F5F00 ; ConfigMaxFreq2Operate+6Cp
P4_rw:400F5F00 LDR R0, =ManufacturerName ; Load from Memory
P4_rw:400F5F04 LDR R0, [R0,#(FreqVersion2 - 0x40761C9C)] ; Load from Memory
P4_rw:400F5F08 BX LR ; Branch to/from Thumb mode
Having received the required parameter, the subroutine fills the response field, after which the data goes in the opposite direction - the system thread copies the data to the source buffer, frees the previously occupied memory blocks and awakens the requesting. And this is all for the sake of reading one word. In some cases, one module may give nested queries to other modules when processing a request. It reminds me very much of SendMessage / PostMessage from Windows, but can this mechanism be fast?