8282
8383# Button and joystick handling code:
8484from machine import ADC ,Pin
85+ import time
8586
8687btn_x = Pin (38 ,Pin .IN ,Pin .PULL_UP )# X
8788btn_y = Pin (41 ,Pin .IN ,Pin .PULL_UP )# Y
@@ -116,22 +117,28 @@ def read_joystick():
116117return None # No key triggered
117118
118119
119- # Track button states for debouncing (only for buttons, not joystick)
120- last_button_key = None
121- last_button_state = lv .INDEV_STATE .RELEASED
120+ # Key repeat configuration
121+ # This whole debounce logic is only necessary because LVGL 9.2.2 seems to have an issue where
122+ # the lv_keyboard widget doesn't handle PRESSING (long presses) properly, it loses focus.
123+ REPEAT_INITIAL_DELAY_MS = 500 # Delay before first repeat
124+ REPEAT_RATE_MS = 200 # Interval between repeats
125+ last_key = None
126+ last_state = lv .INDEV_STATE .RELEASED
127+ key_press_start = 0 # Time when key was first pressed
128+ last_repeat_time = 0 # Time of last repeat event
122129
123130# Read callback
124131# Warning: This gets called several times per second, and if it outputs continuous debugging on the serial line,
125132# that will break tools like mpremote from working properly to upload new files over the serial line, thus needing a reflash.
126133def keypad_read_cb (indev ,data ):
127- global last_button_key , last_button_state
134+ global last_key , last_state , key_press_start , last_repeat_time
128135data .continue_reading = False
129136
130137# Check buttons and joystick
131138current_key = None
132- is_joystick = False
139+ current_time = time . ticks_ms ()
133140
134- # Check buttons first (debounced)
141+ # Check buttons
135142if btn_x .value ()== 0 :
136143current_key = lv .KEY .ESC
137144elif btn_y .value ()== 0 :
@@ -145,43 +152,52 @@ def keypad_read_cb(indev, data):
145152elif btn_start .value ()== 0 :
146153current_key = lv .KEY .END
147154else :
148- # Check joystick (not debounced)
155+ # Check joystick
149156joystick = read_joystick ()
150157if joystick == "LEFT" :
151158current_key = lv .KEY .LEFT
152- is_joystick = True
153159elif joystick == "RIGHT" :
154160current_key = lv .KEY .RIGHT
155- is_joystick = True
156161elif joystick == "UP" :
157162current_key = lv .KEY .UP
158- is_joystick = True
159163elif joystick == "DOWN" :
160164current_key = lv .KEY .DOWN
161- is_joystick = True
162-
163- # Handle joystick (continuous pressing allowed)
164- if is_joystick and current_key :
165- data .key = current_key
166- data .state = lv .INDEV_STATE .PRESSED # Always send PRESSED for joystick
167- # Handle buttons (debounced)
168- elif current_key :
169- if current_key != last_button_key :
165+
166+ # Key repeat logic
167+ if current_key :
168+ if current_key != last_key :
169+ # New key press
170170data .key = current_key
171171data .state = lv .INDEV_STATE .PRESSED
172- last_button_key = current_key
173- last_button_state = lv .INDEV_STATE .PRESSED
172+ last_key = current_key
173+ last_state = lv .INDEV_STATE .PRESSED
174+ key_press_start = current_time
175+ last_repeat_time = current_time
174176else :
175- data .state = lv .INDEV_STATE .RELEASED # Avoid continuous PRESSED
177+ # Key held: Check for repeat
178+ elapsed = time .ticks_diff (current_time ,key_press_start )
179+ since_last_repeat = time .ticks_diff (current_time ,last_repeat_time )
180+ if elapsed >= REPEAT_INITIAL_DELAY_MS and since_last_repeat >= REPEAT_RATE_MS :
181+ # Send a new PRESSED/RELEASED pair for repeat
182+ data .key = current_key
183+ data .state = lv .INDEV_STATE .PRESSED if last_state == lv .INDEV_STATE .RELEASED else lv .INDEV_STATE .RELEASED
184+ last_state = data .state
185+ last_repeat_time = current_time
186+ else :
187+ # No repeat yet, send RELEASED to avoid PRESSING
188+ data .state = lv .INDEV_STATE .RELEASED
189+ last_state = lv .INDEV_STATE .RELEASED
176190else :
177- # Noinput
178- data .key = last_button_key if last_button_key else lv .KEY .ENTER
191+ # Nokey pressed
192+ data .key = last_key if last_key else lv .KEY .ENTER
179193data .state = lv .INDEV_STATE .RELEASED
180- last_button_key = None
181- last_button_state = lv .INDEV_STATE .RELEASED
194+ last_key = None
195+ last_state = lv .INDEV_STATE .RELEASED
196+ key_press_start = 0
197+ last_repeat_time = 0
182198
183- # Handle ESC for back navigation
184- if current_key == lv .KEY .ESC and last_button_state == lv .INDEV_STATE .PRESSED :
199+ # Handle ESC for back navigation (only on initial PRESSED)
200+ if current_key == lv .KEY .ESC and last_state == lv .INDEV_STATE .PRESSED and since_last_repeat == 0 :
185201import mpos
186202mpos .ui .back_screen ()
187203