fix(device): block digital writes while PWM is active on the channel - #473
Conversation
SetDioValue/SetDioDirection (and the MCP set_digital_output / set_digital_direction tools) reported success and mirrored the commanded level/direction into local channel state even while PWM was running on that channel. The firmware silently ignores the command, so the pin keeps outputting its PWM waveform while every readable property in Core claims a static driven level — confirmed on bench hardware (fw 3.7.2): duty/transition counts are unchanged after a "successful" digital write during PWM. Add a guard symmetric to the one SetPwmEnabled already has for the non-capable-channel case: SetDioValue/SetDioDirection now throw InvalidOperationException when IDigitalChannel.IsPwmEnabled is true, pointing the caller at SetPwmEnabled(channel, false). No local mirroring, no SCPI sent. Update the set_digital_output/set_digital_direction/set_pwm_output MCP tool descriptions to document the precondition. Fixes #449
PR Summary by QodoFix: reject digital writes while PWM is enabled on a channel
AI Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
1.
|
- Document the new InvalidOperationException precondition on
IStreamingDevice.SetDioDirection/SetDioValue (sync + async), so SDK
consumers see it in the public contract, not just Core internals.
- Add DaqifiAgent.RequirePwmDisabled so the MCP set_digital_direction/
set_digital_output tools fail fast with MCP-actionable guidance
("Call disable_pwm on this channel first") instead of surfacing
Core's SDK-oriented message, which points at SetPwmEnabled — a
method MCP callers have no tool for.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit ccc1855 |
RequirePwmDisabled ran before device.RunExclusiveAsync, so a concurrent tool call could toggle PWM between the check and the actual SetDioDirection/SetDioValue send, letting Core's SDK-oriented exception (naming SetPwmEnabled, not an MCP tool) leak through instead of the MCP-specific message. Move the check into the same exclusive delegate as the write it guards, so both observe the same state. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit 0017f43 |
- Core's InvalidOperationException from EnsurePwmNotEnabled now also names the MCP disable_pwm tool alongside SetPwmEnabled, so the text is actionable for both SDK and MCP callers even in a path where the MCP-side guard doesn't get there first. - Fix a stray #473 (this PR) reference in a new comment to #449 (the originating issue), matching the file's existing convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit 18ec370 |
Summary
SetDioValue/SetDioDirection(and therefore the MCPset_digital_output/set_digital_directiontools) reported success and mirrored the commanded level/direction into local channel state while PWM was active on that channel, even though the firmware silently ignores the command. The pin keeps running its PWM waveform while every readable property in Core says it's a static driven level.Confirmed on bench hardware (Nq1, fw 3.7.2, loopback rig) in #449: duty cycle and transition counts are unchanged after a "successful" digital write issued during PWM.
Fix
Adds a guard symmetric to the one
SetPwmEnabledalready has for the non-capable-channel case:SetDioValue/SetDioDirectionnow throwInvalidOperationExceptionwhenIDigitalChannel.IsPwmEnabledistrue, pointing the caller atSetPwmEnabled(channel, false)(the existing recovery path). No local mirroring happens, no SCPI is sent.Also updates the
set_digital_output/set_digital_direction/set_pwm_outputMCP tool descriptions to document the precondition, per the issue's suggestion.Testing
SetDioDirection_WhilePwmEnabled_ThrowsInvalidOperationExceptionSetDioValue_WhilePwmEnabled_ThrowsInvalidOperationExceptionAndDoesNotMirrorOutputValueDaqifi.Core.Testssuite: 2855 passedDaqifi.Mcp.Testssuite: 36 passedFixes #449
🤖 Generated with Claude Code