Commit Graph

9 Commits

Author SHA1 Message Date
1920b2b822 docs: tunie research for bonneville 2026-09-30 16:54:09 -05:00
f830f8937d Log real-world road test results and correct/extend the CO-trim theory
New research/ROAD_TEST_LOG.md: the 2026-09-15 flash of
20262-arrow-delete-lowthrottle-composed.hex was a major real-world
success (stalling fully resolved, decel backfire much reduced but not
eliminated). Captures the live diagnostic reasoning that followed:
correcting an overly-lean-leaning framing mid-session (residual decel pop
is more likely a rich-unburned-mixture-with-no-SAI-assist problem, not a
lean one), a structural hypothesis that the Idle Fuel Trim (CO) curve
likely applies whenever the throttle is closed at any RPM rather than
only at a literal stop (only 2 of its 32 points are currently corrected,
and the untouched middle range lines up with the residual pop's RPM
window), and the reasoning for rejecting airbox-baffle removal as a fix
for decel popping specifically (wrong mechanism -- closed throttle isn't
airbox-limited -- and risks worsening the separately-flagged, still
unaddressed main-VE-table leanness gap).

Also updates TABLES.md with the CO-trim applicability open question, and
brings TUNING_GUIDE.md's "local research assets" section up to date (it
still said maps were gitignored/unflashable, both stale).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FP2GaxS9HkUdL5sLBnjKje
2026-09-16 09:07:35 -05:00
2ad5fab677 Add a layered low-throttle fuel correction on top of the Arrow delete tune
Real-world reports: stalling/choking under ~10% throttle and while
blipping the throttle at low speed, after snorkel removal with no
main-table correction for the extra airflow. Confirmed via a genuine
percentage-delta pulled from 20184dynoTuneSteveO2-Disable.hex (also
snorkel-removed) vs its own stock baseline 20186Map.hex, in the
Low-throttle fuel tables, restricted to the throttle columns actually
implicated (raw throttle <= 100, ~10%).

compose_lowthrottle.py composes onto the already-composed
20262-arrow-delete-composed.hex (not raw stock 20262) -- additive on top
of the existing SAI/O2-off + idle-trim layer, same "respect what's
already there" principle as compose_arrow_delete.py. Percentage-based
per-cell, not flat additive, since Arrow's own table already has its own
exhaust-specific correction baked in.

Output: derived/20262-arrow-delete-lowthrottle-composed.hex. Checksum
patched and verified valid; confirmed layer-1's device flags and trim
bytes survive unchanged underneath.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FP2GaxS9HkUdL5sLBnjKje
2026-09-10 15:39:10 -05:00
b1b81a6dc6 Patch the flash checksum into the composed Arrow delete tunes
The composed .hex files were missing a valid flash checksum entirely
(checksum.py flagged MISMATCH on both) -- not flash-ready as committed.
Patches the checksum in-place for both, and fixes compose_arrow_delete.py
to patch it automatically on future regenerations instead of leaving it
as a manual follow-up step.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FP2GaxS9HkUdL5sLBnjKje
2026-08-27 01:41:04 -05:00
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
80c9373ded Mark device-flag confidence honestly (SAI confirmed, O2 probable)
The NO-SAI-NO-O2 reference map bundles SAI + O2 + airbox deletes, so it validates
the three flag bytes as a GROUP but doesn't isolate O2 individually; no single-mod
map exists and the x.a() device-layout branch for this ECU is too nested to trace.

- SAI @ 0x53801: confirmed (code lc() -> Devices[0] via fe[33], + the delete map).
- O2 @ 0x53818/0x53819: probable (2 O2 sensors declared off <-> 2 adjacent bytes
  cleared; 865 has no air-flap so airbox removal is fuel-only).

Viewer now shows confirmed/probable badges and a warning that flags alone are not
a tune: O2 delete forces open-loop and needs fuel enrichment, so prefer flashing a
complete matching delete map over hand-toggling a stock one. See DEVICES.md.
2026-08-11 08:16:22 -05:00
eaa804fc35 Add validated SAI/O2 device-flag checkbox editor
Reversed the device-flag mechanism (l.java lc() + ee bit logic) and validated the
flag locations against a real reference map: 20188Map2009AIRBOXBONNY (explicitly
"NO SAI, NO O2 SENSORS"). Diffing its flat ROM vs stock 20188 isolated exactly
three byte-boolean flags that flip 1->0:

  0x53801  SAI            (= base + fe[33] + 0x00)
  0x53818  O2 sensor      (+ 0x17)
  0x53819  O2 sensor (2)  (+ 0x18)

1 = enabled, 0 = disabled. Neither stock map could reveal these (both have SAI+O2
on); the delete map was the key. See research/reference-maps/DEVICES.md.

Viewer: the Triumph-tables tab now has a Device flags panel — checkboxes reflect
the loaded map's real state (stock: all on; delete map: all off), toggling flips
the byte, and "Export edited .hex" re-encodes the distribution format. The
decode->edit->encode round-trip is byte-exact (verified). The caXX header bytes
are map-ID metadata, not a cal checksum; the ECU-flash checksum is applied at
write time.
2026-08-11 08:04:13 -05:00
173f6fa0c4 Locate Keihin tables + render real fuel maps in the viewer
Reversed the inner map format from l.java (Nc/Lb) and validated it against the
stock reference maps:

- reconstruct_rom.py: decoded map -> unpack directory -> 384KB flat ROM. In the
  flat ROM, production (20187) vs aftermarket (20188) differ only 1.4% (vs 96%
  packed), i.e. real fuel enrichment.
- table_map.py + TABLES.md: fe = c.a[Qd*48]; base = (fe[0]&0x2F0)<<12 = 0x50000;
  table = base + fe[k]. Located 9 tables (main/low-throttle fuel per cylinder,
  base/idle fuel, ignition by gear x4), 32 RPM rows x 20 throttle cols, with real
  axes (RPM fe[8], throttle fe[27]) and the AFR curve (fe[2], 128=lambda 1.00).
  Validated: main-fuel delta is uniformly richer in the aftermarket map.

Viewer now has a "Triumph tables" tab: drop a real .hex (or pick two) and it
decodes, unpacks, and renders the fuel/ignition tables as heatmaps with real
axes, plus an A->B difference view. build_viewer.py embeds the c.a/s.a directory
so any map resolves in-browser.

Catalogue dropdown: download_maps.py fetches map .hex files into maps_cache/;
serve.py serves the viewer over http so the dropdown can fetch them (drag-and-drop
still works on file://).

Proprietary map binaries (*.hex, *.dec.bin, maps_cache/) are gitignored — code and
docs only.
2026-08-11 07:00:19 -05:00
4c44933b5d Add tunie: read-only KWP2000 diagnostics for Triumph Keihin ECU
A Python tool to safely read the Keihin ECU on a 2010 Bonneville T100 over
K-Line (KKL cable) or a Bluetooth ELM327, plus the reverse-engineering research
behind it. Phase 1 (read-only comms) of an open tuning toolchain to replace the
closed TuneECU app.

Read-only by construction: safety.assert_read_only() runs on every outbound
request before it hits the wire and refuses all write/flash services (0x27,
0x31, 0x34/0x36, 0x35, 0x37, 0x14, 0x11, 0x2E) and programming sessions, so a
bug cannot brick the ECU. Verified frames match TuneECU byte-for-byte in
tests/verify_protocol.py.

Protocol constants recovered from the TuneECU APK (not guessed): ECU address
0xD5, K-Line tester 0xF5, format byte 0x80|len, additive mod-256 checksum.
Includes the full TuneECU map catalogue (1811 entries) extracted to maps.json,
searchable and filterable by ECU type and mechanical-vs-LCD odometer.

research/ documents the Security Access seed/key algorithm, recovered as
standard AES-128 (three embedded keys), with a self-testing reference impl
verified against FIPS-197. This is write-path material, kept outside the
read-only package.

STATUS.md and README.md capture full context, the risk register, and where we
left off: comms built but not yet run against the bike; next step is wiring the
VAG KKL cable to the Triumph connector and running the first scan.
2026-08-10 14:29:50 -05:00