1+ # Breakout app UI/driver glue. This app renders into a framebuffer that may be
2+ # smaller than the full display (partial framebuffer). The draw loop is more
3+ # complex because it slices the screen into chunks, renders each slice in C,
4+ # and flushes them sequentially using a flush-ready IRQ callback. A scheduled
5+ # (non-IRQ) handler advances chunks so it can work on larger-than-320x230
6+ # displays without requiring a full-size framebuffer.
17import lvgl as lv
28import time
39import mpos .ui
10+ import micropython
411from mpos import Activity , DisplayMetrics , InputManager
512
613import sys
@@ -30,8 +37,8 @@ class Breakout(Activity):
3037 chunk_rows_per = 0
3138 chunk_total = 0
3239 chunk_index = 0
33-
34- refresh_timer = None
40+ _draw_scheduled = False
41+ _scheduled_draw_cb = None
3542
3643 # Widgets:
3744 screen = None
@@ -47,7 +54,7 @@ def onCreate(self):
4754
4855 d = lv .display_get_default ()
4956 self .hor_res = d .get_horizontal_resolution ()
50- self .paddle_move_step = round (self .hor_res / 16 )
57+ self .paddle_move_step = round (self .hor_res / 10 )
5158 self .ver_res = d .get_vertical_resolution ()
5259
5360 self .leftbutton = lv .button (self .screen )
@@ -74,25 +81,12 @@ def onCreate(self):
7481
7582 def onResume (self , screen ):
7683 lv .log_register_print_cb (self .log_callback )
77- lv .timer_create (self .startit , 4000 , None ).set_repeat_count (1 ) # this needs to be delayed, otherwise the whole thing hangs
84+ lv .timer_create (self .startit , 5000 , None ).set_repeat_count (1 ) # this needs to be delayed, otherwise the whole thing hangs
7885
7986 def onPause (self , screen ):
80- if self .refresh_timer :
81- self .refresh_timer .delete ()
82- mpos .ui .task_handler .remove_event_cb (self .drawframe )
8387 lv .log_register_print_cb (None )
8488 mpos .ui .main_display ._data_bus .register_callback (mpos .ui .main_display ._flush_ready_cb )
8589
86- def startit (self , arg1 = None ):
87- print ("starting it!" )
88- breakout .init (mpos .ui .main_display ._frame_buffer1 , self .hor_res , self .ver_res )
89- mpos .ui .main_display ._data_bus .register_callback (self .flush_ready_cb )
90- mpos .ui .task_handler .add_event_cb (self .drawframe , mpos .ui .task_handler .TASK_HANDLER_STARTED )
91-
92- def flush_ready_cb (self , arg1 = None , arg2 = None ):
93- mpos .ui .main_display ._disp_drv .flush_ready () # with this, it hangs, and without it, the device crashes
94- self .flush_ready = True
95-
9690 def move_left (self ):
9791 breakout .move_paddle (- self .paddle_move_step )
9892
@@ -124,6 +118,21 @@ def unfocus(self):
124118 else :
125119 print ("focus isn't on next or previous, leaving it..." )
126120
121+ def startit (self , arg1 = None ):
122+ print ("starting it!" )
123+ breakout .init (mpos .ui .main_display ._frame_buffer1 , self .hor_res , self .ver_res )
124+ mpos .ui .main_display ._data_bus .register_callback (self .flush_ready_cb )
125+ # Using a scheduled draw would be faster than a periodic one (lv.timer or mpos.ui.task_handler.add_event_cb) but no...
126+ self ._scheduled_draw_cb = self ._scheduled_draw
127+ self ._request_draw ()
128+
129+ def flush_ready_cb (self , arg1 = None , arg2 = None ):
130+ # This is called in IRQ (interrupt) context so it can't allocate memory
131+ # So no printf, no calling drawframe() directly, just setting variables or scheduling...
132+ mpos .ui .main_display ._disp_drv .flush_ready ()
133+ self .flush_ready = True
134+ self ._request_draw ()
135+
127136 def send_to_display (self , y_offset = 0 , rows = None , is_last = True ):
128137 x1 = 0
129138 x2 = mpos .ui .main_display .get_horizontal_resolution () - 1
@@ -159,6 +168,7 @@ def drawframe(self, arg1=None, arg2=None):
159168 if self .chunk_index >= self .chunk_total :
160169 self .chunk_in_progress = False
161170 self .render_next = True
171+ self ._request_draw ()
162172 else :
163173 self ._render_and_send_chunk ()
164174 return
@@ -212,6 +222,18 @@ def _render_and_send_chunk(self):
212222 breakout .render (y_offset , rows , advance )
213223 self .send_to_display (y_offset , rows , is_last )
214224
225+ def _request_draw (self ):
226+ if not self ._draw_scheduled and self ._scheduled_draw_cb :
227+ self ._draw_scheduled = True
228+ try :
229+ micropython .schedule (self ._scheduled_draw_cb , 0 )
230+ except Exception :
231+ self ._draw_scheduled = False
232+
233+ def _scheduled_draw (self , _ ):
234+ self ._draw_scheduled = False
235+ self .drawframe ()
236+
215237 def touch_cb (self , event ):
216238 event_code = event .get_code ()
217239 if event_code == lv .EVENT .PRESSED :
0 commit comments