Skip to content

Fill tx buffer incrementally to avoid packet loss - #19

Open
jcedergr wants to merge 1 commit into
dotcypress:mainfrom
jcedergr:pr/incremental-drain
Open

Fill tx buffer incrementally to avoid packet loss#19
jcedergr wants to merge 1 commit into
dotcypress:mainfrom
jcedergr:pr/incremental-drain

Conversation

@jcedergr

Copy link
Copy Markdown

The upstream USB buffer is not guaranteed to be emptied by the host faster than the uLA device writes to it while draining. This can cause packet loss, corrupting the data received by the host.

Instead of filling the TX buffer all at once and hoping it drains in time, refill it incrementally: once when the DMA transfer completes, and again on every subsequent USB interrupt, until all sample data has been sent.

This packet loss explains the strange artifacts seen in #8 and #12. If any odd number of packets are dropped in a row, the interpreted data by sigrok gets shifted by 8 channels. E.g. channel 5 is observed at channel 13 as seen in #12. This is since the in-memory representation of 16 channels is 2 bytes (1 bit/channel), which sigrok expects in-order on the wire.

The packet loss can easily be observed when capturing through sigrok-cli, since prints a warning to stdout when the requested amount of samples differ from the received amount of samples. This is in contrast to Pulseview which does not indicate any errors.

An example capture before this fix:

$ sigrok-cli -d ols:conn=$ULA_DEVICE \
   -o /dev/null \
   --config samplerate=100m \
   --samples 10000

Device only sent 3024 samples.

Verified on the following system:

$ hostnamectl | grep "Operating System\|Kernel\|Architecture"
Operating System: Ubuntu 24.04.4 LTS
          Kernel: Linux 6.8.0-138-generic
    Architecture: x86-64

$ sigrok-cli --version
sigrok-cli 0.7.2

Libraries and features:
- libsigrok 0.5.2/5:1:1 (rt: 0.5.2/5:1:1).
 - Libs:
  - glib 2.80.0 (rt: 2.80.0/8000:0)
  - libzip 1.7.3
  - libserialport 0.1.1/1:0:1 (rt: 0.1.1/1:0:1)
  - libusb-1.0 1.0.27.11882 API 0x0100010a
  - hidapi 0.14.0
  - bluez 5.72
  - libftdi 1.5
  - Host: x86_64-pc-linux-gnu, little-endian.
  - SCPI backends: TCP, serial, USBTMC.
- libsigrokdecode 0.5.3/6:1:2 (rt: 0.5.3/6:1:2).
 - Libs:
  - glib 2.80.0 (rt: 2.80.0/8000:0)
  - Python 3.12.2 / 0x30c02f0 (API 1013, ABI 3)
  - Host: x86_64-pc-linux-gnu, little-endian.

The upstream USB buffer is not guaranteed to be emptied by the host
faster than the uLA device writes to it while draining. This can cause
packet loss, corrupting the data received by the host.

Instead of filling the TX buffer all at once and hoping it drains in
time, refill it incrementally: once when the DMA transfer completes, and
again on every subsequent USB interrupt, until all sample data has been
sent.
@jcedergr
jcedergr marked this pull request as ready for review August 25, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant