Oscilloscope over WiFi
WhyHow      hardware      software, scope-side      software, client-sideProtocols and interfaces      VISA      hardware communication            subrack/chassis            inter-instrument - cables      network communication      commands and protocols            usual network ports            mDNS typesVXI-11            RPC channelsUSBTMC (Test & Measurement Class, instrument connection)      GPIB interface            USB488 registers      USB488 subclass - features and capabilities            USB488 Trigger message            USB488 bulk message            usbtmc constants            cautionsSCPI (protocol)            examples            Mandatory SCPI commands for USB488            Optional SCPI/USB488 commands for USB488      binary/bulk data responses            nonconforming devices      VISA resource name, device addressesSoftware      Server side: usbtmc-server.py            MODIFICATION: universal_usbtmc            FILES            Further possible modifications      python: usbtmc            MODIFICATION            FILES      Client side: lxi, liblxi            MODIFICATIONS            FILESRigol DS1054Z notes      LAN interface            ports            network configuration, mDNS enable (fail)            LXI vs USBTMC            discovery            network communication, detailed                  DISCOVERY, network segment broadcast                  RPC PORTMAP QUERY                  VXI-11 call            RPC      PTP/PictBridge mode (failure?)            Windows 10      network and web interface      LXI speed            speed, LAN/LXI            speed, wifi/python/USBTMC      SCPI commands      data acquisition            screenshot            waveformRigol DS1052D notes            speed, wifi/python/USBTMC      SCPI commands      data acquisition            screenshot            waveformConversions and simulations      time synchronization            PTP, IEEE 1588 Precision Time Protocol            GPS as alternative                  USB-serial                  Raspberry Pi                  wireless options            triggersSee alsoTodo 
Why
Because often it's handy to control oscilloscopes, and other instrumentation, over the network.
Because wireless connection is often more handy than a network cable.
Because cheap Raspberry Pi Zero W can be used to retrofit a USB-only device for full-scale wifi operation.
The implementation is specific for Rigol DS1054Z (and Rigol DS1052D, todo).
How
 hardware
The DS1054Z scope has Ethernet and USB. The USB port is a standard instrument driver USB-TMC class interface.
The Ethernet port is a standard LXI
 USB-TMC class interface.
The Ethernet port is a standard LXI interface.
 interface.
The scope gets a "backpack" with a Raspberry Pi computer. The raspi is connected to the scope by a short USB cable,
accessing the TMC interface.
The raspi may or may not have a display of its own and a touchscreen or set of buttons, for more operations
(sending screenshots and acquired data to the server, server-based protocol decoding, voice annotations,
store banks of configurations, probe gains for nonstandard or ganged-together[1] probes...).
[1] When reverse-engineering mixed signal systems, it's often needed to see both the DC analog level and the weaker
AC signal riding on it. Switching between DC and AC coupling and adjusting the gain for each signal is a pain in the
weknowwhere. Adapter that couples together two channels, and then separate setting of one channel as DC and the other
as more sensitive AC is a good hack, but it halves the input impedance (typ. a megaohm) and screws up the probe
attenuation and the voltages are incorrect. One-touch attenuation setting to the not-in-the-common-list probe value can be handy.
(Also it may be possible to tweak the two-to-one adapter with a trimpot to set up the apparent gain.)
 software, scope-side
The raspi needs to run a daemon for the network connectivity, acting as a gateway between a TCP/IP socket
and the TMC device. A python solution was chosen, for flexibility.
Adding functionality to the python daemon will be easy - HTTP-based screenshots and waveform requests, touchscreen interface,
iGornet-class MQTT data feeds...
 software, client-side
The "LXI" client, with corresponding "liblxi" library, was chosen.
 Protocols and interfaces
The measurement instrumentation is a wild mess of standards old and new, of abstraction layers good and poor.
The standards can be split to the hardware and the software/data halves; the SCPI commands can be relayed through GPIB, USB-TMC, RS232/485, LXI, whatever.
-  Instrument Driver - generic name for connection to the instruments; covers the older (1993) VXIplug&play and the newer IVI drivers - generic name for connection to the instruments; covers the older (1993) VXIplug&play and the newer IVI drivers
Essentially, the hardware/interface/communication standards are about setting up a way to send SCPI messages to the instruments and getting responses; in some
variants also synchronizing time between instruments and sending them triggers.
 VISA
VISA - "Virtual instrument software architecture", abstraction layer over different communication standards
 - "Virtual instrument software architecture", abstraction layer over different communication standards
-  one-size-fits-all, hundreds of megabytes of drivers, clogging the machine with processes, sometimes breaking things
-  good for big labs, the usual Windows multihundred-megabyte software bundles are overkill for garage operations with cheap instruments
-  the other VISA, not the one that is also about pushing numbers around - this VISA's numbers are real values with real meaning, instead of virtual meaning given only by enough people believing in fiat money
-  pyVISA seems to be pretty good lightweight alternative
 hardware communication
 subrack/chassis
high-speed buses, between instrument cards, within one compact unit - motherboard or backplane and cards
-  PXI , "PCI eXtensions for Instrumentation" - high-speed chassis/subrack interconnection for instrumentation cards, based on PCI , "PCI eXtensions for Instrumentation" - high-speed chassis/subrack interconnection for instrumentation cards, based on PCI /CompactPCI /CompactPCI  
-  VXI , "VME eXtensions for Instrumentation" aka ANSI/IEEE 1014-1987, ANSI/VITA 1-1994 - older and slower than PXI , "VME eXtensions for Instrumentation" aka ANSI/IEEE 1014-1987, ANSI/VITA 1-1994 - older and slower than PXI
-  based on VMEbus , 16bit (later also 32bit and 64bit) parallel bus , 16bit (later also 32bit and 64bit) parallel bus
-  related: VPX aka VITA 46, ANSI/VITA 46.0-2019; STEbus aka VITA 46, ANSI/VITA 46.0-2019; STEbus aka IEEE 1000-1987 (8bit data, 20bit address, cheaper than VMEbus, industrial automation, 1980s-1990s before IBM-PC domination) aka IEEE 1000-1987 (8bit data, 20bit address, cheaper than VMEbus, industrial automation, 1980s-1990s before IBM-PC domination)
-  many MANY more
 inter-instrument - cables
-  IEEE-488 , aka HP-IB, GPIB - the grandmother of them all; parallel LPT-like , aka HP-IB, GPIB - the grandmother of them all; parallel LPT-like bus specific for instrumentation, 8bit, multimaster, multidrop bus specific for instrumentation, 8bit, multimaster, multidrop
-  RS-232 - plain old serial port - common on older instruments; often essentially SCPI-raw, or SCPI-telnet - plain old serial port - common on older instruments; often essentially SCPI-raw, or SCPI-telnet
-  USBTMC, USB with instrumentation class - common on less-ancient instruments with instrumentation class - common on less-ancient instruments
-  messages with 12-byte header, same as in the GPIB protocol
-  essentially GPIB-over-USB
-  USB488 - USBTMC subclass, GPIB/IEEE488 functionality implemented over USB
 network communication
over TCP/IP , usually ethernet
, usually ethernet -based, can be wireless (then beware of unpredictable delays and increased roundtrips)
-based, can be wireless (then beware of unpredictable delays and increased roundtrips)
-  LXI , "LAN eXtensions for Instrumentation" - protocols for communication using TCP/IP over local networks , "LAN eXtensions for Instrumentation" - protocols for communication using TCP/IP over local networks
-  usually uses either VXI-11 or HiSLIP, can use SCPI-raw
-  may implement Precision Time Protocol , IEEE 1588, when timing is necessary - multicast , IEEE 1588, when timing is necessary - multicast -based timing messages, where NTP -based timing messages, where NTP is not accurate enough and GPS is not accurate enough and GPS receivers are costly or impractical receivers are costly or impractical
-  VXI-11 - a LXI-like specification over SunRPC  
-  designed to emulate GPIB, including out-of-band signal lines
-  port 111 with portmapper, service ports assigned dynamically [ref]
-  messages with 12-byte header, same as in the GPIB protocol
-  essentially GPIB-over-TCP/IP
-  three TCP ports used - core (main SCPI communication), abort (immediate stop of current operation/transaction), interrupt (instrument has asynchronous request)
-  HiSLIP , "High Speed LAN Instrument Protocol" - successor of VXI-11 , "High Speed LAN Instrument Protocol" - successor of VXI-11
-  two connections to port 4880, asynchronous and synchronous channel
-  remote COM port - like RS-232 over TCP/IP, raw data with fixed speed at the converter or full RFC-2177
 commands and protocols
-  SCPI - "Standard Commands for Programmable Instruments" - "Standard Commands for Programmable Instruments"
-  based on IEEE 488.2 (1987 and 1992 flavors), a command set of IEEE-488 aka HP-IB aka GPIB aka HP-IB aka GPIB
-  plaintext commands for communication with instrumentation, hierarchical structure
-  ":" as hierarchy separator, on the beginning refers to the root of the command structure, if omitted the command is referred to the "current directory" of the last command
-  ends with ? when device is queried, otherwise command is set without expecting response
-  space as separator to parameters for command
-  eg. :MEAS:VOLT:DC? - measures voltage on DC
 usual network ports
https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml 
-  TCP
-  80 - HTTP server, web/browser control of the instrument server, web/browser control of the instrument
-  111 - VXI-11 RPC [link?:portmap] (RFC1833); autodetection (UDP) [link?:portmap] (RFC1833); autodetection (UDP)
-  for dynamic assignment of ports for communication, used by VXI11/SICLLAN
-  3537 - (RFC/IANA) "NI-VISA remote"
-  4880 - (RFC/IANA) HiSLIP ; usually two connections, for sync and async command stream ; usually two connections, for sync and async command stream
-  5024 - (RFC/IANA) SCPI-telnet, SCPI messages encapsulated in RFC855 telnet stream with escape sequences messages encapsulated in RFC855 telnet stream with escape sequences
-  5025 - (RFC/IANA) SCPI-raw, direct SCPI messages messages
-  5044 - (RFC/IANA) LXI-eventsvc - instrument triggering (see also UDP)
-  5555 - Rigol-brand instruments, SCPI-raw, direct SCPI messages messages
-  5900 - (RFC/IANA) VNC , remote desktop GUI console , remote desktop GUI console
-  UDP
-  111 (broadcast) - SunRPC, VXI-11 autodetection
-  319 (multicast, 224.0.1.129/FF02::181) - (RFC/IANA) Precision Time Protocol (IEEE-1588), PTP Events (IEEE-1588), PTP Events
-  320 (multicast, 224.0.1.129/FF02::181) - (RFC/IANA) Precision Time Protocol (IEEE-1588), PTP General (IEEE-1588), PTP General
-  3537 - (RFC/IANA) "NI-VISA remote"
-  5044 (multicast, 224.0.23.159/FF02::138) - (RFC/IANA) LXI-eventsvc - instrument triggering
-  5353 (multicast, 224.0.0.251/FF02::FB) - (RFC/IANA) mDNS - discovery of instruments on the network - discovery of instruments on the network
 mDNS types
-  _lxi._tcp
-  _vxi-11._tcp
-  _scpi-raw._tcp
-  _scpi-telnet._tcp
-  _hislip._tcp
 VXI-11
The VXI-11 protocol is essentially the GPIB interface transferred to Ethernet link.
The functionality is emulated by three network connections:
-  core channel (service no. 395183) - SCPI messages come through here
-  abort channel - the activity on the core channel is immediately aborted
-  interrupt channel - the instrument-initiated messages
The low-level control messages are:
-  aborts:
-  &ABO (Abort) - Aborts processing of the commands just received.
-  &DCL (Device Clear) - Aborts processing of the commands just received and sets the command processing software to a defined initial state. Does not change the instrument setting.
-  local/remote (RL1 devices)
-  >L (Go to Local) - Transition to the "Local" state (manual control).
-  >R (Go to Remote) - Transition to the "Remote" state (remote control).
-  &LLO (Local Lockout) - Disables switchover from remote control to manual control by means of the front panel keys.
-  &NREN (Not Remote Enable) - Enables switchover from remote control to manual control by means of the front panel keys.
-  triggers (DT1 devices), polls
-  &GET (Group Execute Trigger) - Triggers a previously active device function (e.g. a sweep). The effect of the command is the same as with that of a pulse at the external trigger signal input.
-  &POL (Serial Poll) - Starts a serial poll.
The session setup is fairly involved, beginning with the RPC portmapper call. The SCPI messages are wrapped in the GPIB-derived protocol (very similar to USBTMC).
 RPC channels
For whatever reasons, many services do not run on fixed-assigned ports and rely on dynamically assigned ports via a portmapper service.
The most popular one is SunRPC , also called ONC RPC. The portmapper calls request the port of the service via port 111, then connect to
where they were told.
, also called ONC RPC. The portmapper calls request the port of the service via port 111, then connect to
where they were told.
The services requested are identified by a number. Some are:
-  395183 - VXI11 Core Channel (0x0607af) - the requests/responses with the SCPI commands
-  395184 - VXI11 Abort Channel - asynchronous requests to abort operation on core channel
-  395185 - VXI11 Interrupt Channel - asynchronous requests from instrument to host computer
 USBTMC (Test & Measurement Class, instrument connection)
Many non-ancient instruments feature a USB -B port (sometimes microUSB), with USB TMC class device.
-B port (sometimes microUSB), with USB TMC class device.
In Linux, after attachment the device enumerates and forms a /dev/usbtmc* device file. This can be further interfaced with as a character device.
The device behaves similar to usual tty terminals/serial ports with a few important differences. (Eg. usual COM-over-IP attempts won't work.)
The device is usually used to communicate the SCPI command strings and their responses. Eg.
*IDN?
RIGOL TECHNOLOGIES,DS1104Z,DS1ZA210400549,00.04.04.SP4
*IDN?
Rigol Technologies,DS1052D,DS1EC120100007,00.02.02.02.00
 GPIB interface
A detour to the ancient era of GPIB, when the features were born.
GPIB Pinout:
         data bit 0   DIO1   1 ] [ 13   DIO5   data bit 4
         data bit 1   DIO2   2 ] [ 14   DIO6   data bit 5
         data bit 2   DIO3   3 ] [ 15   DIO7   data bit 6
         data bit 3   DIO4   4 ] [ 16   DIO8   data bit 7
    End-or-identify   EOI    5 ] [ 17   REN    Remote Enable
         Data valid   DAV    6 ] [ 18   GND/DAV
 Not ready for data   NRFD   7 ] [ 19   GND/NRFD
   No data accepted   NDAC   8 ] [ 20   GND/NDAC
    Interface clear   IFC    9 ] [ 21   GND/IFC
    Service request   SRQ   10 ] [ 22   GND/SRQ
          Attention   ATN   11 ] [ 23   GND/ATN
                    shield  12 ] [ 24   SG     signal/logic ground
Uniline commands - single control line involved
-  IFC - Interface Clear - clear buffers with pending data
-  Remote Enable - enable remote control
-  Attention - not in USB
-  Identify - not in USB
Multiline commands - 2 or more control lines involved
-  Device Clear - clear buffers with pending data
-  Local Lockout - send REN_CONTROL and LOCAL_LOCKOUT
-  Serial Poll Enable - not in USB
-  Serial Poll Disable - not in USB
-  Parallel Port Unconfigure - not in USB
Addressed messages - "multicast", addressed by bit flags to one or more devices at once
-  GET, Group Execute Trigger
-  Selected Device Clear - clear buffers with pending data
-  Go To Local - send REN_CONTROL and GO_TO_LOCAL
-  Parallel Port Configure - not in USB
-  Take Control (not in USB)
Secondary commands
Capabilities:
-  AH1 - Acceptor Handshake, can receive remote multiline messages; all USB devices are AH1
-  SH1 - Source Handshake, can send multiline messages; all USB devices are SH1
-  T6 - Talker - all USB devices are T6
-  DC1 - Device Clear - supports device buffer clearing; all USBTMC must be DC1
-  C0 - controller - not in USB
-  L2/L0 - Listener - can receive device-dependent data; all USB488.2 must be L2, non-USB488.2 can be talk-only (L0)
-  DT1/DT0 - Device Trigger - supports trigger
-  RL1/RL0 - RemoteLocal - remote control with local lockout
-  SR1/SR0 - ServiceRequest - accepts Service Request via interrupt input
 USB488 registers
STB, Status Byte:
-  bit 7 - OPR (Operation Register Summary)
-  bit 6 - MSS (Master Status Summary - MSS=OPR|ESB|MAV)
-  bit 5 - ESB (Event Status Summary - ESB=set if any bit set in (ESR AND ESE))
-  bit 4 - MAV (Message Available)
-  bit 3..0 - 0x00, reserved or various uses
ESR, Event Status Register byte:
-  bit 7 - PON = Power ON (set by device power-on event)
-  bit 6 - URQ = User Request
-  bit 5 - CME = Command Error (undefined mnemonic, bad syntax, or wrong number of param's)
-  bit 4 - EXE = Execution Error (command parameter is out of bounds, or wrong data type)
-  bit 3 - DDE = Device-Dependent Event (register) summary bit, or Device-Dependent Error
-  bit 2 - QYE = Query Error (e.g. the host requested a response without first sending a query message)
-  bit 1 - RTL = Returned-To-Local state (RL1 devices only)
-  bit 0 - OPC = Operation Completed
ESE, Event Status Enable
-  mask for the ESR, to reflect to STB.ESB
-  AND ESE with ESR, then set ESB if result nonzero
 USB488 subclass - features and capabilities
USB488 is a sub-class of the USBTMC class, implementing various GPIB/IEEE488 features.[ref]
The device is half-duplex. New communication to the instrument must not be sent while there is still a response undelivered.
Each message is prepended by a header, for message synchronization and protection against data loss; a GPIB spec.
USBTMC requests:
-  INITIATE_CLEAR - flush device USB buffers
-  GET_CAPABILITIES - receives bitmap of capabilities
-  interface
-  is USB488
-  accepts REN_CONTROL, GO_TO_LOCAL, LOCAL_LOCKOUT
-  accepts Trigger message
-  device
-  understands all mandatory SCPI commands - interface must be USB488, device must be SR1-capable
-  SR1-capable (ServiceRequest, uses interrupt-in endpoint) - must be set if interface is USB488
-  RL1-capable (RemoteLocal, implements remote/local state machine) - interface must accept REN_CONTROL...
-  DT1-capable (DeviceTrigger, supports trigger) - interface accepts Trigger
USB488 requests:
-  READ_STATUS_BYTE - reads the IEEE488 Status Byte
-  REN_CONTROL - Remote Enable
-  GO_TO_LOCAL - local control
-  LOCAL_LOCKOUT - lock the instrument local control panel, for remote-only
 USB488 Trigger message
12-byte message, same size as bulk header; output-to-device only
MsgID    - 1 byte  - MsgID=128/0x80 for Trigger
cmd      - 3 bytes
0x00     - 8 bytes - reserved
 USB488 bulk message
a 12-byte header prepended to the USBTMC messages, both to and from the device
MsgID    - 1 byte  - message identifier
bTag     - 1 byte  - varies with each transfer
bTagInv  - 1 byte  - bTag, inverted bits, a form of checksum
0x00     - 1 byte  - reserved
size     - 4 bytes, LSB first - size of the message
flags    - 1 byte  - bmTransferAttributes, command-specific flags
0x00     - 3 bytes - reserved
...then the message itself, terminated by \n (0x0a)
...then 0x00 padding to multiple-of-4 length
End of message specified by termination with 0x0a character, and also with EOM bit in flags
 usbtmc constants
USB MsgID codes:
USBTMC_MSGID_DEV_DEP_MSG_OUT            = 1
USBTMC_MSGID_REQUEST_DEV_DEP_MSG_IN     = 2
USBTMC_MSGID_DEV_DEP_MSG_IN             = 2
USBTMC_MSGID_VENDOR_SPECIFIC_OUT        = 126
USBTMC_MSGID_REQUEST_VENDOR_SPECIFIC_IN = 127
USBTMC_MSGID_VENDOR_SPECIFIC_IN         = 127
USB488_MSGID_TRIGGER                    = 128
result status codes:
USBTMC_STATUS_SUCCESS                  = 0x01
USBTMC_STATUS_PENDING                  = 0x02
USBTMC_STATUS_FAILED                   = 0x80
USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81
USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS    = 0x82
USBTMC_STATUS_SPLIT_IN_PROGRESS        = 0x83
USB488_STATUS_INTERRUPT_IN_BUSY        = 0x20
requests:
USBTMC_REQUEST_INITIATE_ABORT_BULK_OUT     = 1
USBTMC_REQUEST_CHECK_ABORT_BULK_OUT_STATUS = 2
USBTMC_REQUEST_INITIATE_ABORT_BULK_IN      = 3
USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS  = 4
USBTMC_REQUEST_INITIATE_CLEAR              = 5
USBTMC_REQUEST_CHECK_CLEAR_STATUS          = 6
USBTMC_REQUEST_GET_CAPABILITIES            = 7
USBTMC_REQUEST_INDICATOR_PULSE             = 64
USB488 request
USB488_READ_STATUS_BYTE = 128
USB488_REN_CONTROL      = 160
USB488_GOTO_LOCAL       = 161
USB488_LOCAL_LOCKOUT    = 162
 cautions
Sometimes the device gets to a weird state after a read, and a subsequent read timeouts (timeout in usb/backend/libusb1.py, from self.bulk_in_ep.read in usbtmc/usbtmc.py).
This usually occurs after the device was closed and opened again. Rerunning the command then works again.
Many devices have quirks; Rigol scopes are common with subtle problems or protocol weirdness. Workarounds are often implemented
in drivers and libraries, which is complicated by later firmwares correcting the issue and then not working with the workaround
(eg. Rigol DS1054Z with 00.04.04.SP4 firmware, which needs self.rigol_quirk=False set in usbtmc/usbtmc.py despite setting it True from
the device type autodetection; to add a worm to the can, the firmware revision is not available in the USB data available from the port).
 SCPI (protocol)
Standard Commands for Programmable Instruments - general specification for text-based communication protocol,
based on IEEE 488.2 (1987 and 1992 flavors), a command set of IEEE-488
 - general specification for text-based communication protocol,
based on IEEE 488.2 (1987 and 1992 flavors), a command set of IEEE-488 aka HP-IB aka GPIB
 aka HP-IB aka GPIB
Simple one-line commands, hierarchical structure, ":" as hierarchy delimiter, "*" for non-hierarchical command (eg. *IDN?, "identify yourself").
Some devices remember the last "directory" in the hierarchy, others (Rigol DS1054Z, I am looking at YOU!) don't and always require full absolute "paths".
The absolute path starts with ":".
SCPI commands have to tell the instrument they are terminated. Over stream links (TCP socket, serial port, direct character device read/write...) the delimiter is \n aka 0x0a.
In packet connections (USBTMC, UDP...) the message itself can act as its delimiter. Some instruments however require the \n termination even then.
It is safer to use it even if not needed.
Other possible line termination characters/delimiters encountered are \r aka 0x0d, and \0 aka NUL aka 0x00.
In VISA, the delimiters are set by read_termination and write_termination properties of the instrument object.[ref]
The SCPI statements consist of one or more "words", separated by spaces.
The first word can be a query (ends with "?", response from the instrument is expected)
or a command (data are written to the device, operation is performed...).
The statements have optional parameters. For example:
-  :DISP:DATA? on,0,png - query screenshot, color, not inverted, in PNG format
-  *STB? - query the status byte
-  :STOP - stop the scope
-  :RUN - ...and run again
-  :WAV:STOP 50000 - set the end of the buffer memory to download to 50,000 points
The statements are case-insensitive.
The statements can have a long and short form, often written in mixed case together; DISPlay can be used as both
DISP and DISPLAY (but usually not as DISPL), both upper and lower and mixed case.
Command sets, even for the same general thing, can vary widely, even between devices from the same vendor.
Eg. for sending a screenshot: (from lxi-tools plugins)
-  Rigol 1052D/E scopes:
-      :HARDCOPY
-      :LCD:DATA? (raw 320x234 2:3:3 LCD dump, 74880 bytes)
-  Rigol 1000Z-series scopes:
-  Rigol 2000 scopes:, Rigol DM3068:
-  Rigol DG4000 scopes:
-      :HCOPy:SDUMp:DATA:FORMat BMP
-      :HCOPy:SDUMp:DATA?
-  Rigol DP800:
-  Rigol DSA:
-  Rohde-Schwarz HMO RTB:
-      HCOPy:FORMat BMP
-      HCOPy:DATA?
-  Keysight multimeter, Keysight IVX:
-      :HARDCOPY:INKSAVER OFF
-      :DISPLAY:DATA? BMP,COLOR
-  Tektronix:
-      SAVE:IMAGE:FILEFORMAT PNG
-      HARDCOPY:INKSAVER OFF
-      HARDCOPY START
-  Siglent SDG, SDM3000, SDC, SSA3000x:
Or for acquire memory depth, where DS1052D/E takes :ACQ:MEMD norm/long, and DS1054Z takes :ACQ:MDEP <number>.
Chaos inherent for many-actors system. The only worse situation would be if it'd be designed by a committee.
 examples
 *IDN?
 Rigol Technologies,DS1052D,DS1EC120100007,00.02.02.02.00
DS1052 screenshot
 :LCD:DATA?
 [raw 74880 bytes]
DS1052 screenshot, more modern firmware (?)
 :LCD:DATA?
 #9000074880[raw 74880 bytes]
DS1052 waveform buffer data
 :WAV:DATA?
 [raw 600,8192,16384,524288 or 1048576 bytes]
DS1052 screenshot, more modern firmware (?)
 :LCD:DATA?
 #9000074880[raw 74880 bytes]
DS1054Z screenshot
 :DISP:DATA? ON,0,PNG
 #90000xxxxx[raw xxxxx bytes]
DS1054Z waveform buffer data, long form; 600,000 bytes read
 :ACQ:MDEP?
 600000
 :WAV:START 1
 :WAV:STOP 250000
 :WAV:DATA?
 #9000250000[raw 250000 bytes]
 :WAV:START 250001
 :WAV:STOP 500000
 :WAV:DATA?
...and we get an error...
 ERR
...so we retry and now succeed...
 :WAV:DATA?
 #9000250000[raw 250000 bytes]
 :WAV:START 500001
 :WAV:STOP 600000
 :WAV:DATA?
 #9000100000[raw 100000 bytes]
run acquisition
 :RUN
stop acquisition
 :STOP
CAUTION: some commands work only in RUN state, others only in STOP state!
 Mandatory SCPI commands for USB488
-  *CLS - Clear Status Command - clear all event registers and error queue
-  *ESE - Standard event status enable
-  *ESE? - Standard event status enable query
-  *ESR - Standard event status register query - cleared by reading
-  *IDN? - device identification query
-  *OPC - Operation Complete command
-  *OPC? - Operation Complete query
-  *RST - Reset command
-  *SRE - Service Request Enable command
-  *SRE? - Service Request Enable query
-  *STB? - GPIB Status Byte query
-  *TRG - Trigger - if device is DT1
-  *TST? - self-test query
-  *WAI - wait-to-continue command
-  *IST? - not in USB - Individual Status query
-  *PRE - not in USB - Parallel poll enable register command
-  *PRE? - not in USB - Parallel poll enable register query
-  *PCB - not in USB - Pass Control Back command
 Optional SCPI/USB488 commands for USB488
-  *CAL? - Calibration query
-  *DDT - Define device trigger command (for DT1 devices)
-  *DDT? - Define device trigger query (for DT1 devices)
-  *PSC - Power on status clear command
-  *PSC? - Power-on status clear query
-  *PUD - Protected user data command
-  *RDT - Resource description transfer command
-  *RDT? - Resource description transfer query
Macro commands
-  *DMC - Define macro command
-  *EMC - Enable macro command
-  *EMC? - Enable macro query
-  *GMC? - Get macro contents query
-  *LMC? - Learn macro query
-  *LRN? - Learn device setup query
-  *PMC - Purge macros command
-  *RCL - Recall command
-  *RMC - Remove individual macro command
-  *SAV - Save command
-  *SDS - Save default device setting command
 binary/bulk data responses
Usually the SCPI command response is a plaintext string. Some types of data (screenshots, raw waveforms...) require a binary blob.
The responses are usually plaintext strings, with numbers as decadic, with exponential notation (eg. 4.546875e-02), and are terminated with newline (\n, 0x0a).
When the response starts with #, it has a different format:
-  #Hxxxx - hexadecimal data, newline-terminated
-  #Oxxxx - octal data, newline-terminated
-  #Bxxxx - binary data, newline-terminated
-  #<1-9>nnnnnnnn<binary> - Arbitrary Block Data, newline-terminated
The Arbitrary Block Data is composed of a header and a variable length binary blob of payload:
-  #Nnnnnnnnnn[binary data follow] (eg. #9000012345...)
-  # - initial signature of the header
-  N - number of characters in the payload length (often 9, can be other number between 1..9)
-  nnnnnnnnn - payload length, integer as zero-padded ASCII string
Presence of this header at the initial response can be used for continuous read from the source (device, port, socket...) until the payload is all received.
With direct device read from usbtmc/usb488, further binary bytes are present. These are usually stripped by the reading plugin.
The #-something binary data header can be used even with shorter binary data, eg. direct transfer of 32 or 64 bit float numbers
where the ASCII representation could lead to unwanted loss of precision.[ref]
-  #70000004<4-bytes> for 32-bit float
The responses, including the binary ones, are always followed by newline character (\n).
 nonconforming devices
Some older devices (DS1052, I am looking at YOU!) may not conform and may send the data without the header.
The read routines then do not know when to stop and have to either rely on the known data lengths (possible false positives) or on the read timeout (introduces delay).
 VISA resource name, device addresses
The VISA/VXI-11 architecture specifies strings for device addressing. The string uses double colon :: as delimiter
and is composed of:
-  interface type (mandatory - USB, TCPIP, GPIB, VXI...), with optional explicit interface number (USB0, USB1, TCPIP1...)
-  interface-type specific address (USP VID::PID, IP address with optional TCP port, host address on a bus...)
-  optional device or sub-device selection (serial number, interface number, secondary address...)
-  resource class (::INSTR, ::SOCKET, ::RAW, ::MEMACC...), default ::INSTR[ref]
The common interfaces are:[ref]
-  USB[board]::<VID>::<PID>[::<serialNumber>][::INSTR]  - connects to the first (number 0) USBTMC class device
-  eg. USB::0x1ab1::0x04ce::INSTR (Rigol DS1054Z)
-  eg. USB::0x1ab1::0x04ce::SNXXYYZZAABBCCDD::INSTR (same, with explicit serial number - for more instruments on one machine)
-  USB[board]::<VID>::<PID>[::<serialNumber>][::<interfaceNumber>::RAW ]] - raw nonclass USB-device access, 
-  eg. USB::0x0123::0x4567::SNAABBCCDD::1::RAW - second (number 1) raw USB interface on a device
-  TCPIP[board]::<host_address>[::<LAN_device_name>][::INSTR]  - uses VXI-11, needs RPC port (111); default LAN device name is inst0 (instr0??)
-  eg. TCPIP::10.1.2.3::INSTR - default (instr0) instrument on IP address (or host name)
-  eg. TCPIP::10.1.2.3::INSTR3::INSTR - INSTR3 instrument on IP address (or host name)
-  TCPIP[board]::<host_address>::<port>::SOCKET - direct socket connection, eg. SCPI-raw
-  eg. TCPIP::10.1.2.3::5025::SOCKET - direct connection to SCPI-raw port on IP address (or host name)
-  visa://<host_address>[:<port>]/remote_resource - NI-VISA remote instrument
-  eg. visa://hostname/ASRL1::INSTR - ASRL1::INSTR exposed on hostname
-  ASRL[board][::hostname][::INSTR]  - Asynchronous SeRial Line, serial port - COM1, /dev/ttyUSB0...
-  eg. ASRL::INSTR1 - COM1
-  eg. ASRL::10.1.2.3::1234::INSTR - serial-over-IP serial port, on 10.1.2.3:1234
-  eg. ASRL/dev/ttyAMA0::INSTR
Other ones, less common with cheapo instruments, are:
-  GPIB (GPIB bus)
-  PXI (chassis bus)
-  VXI (chassis bus)
 Software
For the server (usbtmc-server.py), python was chosen for flexibility and ease of coding.
For the client (liblxi/lxi-tools), C was chosen for the speed of execution (no overhead with loading megabytes of python libraries).
 Server side: usbtmc-server.py
for local Rigol DS1054Z scope, exposing SCPI-raw on default port 5025:
 python3 ./usbtmc-server.py --backend python_usbtmc USB::0x1ab1::0x04ce::INSTR
the same for Rigol DS1052D (no long-reads):
 python3 ./usbtmc-server.py --backend python_usbtmc USB::0x1ab1::0x0588::INSTR
the same for Rigol DS1052D (uses kernel-mode readouts, the reads work):
 python3 ./usbtmc-server.py --backend linux_kernel /dev/usbtmc0
Uses several different backends:
-  python_usbtmc - local, USBTMC interface (USB VID:PID); similar to VXI-11 protocol
-  linux_kernel - local, character device read (eg. /dev/usbtmc0); similar to SCPI-raw protocol
-  pyserial - local, serial port (tty or usb-serial - for old and slow devices)
-  python_vxi11 - network, connection via portmapper
-  tcp_socket - network, direct socket connection
 MODIFICATION: universal_usbtmc
The linux_kernel backend had to be modified for the long-data read for the screenshots and data.
On the first read, the beginning of the response is checked if it starts with #<digit>; if not,
do the read as before. If yes, loop through reads until the indicated payload length is read.
 FILES
-  linux_kernel.py.patch - patch for /usr/local/lib/python3.7/dist-packages/universal_usbtmc/backends/linux_kernel.py - patch for /usr/local/lib/python3.7/dist-packages/universal_usbtmc/backends/linux_kernel.py
 Further possible modifications
The python server can get a thread for listening on HTTP, for commands like screenshots, waveforms, data previews,
save/restore settings, anything else.
Another thread can read buttons or touchscreen.
The scope then will have exposed LXI interface (SCPI-raw), screenshots over HTTP, iGorNet control over MQTT, local buttons/screen control,
arbitrary protocol decoders...
 python: usbtmc
Python interface for USBTMC devices, also used by universal_usbtmc.
Handles various device quirks.
In usbtmc/usbtmc.py (eg. /usr/local/lib/python3.7/dist-packages/usbtmc/usbtmc.py), there are detections of quirks of various devices, set as flags
for workarounds in the code. Eg.
-  self.advantest_quirk - "Advantest/ADCMT devices have a very odd USBTMC implementation which requires max 63 byte reads and never signals EOI on read; may only send one read packet"
-  self.rigol_quirk - "different data flow in multiread communication; Rigol devices only send the header in the first packet, and they lie about whether the transaction is complete"
-  self.rigol_quirk_ieee_block - "transfer_size usbtmc header is lying about the transaction size"
 MODIFICATION
The self.rigol_quirk was set for the DS1054Z scope, however the 00.04.04.SP4 firmware does not need them.
The setting has to be disabled.
It is possible to modify the library to apply the quirks only for certain serial numbers of devices.
Then the software will behave even for the same devices with different firmwares.
A little more involved code can enable/disable the quirk flags based on the *IDN? response (TODO?).
 FILES
-  usbtmc.py.patch - for /usr/local/lib/python3.7/dist-packages/usbtmc/usbtmc.py - for /usr/local/lib/python3.7/dist-packages/usbtmc/usbtmc.py
 Client side: lxi, liblxi
https://lxi-tools.github.io/ 
-  liblxi - the underlying library for handling the connections
-  lxi-tools - a command for sending/receiving SCPI commands; plugins for screenshots
The lxi command connects to the remote either through VXI-11 (SunRPC over port 111, default) or directly (SCPI-raw over port 5025, option -r; in original lxi
the option applies only to SCPI commands, not to screenshots).
get identification from device "wifiscope" (in /etc/hosts), using raw interface
 lxi scpi -r -a wifiscope '*idn?'
get screenshot from device "wifiscope" using rigol-1000z plugin, using raw interface (not in stock lxi)
 lxi screenshot -r -p rigol-1000z -a raspidispw screenshot.png
get waveform data (not in stock lxi) from device "wifiscope" using rigol-1000z plugin, using raw interface (not in stock lxi)
 lxi getdata -r -p rigol-1000z -a raspidispw wav.bin
 MODIFICATIONS
The liblxi was left intact.
The lxi command of lxi-tools got patched to check the beginning of the response if it starts with #<digit>; if not,
do the read as before. If yes, it is the Arbitrary Block Data; loop through reads until the indicated payload length is read.
The screenshot plugin for Rigol 1000Z was amended with this read patch as well.
When the ABD header is not present, the data can be still retrieved using the -L option.
For scpi, the command parsing was modified to allow up to three space-separated arguments. No more need for quotes for simple commands.
Additional options:
-  -r in screenshot/getdata: The screenshot plugin got a modification to allow raw access (via port 5025 instead of via port 111 RPC).
-  getdata function to acquire waveform: The screenshot plugin was modified for handling the waveform readout. The function differs from sceenshot only by the SCPI command (:DISP:DATA? vs :WAV:DATA?).
-  -T,-F,-V,-N in scpi for human-readable output: Time/Frequency/Voltage/None: converts the scientific notation to milli/micro/kilo/mega s/Hz/V/no-units
-  -P <port> in screenshot/getdata - explicit port setting for communication (-p is used in scpi, but it is already taken here by plugin); -r defaults to 5025 but Rigol uses 5555
-  -d for debugging of the communication; data sent to/from the instrument are shown, when enabled in code the time to first response is also shown
Additional options for DS1052D/E workarounds:
-  -D in screenshot/getdata: enable DS1052 quirks (:LCD:DATA? with PNG conversion)
-  -C in screenshot: inhibit conversion of raw LCD image in 2:3:3 format to PNG
-  -L in scpi/screenshot/getdata: workaround for long reads with arbitrary binary data without # preamble, read until timeout or magic length
-  reading stops if the message is 600, 8192, 16384, 74880, 524288, or 1048576 bytes (DS1052 screen wav read, shortmem 2/1 channel, screenshot, longmem 2/1 channel)
-  -M in scpi/screenshot/getdata: with -L, allows disabling magic-legth read stops
-  the data received usually arrive with block of multiple of (MTU minus packet headers); for MTU=1500 the blocks are 1448 bytes
-  the last packet of the transaction has smaller size
-  if the (MTU-headers) gives a whole-number multiple of one of the magic sizes, premature transfer stop can occur
The communication of the options to the screenshot plugin is somewhat crude; it is done by making the options.h options structure
accessible from the plugin.
TODO:
-  option for specifying max read length for -L
 FILES
Patches again lxi-1.21
Rigol DS1054Z notes
 
 LAN interface
 ports
-  80 - internal webserver, basic configuration, no real features
-  111 - SunRPC (TCP/UDP), portmapper for VXI-11 communication
-  5555 - SCPI-raw (why not 5025?)
 network configuration, mDNS enable (fail)
-  web interface on HTTP port 80
-  card "Network Settings"
-  requires password
-  username blank, password "111111" (works here, other reported username is "rigollan")
-  enable mDNS, click "apply"...
-  ...and the user interface freezes, the IP can't be pinged anymore, the usb requests fail too; probably the controller seizes. (maybe that's why it's passworded?)
-  won't be fooled with more, as the usb-over-wifi is intended for operations on wireless networks; the wifi interface requires a standalone computer (Raspi Zero W?) which can as well run mDNS
 LXI vs USBTMC
-  when USB is connected in USBTMC mode, it takes precedence and LXI via the ethernet port is unavailable
-  when USB is connected in PtP mode, LXI is available (todo: actually check, get scope lsusb in ptp mode)
-  when USB is disconnected, LXI can operate
-  mere connection of the USB cable to the host computer is sufficient for the scope to claim the USBTMC and disable LXI
 discovery
lxi discover
Searching for LXI devices - please wait...
Broadcasting on interface lo
Broadcasting on interface eth0
  Found "RIGOL TECHNOLOGIES,DS1104Z,DS1ZA210400549,00.04.04.SP4" on address 10.0.0.116
Found 1 device
The master sends a UDP broadcast request to port 111, with a fixed discovery payload.
static char rpc_GETPORT_msg[] =
    0x00, 0x00, 0x00, 0x02, 0x00, 0x00,[0x00, 0x03,] 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, [0x00, 0x06, 0x07, 0xaf,]0x00, 0x00, 0x00, 0x01,
    0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00  };
0x0003 is the GET_PORT RPC call, 0x000607af is the VXI-core channel
Present slaves respond with another UDP packet from their port 111. Master then initiates the "standard"
RPC-mediated VXI-11 "*IDN?" request.
 network communication, detailed
 DISCOVERY, network segment broadcast
 UDP: computer:45106 -> broadcast:111
    RPC call: RPCv2, program Portmap (100000) v2, procedyre GETPORT (3)
      portmap v2: procedure GETPORT (3), program VXI-11 Core (395183) version 1, proto TCP (6), port 0
 UDP: scope:111 -> computer:45106
   RPC reply: program Portmap (100000) version 2, procedure GETPORT (3), state=accepted
     portmap v2: GETPORT (3) reply, port=618
 RPC PORTMAP QUERY
  TCP: computer:58770 -> scope:111 OPENING
  TCP: computer:58770 -> scope:111
    RPC call: RPCv2, program Portmap (100000) v2, procedure GETPORT (3)
      portmap v2: procedure GETPORT (3), program VXI-11 Core (395183) version 1, proto TCP (6), port 0
 TCP: scope:111 -> computer:58770
   RPC reply: program Portmap (100000) version 2, procedure GETPORT (3), state=accepted
     portmap v2: GETPORT (3) reply, port=618
  TCP: computer:58770 -> scope:111 : CLOSING
 VXI-11 call
  TCP: computer:791 -> scope:618 : OPENING
  TCP: computer:791 -> scope:618
    RPC call: RPCv2, program VXI-11 Core (395183) v1, procedure CREATE_LINK (10)
      VXI-11 Core Protocol (Create_LinkParms) inst0: procedure CREATE_LINK (10), device name inst0
 TCP: scope:618 -> computer:791
   RPC reply: program VXI-11 Core (395183) v1, procedure CREATE_LINK (10), state=accepted, AcceptState=RPC executed successfully (0)
     VXI-11 Core Protocol (Create_LinkResp) No Error LID=0: error code=no error, abort port=619, max receive size=1500
  TCP: computer:791 -> scope:618
    RPC call: RPCv2, program VXI-11 Core (395183) v1, procedure DEVICE_WRITE (11)
      VXI-11 Core Protocol (Device_WriteParms) LID=0: I/O Timeout=1000, lock timeout=0, flags=0x09 (Wait Until Locked, Set EOI), payload length=6, payload=*IDN?\a
 TCP: scope:618 -> computer:791
   RPC reply: program VXI-11 Core (395183) v1, procedure DEVICE_WRITE (11), ReplyState=accepted, AcceptState=RPC executed successfully (0)
     VXI-11 Core Protocol (Device_WriteResp) No Error: Error Code: no error, size=6
  TCP: computer:791 -> scope:618
    RPC call: RPCv2, program VXI-11 Core (395183) v1, procedure DEVICE_READ (12)
      VXI-11 Core Protocol (Device_ReadParms) LID=0: procedure DEVICE_READ (12), link id=0, size=65536, I/O Timeout=1000, lock timeout=0, flags=0x00, termination char=0x00
 TCP: scope:618 -> computer:791
   RPC reply: program VXI-11 Core (395183) v1, procedure DEVICE_READ (12)], ReplyState=accepted, AcceptState=RPC executed successfully (0)
     VXI-11 Core Protocol (Device_ReadResp) No Error: Error Code: No Error (0), reason=0x04 (END, EOI=true), payload length=55, payload=RIGOL TECHNOLOGIES,DS1104Z,DS1ZA210400549,00.04.04.SP4
  TCP: computer:791 -> scope:618
    RPC call: RPCv2, program VXI-11 Core (395183) v1, procedure DESTROY_LINK (23)
      VXI-11 Core Protocol (Device_Link) LID=0: procedure DESTROY_LINK (23), link id=0
 TCP: scope:618 -> computer:791
   RPC reply: program VXI-11 Core (395183) v1, procedure DESTROY_LINK (23), ReplyState=accepted, AcceptState=RPC executed successfully (0)
     VXI-11 Core Protocol (Device_Error) No Error: procedure DESTROY_LINK (23), error code=No Error (0)
  TCP: computer:791 -> scope:618 : CLOSE
 RPC
rpcinfo scope
  program version netid     address                service    owner
    395185    1    tcp       0.0.0.0.2.107          -          unknown
    395183    1    tcp       0.0.0.0.2.106          -          unknown
    395184    1    tcp       0.0.0.0.2.105          -          unknown
    100000    2    tcp       0.0.0.0.0.111          portmapper unknown
    100000    2    udp       0.0.0.0.0.111          portmapper unknown
 rpcinfo scope -p
  program vers proto   port  service
    395185    1   tcp    619
    395183    1   tcp    618
    395184    1   tcp    617
    100000    2   tcp    111  portmapper
    100000    2   udp    111  portmapper
nmap for 
PORT     STATE SERVICE
80/tcp   open          http
111/tcp  open          rpcbind
111/udp  open          rpcbind
617/tcp  open          sco-dtmgr      // RPC-assigned VXI-11 channel, abort
618/tcp  open          dei-icda       // RPC-assigned VXI-11 channel, core
619/tcp  open          compaq-evm     // RPC-assigned VXI-11 channel, interrupt
5353/udp open|filtered zeroconf       // mDNS, but doesn't seem to work
5555/tcp open          freeciv        // Rigol-flavor scpi-raw
6000/udp open|filtered X11
 PTP/PictBridge mode (failure?)
Picture Transfer Protocol 
The USB interface can be selected to either USBTMC or PTP mode.
gphoto2 --auto-detect
Model                          Port
----------------------------------------------------------
USB PTP Class Camera           usb:001,018
...but gphoto is failing to access the camera, some critical function is apparently not supported by the scope.
Let's try ptpcam from libusb:[ref]...
-  get libptp , unpack to somewhere in /usr/src , unpack to somewhere in /usr/src
-  apt-get install libusb-dev (configure would cry about libusb-config)
-  ./configure (and fill in more missing libraries if needed)
-  make (it'll spit some compiler warnings)
-  make install
-  ldconfig (otherwise ptpcam would complain with "ptpcam: error while loading shared libraries: libptp2.so.1: cannot open shared object file: No such file or directory")
...but ptpcam fails with, drumroll please...
 ERROR: Could not get device info!
The ptp_getdeviceinfo call, a PTP_OC_GetDeviceInfo ptp request, does not get through.
The screenshots can be already acquired via LXI or USBTMC, so this is a minor concern.
Apparently the PictBridge thing acts as a client that connects to a server (usually a printer) and sends data to print. The server-side software, which establishes
connection with the PictBridge device (a camera, or here the scope), was too difficult to locate.
 Windows 10
The scope becomes visible on USB connection in "Devices and Printers" under "Unspecified" section as "DS1000Z Series". (Driver installation can take a couple minutes.)
In Device Manager, the scope is seen under "Portable devices" as "MTP USB device". Generic WpdMtp driver is apparently used.
In TMC mode, it shows in Device Manager as "USB Test and Measurement Device (IVI)".
 network and web interface
       Instrument Model:    DS1104Z
           Manufacturer:    RIGOL TECHNOLOGIES
          Serial Number:    DS1ZA210400549
            Description:
              LXI Class:    LXI Core 2011
            LXI Version:    1.4
              Host Name:
            MAC Address:    00-19-AF-xx-xx-xx
             IP Address:    10.0.0.116
      Firmware Revision:    00.04.04.SP4
     VISA TCP/IP String:    TCPIP::10.0.0.116::INSTR
      Auto-MDIX Capable:    NO
VISA USB Connect String:    USB0::0x1AB1::0x4CE::DS1ZA210400549::INSTR
Network Hardware Configuration
                           Status:    CONFIGURED
                         Password:    Not Specified
Link Speed And Duplex Negotiation:    Automatic
                       Link Speed:    100 Mbps
                           Duplex:    Full Automatic
 LXI speed
 speed, LAN/LXI
direct connection to the network, using ethernet cable and socket on the scope
faster response time than USBTMC/wifi, but lower bulk transfer speed
-  almost 3 times faster roundtrip for IDN query
-  almost 1/3 slower bulk data transfer for big chunks
-  better for 
LXI benchmark: 100 ID requests, 154.3 requests/second
action                 bytes      response        total
ident                     56        0.001       0.02..0.05
screenshot/bmp       1152054      1.67..1.78    1.88..2.00
screenshot/png        ~88000      0.05..0.08    0.77..0.81
live data read          1200      0.02..0.05    0.04..0.07
mem read                8192        0.005       0.06..0.11
mem read               16384        0.008       0.07..0.12
mem read              125000      0.34..0.51    0.39..0.65
mem read              250000      0.32..0.67    0.67..0.80     max length of read at once, need to partition to pieces
mem read calculated   524288         ~0.9          ~1.4
mem read calculated  1048576         ~1.8          ~2.8
mem read calculated      12M        ~20.2         ~32.2
mem read calculated      24M        ~40.3         ~64.3
 speed, wifi/python/USBTMC
connected over USBTMC to raspi3, with wifi link over python server as above
LXI benchmark: 100 ID requests, 57.5 requests/second
action                 bytes      response        total
ident                     56      0.02..0.03    0.04..0.05
screenshot/bmp       1152054      0.97..1.16    1.50..1.64
screenshot/png        ~32000      0.53..0.55    0.57..0.60
live data read          1200      0.02..0.05    0.04..0.07
mem read                8192      0.03..0.04    0.05..0.06
mem read               16384      0.03..0.04    0.06..0.08
mem read              125000      0.22..0.24    0.30..0.34
mem read              250000      0.43..0.44    0.55..0.60     max length of read at once, need to partition to pieces
mem read calculated   524288         ~0.9          ~1.1
mem read calculated  1048576         ~1.8          ~2.2
mem read calculated      12M        ~20.2         ~25.0
mem read calculated      24M        ~40.3         ~49.9
 SCPI commands
 data acquisition
 screenshot
:DISP:DATA? [<color:on/off>,<invert:1/0>,<format:bmp24/bmp8/png/jpeg/tiff>] 
-  color = on|off
-  invert = 1|0
-  format = bmp24|bmp8|png|jpeg|tiff (default bmp24)
-  common: :DISP:DATA? ON,0,PNG
settings:
-  :DISP:TYPE VECT
-  :DISP:TYPE DOTS
 waveform
-  :ACQ:MDEP <memory> - memory depth for a single channel
allowed values (without the commas):
single channel  AUTO  12,000  120,000  1,200,000  12,000,000  24,000,000
two channels    AUTO   6,000   60,000    600,000   6,000,000  12,000,000
four channels   AUTO   3,000   30,000    300,000   3,000,000   6,000,000
Do the change in :RUN mode or the scope will ignore the command. (todo: check)
-  :ACQ:TYPE <norm/aver/peak/hres>
-  norm - evenly spaced samples
-  aver - averaging waveform from multiple samples (:ACQ:AVER)
-  peak - shows peak values for the signal envelope; sees tiny pulses but also gets more noise
-  hres - high resolution, higher samplerate in converter than for memory, oversampling/averaging
-  :ACQ:SRATE? - query current samplerate
-  :WAV:SOUR <d0..d15/chan1..chan4/math - waveform source
-  :WAV:MODE <norm/max/raw>
-  norm - gives data shown on screen (only one that works for MATH)
-  max - data on screen when running, memory when stopped
-  raw - data from memory (works only when stopped)
-  :WAV:FORM <byte/word/asc> - word has MSB=0, ascii takes too much space
-  :WAV:START <n> - memory window beginning, first=1
-  :WAV:STOP <n> - memory window end
-  :WAV:DATA? - read the memory window
-  window MUST be at most 250,000 bytes (125,000 words, 15,625 characters)
-  iterate through larger windows
 Rigol DS1052D notes
 
Compared to 1054, 1052 is much older and weaker. The most basic SCPI functionality is present; a lot of controls can be done.
The screenshots aren't normally working. The :DISP:DATA? command is not present.
It is however possible to get the raw framebuffer data as a constant-size 320x234 ".raw" image, with 8 bits per pixel, with colors packed
in RR-GGG-BBB scheme (MSB to LSB). Use :HARDCOPY and then :LCD:DATA?.
The firmware revision 00.02.02.02.00 of course does not start the bulk transfers with the #number-length preamble
so read until timeout is needed. Dislike.
The long read from memory seems to be failing with python_usbtmc backend (and works with modified linux_kernel backend).
:ACQ:MEMD LONG/NORMAL works only after next run/stop cycle; :WAV:DATA? done after acq:memd give the length when the memory was acquired.
The scope also has a RS232 port. Its speed is between 9600 and 38400 bps (selectable in menu). While a bit too slow (estimated 20 seconds for a screenshot,
4.5 seconds for 16k memory, and over 4.5 minutes for the megabyte of samples), it is still good enough for using the scope with an arduino.
An "emergency" wireless connection could be made with ESP8266 and serial-to-tcp RFC2177 interface.
 speed, wifi/python/USBTMC
Caution: the long memory reads take quite some time, up to 25 seconds for the entire megabyte. This may appear as a timeout to the unwary.
Rough timing of reads, response time (between issuing command and starting receiving data) and total command running time
(against raspi running usbtmc-server.py, over wifi with ping time between 5..12 msec):
LXI benchmark: 100 ID requests, ~22.5 requests/second
action                 bytes      response        total
screenshot             74880      1.74-1.77     1.81-1.96     (raw, without compression)
live data read           600      0.03-0.04     0.05-0.06
mem read, 2ch           8192      0.19-0.21     0.21-0.23
mem read, 1ch          16384      0.41-0.43     0.43-0.46
longmem read, 2ch     524288      11.9-12.3     12.1-12.5
longmem read, 1ch    1048576      24.4-24.8     24.9-25.9
 SCPI commands
 data acquisition
 screenshot
:hardcopy (is it necessary?)
:LCD:DATA? (returns 74880 bytes of raw LCD image, 320x234, 8bpp RGB 2:3:3)
Patched LXI can do the conversion to PNG on demand.
TODO: server-side (usbtmc-server.py) emulation of :DISP:DATA? with PNG conversion
 waveform
-  :ACQ:MEMD <norm/long> - memory depth for a single channel
 NORM        LONGsingle channel    16384     1048576       (0.2/12.5 seconds read)
two channels       8192      524288       (0.4/25.5 seconds read)
-  :ACQ:TYPE <norm/aver/peak>
-  :ACQ:AVER <num> - average over samples; can be 2,4,8,16,32,64,128,256
-  :ACQ:MODE <rtim/etim> - realtime vs equal time
-  :ACQ:SAMP? - get current samplerate
-  :WAV:DATA? - get the whole waveform in memory - 600 if running, 8192/16384 if NORMAL mem, 524288/1048576 if LONGMEM
-  :WAV:POIN:MODE <norm/max/raw> - memory retrieval
-  NORM - screen-only length, 600 bytes; in :RUN and :STOP modes
-  RAW - full NORM or LONG memory length; in :STOP mode only
-  MAX - gives NORM in :RUN mode, RAW in :STOP mode
The :acq:memd setting reflects to the amount of data read by :wav:data? only after the scope was run, triggered, and stopped.
Other useful commands:
-  :KEY:LOCK <enab/dis> - lock/unlock the front panel
-  :TRIG:STAT? - trigger status - RUN/STOP/T'D/WAIT/AUTO
-  :AUTO - autoguess setting for current input
Conversions and simulations
The LXI/SCPI infrastructure allows very simple interfacing of instrumentation.
E.g. a simple python server can listen on messages from MQTT with data, cache the last one, and serve it on a request.
(Or look up the last value from a log. Or whatever.)
A meteo station then can be implemented as a ESP8266 sensor with periodic MQTT feed, and the measurement can be made
available via eg. ":MEAS:OUTTEMP?" query from standard LabView/MatLab/anything with VISA libraries.
Such "virtual instruments" ("simstruments"?) can be also made visible on the LAN easily via mDNS.
 time synchronization
 PTP, IEEE 1588 Precision Time Protocol
(do not confuse with Picture Transfer Protocol)
PTP , IEEE 1588, is a tool for time synchronization between devices on a LAN,
similar to but more accurate than NTP
, IEEE 1588, is a tool for time synchronization between devices on a LAN,
similar to but more accurate than NTP and alternative to GPS sync (not needing the receiver
at each node, not needing GPS signal reception).
 and alternative to GPS sync (not needing the receiver
at each node, not needing GPS signal reception).
In linux, it is available as the linuxptp package, with ptp4l command. Uses timemaster to run PTP with NTP
as reference clocks (PTP for precision sync of relative time, NTP for less accurate absolute time).
https://www.nwtime.org/projects/linuxptp/ 
 GPS as alternative
GPS is commonly used to synchronize time of machines. The receivers provide absolute time usually in NMEA-formatted strings
over a serial line, and precision-edge pulse-per-second sync as a separate digital signal. (Take good care about the line
impedance and other transmission line
 sync as a separate digital signal. (Take good care about the line
impedance and other transmission line factors when handling this signal; if the edge has to have properly short rise time, the line must not
attenuate even very high frequencies.)
 factors when handling this signal; if the edge has to have properly short rise time, the line must not
attenuate even very high frequencies.)
On unix/linux computers, the signal is usually connected to the DCD input of the serial port, as by RFC2783 and
https://www.kernel.org/doc/Documentation/pps/pps.txt
 input of the serial port, as by RFC2783 and
https://www.kernel.org/doc/Documentation/pps/pps.txt .
.
This PPS sync can be leveraged even without GPS (or the GPS can be simulated completely including the time-bearing NMEA sentences,
using a shared single-Tx-to-many-Rx bus). A master clock can send the PPS (with or without the NMEA), the slaves then take the data as if it was
a real GPS receiver.
 USB-serial
USB-serial is polling-based. The interface is queried many times per second. This introduces a possibly significant jitter (up to 125 microseconds
on USB2, much more on USB1).
 Raspberry Pi
http://www.unixwiz.net/techtips/raspberry-pi3-gps-time.html 
 wireless options
The same could be possibly implemented locally via microcontroller-and-nRF24L01 combination. The packets can be delivered one-to-many, the delays
are the same (if retransmissions are disabled, which in one-to-many they have to be anyway as the delivery confirmation would only throw in chaos),
missing a couple packets doesn't throw the local clock off significantly, and it's cheap.
Any other packet radio with low and constant latency will do the job too. Raw pulse-per-second can be sent via a very simple radio too,
with caveats for the rf noise.
For distributed dataloggers, log also some metadata with the timing quality - absent or spurious sync pulses may then help explain
discrepancies in stored data, allow to reliably know the timestamps are unreliable.
Optical methods are also possible, whether free-space or fiber-guided.
 triggers
For very high precision, a good shared wire can do the job. Same principle as for the PPS syncing, but missing pulses can be highly
detrimental for the equipment-group operation.
For pulse-based or command-based triggering over wireless, be wary of jitters and especially of missing packets. Wireless, especially 2.4 GHz in urban areas,
can get clogged fairly randomly - usually just the millisecond before DAQ for an unrepeatable test has to be started.
For lower precision, shared-sync clock can do, with a clock offset to trigger at. The offsets then can be unicasted or repeatedly broadcasted
to each equipment piece in advance, with assured delivery of at least one command to each device.
See also
Todo
-  USBTMC-to-SCPIraw server
-  add mDNS server
-  add HTTP screenshot
-  add (or make separate) touchscreen daemon
-  add VXI-11 support
-  RPC support
-  encapsulation of in/out messages
-  LXI-tools
-  options for more advanced waveform saving
-  saving to multichannel .WAV file
-  retrieval of bulk configurations, together with waveforms or standalone
-  auto filenames
-  DS1052 extensions as #ifdef
| If you have any comments or questions about the topic, please let me know here: |