Skip to content

Commit 403cd8d

Browse files
Add qemu board
1 parent 0b23684 commit 403cd8d

1 file changed

Lines changed: 134 additions & 0 deletions

File tree

  • internal_filesystem/lib/mpos/board
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
print("qemu.py running")
2+
3+
import lcd_bus
4+
import lvgl as lv
5+
import machine
6+
import time
7+
8+
import mpos.ui
9+
10+
print("qemu.py display bus initialization")
11+
try:
12+
display_bus = lcd_bus.I80Bus(
13+
dc=7,
14+
wr=8,
15+
cs=6,
16+
data0=39,
17+
data1=40,
18+
data2=41,
19+
data3=42,
20+
data4=45,
21+
data5=46,
22+
data6=47,
23+
data7=48,
24+
reverse_color_bits=False # doesnt seem to do anything?
25+
)
26+
except Exception as e:
27+
print(f"Error initializing display bus: {e}")
28+
print("Attempting hard reset in 3sec...")
29+
time.sleep(3)
30+
machine.reset()
31+
32+
_BUFFER_SIZE = const(28800)
33+
fb1 = display_bus.allocate_framebuffer(_BUFFER_SIZE, lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_DMA)
34+
fb2 = display_bus.allocate_framebuffer(_BUFFER_SIZE, lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_DMA)
35+
36+
import drivers.display.st7789 as st7789
37+
# 320x200 => make 320x240 screenshot => it's 240x200 (but the display shows more than 200)
38+
mpos.ui.main_display = st7789.ST7789(
39+
data_bus=display_bus,
40+
frame_buffer1=fb1,
41+
frame_buffer2=fb2,
42+
display_width=170, # emulator st7789.c has 135
43+
display_height=320, # emulator st7789.c has 240
44+
color_space=lv.COLOR_FORMAT.RGB565,
45+
#color_space=lv.COLOR_FORMAT.RGB888,
46+
color_byte_order=st7789.BYTE_ORDER_RGB,
47+
# rgb565_byte_swap=False, # always False is data_bus.get_lane_count() == 8
48+
reset_pin=5,
49+
backlight_pin=38,
50+
backlight_on_state=st7789.STATE_PWM,
51+
)
52+
mpos.ui.main_display.init()
53+
mpos.ui.main_display.set_power(True)
54+
mpos.ui.main_display.set_backlight(100)
55+
56+
lv.init()
57+
#mpos.ui.main_display.set_rotation(lv.DISPLAY_ROTATION._90) # must be done after initializing display and creating the touch drivers, to ensure proper handling
58+
mpos.ui.main_display.set_color_inversion(True) # doesnt seem to do anything?
59+
60+
# Button handling code:
61+
from machine import Pin
62+
btn_a = Pin(0, Pin.IN, Pin.PULL_UP) # 1
63+
btn_b = Pin(14, Pin.IN, Pin.PULL_UP) # 2
64+
btn_c = Pin(3, Pin.IN, Pin.PULL_UP) # 3
65+
66+
# Key repeat configuration
67+
# This whole debounce logic is only necessary because LVGL 9.2.2 seems to have an issue where
68+
# the lv_keyboard widget doesn't handle PRESSING (long presses) properly, it loses focus.
69+
REPEAT_INITIAL_DELAY_MS = 300 # Delay before first repeat
70+
REPEAT_RATE_MS = 100 # Interval between repeats
71+
last_key = None
72+
last_state = lv.INDEV_STATE.RELEASED
73+
key_press_start = 0 # Time when key was first pressed
74+
last_repeat_time = 0 # Time of last repeat event
75+
76+
# Read callback
77+
# Warning: This gets called several times per second, and if it outputs continuous debugging on the serial line,
78+
# that will break tools like mpremote from working properly to upload new files over the serial line, thus needing a reflash.
79+
def keypad_read_cb(indev, data):
80+
global last_key, last_state, key_press_start, last_repeat_time
81+
since_last_repeat = 0
82+
83+
# Check buttons
84+
current_key = None
85+
current_time = time.ticks_ms()
86+
if btn_a.value() == 0:
87+
current_key = lv.KEY.PREV
88+
elif btn_b.value() == 0:
89+
current_key = lv.KEY.ENTER
90+
elif btn_c.value() == 0:
91+
current_key = lv.KEY.NEXT
92+
93+
if (btn_a.value() == 0) and (btn_c.value() == 0):
94+
current_key = lv.KEY.ESC
95+
96+
if current_key:
97+
if current_key != last_key:
98+
# New key press
99+
data.key = current_key
100+
data.state = lv.INDEV_STATE.PRESSED
101+
last_key = current_key
102+
last_state = lv.INDEV_STATE.PRESSED
103+
key_press_start = current_time
104+
last_repeat_time = current_time
105+
else:
106+
# No key pressed
107+
data.key = last_key if last_key else lv.KEY.ENTER
108+
data.state = lv.INDEV_STATE.RELEASED
109+
last_key = None
110+
last_state = lv.INDEV_STATE.RELEASED
111+
key_press_start = 0
112+
last_repeat_time = 0
113+
114+
# Handle ESC for back navigation (only on initial PRESSED)
115+
if last_state == lv.INDEV_STATE.PRESSED:
116+
if current_key == lv.KEY.ESC:
117+
mpos.ui.back_screen()
118+
119+
120+
group = lv.group_create()
121+
group.set_default()
122+
123+
# Create and set up the input device
124+
indev = lv.indev_create()
125+
indev.set_type(lv.INDEV_TYPE.KEYPAD)
126+
indev.set_read_cb(keypad_read_cb)
127+
indev.set_group(group) # is this needed? maybe better to move the default group creation to main.py so it's available everywhere...
128+
disp = lv.display_get_default() # NOQA
129+
indev.set_display(disp) # different from display
130+
indev.enable(True) # NOQA
131+
from mpos import InputManager
132+
InputManager.register_indev(indev)
133+
134+
print("qemu.py finished")

0 commit comments

Comments
 (0)