You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Add Benchmark app
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "Benchmark",
|
||||
"publisher": "MicroPythonOS",
|
||||
"short_description": "Benchmark MicroPythonOS",
|
||||
"long_description": "Different benchmarks to measure the speed of MicroPythonOS.",
|
||||
"icon_url": "https://apps.micropythonos.com/apps/com.micropythonos.benchmark/icons/com.micropythonos.benchmark_0.0.1_64x64.png",
|
||||
"download_url": "https://apps.micropythonos.com/apps/com.micropythonos.benchmark/mpks/com.micropythonos.benchmark_0.0.1.mpk",
|
||||
"fullname": "com.micropythonos.benchmark",
|
||||
"version": "0.0.1",
|
||||
"category": "benchmark",
|
||||
"activities": [
|
||||
{
|
||||
"entrypoint": "assets/benchmark.py",
|
||||
"classname": "Benchmark",
|
||||
"intent_filters": [
|
||||
{
|
||||
"action": "main",
|
||||
"category": "launcher"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
import time
|
||||
import _thread
|
||||
|
||||
from mpos.apps import Activity
|
||||
import mpos.ui
|
||||
|
||||
indev_error_x = 160
|
||||
indev_error_y = 120
|
||||
|
||||
DARKPINK = lv.color_hex(0xEC048C)
|
||||
|
||||
class Benchmark(Activity):
|
||||
|
||||
hor_res = 0
|
||||
ver_res = 0
|
||||
layer = None
|
||||
fps_buffer = [0] # Buffer to store FPS
|
||||
bird_x = 100
|
||||
bird_y = 0
|
||||
image_w = 296
|
||||
image_h = 240
|
||||
image_target_w = 160
|
||||
image_target_h = 120
|
||||
image_x = image_w
|
||||
image_y = 0
|
||||
|
||||
#lvgl_w = 160
|
||||
#lvgl_h = 120
|
||||
|
||||
# Widgets:
|
||||
canvas = None
|
||||
image = None
|
||||
|
||||
def onCreate(self):
|
||||
screen = lv.obj()
|
||||
# Make the screen focusable so it can be scrolled with the arrow keys
|
||||
focusgroup = lv.group_get_default()
|
||||
if focusgroup:
|
||||
focusgroup.add_obj(screen)
|
||||
screen.add_event_cb(self.key_cb, lv.EVENT.KEY, None)
|
||||
self.image = lv.image(screen)
|
||||
#self.load_image("data/images/screenshots/snapshot_640x480_RGB565.raw")
|
||||
self.load_image("data/images/screenshots/snapshot_296x240_RGB565.raw")
|
||||
#self.image.set_size(self.lvgl_w, self.lvgl_h)
|
||||
#self.gif.set_size(lvgl_w, lvgl_h) doesn't seem to do anything. get_style_transform_scale_x/y works but then it needs get_style_translate_x/y
|
||||
#self.image.set_scale(max(scale_factor_w,scale_factor_h)) # fills the entire screen but cuts off borders
|
||||
scale_factor_w = round(self.image_target_w * 256 / self.image_w)
|
||||
self.image.set_scale(scale_factor_w)
|
||||
#self.image.set_scale(128)
|
||||
#self.image.set_size(640, 480)
|
||||
self.spinner = lv.spinner(screen)
|
||||
self.spinner.set_size(16, 16)
|
||||
self.setContentView(screen)
|
||||
|
||||
def onResume(self, screen):
|
||||
super().onResume(screen)
|
||||
lv.log_register_print_cb(self.log_callback)
|
||||
try:
|
||||
_thread.stack_size(mpos.apps.good_stack_size())
|
||||
_thread.start_new_thread(self.game, ())
|
||||
except Exception as e:
|
||||
print("Could not start thread: ", e)
|
||||
|
||||
def onStop(self, screen):
|
||||
super().onStop(screen)
|
||||
lv.log_register_print_cb(None)
|
||||
|
||||
|
||||
def extract_dimensions_and_format(self, filename):
|
||||
# Split the filename by '_'
|
||||
parts = filename.split('_')
|
||||
# Get the color format (last part before '.raw')
|
||||
color_format = parts[-1].split('.')[0] # e.g., "RGB565"
|
||||
# Get the resolution (second-to-last part)
|
||||
resolution = parts[-2] # e.g., "240x240"
|
||||
# Split resolution by 'x' to get width and height
|
||||
width, height = map(int, resolution.split('x'))
|
||||
return width, height, color_format.upper()
|
||||
|
||||
def load_image(self, name):
|
||||
if not name.lower().endswith(".raw"):
|
||||
self.image.remove_flag(lv.obj.FLAG.HIDDEN)
|
||||
self.image.set_src(f"M:{name}")
|
||||
else:
|
||||
f = open(name, 'rb')
|
||||
image_data = f.read()
|
||||
print(f"loaded {len(image_data)} bytes from .raw file")
|
||||
f.close()
|
||||
try:
|
||||
width, height, color_format = self.extract_dimensions_and_format(name)
|
||||
except ValueError as e:
|
||||
print(f"Warning: could not extract dimensions and format from raw image: {e}")
|
||||
return
|
||||
print(f"Raw image has width: {width}, Height: {height}, Color Format: {color_format}")
|
||||
stride = width * 2
|
||||
cf = lv.COLOR_FORMAT.RGB565
|
||||
if color_format != "RGB565":
|
||||
print(f"WARNING: unknown color format {color_format}, assuming RGB565...")
|
||||
self.current_image_dsc = lv.image_dsc_t({
|
||||
"header": {
|
||||
"magic": lv.IMAGE_HEADER_MAGIC,
|
||||
"w": width,
|
||||
"h": height,
|
||||
"stride": stride,
|
||||
"cf": cf
|
||||
},
|
||||
'data_size': len(image_data),
|
||||
'data': image_data
|
||||
})
|
||||
self.image.set_src(self.current_image_dsc)
|
||||
|
||||
def touch_cb(self, event):
|
||||
event_code=event.get_code()
|
||||
#print(f"lv_event_t: code={event_code}")
|
||||
if event_code == lv.EVENT.PRESSING:
|
||||
self.runall()
|
||||
|
||||
# Custom log callback to capture FPS
|
||||
def log_callback(self,level, log_str):
|
||||
# Convert log_str to string if it's a bytes object
|
||||
log_str = log_str.decode() if isinstance(log_str, bytes) else log_str
|
||||
# Optional: Print for debugging
|
||||
#print(f"Level: {level}, Log: {log_str}")
|
||||
# Log message format: "sysmon: 25 FPS (refr_cnt: 8 | redraw_cnt: 1), ..."
|
||||
if "sysmon:" in log_str and "FPS" in log_str:
|
||||
try:
|
||||
# Extract FPS value (e.g., "25" from "sysmon: 25 FPS ...")
|
||||
fps_part = log_str.split("FPS")[0].split("sysmon:")[1].strip()
|
||||
fps = int(fps_part)
|
||||
print("Current FPS:", fps)
|
||||
self.fps_buffer[0] = fps
|
||||
except (IndexError, ValueError):
|
||||
pass
|
||||
|
||||
def key_cb(self, event):
|
||||
key = event.get_key()
|
||||
#print(f"got key {key}")
|
||||
|
||||
if key == lv.KEY.UP:
|
||||
self.image_target_w += 20
|
||||
scale_factor_w = round(self.image_target_w * 256 / self.image_w)
|
||||
self.image.set_scale(scale_factor_w)
|
||||
#self.bird_y -= 10
|
||||
elif key == lv.KEY.DOWN:
|
||||
self.image_target_w -= 20
|
||||
scale_factor_w = round(self.image_target_w * 256 / self.image_w)
|
||||
self.image.set_scale(scale_factor_w)
|
||||
#self.bird_y += 10
|
||||
elif key == lv.KEY.LEFT:
|
||||
self.bird_x -= 10
|
||||
elif key == lv.KEY.RIGHT:
|
||||
self.bird_x += 10
|
||||
elif key == lv.KEY.ENTER:
|
||||
self.bird_y -= 25
|
||||
|
||||
def game(self):
|
||||
# print("Waiting a bit before starting...") ; time.sleep(1) # wait for top bar to go away
|
||||
while self.has_foreground():
|
||||
self.update_ui_threadsafe_if_foreground(self.spinner.set_pos, self.bird_x, self.bird_y)
|
||||
self.update_ui_threadsafe_if_foreground(self.image.set_x, self.image_x)
|
||||
time.sleep_ms(10)
|
||||
self.image_x -= 1
|
||||
if self.image_x < (-self.image_target_w*2):
|
||||
self.image_x = self.image_w
|
||||
self.bird_y += 1
|
||||
if self.bird_y > self.image_h:
|
||||
self.bird_y = 0
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
import time
|
||||
import _thread
|
||||
|
||||
from mpos.apps import Activity
|
||||
import mpos.ui
|
||||
|
||||
indev_error_x = 160
|
||||
indev_error_y = 120
|
||||
|
||||
DARKPINK = lv.color_hex(0xEC048C)
|
||||
|
||||
class Benchmark(Activity):
|
||||
|
||||
hor_res = 0
|
||||
ver_res = 0
|
||||
layer = None
|
||||
fps_buffer = [0] # Buffer to store FPS
|
||||
|
||||
# Widgets:
|
||||
canvas = None
|
||||
|
||||
def onCreate(self):
|
||||
screen = lv.obj()
|
||||
self.canvas = lv.canvas(screen)
|
||||
disp = lv.display_get_default()
|
||||
self.hor_res = disp.get_horizontal_resolution()
|
||||
self.ver_res = disp.get_vertical_resolution()
|
||||
self.canvas.set_size(self.hor_res, self.ver_res)
|
||||
self.canvas.set_style_bg_color(lv.color_white(), 0)
|
||||
buffer = bytearray(self.hor_res * self.ver_res * 4)
|
||||
self.canvas.set_buffer(buffer, self.hor_res, self.ver_res, lv.COLOR_FORMAT.NATIVE)
|
||||
self.canvas.fill_bg(lv.color_white(), lv.OPA.COVER)
|
||||
self.layer = lv.layer_t()
|
||||
self.canvas.init_layer(self.layer)
|
||||
self.canvas.add_flag(lv.obj.FLAG.CLICKABLE)
|
||||
self.canvas.add_event_cb(self.touch_cb, lv.EVENT.ALL, None)
|
||||
self.setContentView(screen)
|
||||
|
||||
def onResume(self, screen):
|
||||
#lv.perf_monitor_create(10, NULL, NULL)
|
||||
lv.log_register_print_cb(self.log_callback)
|
||||
#try:
|
||||
# _thread.stack_size(mpos.apps.good_stack_size())
|
||||
# _thread.start_new_thread(self.runall, ())
|
||||
#except Exception as e:
|
||||
# print("Could not start thread: ", e)
|
||||
|
||||
def onStop(self, screen):
|
||||
super().onStop(screen)
|
||||
lv.log_register_print_cb(None)
|
||||
|
||||
def touch_cb(self, event):
|
||||
event_code=event.get_code()
|
||||
#print(f"lv_event_t: code={event_code}")
|
||||
if event_code == lv.EVENT.PRESSING:
|
||||
self.runall()
|
||||
|
||||
# Custom log callback to capture FPS
|
||||
def log_callback(self,level, log_str):
|
||||
# Convert log_str to string if it's a bytes object
|
||||
log_str = log_str.decode() if isinstance(log_str, bytes) else log_str
|
||||
# Optional: Print for debugging
|
||||
#print(f"Level: {level}, Log: {log_str}")
|
||||
# Log message format: "sysmon: 25 FPS (refr_cnt: 8 | redraw_cnt: 1), ..."
|
||||
if "sysmon:" in log_str and "FPS" in log_str:
|
||||
try:
|
||||
# Extract FPS value (e.g., "25" from "sysmon: 25 FPS ...")
|
||||
fps_part = log_str.split("FPS")[0].split("sysmon:")[1].strip()
|
||||
fps = int(fps_part)
|
||||
print("Current FPS:", fps)
|
||||
self.fps_buffer[0] = fps
|
||||
except (IndexError, ValueError):
|
||||
pass
|
||||
|
||||
def runall(self):
|
||||
print("Waiting a bit before starting...")
|
||||
time.sleep(1) # wait for top bar to go away
|
||||
for _ in range(5):
|
||||
self.draw_n_squares(10000)
|
||||
|
||||
def draw_n_squares(self, n):
|
||||
start = time.ticks_ms()
|
||||
for _ in range(n):
|
||||
self.draw_rect(100, 100)
|
||||
end = time.ticks_ms()
|
||||
diff = end - start
|
||||
print(f"draw_rect x {n} took {diff}ms")
|
||||
start = time.ticks_ms()
|
||||
for _ in range(n):
|
||||
self.draw_rect_viper(100, 100)
|
||||
end = time.ticks_ms()
|
||||
diff = end - start
|
||||
print(f"draw_rect_viper x {n} took {diff}ms")
|
||||
|
||||
def draw_rect(self, x: int, y: int):
|
||||
draw_dsc = lv.draw_rect_dsc_t()
|
||||
lv.draw_rect_dsc_t.init(draw_dsc)
|
||||
draw_dsc.bg_color = lv.color_hex(0xffaaaa)
|
||||
draw_dsc.border_color = lv.color_hex(0xff5555)
|
||||
draw_dsc.border_width = 2
|
||||
draw_dsc.outline_color = lv.color_hex(0xff0000)
|
||||
draw_dsc.outline_pad = 3
|
||||
draw_dsc.outline_width = 2
|
||||
a = lv.area_t()
|
||||
a.x1 = x-10
|
||||
a.y1 = y-10
|
||||
a.x2 = x+10
|
||||
a.y2 = y+10
|
||||
lv.draw_rect(self.layer, draw_dsc, a)
|
||||
self.canvas.finish_layer(self.layer)
|
||||
|
||||
@micropython.viper # make it with native compilation
|
||||
def draw_rect_viper(self, x: int, y: int):
|
||||
draw_dsc = lv.draw_rect_dsc_t()
|
||||
lv.draw_rect_dsc_t.init(draw_dsc)
|
||||
draw_dsc.bg_color = lv.color_hex(0xffaaaa)
|
||||
draw_dsc.border_color = lv.color_hex(0xff5555)
|
||||
draw_dsc.border_width = 2
|
||||
draw_dsc.outline_color = lv.color_hex(0xff0000)
|
||||
draw_dsc.outline_pad = 3
|
||||
draw_dsc.outline_width = 2
|
||||
a = lv.area_t()
|
||||
a.x1 = x-10
|
||||
a.y1 = y-10
|
||||
a.x2 = x+10
|
||||
a.y2 = y+10
|
||||
lv.draw_rect(self.layer, draw_dsc, a)
|
||||
self.canvas.finish_layer(self.layer)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
Reference in New Issue
Block a user