π 1.0.0
This release marks the 1.0.0 milestone for Daqifi.Core. The public API is now stable under semantic versioning β breaking changes will bump the major version. The library supports DAQiFi firmware v3.5.0+ (per ADR 0001), and it is the foundation the DAQiFi desktop application is migrating onto.
What's new
π Decoded per-frame sample pipeline (#279)
Core now decodes each live stream-data frame into per-channel samples and raises IChannel.SampleReceived, instead of only re-raising the raw DaqifiOutMessage. Consumers no longer have to hand-demux frames β channel ordering, calibration scaling, digital bit-unpacking, and rollover-aware timestamps all live in Core. Closes #242.
- USB pre-scaled floats (
AnalogInDataFloat) are used directly; WiFi raw ADC counts (AnalogInData) are scaled per channel viaIAnalogChannel.GetScaledValue. Digital bytes are bit-unpacked to per-channel high/low for input-direction channels. - New public API:
IDataSample.RawValue(raw ADC count,nullon the float path),IDataSample.DeviceTimestamp(raw device tick of the frame),SampleReceivedEventArgs.Channel, and anIChannel.SetActiveSample(IDataSample)overload. - Existing
MessageReceivedconsumers are unchanged β the raw re-raise still fires first. Decoding runs only whileIsStreamingand is best-effort per frame, so a malformed frame can't tear down the stream.
Validated end-to-end on a real Nyquist 1 over USB serial, exercising the calibration-scaling path with monotonic frame-aligned device timestamps.
π Digital output, first-class (#280)
Digital output (SetDioDirection / SetDioValue) existed in Core but was undocumented, unexposed over MCP, and unverified on hardware. It's now a first-class, hardware-validated capability β including a stream decode fix: digital stream bits are now indexed by channel number (bit N is pin N, matching how the firmware snapshots the whole DIO port), instead of by position in the enabled-channel list. Previously, enabling a subset of digital channels read the wrong pins β e.g. enabling only DIO 4 read pin 0's state.
- New MCP tools:
configure_digital_channels,set_digital_direction, andset_digital_output(auto-switches an input channel to output so one call drives a pin).list_channelsnow reportsOutputValuefor digital channels;get_device_statusreportsEnabledDigitalChannels. - Docs: README capability row + digital-output recipe; MCP tool table in
src/Daqifi.Mcp/README.md.
Validated on a Nyquist 1 over USB with physical loopbacks β raw SCPI and Core end-to-end, including streaming a strict subset of digital channels (the exact scenario the old positional decode fails).
β‘ PWM output (#281)
Adds PWM output as a first-class, hardware-validated capability, building on #280.
- Device API:
SetPwmEnabled(channel, bool)andSetPwmDutyCycle(channel, 1β100)are per channel;SetPwmFrequency(6β50,000 Hz)is device-wide, because all PWM channels share one hardware timer β a per-channel frequency API would mislead.IDigitalChannelgainsIsPwmCapable(populated from the firmware board mask β channels 0, 3, 4, 5, 6, 7), plusIsPwmEnabled/PwmDutyCyclePercentbookkeeping that survives status refresh. - Client-side guardrails for confirmed firmware traps: enabling PWM on a non-capable channel throws (the firmware would otherwise freeze digital writes on that channel with disable as the only recovery β so disable is accepted on any channel), duty 0 is rejected (firmware readback would claim 0 while the old duty keeps toggling), and frequency is limited to 6β50,000 Hz (below 6 Hz the firmware's period register silently wraps).
- New MCP tools:
set_pwm_output(duty + optional device-wide frequency + enable in one call) anddisable_pwm.list_channelsnow reportsPwmCapable/PwmEnabled.
Validated on a Nyquist 1 over USB: commanded duty and frequency measured through a physically wired loopback from streamed samples (exactly 40 rising edges in 4 s at 10 Hz), including a live duty change and disable β drive-low handback.
Full Changelog: v0.28.0...v1.0.0