Skip to content

sti-merpmod

MerpMod flex-fuel firmware for the 2004 USDM STI stock ECU (A2ZJ710J, SH7055, SH-2E big-endian). Private repo angelEmbeddedEra/sti-merpmod, clone ~/sti-merpmod (ROMs only here). Forks (public, no ROMs): angelEmbeddedEra/MerpMod (clone ~/merpmod, remote upstream = Merp/merpmod), angelEmbeddedEra/SharpTune (~/SharpTune), angelEmbeddedEra/SubaruDefs. Full plan: repo docs/HANDOFF-sti-merpmod.md; proven facts: docs/FINDINGS.md. Related: rusefi-sti-2004 (this is the backup tune).

Rules: never write to an ECU from here; in-car first flash per PLAN "In-car first flash" (owner has no bench ECU); read before write, dated reads; tables come from Angel's own tune, not MerpMod defaults.

Windows live-idle tuning handoff (2026-11-09)

Current development is on feature/launch-rolling-limiters; the November 8 state below is historical. Repository commits c2a75e4 (dedicated live profiles) and 8d87f37 (Windows workflow) are pushed. Prioritize Windows plus the existing Tactrix; Mac setup is deferred. Full procedure: Windows idle-tuning workflow.

  • Separate idle, MAF and timing bench prototypes support four sparse RAM cell edits, apply/undo, CSV observation and calibration export/carry-forward between profiles. These are MAF-only development builds; newer flex guard/extensions, rolling and spark additions are absent. Original core flex blending remains. They are not full-flex replacements.
  • Windows uses 32-bit Python with the existing op20pt32.dll. EcuFlash installs the selected profile with the engine off; the Python console handles temporary RAM edits. Final accepted calibration is exported into matching normal firmware and flashed engine-off.
  • Intended loop after device validation: warm unchanged baseline → confirm active curve/cells → small single-variable target experiment → matched CSV → undo/baseline comparison → electrical-load recovery checks. A higher idle target alone does not establish a fixed hunt.
  • Simulator/host checks passed (nine builds, 20 host tests); actual Windows/Tactrix writes, runtime/stack limits, active curve selection and engine behavior remain unvalidated. The stability table is experimental, not identified PI gains. No ECU was accessed/flashed by this development work. Owner had no spare bench ECU at the last recorded hardware check.

Notes sync was verified working again on 2026-11-09: the previously reported rebase was already absent, and the standard locked notes-sync pull/commit/push succeeded. No abort, reset or stash deletion was needed. Pending changes were backed up before sync; old stashes retained.

Current state (2026-11-08)

Start with docs/TUNING-LOG.md on branch tuning-log-2026-11-08 of the repo (https://github.com/angelEmbeddedEra/sti-merpmod/tree/tuning-log-2026-11-08). That branch is not merged to main yet. It holds every flash, binary, log, tool, and finding from the first in-car session. The Windows tuning computer has no repo clone; session files are in Desktop\STI Logger and Downloads\STI-flash-2026-11-08.

  • On the car: 5_FLASH_FIFTH_mafsmooth_40a2473f.bin (verified 2026-11-08 16:43): -Os rewrite, corrected flex scaling, low-end MAF correction and kink smoothing. The rewrite has run on the real ECU; the handoff below predates that.
  • Results: ECU reads flex 10.6% vs 11% on the display. Idle and light-load trims went from about +12% to near zero.
  • Unresolved: idle hunt about 890–990 rpm, not caused by knock, flex, MAF kink, fuel error, or latency. Next: smoke test, charging voltage at 2,000 rpm (ECU logs 12.7–12.8 V driving), electrical load test.
  • Do not repeat: running the engine with the flex sensor unplugged. Display safe mode commands 100% ethanol on a sensor fault.
  • Injectors unconfirmed: tune scaled 750 cc; eBay listing for DeatschWerks 850cc found. Latency is stock and doesn't change the hunt (0.10 ms moves idle fuel about 10%).
  • Tools: read-only double-click loggers in tools/sti-logger (STI_Logger, _Drive, _Drive_Fast). The latest builds, WB_AFR, and fast polling are untested on the car.
  • Wideband: right TGV input (0x33), AFR = V x 2.375 + 7.3125, from the owner's 2025 RomRaider definition. Needs comparing to a gauge.
  • Mac: review and build only; flashing and car logging stay on Windows (docs/MAC-WORKFLOW.md).
  • Ignition research: docs/IGNITION-CUT-RESEARCH.md. Coil scheduler 0x9E34, table 0xF080, runtime VBR 0x7FC50, spark-cut hook points 0x9EA6–0x9EBE and about 0x9F08–0x9F1E. Read-only; needs a spare ECU, crank simulator, and scope. Exact interrupt vector not determined.
  • Hardware plans: smart screen hardware/sti-hmi/PLAN.md; engine-bay CAN sensor node hardware/sti-sensor-node/PLAN.md (sealed AMPSEAL connectors, potting, direct flex output); Boostino 004 in hardware/boostino; unfinished STM32F103 sensor prototype in hardware/sti-sensor-thermo.

Handoff (updated 2026-10-24, chat 1 → next chat)

State: car runs roms/good_tune.bin (md5 784a5146…). Rewrite done: out/good_tune_mod.bin (md5 73e9a2f1…, checksum OK) = good_tune's mod code rewritten at -Os, 4492 → 2204 B, 2288 B free at 0x7F134–0x7FA23; same ID, all settings/tables at the same addresses. Simulator-proven only, never on an ECU. Repo ~/sti-merpmod (private, pushed). Source src/mod/*.c (RAM offset map in mod.h), build src/build_mod.sh (toolchain image), tests test/run.sh (unit diffs), test/drive.sh (whole image through stock hook slots, VARIANT=0..2), test/mutate.sh (21 mutations), tools/coverage.py. Images: sti-sh-toolchain, sti-sh-sim (GDB 14.2 SH sim patched by toolchain/sim-sh7055.sed: RAM alias, round-to-zero/DAZ, SH_COV coverage). Full results: docs/PLAN-improvements.md "Done: -Os rewrite".

Checks passed: traces identical in 3 setting variants; all reachable code executed; 21/21 mutations caught; stack peak 324 vs 356 B; stock call sites only read callee-saved registers after the call; no MAC/FPSCR use.

Open: bench ECU not yet available (needed before any flash); closed-loop trim logs still wanted (Test-8 received: defs/test8, FINDINGS §13); FFS delta fixed in v1 = out/good_tune_mod_v1.bin (src/build_mod.sh v1, PLAN "v1"); patches/flex_guard.json targets the old code: port the guard into UpdateInputs() instead. Owner requests recorded in PLAN: features 1–10 incl. rev-cut mode (fuel/ignition/both) and shift pops; hardware options (bench rig, K-line module, spare ADC).

Next action: port the flex guard into src/mod/inputs.c (keep the no-change build as its own output), then features in PLAN order, each with a drive.sh diff showing only the intended change. Bench ECU: dated read → flash rewrite → verify → run, before the car.

Gotchas

  • Subaru injector flow scaling is stored as a float where cc/min = 2707090 / x (SubaruDefs 32BITBASE): bigger stored value = MORE fuel. Check a def's toexpr before calling any change lean or rich.
  • The handoff's odd "hook" addresses are the first changed byte of aligned 4-byte pointers; scan for words pointing into 0x7E678+ / 0xFFFFC430+.
  • RAM-layout matches alone don't pin the source tree (flag combos alias); confirm with disassembly.

Open

  • Get the ROMs from Drive (angelgdo7@gmail.com, IDs in the handoff): patched-8.bin, read_image6282022.bin, First Read OEM.bin, Test-8 zip, 3-24-2023 mod.bin. No Drive connector in the session yet; Angel offered access.
  • Phase 0 (Angel, Windows + Openport): read the ECU, current_read_YYYYMMDD.bin, diff vs patched-8. Get a junkyard 04 STI bench ECU.
  • Phase 2: find the source tree that built patched-8 (candidates in FINDINGS §1), compare code region byte for byte.
  • Phase 3: Makefile + linker script + Python patcher (hooks, IDs, subarudbw checksum) on the sh-elf toolchain.

Log

  • 2026-11-09: Verified notes sync restored (old rebase already absent); synced pending changes and copied the Windows live-idle workflow from repo commits c2a75e4/8d87f37 into this handoff. No hardware validation or flashing performed.
  • 2026-10-24: Forked MerpMod (21 branches), SharpTune, SubaruDefs; private repo sti-merpmod created with handoff + findings. Build ID v00.60.d17.10.22.1049 proves patched-8 was NOT built from master@2017-10-14: v00.60 needs pre-aa82f24 TargetSelection.bat (MMVERSION), date format needs SharpTune before e5bc9cc/5f96c02 (2017-10-11). Candidates: master line af6e4d5..2c4ec5a, dev_A8DK101X, kercha_dev, dev_candys_map. HEW toolchain = KPIT GNUSH v13.01 (gcc 4.7), so a Linux gcc will match functionally, not byte for byte. Distro gcc-sh4-linux-gnu rejects -m2e; sh-elf gcc 13.3 built in Docker (toolchain/Dockerfile).
  • 2026-10-24: NAS has EmbeddedEra/Subaru STI 2004/good_tune.srf = EcuFlash container (461 B header with ssm2init/ssm2id, then 512 KB ROM), same MerpMod build as patched-8 but a different tune (MAF mode, inj multiplier 1.07→1.94, LC 4750). Saved to repo roms/. subarudbw checksum proven (table 0x7FB80, Σ words + sum = 0x5AA5A55A; tools/subaru_checksum.py). Mod uses 5117/5248 B of the hole: 131 B free. sh-elf-gcc 13.3 -m2e -mb compiles (Docker image sti-sh-toolchain).
  • 2026-10-24: Owner: good_tune.srf is the ROM running on the car; work from it (baseline = repo roms/good_tune.bin, md5 784a5146…). patched-8 is reference only.
  • 2026-10-24: Hooks recovered from good_tune (22 pointer redirects, FINDINGS §10). Disassembly of the injector hack: InjectorScaling = table(blend) × stock 0x5B8E0 (3609.45 = 750 cc). Units cc/min = 2707090/x, so 1.07→1.94 ADDS fuel (+7% on gas, +94% at full blend); my earlier 'leans out, no E85' warning was wrong and is corrected in FINDINGS §6. Source tree still not pinned: code is f9ada49+ (2014-12) style, no public commit matches exactly. Tools: ecumaptool.py (SharpTune port), ram_layout.py, config_search.py, subaru_checksum.py.
  • 2026-10-24: Owner supplied First Read OEM.bin (stock, 32d9ce60…); diff vs good_tune 120 regions / 10 KB; stock hook targets named (PLAN-improvements.md). Owner wants features/fixes hardcoded on top of good_tune's settings; proposal written, awaiting decisions. Chat over budget → handoff above.
  • 2026-10-24: Owner chose to keep working in the same chat despite the budget warning; handoff above stays as the fallback.
  • 2026-10-24: Owner: keep speed density (wants it later), stay on MAF for now, keep Map 2 tunable. Map 2 in good_tune = stock paired tables; timing/fuel identical to Map 1, only boost 18.5→25 psi and WGDC +10% at 80% throttle (FINDINGS §11).
  • 2026-10-24: Pivot: good_tune's code is non-public (two-pointer blend), so no source rebuild; good_tune binary is the base and changes are patches (tools/patch.py, sh-elf-gcc). Free space: 131 B tail + 116 B dead (tools/reach.py). First patch done: flex input fault guard (src/flex_guard.c, patches/flex_guard.json → out/good_tune_flexguard.bin md5 1b905a62…), host test 7/7, not run on ECU. Next: owner's converter curve (sets Vmin/Vmax + ethanol fuel factor), Test-8 zip (def address list = never-touch set), then table-only edits and CEL on fault. Handoff section above still valid except next action.
  • 2026-10-24: Owner: go with -Os rewrite; keep flat-foot shift and CEL flash; wants all listed TODOs plus shift pops (clutch-in high-rpm retard + fuel). Converter nominal 0.5 V=E0..4.5 V=E100 (= good_tune scaling). Guard limits 0.30/4.70 V (out/good_tune_flexguard.bin ad7bb2b3…). Plan order in PLAN-improvements.md.
  • 2026-10-24: Rewrite test method: GDB 14.2 SH sim patched (toolchain/sim-sh7055.sed) to alias 0xFFFF0000+ RAM and use round-to-zero + denormals-to-zero, matching stock reset FPSCR=0x00040001 (OEM 0xEAD6). test/run.sh runs good_tune's original function vs src/mod rewrite on good_tune.bin, bit-for-bit, each with a mutation check. Build uses -ffp-contract=off (no fmac) and keeps FP op order. Done: blend 0x7F888 (132→70 B), Pull3D hook 0x7EEFC (28 B), BandPass/Smooth (52 B); dropped dead Pull2D hook 0x7EF70 (82 B) and BandPassInt 0x7F320 (104 B). So far 662→150 B. Next: whole-image driver through the stock hook slots (stateful functions: rev limit/LC/FFS, CEL, init) with coverage trace.
  • 2026-10-24: Rewrite done: out/good_tune_mod.bin (73e9a2f1…), 4492→2204 B; proven in the sim only (identical whole-image traces ×3 variants, 21/21 mutations, coverage, stack 324≤356 B). Owner asked for rev-cut mode fuel/ignition/both (ignition cut needs the ATU ignition ISR found; soft retard limiter first) and offered custom hardware (PLAN: bench rig, K-line module, spare ADC). Not run on an ECU.
  • 2026-10-24: Test-8 zip received: defs in defs/test8, patched-8 in roms/. patched-8 code = good_tune code (tune differs). All def + logger addresses match the rewrite (no def change needed). Bug: FFS delta setting 0x7E71C never read (FFS cuts at redline); fix awaits owner choice.
  • 2026-10-24: Owner: fix FFS delta + expose hysteresis. Done: out/good_tune_mod_v1.bin (6a4b957d…), FFS cut 6000/resume 5950 (feature test), outputs equal to no-change build when FFS off; def copy with FFS hysteresis in defs/ecuflash. Redline/LC hysteresis were already editable (my earlier claim wrong). Simulator only.
  • 2026-10-24: Owner has no bench ECU, will flash in car. Added checks (garbage RAM, per-hook instruction count, pointer scan, checksum cross-check): all pass. OBD recovery from a non-booting image unclear -> recommended a spare ECU. Procedure in PLAN 'In-car first flash': base build first, then v1.
  • 2026-11-08: First in-car session. Confirmed good_tune by read, flashed the rewrite (runs on the ECU), then corrected flex scaling and low-end MAF (file 5, current). Latency test showed no effect on the idle hunt. Added loggers, tuning record, hardware plans, and ignition research on branch tuning-log-2026-11-08; not merged.