Skip to content

mazda: decode the MORE_GAS cylinder-status state machine - #12

Closed
mzdnick wants to merge 2 commits into
zoompilot:developfrom
mzdnick:mazda-cyl-deact-ui
Closed

mzdnick wants to merge 2 commits into
zoompilot:developfrom
mzdnick:mazda-cyl-deact-ui

Conversation

@mzdnick

@mzdnick mzdnick commented Sep 12, 2026

Copy link
Copy Markdown

Why

Mazda reports cylinder deactivation on the bus but nothing decodes it. The PCM encodes it as a state machine in MORE_GAS (0x167) byte 7. There is no discrete fuel-cut flag anywhere: all 128 addresses in a driving capture were checked.

What

  • mazda_2017.dbc: new CYL_DEACT_STATE on MORE_GAS, value table in the signal comment: 41 all cylinders (also during fuel cut), 10-17 entry ramp, 20 two cylinders active, 30/40 exit transients.
  • carstate_ext.py: CylinderState (normal / entry / deactivated / engineBraking) plus cyl_entry_progress, the ramp mapped to 0-1. engineBraking is inferred: pedal up, rolling, converter coupled, confirmed 0.5 s. Coupling means the trailing 0.5 s of rpm/kph ratio stays flat (p95-p5 under 2.5 rpm/kph, above 8 kph). The inference is needed because the byte reads 41 during fuel cut, and fuel cut survives grades, so a decel gate cannot detect it.

Validation

  • new test_mazda_cyl_deact.py: 17 cases, all pass. Covers the state boundaries, ramp progress, coupling lock/unlock, and confirm timing.

Known limitation

  • verified on one engine (CX-5 2022 2.5L); other Mazda engines unverified.
  • engineBraking is inferred physics, not a bus signal. Currently inaccurate.

Merge note

Prerequisite for zoompilot/zoompilot#18

AI Usage

Disclaimer: GLM-5.3 by Z.ai was used to help develop, debug, and document this submission. All changes were reviewed and validated by a human.

MORE_GAS (0x167) byte 7 carries the cylinder mode: 41 = all
cylinders, 10-17 = the PCM confirmation ramp toward deactivation,
20 = two cylinders latched off. The byte reports all-cylinders
during fuel cut, so engineBraking is inferred from pedal-up and
converter coupling (a flat rpm/speed ratio) with a 0.5 s confirm;
there is no decel gate, because fuel cut survives grades. MORE_GAS
is registered with the pt parser up front, unmapped modes hold the
resolved state, and the DBC names the CYL_DEACT_STATE values.
Idle creep in Drive holds the rpm/speed ratio flat at idle rpm, so the
coupling gate passes without fuel cut and the ring shows engine braking in
parking lots: 63 windows under 20 kph across the 12-route rlog corpus,
60 of them fully below 900 rpm (the idle band).

Fuel cut never runs at idle rpm. Gate the overrun on EB_MIN_RPM = 1000.

Corpus replay through this code: sub-20 kph engine braking 92.0 s -> 7.9 s;
40+ kph unchanged (863.1 s -> 861.1 s). Mazda tests: 571 pass.
@mzdnick mzdnick closed this Sep 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant