v4.3.0 Beta — SprintTimer, CrossingEngine extraction, DOVES_DISABLE_DEBUG - #49
Merged
Conversation
…tability TODO) Move the in-zone ring buffer, zone state machine (_detectLineCrossing), and crossing interpolation verbatim into a reusable CrossingEngine class; line geometry (side-of-line, segment distance, hypotenuse zone test) becomes GeoMath free functions. DovesLapTimer delegates through thin wrappers - public API, memory layout, and numeric behavior unchanged (Layer-2 suites and all four Layer-3 NMEA replay goldens pass unmodified). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HnTP6BdA9xjLR5hSWE9frb
…urse SprintTimer: sprint-mode (autocross/hillclimb) timing - a run starts at a START line and ends at a separate FINISH line, up to two optional splits (0/1/2 all legal). Two states, purely line-driven: start crossing begins a run and cancels+restarts one already in progress (botched-course re-launch); finish crossings with no active run are ignored; DNF is nothing special. Every line has its own CrossingEngine so all lines stay hot on every fix and start/finish zones may overlap. Duck-typed to DovesLapTimer's getter surface (laps == runs) plus run-native aliases. CourseManager::selectCourse(int) selects a layout directly, bypassing CourseDetector - required for sprint (point-to-point driving can never satisfy drive-a-lap-back-to-your-waypoint detection) and useful for app-chosen circuit courses. 15 SprintTimer tests over a synthetic 500m open course (exact-by- construction times) + 4 selectCourse tests. Coverage 85.2% (gate 80). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HnTP6BdA9xjLR5hSWE9frb
…intTimer Example compiles on the ESP32 + XIAO CI cells only (per-line buffers do not fit small AVRs). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HnTP6BdA9xjLR5hSWE9frb
std::forward doesn't exist on classic AVR without the ArxTypeTraits polyfill (no C++ standard library) - the extracted debug templates used it but the new header didn't pull the polyfill in, breaking the Uno/Mega CI cells for any TU that parses CrossingEngine.h before DovesLapTimer.h. Same first-include rule DovesLapTimer.h already follows. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HnTP6BdA9xjLR5hSWE9frb
… on OKC fixture Per review idea: reuse the recorded OKC session as pseudo-sprint data. Start = the OKC 'Normal' S/F line, finish = its real sector-2 line (from the DovesDataLogger SDCARD OKC.json - S/F coords match the fixture to the last digit). Every recorded lap then contains exactly one point-to-point run whose duration must equal that lap's circuit-timer sector-1 time on the same fixes: two independent accounting layers over the same crossing engine agree to the millisecond (28378 / 27903 / 28304 ms, pinned +/-50 like the other layer-3 goldens). Also verifies zero cancellations on circuit data and the fixture-end abandoned run (DNF-as-normal-op) on real GPS. Synthetic suite unchanged - it still owns the semantics circuit data can't produce (staging stops, cancel/restart, ignored finishes). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HnTP6BdA9xjLR5hSWE9frb
SprintTimer: point-to-point run timing (sprint mode) + CrossingEngine extraction + selectCourse
The debug templates' runtime if(_serial) gate keeps every debug string and print call-site in flash even on firmwares that never attach a debug Stream (~150 call sites across the library - several KB on a fully-featured build; the DovesDataLogger beta image just burst its 320 KB OTA cap at 100.9% partly on this dead weight). Defining DOVES_DISABLE_DEBUG swaps the templates for empty inlines so the compiler drops strings and call-sites entirely. Default behavior unchanged; unit-tests CI now runs the host suite both ways. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HnTP6BdA9xjLR5hSWE9frb
DOVES_DISABLE_DEBUG: compile-time debug kill switch (unblocks the logger's OTA size gate)
GCC Code Coverage Report📂 Overall coverage
📄 File coverage
|
- library.properties: 4.2.0 -> 4.3.0 - Doxyfile PROJECT_NUMBER: stale 4.0.0 -> 4.3.0 - CLAUDE.md version line -> 4.3.0 - CHANGELOG: move Unreleased entries under [4.3.0] - 2026-08-10 with release summary; add the 4.3.0 tag link Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TQK29n1LCebSUxf1nD12FW
12 tasks
…iew-j5itt1 chore: v4.3.0 release prep — version bumps + CHANGELOG release heading
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
Promotes the current beta to master as v4.3.0. Three logical changes (merged into
BETAvia #47 and #48), no breaking API changes — all existingDovesLapTimer/CourseManagertiming behavior is pinned by the Layer-3 NMEA replay goldens.1.
CrossingEngine— crossing detection extracted into a reusable core (refactor)detect()), and crossing interpolation moved verbatim out ofDovesLapTimer's private_detectLineCrossing/interpolateCrossingPointinto a newCrossingEngineclass (src/CrossingEngine.h/.cpp). This resolves the long-standingcheckStartFinishsplit-timing portability TODO.geoPointOnSideOfLine,geoPointLineSegmentDistance,geoInsideLineThreshold) moved toGeoMath.h;DovesLapTimer's public methods delegate unchanged.crossingPointBufferEntry,LineDetectResult,timeSinceMidnightDelta(),DOVES_MILLIS_PER_DAY, and theCROSSING_*constants now live inCrossingEngine.hbut remain visible throughDovesLapTimer.hfor back-compat.CrossingEngine.hbuilds on classic AVR.2.
SprintTimer— point-to-point run timing ("sprint mode") (feature)getCancelledRunCount()); a finish while WAITING is ignored; a DNF simply never completes.DovesLapTimer(validation, teleport rejection, odometer). Duck-typed to the fullDovesLapTimergetter surface (laps == runs) plus run-native aliases (getRuns(),getBestRunTime(),isRunActive(), ...).getCurrentLapTime()returns 0 while WAITING as the downstream "waiting" display signal.CourseManager::selectCourse(int)added alongside: activate a known course directly, bypassingCourseDetector(point-to-point driving can never satisfy the detector's drive-a-lap-back-to-your-waypoint premise).examples/sprint_timing_example(synthetic course, Serial only), wired into the CI compile matrix for the 32-bit boards.3.
DOVES_DISABLE_DEBUG— compile-time debug kill switch (feature)if (_serial)check, so production firmwares that never attach a debug Stream still carried every debug string and call site in flash (~150 call sites, several KB). DefiningDOVES_DISABLE_DEBUGswaps all six classes'debug_print/debug_printlntemplates for empty inlines so the compiler drops it all.Type of change
Testing
cd test && make runpasses locally (all suites green)test/test_sprint_timer.cpp— synthetic point-to-point semantics: run times, cancel/restart, ignored finishes, 0/1/2 splits, missed-split invalidationtest/test_nmea_sprint.cpp— real-data differential replay: the OKC 2-laps fixture through BOTH the circuit timer and a SprintTimer (start = S/F, finish = the real OKC sector-2 line); every run must equal that lap's circuit sector-1 time to ±10 ms, plus pinned run goldenstest/test_course_manager.cpp— extended forselectCourse()unit-tests.yml— second host-suite pass with-DDOVES_DISABLE_DEBUGChecklist
README.mdupdated (SprintTimer section + API tables, debug kill switch)CHANGELOG.mdupdated (entries under Unreleased; v4.3.0 release prep: version bumps + all 8 pre-release code-review fixes #50 cuts them into the[4.3.0]release heading)Notes for reviewers
BETAfirst so this PR ships master with correct release metadata. Tagv4.3.0after this merges.SprintTimerintentionally has noDirectionDetector— backward start crossings self-heal via the cancel/restart rule.🤖 Generated with Claude Code
https://claude.ai/code/session_01TQK29n1LCebSUxf1nD12FW