Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions docs/development/msp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,12 @@ When the MSP JSON specification changes, bump `msp_messages.json` version:
[8744 - MSP2_INAV_TIMESYNC](#msp2_inav_timesync)
[8752 - MSP2_INAV_SET_AUX_RC](#msp2_inav_set_aux_rc)
[8753 - MSP2_INAV_WIND](#msp2_inav_wind)
[8754 - MSP2_INAV_MAG_UNALIGNED](#msp2_inav_mag_unaligned)
[8755 - MSP2_INAV_ESC_SRXL2_STATUS](#msp2_inav_esc_srxl2_status)
[8756 - MSP2_INAV_ESC_SRXL2_CALIBRATE](#msp2_inav_esc_srxl2_calibrate)
[8757 - MSP2_INAV_ESC_DIRECTION](#msp2_inav_esc_direction)
[8758 - MSP2_INAV_SET_ESC_DIRECTION](#msp2_inav_set_esc_direction)
[8759 - MSP2_INAV_SET_ESC_DIRECTION_TEST](#msp2_inav_set_esc_direction_test)
[12288 - MSP2_BETAFLIGHT_BIND](#msp2_betaflight_bind)
[12289 - MSP2_RX_BIND](#msp2_rx_bind)

Expand Down Expand Up @@ -5002,6 +5008,95 @@ When the MSP JSON specification changes, bump `msp_messages.json` version:

**Notes:** Requires `USE_WIND_ESTIMATOR`; returns zeroes when wind estimation is not compiled in or not yet valid. Check bit 0 of `flags` before using speed/angle values.

## <a id="msp2_inav_mag_unaligned"></a>`MSP2_INAV_MAG_UNALIGNED (8754 / 0x2232)`
**Description:** Reads the unaligned magnetometer vector.

**Request Payload:** **None**

**Reply Payload:**
|Field|C Type|Size (Bytes)|Description|
|---|---|---|---|
| `magADCUnaligned` | `int16_t[3]` | 6 | X, Y and Z components, rounded to signed 16-bit values. |

**Notes:** Returns rounded mag.magADCUnaligned values before board alignment. Returns three zeroes without USE_MAG.

## <a id="msp2_inav_esc_srxl2_status"></a>`MSP2_INAV_ESC_SRXL2_STATUS (8755 / 0x2233)`
**Description:** Reads SRXL2 ESC calibration and connection status.

**Request Payload:** **None**

**Reply Payload:**
|Field|C Type|Size (Bytes)|Description|
|---|---|---|---|
| `phase` | `uint8_t` | 1 | Calibration phase (srxl2CalPhase_e). |
| `connected` | `uint8_t` | 1 | 1 when every opened ESC is connected; otherwise 0. |
| `lastResult` | `uint8_t` | 1 | Last calibration start result (srxl2CalResult_e). |
| `portCount` | `uint8_t` | 1 | Number of opened SRXL2 motor ports. |
| `motorCount` | `uint8_t` | 1 | Number of motors in the current mixer. |

**Notes:** Requires USE_MOTOR_SRXL2. Counts report opened motor ports and the current mixer motor count, not hardware capacity.

## <a id="msp2_inav_esc_srxl2_calibrate"></a>`MSP2_INAV_ESC_SRXL2_CALIBRATE (8756 / 0x2234)`
**Description:** Controls SRXL2 ESC throttle-range calibration.

**Request Payload:**
|Field|C Type|Size (Bytes)|Description|
|---|---|---|---|
| `phase` | `uint8_t` | 1 | Requested calibration action (srxl2CalPhase_e): 0, 1, 4 or 5. |

**Reply Payload:** **None**

**Notes:** Requires USE_MOTOR_SRXL2 and at least one request byte. Accepted commands: 0 abort, 1 automatic start, 4 manual high, 5 manual low. Driver safety checks can reject start requests; read MSP2_INAV_ESC_SRXL2_STATUS for the reason. Other command values return an MSP error. Remove propellers before calibration.

## <a id="msp2_inav_esc_direction"></a>`MSP2_INAV_ESC_DIRECTION (8757 / 0x2235)`
**Description:** Reads per-motor DShot direction configuration and bounded test status.

**Request Payload:** **None**

**Reply Payload:**
|Field|C Type|Size (Bytes)|Description|
|---|---|---|---|
| `version` | `uint8_t` | 1 | Protocol version, currently 2. |
| `motorCount` | `uint8_t` | 1 | Available motor count; 0 when direction configuration is unavailable. |
| `phase` | `uint8_t` | 1 | 0 idle/cancelled, 1 stopping, 2 direction, 3 gap, 4 save, 5 settling, 6 sent. |
| `motor` | `uint8_t` | 1 | Zero-based direction motor index. |
| `reverse` | `uint8_t` | 1 | 0 normal, 1 reversed relative to ESC configuration and wiring. |
| `token` | `uint8_t` | 1 | Current or retained direction request token. |
| `simulated` | `uint8_t` | 1 | 1 for SITL simulation, otherwise 0; not an ESC acknowledgement. |
| `testMotor` | `uint8_t` | 1 | Zero-based test motor index. |
| `testActive` | `uint8_t` | 1 | 1 while the bounded test pulse is active, otherwise 0. |
| `testToken` | `uint8_t` | 1 | Current or retained test request token. |

**Notes:** Provisional ID. Requires USE_DSHOT_DIRECTION_CONFIG. Version 2 reply is ten bytes. Phase 6 means commands sent, not acknowledged ESC storage. See esc-direction.md for timing and safety requirements.

## <a id="msp2_inav_set_esc_direction"></a>`MSP2_INAV_SET_ESC_DIRECTION (8758 / 0x2236)`
**Description:** Starts direction configuration for one DShot motor.

**Request Payload:**
|Field|C Type|Size (Bytes)|Description|
|---|---|---|---|
| `motor` | `uint8_t` | 1 | Zero-based motor index. |
| `reverse` | `uint8_t` | 1 | 0 normal or 1 reversed. |
| `token` | `uint8_t` | 1 | Nonzero request token; reuse only to retry the same request. |

**Reply Payload:** **None**

**Notes:** Provisional ID. Requires USE_DSHOT_DIRECTION_CONFIG and exactly three request bytes. Refused while armed, during ordinary motor tests, with invalid arguments or conflicting operations. A duplicate retained token cannot repeat the save. ACK means accepted, not confirmed ESC persistence. Remove propellers; see esc-direction.md.

## <a id="msp2_inav_set_esc_direction_test"></a>`MSP2_INAV_SET_ESC_DIRECTION_TEST (8759 / 0x2237)`
**Description:** Starts or stops a bounded single-motor DShot test pulse.

**Request Payload:**
|Field|C Type|Size (Bytes)|Description|
|---|---|---|---|
| `motor` | `uint8_t` | 1 | Zero-based motor index; ignored for stop. |
| `run` | `uint8_t` | 1 | 0 stop, 1 start; other values rejected. |
| `token` | `uint8_t` | 1 | Nonzero start token; ignored for stop. Retained after expiry or cancellation. |

**Reply Payload:** **None**

**Notes:** Provisional ID. Requires USE_DSHOT_DIRECTION_CONFIG and exactly three request bytes. Run=1 requests DShot120 for at most 1.5 seconds and is refused while armed, during ordinary motor tests or conflicting operations. Run=0 stops unconditionally, ignoring motor and token. Duplicate tokens cannot extend or restart a pulse. Remove propellers; see esc-direction.md.

## <a id="msp2_betaflight_bind"></a>`MSP2_BETAFLIGHT_BIND (12288 / 0x3000)`
**Description:** Initiates the receiver binding procedure for supported serial protocols (CRSF, SRXL2).

Expand Down
110 changes: 110 additions & 0 deletions docs/development/msp/esc-direction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Per-motor ESC direction configuration

Paired firmware/Configurator change for `maintenance-10.x`. Betaflight's Motor
Direction Wizard inspired the workflow; no wizard source was copied.

## Scope

The Outputs tab shows the integrated dialog only for INAV multirotor/tricopter
platforms (`FC.isMultirotor()`), not based on motor count. Airplanes, including
multi-engine models, rovers, boats and unsupported platforms keep the whole panel
hidden and do not start direction polling.

The wizard initializes the selected ESC to Normal, offers a bounded hold-to-test
pulse, reverse and next-motor confirmation. Individual mode changes nothing on
selection; Normal/Reverse are explicit writes. The Quad X diagram uses the existing
INAV mixer image and motor-rule numbering. Other mixers use numbered controls.

## Protocol and ESC storage

Provisional MSP2 codes require maintainer agreement:

- `0x2235` status, ten U8 fields: version=2, available motor count, direction phase,
motor index, reverse (0/1), direction token, simulated (0/1), test motor index,
test active (0/1), test token. Count=0 means unavailable. Direction phases are
0 idle/cancelled, 1 stopping, 2 direction, 3 gap, 4 save, 5 settling, 6 sent.
- `0x2236` set direction: motor, reverse, nonzero token. Repeating the current
token does not repeat the operation, including after cancellation.
- `0x2237` test: motor, run (0/1), token. Run=1 requests DShot120 for at most
1.5 seconds. Run=0 stops unconditionally. Repeated tokens cannot extend or
restart the pulse after stop, expiry or cancellation.

The driver holds unselected motors at zero during the operation, first sends
zero for 1 second, then command 7/8 ten times at >=1ms intervals, waits 10ms,
sends SAVE_SETTINGS (12) ten times and waits >=35ms. Zero frames are suppressed
between repetitions so they cannot reset the ESC's repeat counter.

Requires initialized/enabled STM32/AT32 DShot outputs, no reversible/3D mode and
compatible ESC firmware. RP2350 is unsupported. Direction/save support and
persistent storage cannot be read back; phase 6 means commands sent, not confirmed
ESC storage. Settings live in the ESC, not FC EEPROM. Normal/Reverse are relative
to ESC configuration and wiring, not absolute clockwise/counterclockwise.

## Safety without changing existing arming behavior

All propellers must be removed before powering ESCs and acknowledging the dialog.
Direction writes and tests are refused while armed or ordinary motor testing is
active. Only this operation's active phase temporarily owns the outputs.

**No new arming flag or persistent arming lock is introduced.** The existing arming
rules remain unchanged. If the FC arms, the output driver cancels the operation
before preparing the next frame and returns control to the normal motor path.
Cancellation retains request tokens so delayed retries cannot restart an operation.
An interrupted direction/save sequence has an uncertain result and needs checking.

Ordinary MSP motor-test writes are rejected only during an active direction
sequence or pulse; they work normally afterward. Reboot, EEPROM writes, reset and
passthrough are rejected during active operations because they interrupt the
sequence. Normal DShot/turtle-mode behavior resumes after completion/cancellation.

Release, pointer cancellation/leave, keyboard release, blur, dialog close and tab
cleanup request pulse stop. Release racing with a queued start sends another stop
after that start completes. Firmware expiry does not depend on the UI or USB.

## Validation and manual checks

C tests cover sequence order/repetitions/timing, clock wrap, pulse expiry, explicit
stop, cancellation and token retention. Firmware builds: SITL, SPEEDYBEEF405V4,
IFLIGHT_BLITZ_ATF435. Configurator tests cover parser validity, freshness/safety
checks, tokens and simulated status. Native Electron/SITL checks cover wizard and
individual mode, release/timeout, unchanged ordinary motor-test availability and
platform visibility.

SITL uses the same sequencer and publishes isolated test pulses in the simulator
motor-value range. It reports simulation explicitly and has no physical ESC storage. Hardware validation has not been performed. Before merging:

1. Remove all propellers. Verify mapped output isolation and command timing at
DShot150/300/600, with burst and non-burst DMA, on STM32 and AT32.
2. Verify requests are refused while armed or during existing motor tests.
Arm during a direction sequence/pulse: verify cancellation and normal motor
output ownership without introducing any new arming restriction.
3. Release, close, disconnect USB and hold past the deadline; verify pulse stops.
Inject duplicate/delayed requests after cancellation: no restart or extra save.
4. Power-cycle ESCs and FC; verify selected direction persisted and other motors
are unchanged. Check normal motor testing and turtle mode afterward.
5. Check older firmware, disabled outputs, analog PWM, 3D, missing ESC power and
ESC firmware without direction/save support; do not claim confirmed storage.

The protocol timings follow https://betaflight.com/docs/development/API/Dshot .
Upstream Configurator currently accepts 9.x only while the firmware development
branch now reports 10.0.0. Version-policy changes are deliberately outside this
feature PR. The local native validation package temporarily accepts 10.x; that
packaging-only override is not included in the PR source.

## Review regression coverage

Configurator probes capability once on mounting. Periodic status requests run only
while the dialog is open or an operation needs tracking; unsupported firmware stops
polling. Write acknowledgements have separate nullable state fields and never imply
ESC persistence. Queue drops and MSP errors are failures; unconditional stops retry
up to three times, including after cleanup. The firmware deadline remains the final
guarantee after a total connection loss.

Quad diagrams are bundled directly, including reversed mixer direction, without
copying the asynchronously loaded Outputs preview. Dialog/map sizing is fluid and
text uses relative units; the icon close control has a localized accessible name.

Firmware prepares configuration frames as an overlay without replacing cached
normal outputs. Stop/arming cancellation therefore cannot replay a previous test
value. Ordinary DShot commands remain queued and execute after configuration ends
or arming cancels it, including turtle-mode direction commands.
Loading
Loading