From 826253255b5140d41c466eaa8aa63550f1a6903c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NEDJAR?= Date: Fri, 17 Apr 2026 06:26:22 +0200 Subject: [PATCH 1/3] docs: Document @micropython.native usage policy. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #405. Add a guideline to CONTRIBUTING.md: @micropython.native must not be used in driver code (I2C/SPI bus time dominates, native compilation gains nothing) but may be used in examples on rendering hot-paths where a measurable speedup is expected. Remove the unnecessary @micropython.native from compute_display() in radar_screen.py — the function does 3 comparisons with no loop, so native compilation provides no benefit. Also remove the now-unused `import micropython`. --- CONTRIBUTING.md | 1 + lib/vl53l1x/examples/radar_screen.py | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7786b07..0653061 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,6 +35,7 @@ lib// - **Time**: use `from time import sleep_ms` (not `utime`, not `sleep()` with float seconds). - **Exceptions**: use `except Exception:` instead of bare `except:`. Enforced by ruff (E722). - **No debug `print()`** in production driver code. Enforced by ruff (T20, examples and tests excluded). +- **`@micropython.native`**: do **not** use in driver code (`device.py`) — methods are dominated by I2C/SPI bus time, so native compilation gains nothing and reduces debuggability. In **examples**, it may be used on rendering hot-paths (tight pixel loops, math-heavy drawing functions) where a measurable speedup is expected. Do not apply it to functions with only a few comparisons or I/O calls. Note: the native emitter does not support generators, closures, or `with` statements. ## Driver API conventions diff --git a/lib/vl53l1x/examples/radar_screen.py b/lib/vl53l1x/examples/radar_screen.py index ca1c9c2..c3d3dd8 100644 --- a/lib/vl53l1x/examples/radar_screen.py +++ b/lib/vl53l1x/examples/radar_screen.py @@ -7,7 +7,6 @@ from time import sleep_ms -import micropython import ssd1327 from machine import I2C, SPI, Pin from steami_screen import DARK, GRAY, LIGHT, RED, Screen, SSD1327Display @@ -29,7 +28,6 @@ tof = VL53L1X(i2c) -@micropython.native def compute_display(distance): """Compute proximity and color from distance value. From 0864e700f47a76209489a7778eb69e10130d9c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NEDJAR?= Date: Fri, 17 Apr 2026 06:30:27 +0200 Subject: [PATCH 2/3] perf: Add @micropython.native to rendering hot-paths in examples. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply the policy documented in this PR to the three examples with tight pixel loops: - tamagotchi.py: draw_character() — 4 nested loops, pixel by pixel - spirit_level.py: fill_circle() — double loop with x*x + y*y test - maze_game.py: draw_maze() — double loop over 11x11 grid --- lib/bq27441/examples/tamagotchi.py | 2 ++ lib/ism330dl/examples/maze_game.py | 2 ++ lib/ism330dl/examples/spirit_level.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/lib/bq27441/examples/tamagotchi.py b/lib/bq27441/examples/tamagotchi.py index d5b873d..fa0e027 100644 --- a/lib/bq27441/examples/tamagotchi.py +++ b/lib/bq27441/examples/tamagotchi.py @@ -13,6 +13,7 @@ import random from time import sleep_ms, ticks_diff, ticks_ms +import micropython import ssd1327 from bq27441 import BQ27441 from machine import I2C, SPI, Pin @@ -227,6 +228,7 @@ def wait_for_button(): return None +@micropython.native def draw_character(cx, cy, scale, sprite): """Draw a scaled pixel-art sprite on the display framebuf.""" fb = display.framebuf diff --git a/lib/ism330dl/examples/maze_game.py b/lib/ism330dl/examples/maze_game.py index 36fb054..15fe5f1 100644 --- a/lib/ism330dl/examples/maze_game.py +++ b/lib/ism330dl/examples/maze_game.py @@ -18,6 +18,7 @@ import random from time import sleep_ms +import micropython import ssd1327 from ism330dl import ISM330DL from machine import I2C, SPI, Pin @@ -183,6 +184,7 @@ def cell_to_pixel(row, col): return SAFE_X + col * CELL_SIZE, SAFE_Y + row * CELL_SIZE +@micropython.native def draw_maze(maze): """Draw all maze walls as filled rectangles.""" for row in range(len(maze)): diff --git a/lib/ism330dl/examples/spirit_level.py b/lib/ism330dl/examples/spirit_level.py index 00b7f67..6c64c37 100644 --- a/lib/ism330dl/examples/spirit_level.py +++ b/lib/ism330dl/examples/spirit_level.py @@ -9,6 +9,7 @@ from time import sleep_ms +import micropython import ssd1327 from ism330dl import ISM330DL from machine import I2C, SPI, Pin @@ -38,6 +39,7 @@ POLL_RATE_MS = 20 +@micropython.native def fill_circle(fbuf, x0, y0, r, c): """Helper to draw a filled circle since framebuf lacks it natively.""" for y in range(-r, r + 1): From d011c58457a14f253d7b6d1bde216f4d2c607824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NEDJAR?= Date: Fri, 17 Apr 2026 06:32:27 +0200 Subject: [PATCH 3/3] perf(ssd1327): Add @micropython.native to draw_cube() in 3D cube example. draw_cube() runs 12 math.sin/cos calls + floating-point arithmetic per frame in a tight animation loop. Native compilation reduces the per-frame overhead significantly on the STM32WB55. --- lib/ssd1327/examples/rotating_3d_cube.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ssd1327/examples/rotating_3d_cube.py b/lib/ssd1327/examples/rotating_3d_cube.py index bbfb625..2bfe7c5 100644 --- a/lib/ssd1327/examples/rotating_3d_cube.py +++ b/lib/ssd1327/examples/rotating_3d_cube.py @@ -1,5 +1,6 @@ import math +import micropython import ssd1327 from machine import SPI, Pin @@ -27,6 +28,7 @@ r = [0, 0, 0] +@micropython.native def draw_cube(): r[0] = r[0] + pi / 180.0 r[1] = r[1] + pi / 180.0