CH1How ThunderScope does it
We read ThunderScope's gateware, its driver, its TS.NET server and ngscopeclient's driver for it, end to end.
- The FPGA does almost nothing. The ADC stream goes straight into the PC's memory by PCIe DMA, over a link faster than the ADC. The trigger is a single enable bit; every trigger decision is made in software on the PC.
- The server pushes. The client sends one byte, and from then on the server sends each waveform as it is ready, with up to five unacknowledged in flight. Each waveform carries its own scale, offset and timing.
- The client acknowledges before it reads. The driver acks a waveform on its header, before the samples, so the window stays full. It sends nothing per waveform: no arm, no status poll, no data request.
- The capture never waits for the client. A slow client gets fewer waveforms; the acquisition does not slow down.
One more thing in ngscopeclient matters: it processes one waveform per drawn frame, for every driver. On our PC that is about 64 a second. So what makes ThunderScope fast in ngscopeclient is how many points each waveform carries, and how little time each one costs on the wire.
CH2Why asking for each waveform tops out
ngscopeclient's Rigol driver asks for every waveform: arm a single capture, poll until it has triggered, then for each channel ask for its scale and its samples. Release 69 made each of those answers as fast as we could, and with one channel the Rigol driver now reaches the app's frame limit too. With four channels it still makes four rounds of requests per waveform, so it shows about half the frame rate.
CH3What NovaOS does now
NovaOS answers ngscopeclient's ThunderScope driver on ports 5025 and 5026, with TS.NET's commands and its push protocol byte for byte. Behind it, nothing is like ThunderScope's:
- The trigger stays in the FPGA. The scope runs normally, triggering in hardware, and the acquisition engine already puts every batch of waveforms in shared memory for the screen. When the client has a credit free, NovaOS sends the newest waveform from there. Nothing extra is read from the FPGA, and nothing is asked of the engine per waveform.
- Nothing waits on the network. A slow PC gets the newest waveform when it is ready for one; the scope's own screen and waveform rate do not change.
- Every waveform is labelled by the capture it came from: its volts per code, offset, sample interval, channels and trigger position. A setting changed while a waveform is in flight cannot mis-scale it.
- The commands map to the scope's own settings: channel range, offset, coupling, 50 Ω on the MHO900, the bandwidth limits the unit has, the edge trigger, sample rate and length. A requested rate and length become the time base and memory depth that give them.
CH4Measured in ngscopeclient 0.3
Release 69 on our own DHO924S and MHO934, the same Windows PC and the built-in 100 Mb/s network port, waveforms a second as the app counted them:
| Setup | DHO924S, Rigol driver | DHO924S, ThunderScope driver | MHO934, Rigol driver | MHO934, ThunderScope driver |
|---|---|---|---|---|
| 1 channel, 10 kpts | 63.4 | 64.0 | 59.8 | 64.0 |
| 4 channels, 10 kpts | 31.8 | 64.0 | 31.5 | 64.0 |
| 1 channel, 1 Mpts | 4.8 | 5.9 | 4.8 | 5.9 |
64 a second is the app's frame limit: every waveform took one drawn frame. 5.9 a second at 1 Mpts is 11.8 MB/s, the network port's own limit. The scope sent as many waveforms as the app read, so none were made and thrown away.
How to connect
In ngscopeclient, add an oscilloscope with driver thunderscope, transport twinlan and the path <scope address>:5025:5026, or start it with:
ngscopeclient scope:thunderscope:twinlan:192.168.1.50:5025:5026
The Rigol driver keeps working as before, on scope:rigol:lan:<scope address>:5555. Both ports answer on the network and on the USB link, the same as SCPI.
Limits of borrowing a driver
- ngscopeclient calls the scope a ThunderScope, with ThunderScope's four channels and bandwidth list; NovaOS takes the nearest band the scope has. Only edge triggers.
- On connecting, the driver sets every channel to a 5 V range and 0 V offset, and the trigger to CH1 at 0 V, without reading the scope's settings first. Set the trigger again in the app if your signal is elsewhere.
- Each waveform is what the screen shows, up to 1 Mpts a channel. The full memory depth beyond the screen still comes through the Rigol driver.
- No gapless streaming. ThunderScope can stream every sample because its link is faster than its ADC. These scopes' ADCs make about 1.9 GB/s, and the network port carries about 0.5 % of that, so NovaOS sends triggered waveforms.
A driver of NovaOS's own for ngscopeclient now runs on our DHO924S and MHO934. It uses the same push at the same speed, 64 waveforms a second with four channels, and reads the scope's own channels, ranges, couplings and triggers when it connects instead of setting them.
Measured on our own DHO924S and MHO934 in October 2026. Thanks to the ThunderScope and ngscopeclient projects for open designs worth learning from, and to Hydron, who asked for faster waveform download.