Skip to content

Commit a7c5e46

Browse files
Also emulate repeats on buttons
Not great for games, I'm sure...
1 parent 1ff653e commit a7c5e46

File tree

1 file changed

+44
-28
lines changed

1 file changed

+44
-28
lines changed

internal_filesystem/boot_fri3d-2024.py

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282

8383
# Button and joystick handling code:
8484
from machine import ADC, Pin
85+
import time
8586

8687
btn_x = Pin(38, Pin.IN, Pin.PULL_UP) # X
8788
btn_y = Pin(41, Pin.IN, Pin.PULL_UP) # Y
@@ -116,22 +117,28 @@ def read_joystick():
116117
return 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.
126133
def 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
128135
data.continue_reading = False
129136

130137
# Check buttons and joystick
131138
current_key = None
132-
is_joystick = False
139+
current_time = time.ticks_ms()
133140

134-
# Check buttons first (debounced)
141+
# Check buttons
135142
if btn_x.value() == 0:
136143
current_key = lv.KEY.ESC
137144
elif btn_y.value() == 0:
@@ -145,43 +152,52 @@ def keypad_read_cb(indev, data):
145152
elif btn_start.value() == 0:
146153
current_key = lv.KEY.END
147154
else:
148-
# Check joystick (not debounced)
155+
# Check joystick
149156
joystick = read_joystick()
150157
if joystick == "LEFT":
151158
current_key = lv.KEY.LEFT
152-
is_joystick = True
153159
elif joystick == "RIGHT":
154160
current_key = lv.KEY.RIGHT
155-
is_joystick = True
156161
elif joystick == "UP":
157162
current_key = lv.KEY.UP
158-
is_joystick = True
159163
elif joystick == "DOWN":
160164
current_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
170170
data.key = current_key
171171
data.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
174176
else:
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
176190
else:
177-
# No input
178-
data.key = last_button_key if last_button_key else lv.KEY.ENTER
191+
# No key pressed
192+
data.key = last_key if last_key else lv.KEY.ENTER
179193
data.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:
185201
import mpos
186202
mpos.ui.back_screen()
187203

0 commit comments

Comments
 (0)