Skip to content

refactor(#271): E4 band 3b -- gps, imu, env and battery leave src.ino as units - #276

Merged
Strycher merged 1 commit into
mainfrom
fc/212-e4-sensors
Sep 7, 2026
Merged

Strycher merged 1 commit into
mainfrom
fc/212-e4-sensors

Conversation

@Strycher

@Strycher Strycher commented Sep 7, 2026

Copy link
Copy Markdown
Owner

E4 band 3b, task #271 under #264 and Epic #212. Opened autonomously under the owner's standing grant of 2026-09-07.

What moved

The four sensor domains, one unit each — gps, imu, env, battery — 26 functions and their state, the E4-1 structs going to the unit headers without their instances. Ten cut-set variables leave src.ino (7,483 → 6,598 lines). Full composition in docs/god-object-inventory.md §11.

Two corrections to the diagnosis — please read

  1. The relocation graph never counted read-only data. reference-graph.py skipped nm classes R/r, so every const table (tzPresets, the timeout tables, the 1,943-byte BSEC config blob) was invisible to the fan-in tables, the cut set, and the reference sets the band-2 and 3a proofs compared. It surfaced when initBME688 would not compile without the blob. Fixed; on the pre-3b object the graph now reports 79 variables and the same 22-variable cut set, so no ordering decision changes. This band's proof was re-run against a rebuilt pre-move baseline with the fixed graph.
  2. gnrmcFixThisCycle is write-only (set in parseNMEA, cleared by handleWebGpsReset, read by nothing since Bug: GPS Acquiring stays stuck on boot #115). The compiler had eliminated it as a static; publishing it makes it exist, one byte and its stores. Dead state — deleting it is your call. The verifier now names this case rather than failing on it.

Harness

extract_unit.py: comma declarator lists (float a = 0, b = 0, c = 0;), instances declared with their struct (struct GpsData {…} gpsData;), column-0 anchoring (an indented else x = true; had matched as a declaration), bottom-up orphan sweep. verify_extraction.py: the tolerated-published rule above.

Proof

scripts/verify_extraction.py PASS; full output in §11:

symbols   585 -> 589: three static initialisers (120 bytes; src.ino's shrank 106) and the flag
          76 relocated; 11 linkage changes, all declared; removed none
deltas    25 symbols, net -88, all attributed; unexplained none
sections  .flash.text +164 (our inputs +147: .text +54, literal pools +76, startup +17; +17 alignment)
          .flash.rodata +96 (inputs +228, merged); RAM unchanged
Flash     1,856,146 -> 1,856,406   Both toolchains build. 58 tests pass. Not flashed.

… as units

Four units, one per sensor domain, each taking its state with it:

  src/gps.{h,cpp}      gpsData (GpsData), the NMEA buffer, twelve timing/debug
                       flags, rtcSyncedFromGPS; GPS_*/DEBUG_GPS/NMEA_MAX_FIELDS;
                       initGPS, readGPS, nmeaParse, parseNMEA, getGpsAccuracyMeters
  src/imu.{h,cpp}      imuData (ImuData), imuAvailable, magAvailable, lis, lsm,
                       the twelve magnetometer calibration variables; MAG_*;
                       initIMU, readIMU, loadMagCal, saveMagCal, magLogPrintln
  src/env.{h,cpp}      envData (EnvData), shtData (ShtData), envSensor, sht4,
                       bmeAvailable, shtAvailable, the BSEC state and its config
                       blob; BSEC_*/DEBUG_BSEC; initBME688, initSHT41,
                       bsecDataCallback, readBME688, readSHT41, getIaq*Text,
                       hPaToInHg, load/saveBsecState, save/loadBsecFromFRAM
  src/battery.{h,cpp}  battery, batteryAvailable; BATT_LOG_*; initBattery,
                       logBatteryToSD, logBatteryToFRAM, isBatteryConnected

Ten of the cut-set variables leave src.ino (7,483 -> 6,598 lines).

Two corrections to the diagnosis, found by the build:
  * reference-graph.py never counted read-only data (nm R/r), so const tables
    -- tzPresets, the timeout tables, the 1,943-byte bsec2_config -- were
    invisible to fan-in, the cut set and the proofs' reference sets. Fixed;
    the pre-3b object shows 79 variables and the same 22-variable cut set.
    This proof was re-run against a rebuilt baseline with the fixed graph.
  * gnrmcFixThisCycle is write-only since #115; the compiler had eliminated
    it as a static. Published (a web handler writes it). Dead state, owner's
    call to delete.

Harness: comma declarator lists, struct-with-instance declarations, column-0
anchoring, bottom-up orphan sweep; the verifier names a published variable
that did not exist before.

Verified by scripts/verify_extraction.py, PASS: 585 -> 589 symbols (three
static initialisers, 120 bytes, src.ino's -106; the flag), 76 relocated, 11
linkage changes declared, 25 size deltas net -88 all attributed, unexplained
none. .flash.text +164 (inputs +147: .text +54, literals +76, startup +17;
+17 alignment), .flash.rodata +96 (inputs +228 merged), RAM unchanged.
Flash 1,856,146 -> 1,856,406. Both toolchains build. 58 tests pass.
Record: section 11 of docs/god-object-inventory.md.
@Strycher

Strycher commented Sep 7, 2026

Copy link
Copy Markdown
Owner Author

Merged autonomously under the owner's standing grant of 2026-09-07.

Gate: compile-gate green. Proof: scripts/verify_extraction.py PASS — 585 -> 589 symbols (three static initialisers and the published flag, each named), 76 relocated, 11 linkage changes declared, 25 size deltas attributed, unexplained none; section deltas traced to input sections. Both toolchains build; 58 tests pass. Not flashed.

Set aside for the owner's review, in the PR body: the read-only-data correction to the reference graph, and gnrmcFixThisCycle (write-only dead state) — delete or keep is yours.

@Strycher
Strycher merged commit e6465bb into main Sep 7, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant