Repository navigation
Scroll a number in place instead of hunting for it on a keypad - #7
Merged
Merged
Conversation
Word numbers were typed on a twelve-key keypad: the two buttons walked a cursor across it and the reader had to find each digit, then find Accept. A number is not a position in a grid, and the buttons were spending both their gestures on navigation rather than on the value. Four boxes now, scrolled one at a time - up and down *are* the digit. Adapted from Blockstream Jade's PIN and index entry (main/ui/digit_entry.c), which shows the same three states: a box still to come, the box being set, and a box already set. Always four boxes. A printed wordlist pads to four digits and whoever reads `0004` off it types all four, so a fixed width costs nothing and removes the Accept key along with the question of when a number is finished. Only digits that still leave a word number reachable are on the ring, which is what keeps 2049 untypeable while 2048 stays reachable; the ring carries a backspace past the last digit, the way enter_value's ring already carried [back]. Going back from the confirmation reopens the last digit rather than clearing the number. Dice rolls scroll in one wider box for the same reason, keeping their quality bar underneath. A card keeps the text screen: "A Clubs" does not fit a box, and its running transcript wants the room. seedtool_render_dice_screen's bar moved into draw_progress_bar so both screens draw the same one rather than each carrying a copy.
Four fixed boxes made 240 a dead end. No fourth digit takes 240x into 1..2048, so the reader who typed it found a box holding nothing but backspace, and the only way to mean 240 was to have known to type 0240 from the start. The field is variable length now. The ring carries the digits that still lead somewhere, then OK once what is typed already names a word, then backspace - the same ring Jade's index entry uses, where a short number also has to be able to stop early. 240 is three presses and an OK. Ending early is not a convenience here. Without it, three-digit numbers are not reachable at all except by a leading zero the reader has no reason to expect. OK appears only once the digits already name a word, so an empty field does not offer it. On a prefix like 20 it does appear, because 20 is both a number and a step towards 200x - both readings are live, which is why the reader is the one who says which was meant. A fourth digit still confirms itself: there is no fifth box to put an OK in. Going back from the confirmation reopens the fourth digit when it was the fourth digit that confirmed, and returns to the field untouched when the reader ended with OK.
The branch predated oroderico#4, and rewriting enter_word_number around the scrolled field dropped the wordset the letter keyboard narrows by: the signature lost `allowed` and the body called the unnarrowed seedtool_word_number. On a mnemonic's last word that leaves the number pad accepting words the letters refuse - the exact asymmetry oroderico#4 exists to prevent, and worse than having neither, since the reader who used the number pad has been told nothing. Nothing caught it. The self-test proves seedtool_word_number_in exact against all 2048 words, but that proves the function; the screen quietly not calling it leaves every test green. So the filter is back in three places and pinned in a fourth: - the ring is built from seedtool_next_digits_in, so a digit that cannot begin an allowed word is never scrollable to in the first place; - OK appears only when seedtool_word_number_in says the digits already name an allowed word; - the confirmation gate narrows too. The ring should already have made a disallowed number untypeable, but this is where a number becomes a word, and a gate inheriting its guarantee from the screen upstream is one bug away from accepting what that screen was supposed to refuse - the same "verified rather than inherited" the address index gets in browse_addresses; - a source-grep test asserts enter_word_number takes the set and calls neither plain function, proved by putting the unnarrowed call back and watching it fail by name. The box geometry was arithmetic checked by eye. Four _Static_asserts now hold it: the widest field against the display, and the arrows against the boxes, the title and the footer. The row is centred, so boxes that do not fit run off both edges where fill_rect clips them silently - a field that looks wrong on the device and fails nowhere. SEEDTOOL_DIGIT_BOXES_MAX names what the renderer can draw, and the app asserts a word number's digits fit inside it, so the two ends are held together rather than agreeing by coincidence. Proved by widening a box to 60px and watching the build fail. Verified with the host self-test and 50 Python tests.
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.
Word numbers are typed on a twelve-key keypad. The two buttons walk a cursor
across it, so both gestures go on navigation and the reader has to find each
digit, then find Accept. A number is not a position in a grid.
This scrolls the value in place instead: up and down are the digit.
Boxes before the active one are set, the active one scrolls, the ones after are
still to come. Adapted from Blockstream Jade's PIN and index entry
(
main/ui/digit_entry.c), which shows the same three states.Dice rolls scroll in one wider box for the same reason, keeping their quality
bar underneath. A card keeps the text screen:
A Clubsdoes not fit a box, andits running transcript wants the room.
Where a number ends
The ring for the active box carries the digits that still lead somewhere, then
OKonce what is typed already names a word, then backspace.That
OKis the part that matters, and the first version of this branch got itwrong by leaving it out. With a fixed four-box field,
240is a dead end — nofourth digit takes
240xinto 1..2048 — so the reader who typed it found a boxholding nothing but backspace, and the only way to mean 240 was to have known
to type
0240from the start. Ending a number early is not a convenience here;without it, three-digit numbers are not reachable at all except through a
leading zero the reader has no reason to expect.
Two consequences worth stating, because neither is arbitrary:
OKis absent on an empty field, since nothing is named yet.OKis present on a prefix like20, because 20 is both a word numberand a step towards 200x. Both readings are live, so the reader is the one who
says which was meant rather than the field guessing.
A fourth digit still confirms itself — there is no fifth box to put an
OKin.Going back from the confirmation reopens that fourth digit when it was the
fourth digit that confirmed, and returns to the field untouched when the reader
ended with
OK.Digit pruning is unchanged:
seedtool_next_digitsalready offered only digitsthat leave a word number reachable, which is what keeps 2049 untypeable while
2048 stays reachable. The ring is built from its answer.
What moved
seedtool_render_digits— the row of boxes, andseedtool_render_value_boxfor a value scrolled whole rather than digit by digit.
seedtool_render_dice_screen's bar moved intodraw_progress_bar, so thedice screen and the scrolled field draw the same bar instead of each carrying
a copy.
enter_word_numberrewritten around the ring;enter_valueroutes a plainnumber to the box and leaves formatted values (cards) on the text screen.
The account-index keypad is deliberately untouched. Its prefixes are all
already valid in-range values, so it has nothing to prune and no early-ending
question to answer — the keypad costs it nothing. Converting it would be
consistency for its own sake, and is easy to add later if that reads better.
Testing
Neither suite reaches rendering or navigation, so this change is almost
entirely outside what they cover. It was driven by hand in the simulator, and
the
240dead end above was found that way rather than by any test — after thefirst version had already been pushed. Worth knowing when reviewing: the box
geometry (34x32 boxes, 11x7 arrows,
OKcentred in a box) is arithmetic thathas only been checked by eye on the simulator, not measured.
The firmware build and its reproducibility check have not been run here — only
the host build and the Python suite.
Notes
Branched from
main. Merges cleanly with #3 and #6.Conflicts with #4, and not trivially: that PR threads a checksum filter
through
enter_word_number, and this rewrites that function. If #4 landsfirst I will reapply the filter on top of the ring — it fits well there, since
the ring is built per box and would simply drop digits that cannot lead to an
allowed word, making the impossible last words unreachable on the number pad
the same way they are on the letters.