breakout: micropython.schedule() doesnt help

This commit is contained in:
Thomas Farstrike
2026-03-11 13:49:05 +01:00
parent ff563b5427
commit 1cf054e0e3
2 changed files with 45 additions and 17 deletions
+6
View File
@@ -1,3 +1,9 @@
// Breakout native module renderer. Draws into a framebuffer that may be
// smaller than the full display (partial framebuffer). Rendering is done
// per-slice using a y-offset/row count so MicroPythonOS can refresh displays
// larger than 320x230 without allocating a full-size framebuffer. This keeps
// the simulation state global while allowing sequential chunk flushes.
// Include the header file to get access to the MicroPython API
#include "py/dynruntime.h"
#include <stdbool.h>
@@ -1,6 +1,13 @@
# Breakout app UI/driver glue. This app renders into a framebuffer that may be
# smaller than the full display (partial framebuffer). The draw loop is more
# complex because it slices the screen into chunks, renders each slice in C,
# and flushes them sequentially using a flush-ready IRQ callback. A scheduled
# (non-IRQ) handler advances chunks so it can work on larger-than-320x230
# displays without requiring a full-size framebuffer.
import lvgl as lv
import time
import mpos.ui
import micropython
from mpos import Activity, DisplayMetrics, InputManager
import sys
@@ -30,8 +37,8 @@ class Breakout(Activity):
chunk_rows_per = 0
chunk_total = 0
chunk_index = 0
refresh_timer = None
_draw_scheduled = False
_scheduled_draw_cb = None
# Widgets:
screen = None
@@ -47,7 +54,7 @@ class Breakout(Activity):
d = lv.display_get_default()
self.hor_res = d.get_horizontal_resolution()
self.paddle_move_step = round(self.hor_res/16)
self.paddle_move_step = round(self.hor_res/10)
self.ver_res = d.get_vertical_resolution()
self.leftbutton = lv.button(self.screen)
@@ -74,25 +81,12 @@ class Breakout(Activity):
def onResume(self, screen):
lv.log_register_print_cb(self.log_callback)
lv.timer_create(self.startit, 4000, None).set_repeat_count(1) # this needs to be delayed, otherwise the whole thing hangs
lv.timer_create(self.startit, 5000, None).set_repeat_count(1) # this needs to be delayed, otherwise the whole thing hangs
def onPause(self, screen):
if self.refresh_timer:
self.refresh_timer.delete()
mpos.ui.task_handler.remove_event_cb(self.drawframe)
lv.log_register_print_cb(None)
mpos.ui.main_display._data_bus.register_callback(mpos.ui.main_display._flush_ready_cb)
def startit(self, arg1=None):
print("starting it!")
breakout.init(mpos.ui.main_display._frame_buffer1, self.hor_res, self.ver_res)
mpos.ui.main_display._data_bus.register_callback(self.flush_ready_cb)
mpos.ui.task_handler.add_event_cb(self.drawframe, mpos.ui.task_handler.TASK_HANDLER_STARTED)
def flush_ready_cb(self, arg1=None, arg2=None):
mpos.ui.main_display._disp_drv.flush_ready() # with this, it hangs, and without it, the device crashes
self.flush_ready = True
def move_left(self):
breakout.move_paddle(-self.paddle_move_step)
@@ -124,6 +118,21 @@ class Breakout(Activity):
else:
print("focus isn't on next or previous, leaving it...")
def startit(self, arg1=None):
print("starting it!")
breakout.init(mpos.ui.main_display._frame_buffer1, self.hor_res, self.ver_res)
mpos.ui.main_display._data_bus.register_callback(self.flush_ready_cb)
# Using a scheduled draw would be faster than a periodic one (lv.timer or mpos.ui.task_handler.add_event_cb) but no...
self._scheduled_draw_cb = self._scheduled_draw
self._request_draw()
def flush_ready_cb(self, arg1=None, arg2=None):
# This is called in IRQ (interrupt) context so it can't allocate memory
# So no printf, no calling drawframe() directly, just setting variables or scheduling...
mpos.ui.main_display._disp_drv.flush_ready()
self.flush_ready = True
self._request_draw()
def send_to_display(self, y_offset=0, rows=None, is_last=True):
x1 = 0
x2 = mpos.ui.main_display.get_horizontal_resolution() - 1
@@ -159,6 +168,7 @@ class Breakout(Activity):
if self.chunk_index >= self.chunk_total:
self.chunk_in_progress = False
self.render_next = True
self._request_draw()
else:
self._render_and_send_chunk()
return
@@ -212,6 +222,18 @@ class Breakout(Activity):
breakout.render(y_offset, rows, advance)
self.send_to_display(y_offset, rows, is_last)
def _request_draw(self):
if not self._draw_scheduled and self._scheduled_draw_cb:
self._draw_scheduled = True
try:
micropython.schedule(self._scheduled_draw_cb, 0)
except Exception:
self._draw_scheduled = False
def _scheduled_draw(self, _):
self._draw_scheduled = False
self.drawframe()
def touch_cb(self, event):
event_code = event.get_code()
if event_code == lv.EVENT.PRESSED: