SCPI Parameter Syntax
| Hexadecimal | #HFF | |
|---|---|---|
| Octal | #Q77 | |
| Binary | #B11 | |
| String | “text”, ‘text’ | String parameters must be enclosed in single or double quotes. Always quote any free-form string — filenames, paths, SSIDs, passwords, IP addresses, hostnames. Example: SYSTem:COMMunicate:LAN:SSID "test me", SYSTem:WIFI:IPERF:TCPClient "192.168.1.133",5001,10, SYSTem:STORage:SD:GET "data.csv". Unquoted strings only work for plain SCPI keywords (uppercase letters and digits, no dots, no special characters) such as ON/OFF/AUTO. A bare dotted-decimal IP like 192.168.1.133 is parsed as a malformed number and rejected with -101 "Invalid character" — quote it. |
Quiescence Rule — No Queries During a Benchmarked Test
Send no SCPI commands while a streaming or iperf2 test is running. Every
query preempts the data path you’re measuring (USB SCPI = priority 7; TCP
SCPI runs on the WifiTask itself), so polling skews the result.
The firmware preserves end-of-test stats in IDLE: IPERF:STATs? returns
gCtx.last_stats (frozen by FinalizeStats); STR:STATS? survives across
StopStreamData until the next StartStreamData or STATS:CLEar.
Pattern: start → time.sleep(duration + margin) → single STATS query.
For progress visibility on long runs, use an out-of-band signal (Saleae,
PC-side iperf2.log) — never poll the device under test.
List of SCPI Commands
IEEE 488.2 Standard Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| *IDN? | Get device identification: manufacturer, model, serial, firmware version | *IDN? | SCPI_CoreIdnQ |
| *CLS | Clear status registers and error queue | *CLS | SCPI_CoreCls |
| *ESE | Set event status enable register | *ESE 255 | SCPI_CoreEse |
| *ESE? | Get event status enable register | *ESE? | SCPI_CoreEseQ |
| *ESR? | Get event status register (clears on read). Bit 5 = command error, bit 0 = OPC | *ESR? | SCPI_CoreEsrQ |
| *OPC | Set operation complete bit in ESR when all pending operations finish | *OPC | SCPI_CoreOpc |
| *OPC? | Query operation complete (returns 1 when all operations done) | *OPC? | SCPI_CoreOpcQ |
| *SRE | Set service request enable register | *SRE 255 | SCPI_CoreSre |
| *SRE? | Get service request enable register | *SRE? | SCPI_CoreSreQ |
| *STB? | Get status byte register. Bit 2 = error queue not empty, bit 7 = operation status | *STB? | SCPI_CoreStbQ |
| *TST? | Run self-test (returns 0 = pass) | *TST? | SCPI_CoreTstQ |
| *WAI | Wait for all pending operations to complete | *WAI | SCPI_CoreWai |
Error and Status Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:ERRor? | Pop oldest error from SCPI error queue (FIFO, 17 slots). Returns error code and description. Returns 0,"No error" when queue is empty. |
SYSTem:ERRor? | SCPI_SystemErrorNextQ |
| SYSTem:ERRor:NEXT? | Alias for SYSTem:ERRor? | SYSTem:ERRor:NEXT? | SCPI_SystemErrorNextQ |
| SYSTem:ERRor:COUNt? | Get number of errors in the SCPI error queue (non-destructive) | SYSTem:ERRor:COUNt? | SCPI_SystemErrorCountQ |
| SYSTem:VERSion? | Get SCPI standard version (returns “1999.0”) | SYSTem:VERSion? | SCPI_SystemVersionQ |
| STATus:QUEStionable? | Get questionable event register (clears on read) | STATus:QUEStionable? | SCPI_QuesEventQ |
| STATus:QUEStionable:EVENt? | Get questionable event register (clears on read) | STATus:QUEStionable:EVENt? | SCPI_QuesEventQ |
| STATus:QUEStionable:CONDition? | Get questionable condition register (real-time, does not clear on read) | STATus:QUEStionable:CONDition? | SCPI_QuesConditionQ |
| STATus:QUEStionable:ENABle | Set questionable status enable mask | STATus:QUEStionable:ENABle 255 | SCPI_StatusQuestionableEnable |
| STATus:QUEStionable:ENABle? | Get questionable status enable mask | STATus:QUEStionable:ENABle? | SCPI_StatusQuestionableEnableQ |
| STATus:OPERation? | Get operation event register (clears on read). Shorthand for STATus:OPERation:EVENt? per SCPI standard. Returns 0 until firmware sets condition bits. | STATus:OPERation? | SCPI_StatusOperationEventQ |
| STATus:OPERation:EVENt? | Get operation event register (clears on read) | STATus:OPERation:EVENt? | SCPI_StatusOperationEventQ |
| STATus:OPERation:CONDition? | Get operation condition register (real-time, does not clear on read) | STATus:OPERation:CONDition? | SCPI_StatusOperationConditionQ |
| STATus:OPERation:ENABle | Set operation status enable mask (controls which bits propagate to *STB?) | STATus:OPERation:ENABle 255 | SCPI_StatusOperationEnable |
| STATus:OPERation:ENABle? | Get operation status enable mask | STATus:OPERation:ENABle? | SCPI_StatusOperationEnableQ |
| STATus:PRESet | Reset all status enable registers to default values | STATus:PRESet | SCPI_StatusPreset |
OPERation Condition Register Bits
The firmware sets these bits in the OPER condition register to reflect real-time device state:
| Bit | Value | Name | Description |
|---|---|---|---|
| 4 | 16 | Measuring | Streaming/measuring is active |
| 10 | 1024 | SD Logging | SD card logging is active |
Bits are set on STR:START and cleared on STR:STOP.
QUEStionable Condition Register Bits
The firmware sets these bits in the QUES condition register to reflect streaming health:
| Bit | Value | Name | Description |
|---|---|---|---|
| 4 | 16 | Data Loss | Windowed sample loss >= threshold (default 5%, configurable via SYST:STR:LOSS:THREshold) |
| 8 | 256 | USB Overflow | USB circular buffer overflow detected |
| 9 | 512 | WiFi Overflow | WiFi circular buffer overflow detected |
| 10 | 1024 | SD Overflow | SD write failure detected |
| 11 | 2048 | Encoder Fail | Encoder returned 0 bytes with data available |
QUES bits are set in real-time during streaming and cleared when streaming stops. The QUES CONDition register reflects current health; the QUES EVENt register latches transitions (clears on read).
System Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:REboot | Reboots the device immediately. Returns “System reset initiated” before restarting | SYSTem:REboot | SCPI_Reset |
| help | Display available SCPI commands | help | SCPI_Help |
| SYSTem:SYSInfoPB? | Returns protobuf message with board information – actual message fields are listed below this section | SYSTem:SYSInfoPB? | SCPI_SysInfoGet |
| SYSTem:INFo? | Get human-readable system information including detailed power state names (STANDBY, POWERED_UP, etc.), battery voltage, charge state, network config, and system status | SYSTem:INFo? | SCPI_SystemInfo |
| SYSTem:LOG? | Get system log entries (dumps all, clears buffer). Also resets one-shot suppression flags so ISR one-shot log sites can fire again. Independent from SCPI error queue. 64 entries x 128 bytes, circular buffer. | SYSTem:LOG? | SCPI_SysLogGet |
| SYSTem:LOG:CLEar | Clear log buffer without reading. Also resets one-shot suppression flags. | SYSTem:LOG:CLEar | SCPI_SysLogClear |
| SYSTem:LOG:TEST | Add test messages to log buffer (for verification) | SYSTem:LOG:TEST | SCPI_SysLogTest |
| SYSTem:LOG:LEVel | Set runtime log level for a module. Module names: POWER, WIFI, SD, USB, SCPI, ADC, DAC, STREAM, ENCODER, GENERAL. Levels: 0=NONE, 1=ERROR, 2=INFO, 3=DEBUG. Each module is clamped to its compile-time ceiling (all modules: DEBUG). Runtime-only, resets on reboot. | SYST:LOG:LEV STREAM,2 | SCPI_SysLogLevelSet |
| SYSTem:LOG:LEVel? | Query runtime log level. With module name returns integer level; without parameter dumps all modules with levels and ceilings. | SYST:LOG:LEV? STREAM / SYST:LOG:LEV? | SCPI_SysLogLevelGet |
| SYSTem:LOG:LEVel:ALL | Set all modules to the same runtime log level. Each module still clamped to its compile-time ceiling. | SYST:LOG:LEV:ALL 3 | SCPI_SysLogLevelAllSet |
| SYSTem:LOG:CMDHistory? | Get recent SCPI command history | SYSTem:LOG:CMDHistory? | SCPI_SysLogCmdHistory |
| SYSTem:ECHO | Set echo for use with terminal/human readable. Default = 1. | SYSTem:ECHO -1 turns off all echoed characters. SYSTem:ECHO 0 turns off echo but leaves DAQiFi> prompt. SYSTem:ECHO 1 turns on echo. | SCPI_SetEcho |
| SYSTem:FORceBoot | Force device to enter bootloader mode for firmware updates | SYSTem:FORceBoot | SCPI_ForceBootloader |
| SYSTem:SERialNUMber? | Get device serial number in SCPI hex format (#H prefix followed by 16 hex digits) | SYSTem:SERialNUMber? | SCPI_GetSerialNumber |
| SYSTem:USB:TRANSparent:MODE | Set USB transparent mode for WiFi radio firmware updates (0=SCPI mode, 1=transparent mode) | SYSTem:USB:TRANSparent:MODE 0 | SCPI_UsbSetTransparentMode |
| SYSTem:COMMunication:TCPIP:CONTROL? | (not implemented) | – | SCPI_NotImplemented |
Power Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:POWer:SOURce? | Get external power source type (0=none, 1=unknown, 2=1A charger, 3=2A charger, 4=USB 100mA, 5=USB 500mA) | SYSTem:POWer:SOURce? | SCPI_PowerSourceGet |
| SYSTem:BAT:LEVel? | Get battery charge level percentage (0-100). Returns -1 when device is in STANDBY mode (battery monitoring inactive) | SYSTem:BAT:LEVel? | SCPI_BatteryLevelGet |
| SYSTem:POWer:STATe? | Get power state. Returns binary values: • 0 = STANDBY (device in low-power mode) – On USB power: MCU remains on, 3.3V rail enabled – On battery power: MCU powers off to save battery • 1 = POWERED (device fully operational) – Maps to internal states POWERED_UP or POWERED_UP_EXT_DOWN – All systems operational, ADC readings valid Device automatically manages 3.3V rail to prevent power loss on USB disconnect |
SYSTem:POWer:STATe? | SCPI_GetPowerState |
| SYSTem:POWer:STATe | Set power state: • 0 = STANDBY (low-power mode) • 1 = POWERED (fully operational) |
SYSTem:POWer:STATe 1 | SCPI_SetPowerState |
| SYSTem:POWer:OTG? | Get OTG boost mode status (0=off, 1=on) | SYSTem:POWer:OTG? | SCPI_GetOTGMode |
| SYSTem:POWer:OTG | Set OTG boost mode: • 0 = Disable OTG • 1 = Enable battery boost operation Notes: • OTG provides 5V output from battery • Cannot be enabled while USB is connected • Disable when no longer needed to save battery |
SYSTem:POWer:OTG 1 | SCPI_SetOTGMode |
| SYSTem:FORce5V5POWer:STATe | Force enable/disable external 5V supply (overrides automatic control) | SYSTem:FORce5V5POWer:STATe 1 | SCPI_Force5v5PowerStateSet |
| SYSTem:POWer:AUTO:EXTernal | Set auto-external power behavior | SYSTem:POWer:AUTO:EXTernal 1 | SCPI_SetAutoExtPower |
| SYSTem:POWer:AUTO:EXTernal? | Query auto-external power setting | SYSTem:POWer:AUTO:EXTernal? | SCPI_GetAutoExtPower |
BQ24297 Battery Charger Diagnostics
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:POWer:BQ:REGisters? | Dump all BQ24297 registers (REG00-REG0A hex values) | SYSTem:POWer:BQ:REGisters? | SCPI_BQ24297Registers |
| SYSTem:POWer:BQ:ILIM | Set IINLIM directly (0=100mA, 2=500mA, 6=2A, 7=3A) | SYSTem:POWer:BQ:ILIM 2 | SCPI_BQ24297SetILIM |
| SYSTem:POWer:BQ:DPDM | Force D+/D- re-detection. WARNING: Disrupts USB connection — requires cable replug to recover. Diagnostic only. | SYSTem:POWer:BQ:DPDM | SCPI_BQ24297ForceDPDM |
| SYSTem:POWer:BQ:FAULT:CLEar | Clear latched BQ24297 fault flags | SYSTem:POWer:BQ:FAULT:CLEar | SCPI_BQ24297FaultClear |
| SYSTem:POWer:BQ:DIAGnostics? | Comprehensive diagnostics: battery state, registers, GPIO, IINLIM state machine, power state, VBUS level. Note: reads REG09 which clears latched fault flags. | SYSTem:POWer:BQ:DIAGnostics? | SCPI_BQ24297Diagnostics |
DIO Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| DIO:PORt:DIRection | Sets Digital Port Direction. First parameter is the DIO number. Second parameter is for Direction, ‘0’ for input and ‘1’ for output. | DIO:PORt:DIRection 0,1 | SCPI_GPIODirectionSet |
| DIO:PORt:DIRection? | Gets Digital Port Direction. Parameter passed is the DIO number whose Direction needs to be checked. | DIO:PORt:DIRection? 0 | SCPI_GPIODirectionGet |
| DIO:PORt:STATe | Sets Digital Port State. First parameter is the DIO number. Second parameter is for State, ‘0’ for LOW State and ‘1’ for HIGH State. | DIO:PORt:STATe 0,1 | SCPI_GPIOStateSet |
| DIO:PORt:STATe? | Gets Digital Port State. Parameter passed is the DIO number whose State needs to be checked. | DIO:PORt:STATe? 0 | SCPI_GPIOStateGet |
| DIO:PORt:ENAble | Enables Digital Port. This command should be used everytime a new DIO needs to be used, before using commands like DIO:PORt:DIRection, and DIO:PORt:STATe. The parameter passed should be ‘1’ to Enable the DIO port. | DIO:PORt:ENAble 1 | SCPI_GPIOEnableSet |
| DIO:PORt:ENAble? | Gets Digital Port Enabled State. | DIO:PORt:ENAble? | SCPI_GPIOEnableGet |
DIO Debug Probe Commands
Lightweight framework for toggling or pulsing DIO pins from anywhere in the streaming pipeline to enable logic-analyzer timing analysis. While a probe is assigned to a DIO channel, that channel is owned exclusively — normal DIO:PORt:STATe / DIO:PORt:DIRection / PWM commands on an owned channel are rejected with -200 Execution error. Clearing a probe restores the user-configured state automatically.
Two probe classes:
- Standard probes 0–9 mapped 1:1 to DIO_0..DIO_9, permanently wired to streaming pipeline stages, controlled at runtime via these SCPI commands.
- Ad-hoc probes 10–15 mapped 1:1 to DIO_10..DIO_15, compile-time only (set bits in
DIO_PROBE_ENABLE_MASKinBoardConfig.h).
Standard probe map — hardcoded call sites:
| Probe | Stage |
|---|---|
| 0 | Streaming timer ISR entry |
| 1 | ADC EOS ISR entry |
| 2 | Deferred task wake |
| 3 | Deferred task: alloc + channel loop + queue push |
| 4 | Deferred task: ADC + DIO trigger |
| 5 | ADC EOS task wake |
| 6 | ADC EOS task: result read loop |
| 7 | Encoder task wake |
| 8 | Encoder: encode call |
| 9 | Encoder: output write |
Modes:
OFF— inert, no togglesTOGGLE— flip pin on each call (use for event rate / cadence capture)PULSE— drive HIGH onPulseStart, LOW onPulseEnd(use for duration capture)
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:DIOProbe:ASSign | Assign a standard probe (0–9) to a mode (OFF / TOGGLE / PULSE). Channel = probe id. Rejects if PWM is active on the target channel. | SYSTem:DIOProbe:ASSign 0,TOGGLE | SCPI_DioProbeAssign |
| SYSTem:DIOProbe:ASSign? | Query a probe’s current mode. Works for standard (0–9) and ad-hoc (10–15) probes. Returns OFF, TOGGLE, or PULSE. |
SYSTem:DIOProbe:ASSign? 0 | SCPI_DioProbeAssignGet |
| SYSTem:DIOProbe:CLEar | Release a standard probe, return the channel to normal DIO control. | SYSTem:DIOProbe:CLEar 0 | SCPI_DioProbeClear |
| SYSTem:DIOProbe:CLEar:ALL | Release all 10 standard probes (ad-hoc probes are not affected). | SYSTem:DIOProbe:CLEar:ALL | SCPI_DioProbeClearAll |
| SYSTem:DIOProbe:PIPELine | Set all 10 standard probes to the given mode in one call. Convenience for capturing the full pipeline. | SYSTem:DIOProbe:PIPELine TOGGLE | SCPI_DioProbePipeline |
| SYSTem:DIOProbe:LIST? | Dump all 16 slots (10 standard + 6 ad-hoc) with channel, mode, and compile-time flag. | SYSTem:DIOProbe:LIST? | SCPI_DioProbeList |
Caps-only abbreviations: DIOProbe abbreviates to DIOP (not DIOPR). ASSign → ASS, CLEar → CLE, PIPELine → PIPEL. E.g. SYST:DIOP:ASS 0,TOGGLE.
See docs/PIPELINE_TIMING.md in the firmware repo for captured timing measurements and per-stage CPU-budget tables.
PWM Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| PWM:CHannel:FREQuency | Sets the Frequency of a PWM channel (0,3,4,5,6,7) in Hz | PWM:CHannel:FREQuency 0,10000 | SCPI_PWMChannelFrequencySet |
| PWM:CHannel:FREQuency? | Gets the PWM frequencty in Hz. Parameter passed is the PWM channel number. | PWM:CHannel:FREQuency? 0 | SCPI_PWMChannelFrequencyGet |
| PWM:CHannel:DUTY | Sets the duty cycle of a PWM channel in percentage | PWM:CHannel:DUTY 0,50 | SCPI_PWMChannelDUTYSet |
| PWM:CHannel:DUTY? | Gets the duty cycle of a PWM channel in percentage. Parameter passed is the PWM channel number. | PWM:CHannel:DUTY? 0 | SCPI_PWMChannelDUTYGet |
| PWM:CHannel:ENable | Enable PWM in a particular channel. This command should be used everytime a new PWM channel needs to be used, before using commands like PWM:CHannel:FREQuency, and PWM:CHannel:DUTY. | PWM:CHannel:ENable 0,1 (Enable PWM in channel 0) PWM:CHannel:ENable 0,0 (Disable PWM in channel 0) |
SCPI_PWMChannelEnableSet |
| PWM:CHannel:ENable? | Check if PWM is enabled in a channel. Parameter passed is the PWM channel number that needs to be checked. | PWM:CHannel:ENable? 0 | SCPI_PWMChannelEnableGet |
WiFi Commands
Note: Commands marked Requires WiFi powered return
SCPI_ERROR_EXECUTION_ERRORwhen WiFi is disabled (STANDBY mode). Configuration SET commands and queries for settings (SSID?, NETType?, SECurity?) work in any power state. In STA mode with DHCP,ADDRess?,MASK?, andGATEway?return DHCP-assigned values; use theCONFigure:variants to read user-configured values.
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:COMMunicate:LAN:ENAbled? | Get WiFi enabled status (0=disabled, 1=enabled) | SYSTem:COMMunicate:LAN:ENAbled? | SCPI_LANEnabledGet |
| SYSTem:COMMunicate:LAN:ENAbled | Enable or disable WiFi (0=disable, 1=enable) | SYSTem:COMMunicate:LAN:ENAbled 1 | SCPI_LANEnabledSet |
| SYSTem:COMMunicate:LAN:NETType? | Get network type: 1 = NETWORK_TYPE_INFRASTRUCTURE 4 = NETWORK_TYPE_SOFT_AP |
SYSTem:COMMunicate:LAN:NETType? | SCPI_LANNetTypeGet |
| SYSTem:COMMunicate:LAN:NETType | Set network type: 1 = Infrastructure (connect to router) 4 = Soft AP (device creates access point) |
SYSTem:COMMunicate:LAN:NETType 1 | SCPI_LANNetTypeSet |
| SYSTem:COMMunicate:LAN:ADDRess? | Get actual IP address (DHCP-assigned in STA mode). Requires WiFi powered. | SYSTem:COMMunicate:LAN:ADDRess? | SCPI_LANAddrGet |
| SYSTem:COMMunicate:LAN:ADDRess | Set device IP address | SYSTem:COMMunicate:LAN:ADDRess “192.168.1.100” | SCPI_LANAddrSet |
| SYSTem:COMMunicate:LAN:CONFigure:ADDRess? | Get configured (pre-DHCP) IP address | SYSTem:COMMunicate:LAN:CONF:ADDR? | SCPI_LANConfAddrGet |
| SYSTem:COMMunicate:LAN:MASK? | Get actual subnet mask (DHCP-assigned in STA mode). Requires WiFi powered. | SYSTem:COMMunicate:LAN:MASK? | SCPI_LANMaskGet |
| SYSTem:COMMunicate:LAN:MASK | Set subnet mask | SYSTem:COMMunicate:LAN:MASK “255.255.255.0” | SCPI_LANMaskSet |
| SYSTem:COMMunicate:LAN:CONFigure:MASK? | Get configured (pre-DHCP) subnet mask | SYSTem:COMMunicate:LAN:CONF:MASK? | SCPI_LANConfMaskGet |
| SYSTem:COMMunicate:LAN:GATEway? | Get actual gateway IP (DHCP-assigned in STA mode). Requires WiFi powered. | SYSTem:COMMunicate:LAN:GATEway? | SCPI_LANGatewayGet |
| SYSTem:COMMunicate:LAN:GATEway | Set gateway IP address | SYSTem:COMMunicate:LAN:GATEway “192.168.1.1” | SCPI_LANGatewaySet |
| SYSTem:COMMunicate:LAN:CONFigure:GATEway? | Get configured (pre-DHCP) gateway IP | SYSTem:COMMunicate:LAN:CONF:GATE? | SCPI_LANConfGatewayGet |
| SYSTem:COMMunicate:LAN:IPV6? | Get IPv6 support status (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:IPV6 | Set IPv6 support (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:DNS1? | Get primary DNS server (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:DNS1 | Set primary DNS server (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:DNS2? | Get secondary DNS server (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:DNS2 | Set secondary DNS server (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:MAC? | Get device MAC address. Requires WiFi powered. | SYSTem:COMMunicate:LAN:MAC? | SCPI_LANMacGet |
| SYSTem:COMMunicate:LAN:MAC | Set custom MAC address (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:CONnected? | Check if WiFi is connected (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:HOST? | Get device hostname (returns runtime hostname with MAC suffix, e.g. “DAQiFi-95A7”) | SYSTem:COMMunicate:LAN:HOST? | SCPI_LANHostnameGet |
| SYSTem:COMMunicate:LAN:HOST | Set device hostname (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:SSID? | Get WiFi SSID | SYSTem:COMMunicate:LAN:SSID? | SCPI_LANSsidGet |
| SYSTem:COMMunicate:LAN:SSID | Set WiFi SSID to connect to | SYSTem:COMMunicate:LAN:SSID “MyNetwork” | SCPI_LANSsidSet |
| SYSTem:COMMunicate:LAN:SSIDSTR? | Get WiFi signal strength (RSSI %). Requires WiFi powered. | SYSTem:COMMunicate:LAN:SSIDSTR? | SCPI_LANSsidStrengthGet |
| SYSTem:COMMunicate:LAN:AvSSIDScan | Scan for available WiFi networks (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:AvSSID? | Get list of available WiFi networks from scan (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:SECurity? | Get security type: 0 = OPEN, 3 = WPA_AUTO_WITH_PASS_PHRASE (Other options deprecated or not implemented) |
SYSTem:COMMunicate:LAN:SECurity? | SCPI_LANSecurityGet |
| SYSTem:COMMunicate:LAN:SECurity | Set security type: 0 = OPEN, 3 = WPA/WPA2 | SYSTem:COMMunicate:LAN:SECurity 3 | SCPI_LANSecuritySet |
| SYSTem:COMMunicate:LAN:PASs | Set WiFi password/passphrase (requires non-open security mode) | SYSTem:COMMunicate:LAN:PASs MyPassword123 | SCPI_LANPasskeySet |
| SYSTem:COMMunicate:LAN:PASSCHECK? | Check if given password matches stored password (returns 1 if match, 0 if not) | SYSTem:COMMunicate:LAN:PASSCHECK? MyPassword123 | SCPI_LANPasskeyGet |
| SYSTem:COMMunicate:LAN:DISPlay | Display network settings (not implemented) | – | SCPI_NotImplemented |
| SYSTem:COMMunicate:LAN:APPLY | Apply WiFi settings to device (required for network changes to take effect). After APPLY the WiFi module re-initializes, associates with the AP (STA mode) or starts the AP (AP mode), and brings the TCP server back up. Allow up to 20 s for the TCP server on port 9760 to accept connections; SYST:COMM:LAN:ADDR? may return the DHCP-assigned IP before TCP is actually listening. APPLY is a soft restart — see WiFi Command Notes for hardware reset (HRESet). |
SYSTem:COMMunicate:LAN:APPLY | SCPI_LANSettingsApply |
| SYSTem:COMMunicate:LAN:HRESet | Hardware-reset the WINC1500 chip via the GPIO reset path (DEINIT → CHIP_EN/RESET_N toggle → INIT). Use to recover a wedged outbound TCP stack (#383): symptoms are ICMP ping still works but TCP connect() from the MCU times out. Returns immediately; full recovery (chip reset + STA reassoc + DHCP) takes ~20-25 s. Poll LAN:ADDR? until non-192.168.1.1 to confirm DHCP completed. |
SYSTem:COMMunicate:LAN:HRESet | SCPI_LANHardReset |
| SYSTem:COMMunicate:LAN:LOAD | Load WiFi settings from NVM | SYSTem:COMMunicate:LAN:LOAD | SCPI_LANSettingsLoad |
| SYSTem:COMMunicate:LAN:SAVE | Save current WiFi settings to NVM (allow settings to persist after power-off) | SYSTem:COMMunicate:LAN:SAVE | SCPI_LANSettingsSave |
| SYSTem:COMMunicate:LAN:FACRESET | Load factory default WiFi settings (SSID=”DAQiFi”, Open security, etc.) | SYSTem:COMMunicate:LAN:FACRESET | SCPI_LANSettingsFactoryLoad |
| SYSTem:COMMunicate:LAN:GETChipInfo? | Get WiFi module chip information as JSON: ChipId, firmware version, and build date | SYSTem:COMMunicate:LAN:GETChipInfo? | SCPI_LANGetChipInfo |
| SYSTem:COMMUnicate:LAN:FWUpdate | Sets the serial interface to transparent mode for WiFi radio WiFi module firmware updates, bypassing the SCPI interface. Command Sequence to enter WINC FW update mode: 1. SYSTem:POWer:STATe 1 2. SYSTem:COMMUnicate:LAN:FWUpdate 3. SYSTem:COMMUnicate:LAN:APPLY Now, flash using the MCHP winc_flash_tool.cmd Command Sequence to exit WINC FW update mode: 1. SYSTem:USB:TRANSparent:MODE 0 2. SYSTem:COMMunicate:LAN:ENabled 1 3. SYSTem:COMMUnicate:LAN:APPLY Note: This uses the same transparent mode functionality as SYSTem:USB:TRANSparent:MODE |
WiFi Command Notes
- The device creates an open WiFi access point by default with SSID “DAQiFi”
- WiFi must be enabled (
ENAbled 1) and applied (APPLY) for changes to take effect - Settings must be saved (
SAVE) to persist across power cycles - The device must be in POWERED_UP state (power state 1) for WiFi to operate
- Post-APPLY timing: the WiFi module takes time to re-initialize, associate/start, obtain DHCP, and reopen the TCP server on port 9760. Allow up to ~20 s before attempting a client TCP connection — pinging may succeed earlier than TCP accepts, and
ADDR?may report the DHCP IP before the TCP server is actually listening. A handy readiness pattern: afterAPPLY, pollADDR?until it returns a non-default IP, then attemptconnect(ip, 9760)with a short retry loop. - APPLY is a soft restart, NOT a hardware reset. Internally
APPLYtriggersWIFI_MANAGER_EVENT_REINITwhich the state machine handles byBSSDisconnect+ reconnect with new settings — it explicitly avoidsWDRV_WINC_Deinitialize(Microchip driver bug: leaves the chip in permanent reset; seewifi_manager.c:867). APPLY does not toggle the WINC’sCHIP_EN/RESET_NGPIOs. - WINC hardware reset path: use
SYST:COMM:LAN:HRESet. Internally firesWIFI_MANAGER_EVENT_DEINIT→WDRV_WINC_Close→WDRV_WINC_Deinitialize→wifi_manager_FixWincResetState()(assertsCHIP_EN, deassertsRESET_Non the WINC GPIO pins) → 2 s settle →WIFI_MANAGER_EVENT_INITto bring the chip back up cleanly. Validated 2026-04-28: recovers a wedged outbound TCP stack within ~25 s. Symptoms requiring this: ICMP ping still works but TCPconnect()from MCU times out indefinitely. Returns immediately; pollLAN:ADDR?until non-192.168.1.1to confirm DHCP completed. *RSTnow also resets the WINC. From the v3.4.6+ firmware, the*RSThandler fireswifi_manager_Deinit()beforeRCON_SoftwareReset, so the WINC chip GPIO reset and the PIC32 soft reset happen together — the user gets the expected “everything fresh” state. Earlier firmware left the WINC running with stale state across*RST.- Recovery hierarchy (least to most invasive):
SYST:WIFI:IPERF:STOP— clears iperf2 module’s gCtx; rarely sufficientLAN:APPLY— soft restart; refreshes association but leaves WINC chip state untouched (does not recover wedge)SYST:POWer:STATe 0→1— cycles 10V rail; doesn’t drive WINC reset GPIOs (does not recover wedge)SYST:COMM:LAN:HRESet— drives DEINIT → GPIO reset → INIT; recovers wedged TCP stack ✓ validated*RST— full PIC32 reset; on v3.4.6+ also drives WINC reset GPIO via the bundledwifi_manager_Deinit✓- Physical power cycle — last resort. Required only if even the GPIO reset doesn’t recover (rare; see #384 for ongoing investigation).
- Manual ENA 0 / APPLY / ENA 1 / APPLY recipe is NOT reliable. Earlier wiki revisions described this as the recovery path. Empirical testing (2026-04-28) showed it sometimes works and sometimes doesn’t, depending on what state the WiFi state machine is in. Use
LAN:HRESetinstead.
Automatic SSID/Hostname MAC Suffix
When the SSID or hostname is the bare default “DAQiFi”, the firmware automatically appends the last 4 hex digits of the device’s MAC address to make each device distinguishable on the network (e.g. “DAQiFi-95A7”). This applies to:
- AP SSID: The broadcast network name visible to WiFi clients
- DHCP hostname: The device name reported to routers and network discovery tools (DHCP Option 12)
The suffix is applied on every WiFi init and reinit (including after APPLY), so factory resets and default values always get the suffix. User-customized values (anything other than bare “DAQiFi”) are preserved without modification. The HOST? and SSID? queries return the suffixed values.
iperf2 Commands
Quiescence rule applies. Query
IPERF:STATs?once after the run; firmware returnslast_statsin IDLE.
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:WIFI:IPERF:TCPServer | Start iperf2 TCP server. Requires WiFi associated. | SYSTem:WIFI:IPERF:TCPServer 5002 | SCPI_Iperf2_TcpServer |
| SYSTem:WIFI:IPERF:UDPServer | Start iperf2 UDP server. | SYSTem:WIFI:IPERF:UDPServer 5002 | SCPI_Iperf2_UdpServer |
| SYSTem:WIFI:IPERF:TCPClient | TCP client <ip>,[port=5001],[dur_s=10]. IP must be quoted. |
SYSTem:WIFI:IPERF:TCPClient “192.168.1.133”,5002,12 | SCPI_Iperf2_TcpClient |
| SYSTem:WIFI:IPERF:UDPClient | UDP client (also reports loss). | SYSTem:WIFI:IPERF:UDPClient “192.168.1.133”,5002,10 | SCPI_Iperf2_UdpClient |
| SYSTem:WIFI:IPERF:TXBLast | TX-blast TCP server <port>,<dur_s>. Pure raw-byte blasting from a static buffer — no iperf2 protocol overhead. PC connects with any TCP byte-counter (nc, iperf -c if you ignore the protocol noise, or a custom socket reader). Useful for separating “iperf2 protocol cost” from “WINC SPI staging ceiling.” Duration is measured from peer accept, not bind. |
SYSTem:WIFI:IPERF:TXBLast 5003,60 | SCPI_Iperf2_TxBlast |
| SYSTem:WIFI:IPERF:STOP | Finalize stats and return to IDLE. | SYSTem:WIFI:IPERF:STOP | SCPI_Iperf2_Stop |
| SYSTem:WIFI:IPERF:STATs? | End-of-test snapshot (in IDLE) or live counters (during run — don’t poll). | SYSTem:WIFI:IPERF:STATs? | SCPI_Iperf2_Stats |
| SYSTem:WIFI:IPERF:DIAGnostics? | Diagnostic dump for #399 investigations: current mode, listen/data socket fds, pending_tx, abort_pending, bytes_confirmed, last_send_rc, send_err_count, WINC state, plus a free-socket probe when idle. | SYSTem:WIFI:IPERF:DIAGnostics? | SCPI_Iperf2_Diag |
| SYSTem:WIFI:IPERF:AUTOReset | Toggle auto-HRESet on session end (0=off, 1=on, default 1). When on, runs wifi_manager_HardReset after every iperf2 session — costs ~12 s WiFi reassociation but gives clean WINC state per session (#399 workaround). Set to 0 for back-to-back fast trials where reassoc overhead dominates measurement. |
SYSTem:WIFI:IPERF:AUTOReset 0 | SCPI_Iperf2_SetAutoReset |
| SYSTem:WIFI:IPERF:AUTOReset? | Query auto-HRESet state. | SYSTem:WIFI:IPERF:AUTOReset? | SCPI_Iperf2_GetAutoReset |
| SYSTem:WIFI:IPERF:MAXPending | Dormant debug knob, default 0 (use compile-time IPERF2_MAX_PENDING_TX = 4). Set 0..4 to throttle the WINC HIF queue depth at runtime (N=3 ≈ 75% rate, N=2 ≈ 50%). Tested 2026-04-30 / 2026-05-01 against #399 sustained-rate decay — did not improve stability or throughput. Kept available for future investigations. |
SYSTem:WIFI:IPERF:MAXPending 2 | SCPI_Iperf2_SetMaxPending |
| SYSTem:WIFI:IPERF:MAXPending? | Query effective MAXPending (returns the override if set, else the compile-time default). | SYSTem:WIFI:IPERF:MAXPending? | SCPI_Iperf2_GetMaxPending |
IPERF:STATs? Response Fields
| Field | Description |
|---|---|
| Mode | 0=IDLE, 1=TCP svr, 2=TCP cli, 3=UDP svr, 4=UDP cli, 5=TX-blast (always 0 in IDLE) |
| Active / Completed | 1/0 in-test; 0/1 after completion |
| Bytes | uint64, transferred bytes (preserved in IDLE) |
| DurationMs | actual elapsed at end-of-test (preserved in IDLE) |
| KBps | Bytes × 1000 / DurationMs / 1024 |
| UdpTotalPkt / UdpLostPkt / UdpOutOfOrder | UDP only |
IPERF:DIAGnostics? Response Fields
| Field | Description |
|---|---|
| Mode | Same encoding as STATs? Mode |
| DataSock / ListenSock | Current socket fds (-1 if not allocated) |
| PendingTx | TX in flight, bounded by IPERF2_MAX_PENDING_TX (default 4) or MAXPending override |
| AbortPending | 1 if a deferred abort was scheduled in callback context (cleared by Iperf2_Tasks) |
| BytesConfirmed | Cumulative bytes the WINC SOCKET_MSG_SEND callback has acknowledged this session |
| LastSendRc / SendErrCount | Sticky tracking of m2m_send failures (reset on Iperf2_Initialize, not by ResetContext) |
| WincState | wifi_manager state machine value (see WIFI_STATE enum) |
| FreeTcpSockets / FreeUdpSockets | Probed at IDLE only — opens then closes a throwaway socket of each type to verify WINC pool isn’t exhausted (#399 hypothesis check) |
Mode 5 — TX-blast notes
- Server-mode: device binds and listens on the requested port, PC connects. Duration starts at accept, not bind, so the user has time to start the PC reader after sending the SCPI.
- Throughput is the upper bound for any iperf2 mode — protocol overhead is zero (raw 1400-byte payloads from a static buffer). PC and device byte counts agree to ≤2% (E: 2026-05-02 5×60s battery).
- Stats schema is the same as iperf2 modes —
Bytes,DurationMs,KBpspopulate at session end viaFinalizeStats.
ADC Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| MEASure:VOLTage:DC? | Measure DC voltage on specified channel | MEASure:VOLTage:DC? 0 | SCPI_ADCVoltageGet |
| ENAble:VOLTage:DC | Enable/disable ADC channels for voltage measurement | Enable Ch0: ENAble:VOLTage:DC 0,1 Enable Ch1: ENAble:VOLTage:DC 1,1 Enable all: ENAble:VOLTage:DC 65535 |
SCPI_ADCChanEnableSet |
| ENAble:VOLTage:DC? | Get channel enable status | ENAble:VOLTage:DC? 0 | SCPI_ADCChanEnableGet |
| SOURce:VOLTage:LEVel | Set output voltage level (not implemented) | SOURce:VOLTage:LEVel 5.0 | SCPI_NotImplemented |
| CONFigure:ADC:SINGleend | Set channel to single-ended (1) or differential (0) mode (if device supports it) | CONFigure:ADC:SINGleend 0,1 | SCPI_ADCChanSingleEndSet |
| CONFigure:ADC:SINGleend? | Get channel single-ended/differential setting | CONFigure:ADC:SINGleend? 0 | SCPI_ADCChanSingleEndGet |
| CONFigure:ADC:RANGe | Set ADC channel voltage range (if device supports it) | CONFigure:ADC:RANGe 0,10 | SCPI_ADCChanRangeSet |
| CONFigure:ADC:RANGe? | Get ADC channel voltage range | CONFigure:ADC:RANGe? 0 | SCPI_ADCChanRangeGet |
| CONFigure:ADC:CHANnel | Enable/disable ADC channel (alias for ENAble:VOLTage:DC for backwards compatibility) | CONFigure:ADC:CHANnel 0,1 | SCPI_ADCChanEnableSet |
| CONFigure:ADC:CHANnel? | Get channel enable status (alias for ENAble:VOLTage:DC? for backwards compatibility) | CONFigure:ADC:CHANnel? 0 | SCPI_ADCChanEnableGet |
| CONFigure:ADC:chanCALM | Sets the m (slope) calibration value on a single channel | CONFigure:ADC:chanCALM 0 1.0023 | SCPI_ADCChanCalmSet |
| CONFigure:ADC:chanCALB | Sets the b (intercept) calibration value on a single channel | CONFigure:ADC:chanCALB 0 0.0012 | SCPI_ADCChanCalbSet |
| CONFigure:ADC:chanCALM? | Gets the m (slope) calibration value for a channel | CONFigure:ADC:chanCALM? 0 | SCPI_ADCChanCalmGet |
| CONFigure:ADC:chanCALB? | Gets the b (intercept) calibration value for a channel | CONFigure:ADC:chanCALB? 0 | SCPI_ADCChanCalbGet |
| CONFigure:ADC:SAVEcal | Saves current user calibration values for all channels to NVM | CONFigure:ADC:SAVEcal | SCPI_ADCCalSave |
| CONFigure:ADC:SAVEFcal | Saves current calibration as factory values (use with caution) | CONFigure:ADC:SAVEFcal | SCPI_ADCCalFSave |
| CONFigure:ADC:LOADcal | Loads user calibration values from NVM | CONFigure:ADC:LOADcal | SCPI_ADCCalLoad |
| CONFigure:ADC:LOADFcal | Loads factory calibration values from NVM | CONFigure:ADC:LOADFcal | SCPI_ADCCalFLoad |
| CONFigure:ADC:USECal | Select factory (0) or user (1) calibration values | CONFigure:ADC:USECal 1 | SCPI_ADCUseCalSet |
| CONFigure:ADC:USECal? | Get calibration mode: factory (0) or user (1) | CONFigure:ADC:USECal? | SCPI_ADCUseCalGet |
Capabilities Discovery
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| CONFigure:CAPabilities:JSON? | Returns a single-line JSON document describing every device capability — identity, channel topology, ADC ranges, streaming limits, transports, power, storage, triggers. Intended for client tools that need to discover what the device can do at connect time. ~5 KB on NQ1. See Capabilities JSON Schema for the full field reference. | CONFigure:CAPabilities:JSON? | SCPI_CapabilitiesJsonGet |
DAC Commands (NQ3 Only)
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SOURce:VOLTage:LEVel | Set DAC channel voltage. Two params: channel,voltage. Or one param: set all channels. | SOURce:VOLTage:LEVel 0,5.0 | SCPI_DACVoltageSet |
| SOURce:VOLTage:LEVel? | Query DAC channel voltage. Optional param: channel number. Omit for all channels. | SOURce:VOLTage:LEVel? 0 | SCPI_DACVoltageGet |
| CONFigure:DAC:UPDATE | Update all DAC outputs (apply pending voltage changes) | CONFigure:DAC:UPDATE | SCPI_DACUpdate |
| CONFigure:DAC:chanCALM | Set DAC channel calibration slope | CONFigure:DAC:chanCALM 0,1.0 | SCPI_DACChanCalmSet |
| CONFigure:DAC:chanCALM? | Get DAC channel calibration slope | CONFigure:DAC:chanCALM? 0 | SCPI_DACChanCalmGet |
| CONFigure:DAC:chanCALB | Set DAC channel calibration offset | CONFigure:DAC:chanCALB 0,0.0 | SCPI_DACChanCalbSet |
| CONFigure:DAC:chanCALB? | Get DAC channel calibration offset | CONFigure:DAC:chanCALB? 0 | SCPI_DACChanCalbGet |
| CONFigure:DAC:USECal | Select factory (0) or user (1) DAC calibration | CONFigure:DAC:USECal 1 | SCPI_DACUseCalSet |
| CONFigure:DAC:USECal? | Get DAC calibration mode | CONFigure:DAC:USECal? | SCPI_DACUseCalGet |
| CONFigure:DAC:SAVEcal | Save user DAC calibration to NVM | CONFigure:DAC:SAVEcal | SCPI_DACCalSave |
| CONFigure:DAC:LOADcal | Load user DAC calibration from NVM | CONFigure:DAC:LOADcal | SCPI_DACCalLoad |
| CONFigure:DAC:SAVEFcal | Save factory DAC calibration to NVM | CONFigure:DAC:SAVEFcal | SCPI_DACCalFSave |
| CONFigure:DAC:LOADFcal | Load factory DAC calibration from NVM | CONFigure:DAC:LOADFcal | SCPI_DACCalFLoad |
Voltage Output Precision
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| CONFigure:VOLTage:PRECision | Set voltage output precision. 0 = integer millivolts, 1-10 = volts with N decimal places. | CONF:VOLT:PREC 4 | SCPI_SetDataPrecision |
| CONFigure:VOLTage:PRECision? | Get current voltage output precision | CONF:VOLT:PREC? | SCPI_GetDataPrecision |
| CONFigure:VOLTage:SAVE | Save current precision to NVM (persists across reboots) | CONF:VOLT:SAVE | SCPI_SaveDataPrecision |
| CONFigure:VOLTage:LOAD | Load precision from NVM | CONF:VOLT:LOAD | SCPI_LoadDataPrecision |
Precision Values:
| Value | Unit | Format Example | Notes |
|---|---|---|---|
| 0 | millivolts (integer) | 1221 |
Backwards compatible, fastest output path |
| 1-3 | volts | 1.2, 1.22, 1.221 |
Low precision |
| 4 | volts | 1.2207 |
Default (NQ1) — 0.1mV resolution, preserves 12-bit ADC |
| 5-6 | volts | 1.22070, 1.220703 |
Default 6 (NQ3) — 18-bit ADC (AD7609) |
| 7-10 | volts | 1.2207031 … |
Default 7 (NQ2) — 24-bit ADC (AD7173) |
Board-Specific Defaults:
| Board | ADC | Resolution | Default Precision |
|---|---|---|---|
| NQ1 | MC12bADC | 12-bit | 4 |
| NQ3 | AD7609 | 18-bit | 6 |
| NQ2 | AD7173 | 24-bit | 7 |
Notes:
- Applied systemwide: CSV streaming, JSON streaming, and SCPI voltage queries (
MEAS:VOLT:DC?,SOUR:VOLT:LEV?) - Protobuf streaming is unaffected
- Can be changed while streaming is active; takes effect on the next encoded sample
- Use
CONF:DATA:SAVEto persist across reboots; otherwise resets to board default
SPI Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| OUTPut:SPI:WRIte | Write data to SPI bus (not implemented) | OUTPut:SPI:WRIte 0xFF,0x00 | SCPI_NotImplemented |
Streaming Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:STReam:START | Start streaming enabled channels at specified frequency | SYSTem:STReam:START 100 | SCPI_StartStreaming |
| SYSTem:STReam:STOP | Stop data streaming | SYSTem:STReam:STOP | SCPI_StopStreaming |
| SYSTem:STReam:DATA? | Check if streaming is active (0=stopped, 1=streaming) | SYSTem:STReam:DATA? | SCPI_IsStreaming |
| SYSTem:STReam:FORmat <format>,<TestData_Len> |
Argument 1: <format>
Argument 2 (optional):<TestData_Len>
Byte [0] – The first byte is always a ‘#’, which indicates a header byte. Byte [1] – Byte [4] – 32-bit tick in 1 millisecond resolution. Byte [5] – Byte [6] – 16-bit cycle counter, increments every packet. Useful for packet loss detection. Byte [7] – Byte [TestData_Len-5] – padded with Dummy Data. Byte [TestData_Len-4] – Byte[TestData_Len-3] – 16-bit checksum using simple additive summation. Byte [TestData_Len-2] – Byte[TestData_Len-1] – 2 bytes delimiter ‘\r\n’ |
SYSTem:STReam:FORmat 2,1000 Sets the stream format to TestData with fixed length at 1000 bytes (maximum length). |
SCPI_SetStreamFormat |
| SYSTem:STReam:FORmat? | Get current stream format (0=Protobuf, 1=JSON, 2=CSV) | SYSTem:STReam:FORmat? | SCPI_GetStreamFormat |
| SYSTem:STReam:INTerface | Set streaming output interface: • 0 = USB • 1 = WiFi • 2 = SD card • 3 = All (legacy mode) Auto-detects source interface if not explicitly set. |
SYSTem:STReam:INTerface 2 | SCPI_SetStreamInterface |
| SYSTem:STReam:INTerface? | Get current streaming interface | SYSTem:STReam:INTerface? | SCPI_GetStreamInterface |
| SYSTem:STReam:STATS? | Get streaming loss/throughput statistics (see response fields below). Query after StopStreamData for trustworthy benchmark numbers — see Quiescence Rule. Counters survive across the stop until the next StartStreamData (auto-clears) or explicit STATS:CLEar. |
SYSTem:STReam:STATS? | SCPI_GetStreamStats |
| SYSTem:STReam:STATS:CLEar | Clear all streaming statistics counters | SYSTem:STReam:STATS:CLEar | SCPI_ClearStreamStats |
| SYSTem:STReam:LOSS:THREshold | Set sample-loss percentage threshold that triggers QUES data-loss bit (range 1-100, default 5) | SYSTem:STReam:LOSS:THREshold 10 | SCPI_SetLossThreshold |
| SYSTem:STReam:LOSS:THREshold? | Get current loss threshold percentage | SYSTem:STReam:LOSS:THREshold? | SCPI_GetLossThreshold |
| SYSTem:STReam:LOSS:WINDow | Set flow window size override (0 = auto, 20-10000 = explicit). Auto = clamp(freq×2, 20, 10000). Takes effect at next streaming start. | SYSTem:STReam:LOSS:WINDow 500 | SCPI_SetFlowWindow |
| SYSTem:STReam:LOSS:WINDow? | Get current flow window size override (0 = auto) | SYSTem:STReam:LOSS:WINDow? | SCPI_GetFlowWindow |
| SYSTem:STReam:TEST:PATtern | Set test pattern mode: 0=off (real ADC), 1=counter, 2=midscale, 3=fullscale, 4=walking, 5=triangle, 6=sine | SYSTem:STReam:TEST:PATtern 1 | SCPI_SetTestPattern |
| SYSTem:STReam:TEST:PATtern? | Query current test pattern (0=disabled) | SYSTem:STReam:TEST:PATtern? | SCPI_GetTestPattern |
Streaming Statistics Response Fields
SYSTem:STReam:STATS? returns the following key=value pairs:
| Field | Type | Description |
|---|---|---|
| TotalSamplesStreamed | uint64 | Samples successfully queued from ISR to encoder |
| TotalBytesStreamed | uint64 | Total bytes encoded and offered to output buffers |
| QueueDroppedSamples | uint32 | Samples lost when the 700-sample queue is full |
| UsbDroppedBytes | uint32 | Bytes lost due to USB circular buffer full (16KB) |
| WifiDroppedBytes | uint32 | Bytes lost due to WiFi circular buffer full (5.6KB) |
| SdDroppedBytes | uint32 | Bytes lost due to SD write timeout or partial write |
| SdWriteCalls | uint32 | Total disk_write() invocations |
| SdWriteSectors | uint32 | Total sectors written to SD card |
| SdBytesWritten | uint64 | Total bytes confirmed written to SD card |
| SdWriteErrors | uint32 | disk_write() failures (covers CRC rejects, timeouts, all FatFS-level errors) |
| SdWriteMaxLatencyMs | uint32 | Worst-case single write latency in milliseconds |
| SdWriteAlignedCopies | uint32 | Writes requiring cacheable→aligned buffer copy (performance penalty indicator) |
| WifiTcpBytesSent | uint64 | Bytes accepted by WiFi radio send() (WiFi streaming only). Safe for multi-day sessions. |
| WifiTcpBytesConfirmed | uint64 | Bytes confirmed delivered by WiFi radio callback. If less than WifiTcpBytesSent, data was lost inside the radio module. |
| WifiTcpSendErrors | uint32 | WiFi send callback errors (negative sentBytes — real failures) |
| WifiTcpPartialSends | uint32 | Partial sends (callback confirmed fewer bytes than requested — normal TCP segmentation, indicates link pressure) |
| EncoderFailures | uint32 | Encode attempts that returned 0 bytes with data available |
| TimerISRCalls | uint64 | Actual streaming timer ISR entry count this session (#265). Distinguishes “timer firing at requested rate” from downstream bottlenecks. Invariant: TimerISRCalls == TotalSamplesStreamed + QueueDroppedSamples. Compare against freq × duration to detect rate-limiting at the PIC32MZ ~90 kHz hardware ceiling. |
| SampleLossPercent | uint32 | QueueDroppedSamples / (TotalSamples + Dropped) * 100 |
| ByteLossPercent | uint32 | (USB + WiFi + SD dropped) / TotalBytesStreamed * 100 (can exceed 100% with multiple active outputs) |
| WindowLossPercent | uint32 | Sliding-window sample loss percentage (0-100), updated every N samples. Window size = clamp(freq×2, 20, 10000) or explicit override via SYST:STR:LOSS:WINDow. Threshold for QUES bit 4 configurable via SYST:STR:LOSS:THREshold (default 5%). |
Session lifecycle: Stats are cleared automatically when a new streaming session starts (STR:START). They are preserved after STR:STOP so the user can query them. A LOG_E summary is automatically written at session end if any data was lost (retrieve via SYSTem:LOG?).
Thread safety: 64-bit counters use critical sections for atomic updates on 32-bit PIC32MZ. STATS? returns an atomic snapshot of all fields. TimerISRCalls lives in a separate volatile global written only by the timer ISR (priority 1, no concurrent writers); the snapshot read is taken inside the same critical section, which blocks the timer ISR for coherent 64-bit access.
Diagnostic logic for TimerISRCalls:
TimerISRCalls < freq × duration→ timer is rate-limited (PIC32MZ ~90 kHz hardware ceiling for the streaming ISR + Harmony dispatch)TimerISRCalls == TotalSamples + QueueDropped→ every ISR is fully accounted for between the ISR and the deferred taskQueueDroppedSamples > 0→ sample pool exhausted (encoder/output too slow for the rate the timer is firing)UsbDroppedBytes / SdDroppedBytes > 0→ encoder is fine but transport can’t keep up
Per-interface coverage: WiFi has full pipeline tracking (BytesSent/BytesConfirmed/SendErrors/PartialSends) because the radio transport is non-deterministic. USB and SD only track buffer overflow drops — their transports are deterministic (USB CDC is protocol-ACKed, SD writes are synchronous), so “sent == confirmed” by definition.
Test Pattern Streaming Mode
Test pattern mode replaces real ADC values with synthetic data for deterministic regression testing and benchmarking. The real ISR timing is preserved — patterns only override the ADC value field.
SCPI Commands:
SYSTem:STReam:TEST:PATtern <pattern> # Set pattern (0=off, 1-6)
SYSTem:STReam:TEST:PATtern? # Query current patternPattern Types:
| Pattern | Name | Value Generated | Use Case |
|---|---|---|---|
| 0 | Off | Real ADC data | Normal operation |
| 1 | Counter | (sampleCount + channelId) % (adcMax+1) |
Integrity verification — PC can predict exact values |
| 2 | Midscale | adcMax / 2 |
Consistent encoding size across CSV/JSON/ProtoBuf |
| 3 | Fullscale | adcMax |
Worst-case ProtoBuf variable-length encoding |
| 4 | Walking | (sampleCount * (channelId+1)) % (adcMax+1) |
Multi-channel visual verification |
| 5 | Triangle | Ramps 0→adcMax→0, period=2*(adcMax+1) | Realistic waveform, staggered per channel |
| 6 | Sine | 256-sample sine wave, scaled to [0, adcMax] | Realistic signal testing, 45° phase offset per channel |
adcMax= max raw ADC code = Resolution – 1 (4095 for MC12bADC 12-bit, 262143 for AD7609 18-bit)- Pattern is runtime-only (not persisted to NVM, resets on reboot)
- Sample counter resets at each
STR:STARTfor deterministic sessions - All encoding formats and output interfaces work normally with test patterns
Streaming Throughput Benchmarking
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:STReam:BENCHmark <0|1> | Enable (1) or disable (0) benchmark mode. Bypasses frequency cap for throughput testing. Lowers ISR task priority for fair scheduling. | SYST:STR:BENCH 1 | SCPI_SetBenchmarkMode |
| SYSTem:STReam:BENCHmark? | Query benchmark mode (0=normal, 1=uncapped) | SYST:STR:BENCH? | SCPI_GetBenchmarkMode |
| SYSTem:STReam:THRoughput <freq>,<duration_sec> | Self-contained benchmark: enables benchmark mode + test pattern 2, streams for duration, stops, returns all stats. Blocks SCPI during execution. | SYST:STR:THR 5000,10 | SCPI_RunThroughputBench |
Benchmark Mode Usage:
- Enable test patterns:
SYST:STR:TEST:PATtern 2 - Enable benchmark mode:
SYST:STR:BENCHmark 1 - Start streaming at desired rate:
SYST:STR:START 11000 - Wait, then stop:
SYST:STR:STOP - Check results:
SYST:STR:STATS? - Restore:
SYST:STR:BENCHmark 0
Measured Zero-Loss Throughput Ceilings (NQ1, test patterns):
| Interface | Format | Channels | Max Rate | KB/s |
|---|---|---|---|---|
| USB | CSV | 1 | 13 kHz | 210 |
| USB | CSV | 16 | 3 kHz | 766 |
| USB | PB | 1 | 5 kHz | 62 |
| USB | PB | 16 | 3 kHz | 136 |
| SD | CSV | 1 | 5 kHz | 84 |
| SD | CSV | 16 | 1 kHz | 272 |
| SD | PB | 1 | 5 kHz | 61 |
| SD | PB | 16 | 1 kHz | 46 |
| WiFi | PB | 16 | 1 kHz | 49 |
| WiFi | CSV | 16 | 1 kHz | 206 |
Dynamic Memory Management Commands
Buffer sizes and sample pool depth are configurable at runtime to optimize RAM usage for specific streaming scenarios. All settings take effect at the next STR:START. Settings are runtime-only (not persisted to NVM, reset on reboot to safe defaults). All setters reject changes while streaming is active.
| SCPI Command | Description | Range | Default | Firmware Callback |
|---|---|---|---|---|
| SYSTem:MEMory:SD:BUFfer <bytes> | Set SD circular buffer size | 4096-65536, multiple of 512 | 32768 | SCPI_SetMemSdBuf |
| SYSTem:MEMory:SD:BUFfer? | Query SD circular buffer size | SCPI_GetMemSdBuf | ||
| SYSTem:MEMory:WIFI:BUFfer <bytes> | Set WiFi circular buffer size | 1400-65536 | 14000 | SCPI_SetMemWifiBuf |
| SYSTem:MEMory:WIFI:BUFfer? | Query WiFi circular buffer size | SCPI_GetMemWifiBuf | ||
| SYSTem:MEMory:USB:BUFfer <bytes> | Set USB circular buffer size | 4096-65536 | 16384 | SCPI_SetMemUsbBuf |
| SYSTem:MEMory:USB:BUFfer? | Query USB circular buffer size | SCPI_GetMemUsbBuf | ||
| SYSTem:MEMory:SAMPle:POOL <count> | Set sample pool depth (0=auto) | 0 or 100-2000 | 500 (auto) | SCPI_SetMemSamplePool |
| SYSTem:MEMory:SAMPle:POOL? | Query sample pool depth | SCPI_GetMemSamplePool | ||
| SYSTem:MEMory:FREE? | Query full memory diagnostics | SCPI_GetMemFree | ||
| SYSTem:MEMory:AUTO | Auto-balance buffers for active interfaces | SCPI_MemAutoBalance | ||
| SYSTem:MEMory:STACk? | Query all task stack high-water marks | SCPI_GetStackStats |
Memory Diagnostics Response Fields
SYSTem:MEMory:FREE? returns a comma-separated key:value response:
| Field | Type | Description |
|---|---|---|
| HeapTotal | uint32 | Total FreeRTOS heap size (75000 bytes) |
| HeapFree | uint32 | Currently free heap bytes |
| HeapUsed | uint32 | Currently used heap bytes |
| HeapMinEverFree | uint32 | Lowest heap free since boot (high-water mark) |
| CoherentPoolTotal | uint32 | Total DMA-safe coherent pool size (126976 bytes) |
| CoherentPoolFree | uint32 | Free coherent pool bytes |
| SdCircularSize | uint32 | Current SD circular buffer partition size (streaming pool) |
| SamplePoolCount | uint32 | Current sample pool depth (number of samples) |
| SamplePoolBytes | uint32 | Sample pool data memory (count x 208 bytes) |
| SampleNextFreeBytes | uint32 | Free-list array memory (count x 2 bytes) |
| SampleQueueBytes | uint32 | FreeRTOS queue overhead (estimated) |
Auto-Balance Algorithm
SYSTem:MEMory:AUTO queries the active streaming interface (SYSTem:STReam:INTerface) and SD enable state, then allocates default buffer sizes only for enabled interfaces. Remaining streaming pool space goes to the sample pool (clamped 100-2000). Also re-partitions the 124KB coherent pool among all three DMA consumers (SD write, USB write, WiFi SPI staging) — inactive interfaces get minimums, active interfaces split remaining space (SD 50%, USB 30%, WiFi 20%; single-active gets everything). Returns the allocation as "USB:<n>,WiFi:<n>,SD:<n>,Encoder:<n>,Pool:<n>,UsbDma:<n>,WifiDma:<n>,SdDma:<n>".
SD Logging Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:STORage:SD:ENAble | Enable (1) or disable (0) SD card. WiFi+SD streaming blocked (SPI bus conflict). Cannot disable while SD is busy. | SYSTem:STORage:SD:ENAble 1 | SCPI_StorageSDEnableSet |
| SYSTem:STORage:SD:ENAble? | Query SD card enable status (0=disabled, 1=enabled) | SYSTem:STORage:SD:ENAble? | SCPI_StorageSDEnableGet |
| SYSTem:STORage:SD:FILE | Set filename for SD card logging. File is opened in overwrite mode (not append). | SYSTem:STORage:SD:FILE “data.csv” | SCPI_StorageSDLoggingSet |
| SYSTem:STORage:SD:LISt? | List all files on SD card. Returns chunked output to handle large directories. Optional parameter: directory path. | SYSTem:STORage:SD:LIST? SYSTem:STORage:SD:LIST? “DAQiFi” |
SCPI_StorageSDListDir |
| SYSTem:STORage:SD:GET | Retrieve file contents from SD card. Parameter: filename in quotes. | SYSTem:STORage:SD:GET “data.csv” | SCPI_StorageSDGetData |
| SYSTem:STORage:SD:DELete | Delete a file from SD card. Parameter: filename in quotes. | SYSTem:STORage:SD:DEL “old.csv” | SCPI_StorageSDDelete |
| SYSTem:STORage:SD:FORmat | Format SD card (erase all files). WARNING: Destructive! Non-blocking — returns immediately. Poll FORmat? for progress. |
SYSTem:STORage:SD:FOR | SCPI_StorageSDFormat |
| SYSTem:STORage:SD:FORmat? | Query format status and progress. Returns: <status>,<percent>. Status: 0=idle, 1=in progress, 2=completed OK, -1=failed. Percent: 0-100. Terminal states (2, -1) clear to idle on read. Example: 1,45 = formatting at 45%. |
SYSTem:STORage:SD:FOR? | SCPI_StorageSDFormatQuery |
| SYSTem:STORage:SD:BENCHmark | Run write speed benchmark. Parameter: size in KB (1-1024), optional pattern (0=zeros, 1=sequential, 2=random). Waits for file open before timing, waits for full pipeline flush before stopping timer. Measures actual I/O throughput (no artificial delays). | SYSTem:STORage:SD:BENCH 1024 SYSTem:STORage:SD:BENCH 512,1 |
SCPI_StorageSDBenchmark |
| SYSTem:STORage:SD:BENCHmark? | Query benchmark results. Returns CSV: bytes_written,time_ms,speed_bps | SYSTem:STORage:SD:BENCH? | SCPI_StorageSDBenchmarkQuery |
| SYSTem:STORage:SD:MAXSize | Set maximum file size in bytes before auto-split. Prevents FAT32 4GB limit issues. Range: 1000 bytes to 4GB, or 0 for filesystem maximum. Default: 3.9GB (FAT32-safe). Setting 0 uses safe 3.9GB limit. Files split sequentially: data.csv → data-0001.csv, data-0002.csv, etc. | SYSTem:STORage:SD:MAXSize 2000000000 SYSTem:STORage:SD:MAXSize 0 |
SCPI_StorageSDMaxSizeSet |
| SYSTem:STORage:SD:MAXSize? | Query current maximum file size setting. Returns bytes. | SYSTem:STORage:SD:MAXSize? | SCPI_StorageSDMaxSizeGet |
| SYSTem:STORage:SD:SPACe? | Query SD card free and total space. Returns two values: free bytes, total bytes. Routes through SD card manager state machine (works even when SD is disabled). | SYSTem:STORage:SD:SPACe? | SCPI_StorageSDSpaceGet |
| SYSTem:STORage:SD:ABORt | Abort an in-progress SD file transfer (GET). Closes the file cleanly. No-op if no transfer is active. | SYST:STOR:SD:ABOR | SCPI_StorageSDAbort |
| SYSTem:STORage:SD:INFO? | Query SD card identification (CID register). Returns comma-separated fields: MID (manufacturer ID), OID (OEM string), PNM (product name), PRV (product revision M.N), PSN (serial number), MDT (manufacturing date YYYY/MM). Returns SCPI error if no card present or CID unavailable. | SYST:STOR:SD:INFO? | SCPI_StorageSDInfo |
SD Card INFO Response Example:
3,"SD",SR256,8.4,2818572288,2023/6
Fields: MID=3 (SanDisk), OID=”SD”, Product=”SR256″, Revision=8.4, Serial=2818572288, Date=2023/June
SD Card Logging Example:
SYSTem:POWer:STATe 1
SYSTem:STORage:SD:ENAble 1
SYSTem:STORage:SD:FILE "test.csv"
SYSTem:STReam:INTerface 2 // Set output to SD card
SYSTem:STReam:FORmat 2 // CSV format
CONFigure:ADC:CHANnel 0,1
SYSTem:STReam:START 100
// Data logs to SD card
SYSTem:STReam:STOP
SYSTem:STORage:SD:LISt? // File appears in listing
SYSTem:STORage:SD:GET "test.csv"
SYSTem:STORage:SD:DELete "test.csv"
FreeRTOS Commands
| SCPI Command | Description | Example | Firmware Callback |
|---|---|---|---|
| SYSTem:OS:Stats? | Get FreeRTOS task runtime statistics showing CPU usage per task | SYSTem:OS:Stats? | SCPI_GetOSStats |
Common Usage Examples
Basic Power Control
# Power up the device
SYSTem:POWer:STATe 1
# Check power state
SYSTem:POWer:STATe?
# Get system info
SYSTem:INFo?
# Power down
SYSTem:POWer:STATe 0
WiFi Configuration
# Configure WiFi to connect to a network
SYSTem:COMMunicate:LAN:SSID "MyNetwork"
SYSTem:COMMunicate:LAN:SECurity 3
SYSTem:COMMunicate:LAN:PASs "MyPassword123"
SYSTem:COMMunicate:LAN:NETType 1
SYSTem:COMMunicate:LAN:APPLY
# Save settings to NVM
SYSTem:COMMunicate:LAN:SAVE
# Configure as Access Point
SYSTem:COMMunicate:LAN:NETType 4
SYSTem:COMMunicate:LAN:SSID "DAQiFi-AP"
SYSTem:COMMunicate:LAN:SECurity 0
SYSTem:COMMunicate:LAN:APPLY
ADC Data Acquisition
# Enable channel 0 for 10V range
ENAble:VOLTage:DC 0,1
CONFigure:ADC:RANGe 0,10
# Read single voltage
MEASure:VOLTage:DC? 0
# Start streaming at 100Hz
SYSTem:STReam:START 100
# Stop streaming
SYSTem:STReam:STOP
Digital I/O Control
# Enable DIO port
DIO:PORt:ENAble 1
# Set as output
DIO:PORt:DIRection 0,1
# Set high
DIO:PORt:STATe 0,1
# Read state
DIO:PORt:STATe? 0
PWM Output
# Enable PWM channel 0
PWM:CHannel:ENable 0,1
# Set 1kHz frequency
PWM:CHannel:FREQuency 0,1000
# Set 50% duty cycle
PWM:CHannel:DUTY 0,50
SD Card Logging
# Power up
SYSTem:POWer:STATe 1
# Enable SD card and set filename
SYSTem:STORage:SD:ENAble 1
SYSTem:STORage:SD:FILE "data.csv"
# Set streaming to SD interface and CSV format
SYSTem:STReam:INTerface 2
SYSTem:STReam:FORmat 2
# Enable ADC channel(s)
CONFigure:ADC:CHANnel 0,1
# Start logging at 100 Hz
SYSTem:STReam:START 100
# Stop and retrieve data
SYSTem:STReam:STOP
SYSTem:STORage:SD:LISt?
SYSTem:STORage:SD:GET "data.csv"
Note: WiFi does not need to be disabled for SD logging. However, WiFi streaming (SYSTem:STReam:INTerface 1 or 3) cannot be used simultaneously with SD logging due to shared SPI bus. WiFi firmware update is also blocked while SD is busy.
Source of truth: daqifi/daqifi-nyquist-firmware wiki → 01-SCPI-Interface · Edit on GitHub · this page is auto-synced; edit upstream to update.