Skip to content

v1.6.0

Choose a tag to compare

@tylerkron tylerkron released this 16 Aug 17:40
· 129 commits to main since this release
e59e307

Verified end-to-end against a DAQiFi Nyquist Nq1 (firmware 3.7.2) over USB: serial discovery, connect + populated init, 100 Hz streaming with live acquisition statistics, mid-stream diagnostics, PWM/digital interlock, SD card list/storage/record/download/parse, and LAN chip info all pass. Full unit suite green (7,171 tests) on net9.0 and net10.0.

Highlights

  • Analog outputs are real channels you can see and write — a device's DACs now show up in Channels alongside its inputs, with their voltage range, resolution, and last-commanded value, instead of being a write-only command you had to know the syntax for. Writes are range-checked against what the device itself reported before anything reaches the wire, and a stage/latch pair lets several outputs change together. An MCP agent can drive them too, not just read them. Analog output is NQ3 hardware; Supports(DeviceFeature.AnalogOutput) tells you whether the board in front of you has it. (#526, #546)
  • "Am I actually getting the sample rate I asked for?"AcquisitionStatistics answers that question from the samples themselves: measured rate, per-channel counts and value ranges, sample-interval spread, out-of-order counts, and how far behind the device's own clock the host is running. On our bench Nyquist it immediately surfaced that firmware 3.7.2 streams at 79.6% of the requested rate — the kind of thing that used to require hand-rolled instrumentation. (#518)
  • A short SD download is now a failed download — a transfer that ended early used to be handed back as if it were the whole file, so a truncated log looked like a complete one. Core now checks the size it received against the size the device promised and raises a clear error instead. An SD download also takes exclusive ownership of the device for its duration, so a command issued on another thread can no longer interleave and corrupt the file. (#540, #506)
  • The per-configuration sample-rate cap moved into Core — the ceiling a given channel selection can actually sustain was previously computed in the MCP server alone, leaving the desktop app and every other consumer without it. Every consumer now gets the same answer from one place. (#513)

Features

  • An MCP agent can read a measurement and read back what it recorded to the SD card, not just configure the device. (#524, #511)
  • Channels say what a reading means, not just what it measures — unit and scaling metadata travel with the channel. (#523)

Firmware & device behavior

  • Three log-related commands stalled for a full 3 seconds each waiting for a reply the device had already sent; they now return as soon as the answer arrives. (#542)
  • Reading diagnostic counters mid-stream reported a silently incomplete answer as a complete one — it now raises rather than under-reporting. (#541)
  • Digital writes are blocked while PWM is driving that channel, instead of being silently ignored by the firmware. (#473)
  • An idle connected device no longer burns CPU every second. (#514)

Fixes

  • A live await foreach over samples now ends when the device does, instead of hanging forever. A clean disconnect ends the loop normally; an unplug or lost link throws, so an acquisition cut short can't be mistaken for one that finished. (#507)
  • The synchronous Connect() helpers no longer freeze a UI thread. (#508)
  • Send() racing a disconnect fails with a typed error instead of a NullReferenceException. (#503)
  • A throwing StatusChanged subscriber no longer kills auto-reconnect or leaks the port handle. (#504)
  • The backlog of sends parked during a long exclusive operation is now capped. (#505)
  • discover_devices no longer gives up on a device that just needed a moment — the MCP timeout floor went from 250 ms to 1 s. (#475)

Performance

  • Parsing an SD log no longer loads the whole file into memory first. (#520)
  • Streaming stopped rebuilding the channel map and copying the buffer on every frame. (#512)
  • Serial discovery no longer spends half its time waiting on its own reader thread, and discover_devices starts both transports at once instead of waiting one out. (#509, #510)

Internal

  • DaqifiStreamingDevice continues splitting into focused collaborators — the text-exchange engine is now its own type, and the file gives up the operation lock and its send backlog. (part of #344#479, #530)
  • BootloaderSessionDevice moved into Core so it owns the bootloader stand-in, and the bootloader's duplicated wire constants were single-sourced. (#478, #519)
  • The DaqifiStreamingDevice downcast is gone from the device surface. (#476)
  • One connected-guard replaces fifty copies of it. (#521)
  • New test coverage for the MCP tool layer against an attached device, the PIC32 bootloader exchanges, the SD card text protocol, the WiFi updater's edge cases, and Linux serial-port identification. (#525, #527, #528, #522, #529)

Full Changelog: v1.5.0...v1.6.0