kbd improvements
This commit is contained in:
parent
ae87b63524
commit
388842988d
@ -30,6 +30,7 @@ class FullKeyboard(NumpadBase):
|
||||
|
||||
# after full scan, these flags are set for each key
|
||||
self.is_pressed = bytearray(NUM_ROWS * NUM_COLS)
|
||||
self._char_reported = set()
|
||||
|
||||
# what meta keys are currently pressed
|
||||
self.active_meta_keys = set()
|
||||
@ -88,7 +89,6 @@ class FullKeyboard(NumpadBase):
|
||||
|
||||
def _wait_any(self):
|
||||
# wait for any press.
|
||||
#self.timer.deinit()
|
||||
self.waiting_for_any = True
|
||||
|
||||
for r in self.rows:
|
||||
@ -102,7 +102,7 @@ class FullKeyboard(NumpadBase):
|
||||
self._scan_count = 0
|
||||
self.waiting_for_any = False
|
||||
|
||||
def _measure_irq(self, _timer):
|
||||
def _measure_irq(self, _unused):
|
||||
# CHALLENGE: Called at high rate (61Hz), but can do memory alloc.
|
||||
# - sample all keys once, record any that are pressed
|
||||
if self.waiting_for_any:
|
||||
@ -143,7 +143,7 @@ class FullKeyboard(NumpadBase):
|
||||
def process_chg_state(self, new_presses):
|
||||
# we're done a full scan (mulitple times: NUM_SAMPLES)
|
||||
# - convert that into ascii-like events in a Q for rest of system
|
||||
# - not trying to support multiple presses, just one
|
||||
# - during multiple presses, each reported once, then when "all up", another event
|
||||
shift_down = self.is_pressed[KEYNUM_SHIFT]
|
||||
symbol_down = self.is_pressed[KEYNUM_SYMBOL]
|
||||
status_chg = dict()
|
||||
@ -175,15 +175,17 @@ class FullKeyboard(NumpadBase):
|
||||
continue
|
||||
|
||||
# indicated key was found to be down and then back up
|
||||
key = decoder[kn]
|
||||
if key == '\0':
|
||||
# - now it is a character, not a key anymore
|
||||
ch = decoder[kn]
|
||||
if ch == '\0':
|
||||
# dead/unused key: do nothing - like SYM+D
|
||||
#print("KEYNUM %d is no-op (in this state)" % kn)
|
||||
continue
|
||||
|
||||
if key != self.key_pressed:
|
||||
#print("KEY: event=%d => %c=0x%x" % (kn, key, ord(key)))
|
||||
self._key_event(key)
|
||||
if ch not in self._char_reported:
|
||||
#print("KEY: event=%d => %c=0x%x" % (kn, ch, ord(ch)))
|
||||
self._char_reported.add(ch)
|
||||
self._key_event(ch)
|
||||
|
||||
self.lp_time = utime.ticks_ms()
|
||||
|
||||
@ -205,7 +207,8 @@ class FullKeyboard(NumpadBase):
|
||||
uasyncio.create_task(dis.async_draw_status(**status_chg))
|
||||
|
||||
if not any(self.is_pressed):
|
||||
if self.key_pressed:
|
||||
if self._char_reported:
|
||||
self._char_reported.clear()
|
||||
self._key_event('')
|
||||
|
||||
if utime.ticks_diff(utime.ticks_ms(), self.lp_time) > 250:
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#
|
||||
import pincodes, version, random
|
||||
from glob import dis
|
||||
from ux import PressRelease, ux_wait_keyup, ux_show_story, ux_show_pin, ux_show_phish_words
|
||||
from ux import ux_wait_keyup, ux_wait_keydown, ux_show_story, ux_show_pin, ux_show_phish_words
|
||||
from callgate import show_logout
|
||||
from pincodes import pa
|
||||
from uasyncio import sleep_ms
|
||||
@ -76,9 +76,9 @@ class LoginUX:
|
||||
self.shuffle_keys()
|
||||
|
||||
self.show_pin(True)
|
||||
pr = PressRelease('0123456789y'+KEY_ENTER)
|
||||
while 1:
|
||||
ch = await pr.wait()
|
||||
ch = await ux_wait_keydown(None, 10000)
|
||||
if ch is None: continue
|
||||
|
||||
if has_qwerty and not self.is_setting and ch.upper() == self.kill_btn:
|
||||
# wipe the seed if they press a special key
|
||||
|
||||
@ -14,7 +14,7 @@ from ustruct import pack, unpack
|
||||
from ubinascii import unhexlify as a2b_hex
|
||||
from ubinascii import b2a_base64, a2b_base64
|
||||
|
||||
from ux import ux_show_story, ux_wait_keyup
|
||||
from ux import ux_show_story, ux_wait_keydown
|
||||
from utils import B2A, problem_file_line, parse_addr_fmt_str
|
||||
from public_constants import AF_CLASSIC
|
||||
from charcodes import KEY_ENTER, KEY_CANCEL
|
||||
@ -322,7 +322,6 @@ class NFCHandler:
|
||||
# - user can press OK during this period if they know they are done
|
||||
min_delay = (3000 if write_mode else 1000)
|
||||
|
||||
first = True
|
||||
while 1:
|
||||
if dis.has_lcd:
|
||||
phase = (phase + 1) % 2
|
||||
@ -334,12 +333,7 @@ class NFCHandler:
|
||||
dis.show()
|
||||
|
||||
# wait for key or 250ms animation delay
|
||||
try:
|
||||
ch = await asyncio.wait_for_ms(ux_wait_keyup(flush=first), 250)
|
||||
except asyncio.TimeoutError:
|
||||
ch = None
|
||||
|
||||
first = False
|
||||
ch = await ux_wait_keydown(KEY_ENTER+KEY_CANCEL+'xy', 250)
|
||||
|
||||
if self.last_edge:
|
||||
self.last_edge = 0
|
||||
|
||||
@ -43,6 +43,11 @@ class NumpadBase:
|
||||
self._changes.put_nowait(key)
|
||||
self._changes.put_nowait('')
|
||||
|
||||
def clear_pressed(self):
|
||||
# clear any key that is down right now, but don't generate
|
||||
# a key-up event for it either
|
||||
self.key_pressed = ''
|
||||
|
||||
def _key_event(self, key):
|
||||
if key != self.key_pressed:
|
||||
# annouce change
|
||||
|
||||
@ -206,6 +206,7 @@ class QRScanner:
|
||||
|
||||
break
|
||||
except asyncio.CancelledError:
|
||||
print('scan cancel')
|
||||
return None
|
||||
finally:
|
||||
# Problem: another valid scan can come in just as we are trying
|
||||
|
||||
26
shared/ux.py
26
shared/ux.py
@ -122,6 +122,32 @@ async def ux_wait_keyup(expected=None, flush=False):
|
||||
|
||||
armed = ch
|
||||
|
||||
async def ux_wait_keydown(allowed, timeout_ms):
|
||||
# Wait for PRESS (not press+release) of any key. Return it and arrange so
|
||||
# that the later release doesn't cause confusion.
|
||||
# - no key repeat here
|
||||
from glob import numpad
|
||||
|
||||
for t in range(timeout_ms):
|
||||
if numpad.empty():
|
||||
await sleep_ms(1)
|
||||
continue
|
||||
|
||||
ch = numpad.get_nowait()
|
||||
|
||||
if ch == numpad.ABORT_KEY:
|
||||
raise AbortInteraction()
|
||||
|
||||
if ch == '' or (allowed and (ch not in allowed)):
|
||||
# keyup or unwanted
|
||||
continue
|
||||
|
||||
numpad.clear_pressed()
|
||||
return ch
|
||||
|
||||
# timeout
|
||||
return None
|
||||
|
||||
def ux_poll_key():
|
||||
# non-blocking check if any key is pressed
|
||||
# - responds to key down only
|
||||
|
||||
@ -59,6 +59,7 @@ class PressRelease:
|
||||
self.last_key = ch
|
||||
return ch
|
||||
|
||||
|
||||
async def ux_confirm(msg):
|
||||
# confirmation screen, with stock title and Y=of course.
|
||||
from ux import ux_show_story
|
||||
|
||||
@ -755,7 +755,7 @@ class QRScannerInteraction:
|
||||
# - CANCEL to abort
|
||||
# - returns a string, BBQr object or None.
|
||||
from glob import dis, SCAN
|
||||
from ux import ux_wait_keyup
|
||||
from ux import ux_wait_keydown
|
||||
frames = [ 1, 2, 3, 4, 5, 4, 3, 2 ]
|
||||
|
||||
if not SCAN:
|
||||
@ -780,10 +780,7 @@ class QRScannerInteraction:
|
||||
ph = (ph + 1) % len(frames)
|
||||
|
||||
# wait for key or 250ms animation delay
|
||||
try:
|
||||
ch = await asyncio.wait_for_ms(ux_wait_keyup(), 250)
|
||||
except asyncio.TimeoutError:
|
||||
ch = None
|
||||
ch = await ux_wait_keydown(KEY_CANCEL, 250)
|
||||
|
||||
if ch == KEY_CANCEL:
|
||||
data = None
|
||||
@ -1063,7 +1060,7 @@ async def show_bbqr_codes(type_code, data, msg, already_hex=False):
|
||||
# - TODO this code needs better home
|
||||
from bbqr import TYPE_LABELS, int2base36
|
||||
from glob import PSRAM, dis
|
||||
from ux import ux_wait_keyup
|
||||
from ux import ux_wait_keyup, ux_wait_keydown
|
||||
import uqr
|
||||
|
||||
PAYLOAD_PER_V40 = 2144 # if HEX encoded, active payload (max) per v40 QR
|
||||
@ -1137,13 +1134,7 @@ async def show_bbqr_codes(type_code, data, msg, already_hex=False):
|
||||
return
|
||||
|
||||
# wait for key or animation delay
|
||||
try:
|
||||
ch = await asyncio.wait_for_ms(ux_wait_keyup(flush=True), ms_per_each)
|
||||
except asyncio.CancelledError:
|
||||
# during testing
|
||||
return
|
||||
except asyncio.TimeoutError:
|
||||
ch = None
|
||||
ch = await ux_wait_keydown(None, ms_per_each)
|
||||
|
||||
if ch: return
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user