Repository navigation
feat(ui): add a Navigation mode - #229
Merged
Merged
Conversation
Road speed low and large, the receiver's clock top left, and an arrow top right pointing where the car is going with north at twelve o'clock. Three readouts the device already computed in three separate modes, on one screen. Closes #228. The unit sits beside the speed rather than under it, which is the one place this screen departs from Speed Only and the reason its face is 208 px against Speed Only's 248. Three digits plus "MPH" and its gap have to fit 540 px, which leaves 454 px for the digits and so caps the face at 208. Speed Only keeps 248 and its label underneath - it answers a narrower question with the whole panel to answer it in, and is deliberately not changed to match. The arrow is absent whenever the heading is not trustworthy, with the reason left in the ring where it would have been. The board has no magnetometer, so the direction is course over ground and a parked car has no heading at all - not a stale one, not north. The gates are Compass mode's, reused rather than restated. The view model composes speed_only_view, clock_view and compass_view rather than formatting anything itself, so the absent-state rules stay in the one place that is already tested for them. One thing none of the three source modes needed: with no receiver all three readouts are absent for the same reason, and printing it beside the speed, under the clock and inside the ring reads as three faults. That case is collapsed to one line. Every other combination keeps its three statuses, because a parked car with a fix and a time and no course really is three different things to say. The mode is appended to OperatingMode, so this is one byte that already existed changing value: no settings format bump, no migration, and a device updating to this firmware keeps its settings. The upper bound in valid_settings moves with it, which test_settings now asserts. Two things found by building it: The digits first rendered mid-panel rather than low. A label's box is a line box and carries the face's descent, which figures never use, so hanging the box off the bottom margin left a quarter of the face's height as empty panel under the number. The baseline is placed now and the box hung from it. That descent is taken from this file's arithmetic rather than from lv_font_get_line_height, because the simulator's countdown_font is a stub that answers every size with one 52 px face. Measuring would have laid the screen out differently in the simulator than on the panel. The unit does measure, and can, because it is a built-in face that is the same font in both places. Verified: make check, make firmware-container-build, and all 78 simulator tests. The rendered snapshot confirms the composition and the absent states; it cannot confirm the numeral's size, because the host face is that stub - which is why the measured "MPH" width (70 px against a 72 px budget) and the resulting three-digit fit were checked against the real metrics separately. Not yet flashed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Closes #228.
Road speed low and large, the receiver's clock top left, and an arrow top right pointing where the car is going with north at twelve o'clock.
The departure from Speed Only, and what it cost
MPHsits beside the speed rather than under it, because the digit line has moved to the bottom of the panel and there is nothing below it any more.Speed Only made the opposite call, and its source says why: "beside would mean reserving width that the three-digit case needs, which is exactly the compromise that costs the face its size." That reason still holds, so the cost was paid rather than argued with:
Three digits plus the unit and its gap have to fit 540 px, which leaves 454 px for the digits and caps the face at 208.
MPHat montserrat_28 measures 70 px against a 72 px budget, and a three-digit speed then runs x 33..483 with 17 px of clearance to the unit.Speed Only is unchanged - still 248 px, still with its label underneath. It answers a narrower question with the whole panel to answer it in. A future reader should not reconcile the two.
The arrow
Absent whenever the heading is not trustworthy, with the reason left in the ring where it would have been. The board has no magnetometer, so the direction is course over ground: a parked car has no heading at all - not a stale one, not north.
The gates are Compass mode's, reused rather than restated (
headAccunder 15 degrees, with a 0.5 m/s backstop under it). The arrow is five positioned dots that move only when the bearing changes by a whole degree, followingCompassScreenrather than rotating artwork - that per-frame work is what starved the UI task in #133 and #141.One cause stated once
With no receiver all three readouts are absent for the same reason, and printing it beside the speed, under the clock and inside the ring reads as three faults. That one case collapses to a single line.
Every other combination keeps its three separate statuses, because a parked car with a fix and a time and no course really is three different things to say - and the heading is the only one of them the driver cannot work out for themselves.
Settings
The mode is appended to
OperatingMode, so this is one byte that already existed changing value: no format bump, no migration, and a device updating to this firmware keeps its settings. The upper bound invalid_settingsmoves with it, whichtest_settingsnow asserts as the enum's last enumerator.Two things found while building it
The digits first rendered mid-panel rather than low. A label's box is a line box and carries the face's descent, which figures never use, so hanging the box off the bottom margin left a quarter of the face's height as empty panel under the number. Caught by looking at the rendered snapshot. The baseline is placed now and the box hung from it.
That descent comes from arithmetic, not from
lv_font_get_line_height. The simulator'scountdown_fontis a stub that answers every size with one 52 px face, so measuring would have laid the screen out differently in the simulator than on the panel. Every other large numeral here is positioned from the same arithmetic for that reason. The unit does measure, and can, because it is a built-in face that is the same font in both places.Verification
make check,make firmware-container-build, all 78 simulator testsnavigation-mode-test: composed readouts, a parked car losing only its arrow, an optimisticheadAccnot beating standing still, one cause stated once, and a quiet receiver holding the clock while dropping the restsimulator-navigation-screenrenders the layout and asserts the absent states;simulator-navigation-live-viewasserts speed and a three-digit heading together against the real replayed streamNot yet flashed.
🤖 Generated with Claude Code