Files
samplez/tunie/research/reference-maps/DEVICES.md
uhryniuk 4aa5da53d2 Commit tune maps and research so tunes are reachable from the phone
Removes the *.hex/maps_cache gitignore rule (explicit user call, reversing
the earlier no-redistribution stance) so the official TuneECU catalogue
maps, derived SAI/O2-delete composites, and the checksum/composition
tooling are actually available to pull up on a phone browser when using
the real TuneECU app. Also folds in tonight's KWP2000 fixes (TesterPresent
keep-alive, connect-failure cleanup, slow-init StartCommunication fix) and
the accumulated research docs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FP2GaxS9HkUdL5sLBnjKje
2026-08-27 01:34:05 -05:00

8.5 KiB

Device-enable flags (SAI / O2 / lambda) — validated

Aug 2026 update: re-fetched 20188Map2009AIRBOXBONNY.hex from its real source — it's in tuneecu.net's own custom-map archive (Twin_Custom_Tune_list.html, not a forum attachment as previously assumed), not gitignore-lost this time. Re-ran the diff against a freshly downloaded stock 20188Map.hex and every claim below reproduced exactly: same 1428-byte diff (0.36%), same three device-flag bytes, same two trim bytes. The file now lives in this directory (20188Map2009AIRBOXBONNY.hex, 20187/88/91/92Map.hex) rather than resting on memory of a prior session. See ../COMMUNITY_TUNING.md for the new composability findings (device flags vs. Arrow exhaust delta) this re-verification enabled.

How they were found

Both stock reference maps (20187, 20188) have SAI and O2 active, so diffing them can't reveal the delete flags. The confirmation came from a community map that explicitly disables them:

20188Map2009AIRBOXBONNY.hex — "Bonneville, aftermarket exhaust, mechanical odometer, NO AIR BOX, K&N, British Custom mufflers, NO SAI, NO O² SENSORS". Same base as stock 20188, so the diff isolates the deletes.

Diff (flat ROM) of that map vs stock 20188 = 0.36%, split into:

  • the fuel tables (airbox/K&N enrichment — expected), and
  • a small cluster in the device-config region at 0x53801…0x53819.

The flags

They are a byte-boolean array at flat-ROM base + fe[33] (= 0x50000 + 0x3801 = 0x53801), one byte per device, 1 = enabled, 0 = disabled.

The delete map changed exactly three bytes from 1 → 0:

Flat-ROM offset Stock Deleted Device
0x53801 1 0 SAI (Secondary Air Injection)
0x53818 1 0 O2 sensor
0x53819 1 0 O2 sensor (2)

SAI is the first flag in the array; the two O2 sensors are the last two — consistent with the Devices resource order (SAI = index 0; O2 Sensor / O2 Sensor (2)). The three-byte change matching "NO SAI, NO O²" is unambiguous.

To disable a device: set its byte to 0. (The 0x5369C/0x536AB bytes that also changed are idle/open-loop trim that comes with removing the O2 feedback, not device-enable flags.)

Editing / export

The downloaded .hex format's integrity is the dc stream cipher + the unpack directory; the caXX bytes in the header/tail are map-ID metadata, not a calibration checksum. So a device toggle = flip the byte in the flat ROM, re-pack to the decoded layout, and dc-encode back to .hex. (The separate ECU flash checksum is computed at flash time and is out of scope for the read/edit tool.)

Confidence

  • SAI = 0x53801: ~90% (high). Two independent confirmations: the device-name logic in l.java lc() resolves Devices[0]=SAI via fe[33] to exactly 0x53801, AND the real NO-SAI map cleared precisely that byte.
  • O2 sensors = 0x53818 / 0x53819: ~80% (probable). The map declares "NO O² SENSORS" (the twin has two) and exactly two adjacent boolean bytes cleared beyond SAI; the 865 has no air-flap, so airbox removal is fuel-only (no flag). Not independently isolated — no single-mod reference map exists, and the exact x.a() device-layout branch for this ECU (i27=72) is too deeply nested to trace reliably.

The real-world caveat (more important than the labels)

Correct flags are not a good tune by themselves. Disabling O2 forces the ECU open-loop: it stops live fuel trim and runs entirely on the base fuel map. Stock maps assume closed-loop trim at idle/cruise, so an O2-delete on an otherwise stock map can run lean/rough. A proper delete pairs flags-off with fuel enrichment (which is exactly why the AIRBOXBONNY reference map also changed the fuel tables).

Recommendation: flash a complete, known-good delete map matching the hardware (exhaust/filters), not hand-toggled flags on a stock map. The checkbox editor is for understanding/building a map, not a one-click safe delete.

0x53822 — the extra flag found on the America dyno tune (Aug 2026)

Pushed on identifying this (index 33 past the 0x53801 base, one slot past the two O2 sensors — see COMMUNITY_TUNING.md's original finding on 20184dynoTuneSteveO2-Disable.hex). Real, bounded progress, not a full resolution:

Found the actual device name list — R.array.Devices in arrays.xml:3-18, 15 entries: SAI, Exhaust Valve, O2 Sensor, 2nd Throttle, Air Flap, EPC, O2 Sensor (2), Purge Valve, Idle Speed Control, Traction Control, Immobilizer, Instruments, ABS, Speed Sensor (non ABS), Race ECU. This independently confirms and extends the existing SAI(0)/O2 Sensor(23)/O2 Sensor(2)(24) findings above — matches exactly, real data.

Found the mechanism: l.java's lc() (l.java:5742) resolves the per-device flat-ROM byte-boolean array from three packed nibble-encoded constants (x.t/x.s/x.q in the decompile referenced by docs/ROADMAP.md), looked up against R.array.Devices by index. This confirms flat-ROM byte position and Devices[] array index are not the same thing — SAI (array index 0) sits at byte 0, but O2 Sensor (array index 2) sits at byte 23, O2 Sensor (2) (array index 6) sits at byte 24 — a bike-specific sparse remapping, not a fixed formula.

Where it stops: the specific per-family constants that would decode byte 33 precisely require tracing which branch of x.java's ~46 assignments to the relevant classifier variable applies to Bonneville/T100 specifically. docs/ROADMAP.md's existing note cites i27=72 as the anchor for this ECU family from a prior research pass, but that exact comparison doesn't appear in this decompile snapshot — likely version drift (this decompile's changelog shows APK updates through v6.4.36, June 2026; the i27=72 note may predate that). Didn't find a reliable replacement anchor without a much larger, low-confidence search across all 46 assignment sites.

Best-supported guess, reasoning not proof: narrowing the 12 unassigned Devices[] names by plausibility for a 2010 mechanical-odo Bonneville/ America-class twin — Purge Valve (this project's own system1.html research already documents a "Canister Purge Valve, California models only" on this ECU family — a real, independently-corroborated candidate), Idle Speed Control (the ISC stepper motor genuinely exists on this engine), and Immobilizer (period-correct fuel-injected Triumphs commonly used transponder immobilizers) are the most plausible of the 12; Exhaust Valve, 2nd Throttle, ABS, Traction Control, Race ECU are implausible for this specific bike/era and can likely be ruled out. Not confirmed — a genuine guess ranked by plausibility, not a finding.

Update (Aug 2026) — independently verified, raises confidence further: checked tests.html in this project's own site mirror directly and found a distinct, real testable menu entry: "Purge Control Valve (Only bikes with charcoal canister) — Activate the purge valve, listen for a very quiet noise," listed right alongside its own separate "SAI" test entry. This confirms Purge Valve is a real, independent device on this ECU family with its own dedicated test/enable path, not a guess — genuinely strengthens (does not yet prove) the byte-33 hypothesis. Also confirms from the same list: "Air Flap (675 Daytona)" is explicitly Daytona-675-only, matching this document's elimination reasoning above. (Surfaced by an external research pass, then independently confirmed here directly against this project's own source rather than trusted secondhand — see ../EXTERNAL_RESEARCH_NOTES.md.)

What would actually resolve this: a second real-world reference map where the specific device at byte 33 changes state with a documented description (the same technique that resolved SAI/O2 originally) would settle it definitively without needing the x.t/x.s/x.q trace at all.

Open question raised by community research (unresolved)

Multiple forum threads describe TuneECU's own SAI/O2 checkboxes (the same UI these bytes drive) as only suppressing the fault-code/CEL logic, not actually forcing open-loop fueling — see ../COMMUNITY_TUNING.md. That's in tension with "disabling O2 forces open-loop" above. Possible reconciliation: the three device-enable bytes gate DTC logic only, and the fueling behavior change lives in the other bytes the real delete-map diff also touched (0x5369C, 0x536AB) or in the lambda-target curve (fe[2]/0x52260, TABLES.md). Not yet isolated — needs a second independent delete-map diff to separate device flags from fuel/trim bytes.