Skip to content

Add per-motor DShot direction configuration and bounded test pulses - #12011

Open
Raffi1202 wants to merge 2 commits into
iNavFlight:maintenance-10.xfrom
Raffi1202:motor-direction-wizard
Open

Raffi1202 wants to merge 2 commits into
iNavFlight:maintenance-10.xfrom
Raffi1202:motor-direction-wizard

Conversation

@Raffi1202

@Raffi1202 Raffi1202 commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Problem and behavior

Add per-motor DShot direction configuration and a bounded test pulse for an integrated Configurator wizard. Commands 7/8 and SAVE_SETTINGS (12) target only the selected motor; other outputs stay at zero during the operation. Settings live in the ESC. Completion means commands sent, not confirmed persistence.

Existing arming rules are unchanged: no new arming flag or persistent lock. Requests are rejected while armed or ordinary motor testing is active. Arming cancels the operation before the next output frame and restores normal output ownership. Ordinary motor testing works normally after the operation. Cancellation retains tokens so delayed retries cannot restart it.

The fixed DShot120 test pulse expires after 1.5 seconds independently of USB/UI. Duplicate tokens cannot repeat a save or extend/restart a pulse. SITL uses the same sequencer and reports simulation explicitly.

Integration

  • Companion Configurator PR: Add an integrated multirotor motor direction wizard inav-configurator#2794.
  • Target: maintenance-10.x. Provisional MSP2 codes 0x2235-0x2237 require maintainer agreement.
  • Initialized STM32/AT32 DShot only; no reversible/3D mode; RP2350 unsupported. Compatible ESC direction/save support is required and cannot be detected over DShot.
  • UI is restricted to multirotor/tricopter platforms. Betaflight's Motor Direction Wizard inspired the workflow; no wizard code was copied.

Validation

  • Strict C99 tests passed: sequence order, repetitions, timing, both directions, timer wrap, expiry, stop, cancellation and token retention.
  • Builds passed: SITL, SPEEDYBEEF405V4, IFLIGHT_BLITZ_ATF435.
  • Native Electron Configurator with INAV SITL passed wizard/individual flow, reverse/next, release stop, expiry while held and unchanged ordinary motor-test availability.
  • Whitespace checks passed.

Hardware test plan and limitations

Physical hardware has not been tested. With all propellers removed:

  1. Check selected-output mapping/isolation and command timing at DShot150/300/600 with burst/non-burst DMA on STM32 and AT32.
  2. Verify armed/ordinary-test rejection, cancellation on arming and normal output ownership. Check delayed/duplicate requests after cancellation.
  3. Verify pulse stop on release, timeout, dialog close and USB disconnection electrically.
  4. Power-cycle ESCs and FC; check persistence and unchanged other motors. Check ordinary motor tests and turtle mode afterward.
  5. Check unsupported ESC firmware, disabled outputs, analog PWM, 3D and missing ESC power. A fixed low pulse may not start every motor.

See docs/development/msp/esc-direction.md for protocol details.

@qodo-code-review

Copy link
Copy Markdown
Contributor

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add per-motor DShot direction configuration and bounded test pulses

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Adds tokenized per-motor direction writes with isolated DShot command sequencing.
• Provides fixed DShot120 test pulses with firmware-enforced expiry and arming cancellation.
• Exposes MSP2 status and controls with hardware-independent SITL coverage.
Diagram

sequenceDiagram
    actor CFG as Configurator
    participant MSP as MSP handlers
    participant PWM as DShot output
    participant SEQ as Direction sequencer
    participant ESC as Selected ESC
    participant SITL as SITL simulator
    CFG->>MSP: Direction or test request
    alt Hardware output
        MSP->>PWM: Validate and dispatch
        PWM->>SEQ: Start tokenized operation
        loop Bounded sequence
            SEQ-->>PWM: Isolated command frame
            PWM->>ESC: Selected output only
        end
        PWM-->>MSP: Phase and token status
    else Simulated output
        MSP->>SITL: Validate and dispatch
        SITL->>SEQ: Run same sequencer
        SITL-->>MSP: Simulated status
    end
    MSP-->>CFG: Capability and progress
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Extend the existing DShot command queue
  • ➕ Reuses established command scheduling infrastructure.
  • ➕ Could reduce the amount of dedicated driver state.
  • ➖ The generic queue does not model selected-output isolation or bounded throttle pulses.
  • ➖ Zero-frame suppression, cancellation, and retained token semantics would complicate shared behavior.
  • ➖ Changes could increase regression risk for turtle mode and existing DShot commands.
2. Sequence commands from the Configurator
  • ➕ Keeps firmware state smaller.
  • ➕ Allows the UI to directly control workflow pacing.
  • ➖ USB loss or UI stalls could leave testing behavior unsafe or incomplete.
  • ➖ Cannot reliably enforce frame-level timing and output isolation.
  • ➖ Duplicate requests and retries become harder to make idempotent.

Recommendation: Keep the dedicated firmware sequencer. Frame-level timing, selected-motor isolation, token idempotency, arming cancellation, and pulse expiry belong beside output generation rather than in the UI or generic command queue. Before merging, confirm the provisional MSP2 allocations and complete the documented physical hardware validation.

Files changed (10) +481 / -0

Enhancement (6) +244 / -0
dshot_direction.hAdd the tokenized DShot direction state machine +104/-0

Add the tokenized DShot direction state machine

• Introduces the shared state machine for zeroing outputs, repeating direction and save commands, enforcing timing gaps, and retaining request tokens. It also implements fixed DShot120 test pulses with a 1.5-second deadline and cancellation support.

src/main/drivers/dshot_direction.h

pwm_output.cIntegrate direction sequencing with physical DShot outputs +68/-0

Integrate direction sequencing with physical DShot outputs

• Adds capability checks and APIs for starting, stopping, and inspecting direction operations. Active operations isolate the selected motor, suppress competing DShot commands, expire test pulses, and yield immediately when arming occurs.

src/main/drivers/pwm_output.c

pwm_output.hExpose DShot direction configuration APIs +12/-0

Expose DShot direction configuration APIs

• Defines the feature guard and public status, capability, direction, test, and SITL update interfaces. RP2350 is excluded while SITL explicitly enables the shared interface.

src/main/drivers/pwm_output.h

fc_msp.cAdd MSP2 direction, test, and status handlers +53/-0

Add MSP2 direction, test, and status handlers

• Exposes versioned operation status and accepts tokenized direction or bounded-test requests. It rejects ordinary motor testing and disruptive reboot, persistence, reset, or passthrough commands while the sequencer owns outputs.

src/main/fc/fc_msp.c

mixer.cAdvance DShot direction operations in SITL +2/-0

Advance DShot direction operations in SITL

• Invokes the SITL direction update from the motor write path so simulated operations progress through the normal output cadence.

src/main/flight/mixer.c

msp_protocol_v2_inav.hReserve provisional MSP2 ESC direction commands +5/-0

Reserve provisional MSP2 ESC direction commands

• Defines experimental command identifiers for status, direction changes, and bounded test pulses. The comments flag that allocation requires maintainer coordination before merge.

src/main/msp/msp_protocol_v2_inav.h

Tests (2) +89 / -0
CMakeLists.txtRegister the standalone DShot direction test +6/-0

Register the standalone DShot direction test

• Builds the strict assertion-based sequencer test and adds it to both CTest and the aggregate check target.

src/test/CMakeLists.txt

dshot_direction_test.cTest direction timing, pulse bounds, and cancellation +83/-0

Test direction timing, pulse bounds, and cancellation

• Covers both directions, command repetition and ordering, minimum timing gaps, timer wraparound, and completion. It also verifies pulse expiry, explicit stop behavior, mutual exclusion, cancellation, and duplicate-token retention.

src/test/dshot_direction_test.c

Documentation (1) +92 / -0
esc-direction.mdDocument the ESC direction protocol and safety model +92/-0

Document the ESC direction protocol and safety model

• Documents platform scope, provisional MSP2 payloads, DShot timing, ESC persistence limitations, and unchanged arming behavior. It also records completed validation and the required propeller-free hardware test plan.

docs/development/msp/esc-direction.md

Other (1) +56 / -0
target.cImplement simulated ESC direction sequencing +56/-0

Implement simulated ESC direction sequencing

• Provides SITL implementations of the hardware-facing direction APIs using the shared sequencer. It applies the same validation, token, timeout, and arming-cancellation behavior while explicitly logging simulated commands.

src/main/target/SITL/target.c

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 22, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Turtle mode runs motors forward 🐞 Bug ≡ Correctness ⭐ New
Description
sendDShotCommand() drops every command while directionConfig is busy, rather than preserving the
turtle-mode reverse command. A direction operation may start while disarmed, and turtle arming then
sets the armed and turtle flags immediately, so the next scheduler pass cancels the operation while
the ESCs never receive their required reverse command.
Code

src/main/drivers/pwm_output.c[R590-592]

+    if (dshotDirectionBusy(&directionConfig)) {
+        return;
+    }
Evidence
The new early return drops the reverse command needed by turtle mode. Turtle arming does not check
whether that command was accepted and immediately enables both armed and turtle states; the newly
added scheduler logic subsequently cancels the active direction sequence once armed.

src/main/drivers/pwm_output.c[560-573]
src/main/drivers/pwm_output.c[589-594]
src/main/drivers/pwm_output.c[637-642]
src/main/fc/fc_core.c[606-616]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
DShot commands are discarded while the direction sequencer is active. Turtle-mode arming depends on queuing the ESC reverse command before enabling turtle mode, so dropping that command lets the craft enter turtle mode with its ESC direction unchanged.

## Fix Focus Areas
- src/main/drivers/pwm_output.c[589-594]
- src/main/fc/fc_core.c[606-616]

## Recommended Fix
Do not silently discard DShot commands while a direction operation is active. Queue the command so that, after the armed-state cancellation releases sequencer ownership, the normal DShot command scheduler sends its required repetitions; alternatively explicitly cancel and enqueue before accepting turtle-mode arming. Preserve the existing exclusion that prevents a newly started direction operation from interrupting already queued commands.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Stopped tests can pulse once more 🐞 Bug ≡ Correctness
Description
pwmDshotDirectionTest clears testActive without clearing the test value cached in
motors[].value, and arming cancellation has the same stale-cache behavior. If
pwmCompleteMotorUpdate runs before the mixer writes fresh values, it packages and transmits the
selected motor's previous DShot120 value after an explicit stop or arming cancellation.
Code

src/main/drivers/pwm_output.c[R578-580]

+    if (run == 0) {
+        directionConfig.testActive = false;
+        return true;
Evidence
The digital writer stores values for later transmission, the active-test path places 120 in that
cache, and cancellation only clears state. The subsequent no-command path can return successfully
without overwriting the cache, after which the update routine encodes and transmits it.

src/main/drivers/pwm_output.c[508-510]
src/main/drivers/pwm_output.c[578-580]
src/main/drivers/pwm_output.c[621-634]
src/main/drivers/pwm_output.c[637-657]
src/main/drivers/pwm_output.c[686-700]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Stopping or cancelling a direction test clears only the state flag, leaving DShot120 cached for transmission in the selected motor output.
## Fix Focus Areas
- src/main/drivers/pwm_output.c[578-580]
- src/main/drivers/pwm_output.c[621-634]
## Recommended Fix
On every explicit or arming-triggered cancellation, clear the cached test outputs or retain direction-output ownership long enough to emit a zero frame before returning to the normal command path. Ensure the first frame after cancellation cannot reuse the previous DShot120 value.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. SITL cannot compile this feature 🐞 Bug ≡ Correctness
Description
target.c declares dshotDirection_t and invokes its helpers without including
drivers/pwm_output.h, while its new calls to getMotorCount and areMotorsRunning also lack
flight/mixer.h. Compiling the SITL translation unit therefore encounters an unknown direction type
and undeclared APIs as soon as the new implementation is enabled.
Code

src/main/target/SITL/target.c[R588-590]

+// Exercise the same command sequencer through real MSP in the built-in demo.
+// SITL has no physical ESCs; it explicitly advertises simulated output.
+static dshotDirection_t sitlDirectionConfig;
Evidence
The SITL source's include list contains neither required header, while the direction type is exposed
through pwm_output.h and both motor APIs are declared by mixer.h. The newly added declarations
and calls consequently have no visible definitions in this translation unit.

src/main/target/SITL/target.c[25-53]
src/main/target/SITL/target.c[588-604]
src/main/target/SITL/target.c[617-636]
src/main/drivers/pwm_output.h[67-76]
src/main/flight/mixer.h[148-167]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new SITL implementation uses DShot direction and mixer APIs without including the headers that declare them.
## Fix Focus Areas
- src/main/target/SITL/target.c[45-53]
- src/main/target/SITL/target.c[588-636]
## Recommended Fix
Include `drivers/pwm_output.h` for the direction state and helper declarations and `flight/mixer.h` for `getMotorCount` and `areMotorsRunning`, then verify the SITL target compiles without implicit declarations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Simulator tests never pulse a motor 🐞 Bug ≡ Correctness ⭐ New
Description
sitlDshotDirectionUpdate() advances the test and direction state machines but discards their
resulting output values, only printing positive configuration commands. SITL's simulators read the
mixer's motor[] values directly, so a direction operation leaves ordinary simulated outputs in
place and a DShot120 test pulse produces no simulated motor output or selected-motor isolation.
Code

src/main/target/SITL/target.c[R635-638]

+    dshotDirectionTestFrame(&sitlDirectionConfig, micros());
+    const int16_t command = dshotDirectionFrame(&sitlDirectionConfig, micros());
+    if (command > 0) {
+        fprintf(stderr, "[ESC DEMO] motor=%u command=%d (simulated, no hardware)\n", sitlDirectionConfig.motor + 1, command);
Evidence
The added SITL code invokes both frame helpers but does not store either frame result. Unlike
hardware, where the new sequencer overwrites every output with the selected value or zero, SITL
deliberately has no PWM layer and its simulation backends consume motor[] directly.

src/main/target/SITL/target.c[630-640]
src/main/drivers/pwm_output.c[619-630]
src/main/fc/fc_init.c[361-367]
src/main/target/SITL/sim/realFlight.c[232-238]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The SITL hook advances the shared DShot direction sequencer but does not publish the resulting isolated motor output to the simulator. As a result, SITL does not model either the selected test pulse or the required zeroing of all other motors.

## Fix Focus Areas
- src/main/target/SITL/target.c[630-640]
- src/main/flight/mixer.c[520-601]

## Recommended Fix
In the SITL update hook, translate the sequencer's selected DShot test output to the simulator motor-value range and set every unselected `motor[]` entry to its stopped value while the sequence or pulse owns outputs. Preserve ordinary mixer values once the operation completes or is cancelled, and retain the existing simulated-command logging.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: 🧠 Deep: This is a broad, safety-sensitive runtime feature spanning MSP APIs, motor-output ownership, timing, arming cancellation, SITL, and multiple independent code paths, with known pending defects and substantial opportunity for additional subtle bugs.

Grey Divider

Tip of the day
💡 Did you know, you can route each action level your way: inline, summary, both, or drop

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous reviews

Review updated until commit 2af2025 🧠 Deep

Results up to commit N/A


🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Stopped tests can pulse once more 🐞 Bug ≡ Correctness
Description
pwmDshotDirectionTest clears testActive without clearing the test value cached in
motors[].value, and arming cancellation has the same stale-cache behavior. If
pwmCompleteMotorUpdate runs before the mixer writes fresh values, it packages and transmits the
selected motor's previous DShot120 value after an explicit stop or arming cancellation.
Code

src/main/drivers/pwm_output.c[R578-580]

+    if (run == 0) {
+        directionConfig.testActive = false;
+        return true;
Evidence
The digital writer stores values for later transmission, the active-test path places 120 in that
cache, and cancellation only clears state. The subsequent no-command path can return successfully
without overwriting the cache, after which the update routine encodes and transmits it.

src/main/drivers/pwm_output.c[508-510]
src/main/drivers/pwm_output.c[578-580]
src/main/drivers/pwm_output.c[621-634]
src/main/drivers/pwm_output.c[637-657]
src/main/drivers/pwm_output.c[686-700]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Stopping or cancelling a direction test clears only the state flag, leaving DShot120 cached for transmission in the selected motor output.
## Fix Focus Areas
- src/main/drivers/pwm_output.c[578-580]
- src/main/drivers/pwm_output.c[621-634]
## Recommended Fix
On every explicit or arming-triggered cancellation, clear the cached test outputs or retain direction-output ownership long enough to emit a zero frame before returning to the normal command path. Ensure the first frame after cancellation cannot reuse the previous DShot120 value.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. SITL cannot compile this feature 🐞 Bug ≡ Correctness
Description
target.c declares dshotDirection_t and invokes its helpers without including
drivers/pwm_output.h, while its new calls to getMotorCount and areMotorsRunning also lack
flight/mixer.h. Compiling the SITL translation unit therefore encounters an unknown direction type
and undeclared APIs as soon as the new implementation is enabled.
Code

src/main/target/SITL/target.c[R588-590]

+// Exercise the same command sequencer through real MSP in the built-in demo.
+// SITL has no physical ESCs; it explicitly advertises simulated output.
+static dshotDirection_t sitlDirectionConfig;
Evidence
The SITL source's include list contains neither required header, while the direction type is exposed
through pwm_output.h and both motor APIs are declared by mixer.h. The newly added declarations
and calls consequently have no visible definitions in this translation unit.

src/main/target/SITL/target.c[25-53]
src/main/target/SITL/target.c[588-604]
src/main/target/SITL/target.c[617-636]
src/main/drivers/pwm_output.h[67-76]
src/main/flight/mixer.h[148-167]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new SITL implementation uses DShot direction and mixer APIs without including the headers that declare them.
## Fix Focus Areas
- src/main/target/SITL/target.c[45-53]
- src/main/target/SITL/target.c[588-636]
## Recommended Fix
Include `drivers/pwm_output.h` for the direction state and helper declarations and `flight/mixer.h` for `getMotorCount` and `areMotorsRunning`, then verify the SITL target compiles without implicit declarations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment on lines +578 to +580
if (run == 0) {
directionConfig.testActive = false;
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Stopped tests can pulse once more 🐞 Bug ≡ Correctness

pwmDshotDirectionTest clears testActive without clearing the test value cached in
motors[].value, and arming cancellation has the same stale-cache behavior. If
pwmCompleteMotorUpdate runs before the mixer writes fresh values, it packages and transmits the
selected motor's previous DShot120 value after an explicit stop or arming cancellation.
Agent Prompt
## Issue description
Stopping or cancelling a direction test clears only the state flag, leaving DShot120 cached for transmission in the selected motor output.

## Fix Focus Areas
- src/main/drivers/pwm_output.c[578-580]
- src/main/drivers/pwm_output.c[621-634]

## Recommended Fix
On every explicit or arming-triggered cancellation, clear the cached test outputs or retain direction-output ownership long enough to emit a zero frame before returning to the normal command path. Ensure the first frame after cancellation cannot reuse the previous DShot120 value.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +588 to +590
// Exercise the same command sequencer through real MSP in the built-in demo.
// SITL has no physical ESCs; it explicitly advertises simulated output.
static dshotDirection_t sitlDirectionConfig;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Sitl cannot compile this feature 🐞 Bug ≡ Correctness

target.c declares dshotDirection_t and invokes its helpers without including
drivers/pwm_output.h, while its new calls to getMotorCount and areMotorsRunning also lack
flight/mixer.h. Compiling the SITL translation unit therefore encounters an unknown direction type
and undeclared APIs as soon as the new implementation is enabled.
Agent Prompt
## Issue description
The new SITL implementation uses DShot direction and mixer APIs without including the headers that declare them.

## Fix Focus Areas
- src/main/target/SITL/target.c[45-53]
- src/main/target/SITL/target.c[588-636]

## Recommended Fix
Include `drivers/pwm_output.h` for the direction state and helper declarations and `flight/mixer.h` for `getMotorCount` and `areMotorsRunning`, then verify the SITL target compiles without implicit declarations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@Raffi1202

Copy link
Copy Markdown
Contributor Author

/agentic_review

@github-actions

Copy link
Copy Markdown

RAM / Flash usage vs. base commit 86a0441 — commit 2af2025

Target Flash Δ RAM Δ
MATEKF405 +960 B (+0.13%) CCM: ±0 B (±0.00%)
RAM: +40 B (+0.04%)
MATEKF722 +1136 B (+0.24%) ITCM_RAM: +88 B (+0.71%)
RAM: +32 B (+0.04%)
TCM: ±0 B (±0.00%)
MATEKF765 +1248 B (+0.17%) DTCM_RAM: ±0 B (±0.00%)
SRAM1: +24 B (+0.02%)
MATEKH743 +1104 B (+0.14%) D2_RAM: ±0 B (±0.00%)
DTCM_RAM: ±0 B (±0.00%)
ITCM_RAM: +32 B (+0.20%)
RAM: ±0 B (±0.00%)

See RAM/flash optimization guide for techniques to reduce usage.

Comment on lines +590 to +592
if (dshotDirectionBusy(&directionConfig)) {
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Turtle mode runs motors forward 🐞 Bug ≡ Correctness

sendDShotCommand() drops every command while directionConfig is busy, rather than preserving the
turtle-mode reverse command. A direction operation may start while disarmed, and turtle arming then
sets the armed and turtle flags immediately, so the next scheduler pass cancels the operation while
the ESCs never receive their required reverse command.
Agent Prompt
## Issue description
DShot commands are discarded while the direction sequencer is active. Turtle-mode arming depends on queuing the ESC reverse command before enabling turtle mode, so dropping that command lets the craft enter turtle mode with its ESC direction unchanged.

## Fix Focus Areas
- src/main/drivers/pwm_output.c[589-594]
- src/main/fc/fc_core.c[606-616]

## Recommended Fix
Do not silently discard DShot commands while a direction operation is active. Queue the command so that, after the armed-state cancellation releases sequencer ownership, the normal DShot command scheduler sends its required repetitions; alternatively explicitly cancel and enqueue before accepting turtle-mode arming. Preserve the existing exclusion that prevents a newly started direction operation from interrupting already queued commands.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +635 to +638
dshotDirectionTestFrame(&sitlDirectionConfig, micros());
const int16_t command = dshotDirectionFrame(&sitlDirectionConfig, micros());
if (command > 0) {
fprintf(stderr, "[ESC DEMO] motor=%u command=%d (simulated, no hardware)\n", sitlDirectionConfig.motor + 1, command);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

4. Simulator tests never pulse a motor 🐞 Bug ≡ Correctness

sitlDshotDirectionUpdate() advances the test and direction state machines but discards their
resulting output values, only printing positive configuration commands. SITL's simulators read the
mixer's motor[] values directly, so a direction operation leaves ordinary simulated outputs in
place and a DShot120 test pulse produces no simulated motor output or selected-motor isolation.
Agent Prompt
## Issue description
The SITL hook advances the shared DShot direction sequencer but does not publish the resulting isolated motor output to the simulator. As a result, SITL does not model either the selected test pulse or the required zeroing of all other motors.

## Fix Focus Areas
- src/main/target/SITL/target.c[630-640]
- src/main/flight/mixer.c[520-601]

## Recommended Fix
In the SITL update hook, translate the sequencer's selected DShot test output to the simulator motor-value range and set every unselected `motor[]` entry to its stopped value while the sequence or pulse owns outputs. Preserve ordinary mixer values once the operation completes or is cancelled, and retain the existing simulated-command logging.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 2af2025

@github-actions

Copy link
Copy Markdown

Test firmware build ready — commit 2af2025

Download firmware for PR #12011

250 targets built. Find your board's .hex file by name on that page (e.g. MATEKF405SE.hex). Files are individually downloadable — no GitHub login required.

Development build for testing only. Use Full Chip Erase when flashing.

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