Repository navigation
Board detection: confirm boards only from positive evidence - #345
Merged
Merged
Conversation
Introduce detection request and outcome types and run every chip's embedded detection through one session (attempt count, reset escalation, hint, failure reason). Keep confirmed identification separate from successful display adoption. Behavior is unchanged; the legacy C5/C61 autodetect output pointers are preserved and generated detector lists are checked against the session family limit.
Classify results after preparation as confirmed, provisional (family identified, member unresolved; display built) or weak (suggestion only; no display). Only confirmed adoption may write NVS, and only when the value differs; unknown and candidate results leave the stored hint intact. Keep the hint for every attempt and use it only for ordering and provisional member selection. Restrict hinted-member probing to the first non-final attempt so retries recover other members. Remove chip-specific hint gates and final-attempt policies; the final attempt re-measures the same gates. Add setDetectConfig()/detect_config_t to receive the application fallback board before init. A provisional member that differs from it is not constructed; the candidate is retained and the fallback wins on the final attempt. Select unresolved Core2/Tough and Cardputer members by fallback, then hint, then representative, excluding Tough when AXP2101 is observed. Keep PaperMono when PM1 member evidence is unreadable. Mark the Stack signature bypass provisional and report unreadable UnitC6L identification as a weak candidate without replacing an earlier one. Retain directly adopted panels by setup success rather than confidence, keep candidate metadata aligned after setup failures, and warn about configuration changes after init only when the value changes. Add member-suppression injection and host tests for the result projection.
Add detect_config_t::fixed_board and getFixedBoard(). A fixed identity is resolved only against the chip construction table: no detector probing, no package filtering and no NVS access. Startup uses a clean result and a transaction over the board pins, keeps the accepted identity across display startup failures and retries with reset escalation on later init calls. An identity for another chip is rejected with a warning. Share read-only panel, PMIC and VBUS variant observations with family detection, and add fixed startup callbacks for Core2, Tough, CoreInk, CoreS3, AirQ and Atom displays in their required power order. Member selection by touch, camera, capacitance or firmware is omitted; failed variant reads keep the default panel with a warning. Core2-family startup stops when the PMIC identity is unreadable, and fixed Tough uses the observed AXP2101 backlight instead of writing AXP192 registers. Protect pins owned by active OPI memory, capture the StopWatch TE GPIO before construction, and warn when GPIO ownership cannot be acquired. Add host tests for pin guards, retry policy and the BOARD_ID selection guard.
Probe both StopWatch and PaperMono touch controllers and G12/G13 pulls before selecting a member. Pull-based abnormal rows select a provisional member only on the final attempt. Remove the StopWatch rescue power sequence and the NFC 0x50 exclusion (both members can carry that device). Cold PaperMono keeps one pre-confirmation power sequence for D/D and U/U pulls, followed only by its own touch check. This path can also reach StopWatch when touch is unanswered and both IRQ lines read low or are driven high; it is kept as a documented cold-start exception and never switches members during refinement. IOE1 boots hundreds of milliseconds later than PM1, so its response no longer gates identification; the power lists wait for it once before the first IOE1 access (500 ms deadline from the wait). Pending refinement after a power failure retries on non-final attempts instead of adopting an unresolved member; this also applies to Core2/Tough and CoreS3/CoreS3 SE refinement when their power sequence fails. Add touch-address injection and host tests.
Confirm Core2 and Tough from exclusive touch responses before power. For silent AXP192 members, use G12 with G32/G33 to choose the shared Core2/Tough power sequence or the Station LCD probe. Station has only a weak G12 pull-down, so both Port A lines must read up before Core2 power is chosen; a Station with external pull-ups on both Port A lines can still take that path. Station LCD misses and ambiguous subdivisions never select Core2 power from a hint or preference. Contradictory touch answers (M-Bus devices at 0x2E/0x38) never confirm a member. AXP2101 with unanswered touch takes all five attempts before a provisional Core2. A cold AXP192 Core2/Tough with a Port A line held low follows the Station branch and stays unidentified after a Station LCD miss. Treat post-power panel observation failure as optional and keep the touch-confirmed board. After a valid AXP or PM1 ID, later families are not probed in the same attempt even when member confirmation fails. Prepare SD SPI mode before panel observation, including fixed startup. Declare G12/G32/G33 as probe pins so the transaction restores them. Add pre/post-power injection and host tests.
Extend probe_pin_pulls() with optional released samples after each bias and add classify_pin_pull(): strong up/down, weak up/down, floating, pull dependent (no released sample) and conflicting. A zero release delay keeps the previous probe sequence. Replace the DualKey-only floating probe with the common probe and classifier. Its release wait grows from 32 to 128 microseconds so slower weak pulls are not taken as floating. Add C++11 host tests for all sample combinations.
CoreS3 family: the camera or a long release band confirms the camera family; ambiguous or unavailable release without a camera retries and selects fallback, hint or representative only on the final attempt (unavailable deliberately uses all five attempts). StackChan evidence (G5/G6/G7 base pulls, then IOE ACK and firmware in a gated 50 ms window) is observed before member selection. An ACK with unreadable firmware retries before a provisional member; base firmware below 0x04 remains CoreS3. Confirmed SE is kept when camera observation fails and dedicated GPIO timing is unavailable. Cardputer family: read both variant ICs when both pin pairs are high; conflicting answers fail, and the plain Cardputer requires all four lines to float after release. Booting with a key pressed reaches a displayable provisional member after all attempts. Carry the release band in detector-private refine state. Add catalog notes, injection controls and host outcome tables.
Atom family (PICO-D4): require G18 floating before the Voice probe and a strong G12 pull-down (IR transmitter) before Lite/Matrix/U touch scanning. Unrelated PICO-D4 boards no longer become Atom members from touch ratios alone. Document the Atom IR wiring. Stack family: remove the hint/final-attempt bypass. The SD line pulls are required, so a held line can no longer admit Stack reset and drive G33 (which can release the TimerCam power hold). Modified or faulty units with mismatched SD pulls stay unidentified. G32 is not used as evidence because the same pad is camera output on TimerCam and external SDA on Station and Paper.
StampC6 (flash capacity eFuse) and StampC5 (flash/PSRAM eFuse) matches only suggest the module: they no longer confirm, construct or save. Later families still do not probe these pins, and an earlier weak candidate is preserved. Display initialization reports failure for these modules; an application fallback takes precedence. Remove the unconditional StampP4/StampP4X detector: the chip revision alone duplicates the application default without board evidence. Other P4 candidates and fixed startup are unchanged. Log the unresolved weak candidate.
Skip checks that read M5Unified sources when its checkout is absent, so the board specification workflow runs with M5GFX alone. Name the family-member and package-candidate tests by behavior.
ainyan03
force-pushed
the
detect_positive_evidence
branch
from
October 10, 2026 23:23
bf576b6 to
e49fc66
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reworks the embedded board detection so that a board is confirmed (and saved to NVS) only from evidence that belongs to that board itself: an IC identity, its own touch controller, or the pull state of an internal line. Elimination ("not A, so B"), package facts and hints no longer confirm a board.
getBoard()returns the adopted board,getBoardCandidate()the candidate.M5GFX::setDetectConfig()/detect_config_t: the caller's fallback board is passed beforeinit(). When a provisional member differs from it, no display is built and the caller's choice wins.detect_config_t::fixed_board/getFixedBoard(): a fixed firmware identity (used by M5Unified for a positiveBOARD_ID) starts that board directly, without running other families or touching NVS. Construction variants (panel, PMIC) are still observed. ABOARD_IDfor another chip is rejected with a warning.probe_pin_pulls()with a released-pull sample andclassify_pin_pull()(weak up / weak down / floating / pull dependent).Behavior changes
M5GFX_BOARDfor a different board no longer writes NVS on every boot.Display.init()returns false,getBoard()is unknown andgetBoardCandidate()reports the Stamp board.getBoardCandidate()is unknown (was StampP4 / StampP4X).Testing
extras/board_spec:npm test(213 tests, host tests compile the production detection code) andnpm run check. Tests that read M5Unified sources are skipped when M5Unified is not checked out.M5Unified needs the matching change (m5stack/M5Unified#399) for
setDetectConfig()andgetFixedBoard().