diff --git a/assets/apps/ast_parser.py b/assets/apps/ast_parser.py deleted file mode 100644 index 705433b..0000000 --- a/assets/apps/ast_parser.py +++ /dev/null @@ -1,154 +0,0 @@ -""" -PyDevices C Header Parser & Binding Generator (Hero Canvas App for lvgl-bindings) -================================================================================ -Interactive AST token parser stream and binding generator matrix. -- Real-time token scan and syntax highlighting -- C header struct typedef decomposition and schema graph -- Interactive touch token trigger -""" - -import math -from random import random, choice - -from board_config import display_drv -import board_config -import appdev -import events -import pygraphics - -app = appdev.App(board_config) - - -def _color(value): - value = value.lstrip("#") - red, green, blue = int(value[:2], 16), int(value[2:4], 16), int(value[4:], 16) - return (red & 0xF8) << 8 | (green & 0xFC) << 3 | blue >> 3 - - -def _text(display, value, x, y, color, align="left"): - value = str(value) - if align == "right": - x -= len(value) * 8 - elif align == "center": - x -= len(value) * 4 - pygraphics.text8(display, value, int(x), int(y) - 8, _color(color)) - - -C_TOKENS = [ - ("typedef struct", "#38BDF8"), - ("lv_obj_t*", "#818CF8"), - ("lv_color_t", "#34D399"), - ("lv_area_t", "#FBBF24"), - ("lv_event_cb_t", "#F472B6"), - ("lv_screen_active()", "#60A5FA"), - ("lv_display_create()", "#A78BFA"), - ("lv_arc_set_value()", "#F87171"), - ("lv_anim_t*", "#38BDF8"), - ("lv_image_dsc_t", "#4ADE80"), - ("mp_obj_t", "#F59E0B"), - ("mp_bind_method()", "#10B981"), -] - - -class AstParserHero: - def __init__(self, size=240): - self.size = size - self.w = size - self.h = size - self.drv = display_drv - - self.tokens_parsed = 4820 - self.schemas_gen = 142 - self.scan_line_y = 36.0 - self.log_lines = [ - ("PARSE lv_obj_tree.h ...", "#94A3B8"), - ("EMIT mp_lvgl_obj_type", "#10B981"), - ("AST lv_style_prop_t [OK]", "#38BDF8"), - ("GEN bindings_py.c", "#F59E0B"), - ] - - self.draw() - self._bind_events() - - self._tick_subscription = app.every(33, self._timer_tick) - - def _timer_tick(self, _timer): - self.tick() - - def _bind_events(self): - def on_pointer_down(_event): - self.tokens_parsed += 42 - self.schemas_gen += 1 - tok, col = choice(C_TOKENS) - self.log_lines.pop(0) - self.log_lines.append((f"EMIT {tok}", col)) - self.draw() - - app.on(events.MOUSEBUTTONDOWN, on_pointer_down) - - def tick(self): - self.scan_line_y += 1.8 - if self.scan_line_y > 175: - self.scan_line_y = 36.0 - self.tokens_parsed += 8 - if random() > 0.6: - tok, col = choice(C_TOKENS) - self.log_lines.pop(0) - self.log_lines.append((f"MATCH {tok}", col)) - self.draw() - - def draw(self): - display = self.drv - w, h = self.w, self.h - - # 1. Dark Blueprint Bezel Background - display.fill(_color("#070B12")) - - # Subtle Matrix Grid - for gx in range(16, w, 20): - pygraphics.vline(display, gx, 0, h, _color("#111827")) - for gy in range(16, h, 20): - pygraphics.hline(display, 0, gy, w, _color("#111827")) - - # 2. Header Bar - display.fill_rect(0, 0, w, 26, _color("#0F172A")) - pygraphics.hline(display, 0, 26, w, _color("#1E293B")) - _text(display, "LVGL BINDINGS GEN", 10, 17, "#38BDF8") - _text(display, f"AST: {self.schemas_gen}", w - 10, 17, "#10B981", "right") - - # 3. Token Matrix Window - matrix_y = 32 - for i, (text, color) in enumerate(self.log_lines): - row_y = matrix_y + i * 22 - # Terminal prompt pill - pygraphics.round_rect(display, 10, row_y, w - 20, 18, 4, _color("#0F172A"), True) - pygraphics.round_rect(display, 10, row_y, w - 20, 18, 4, _color("#164E63")) - _text(display, ">", 16, row_y + 12, "#64748B") - _text(display, text, 28, row_y + 12, color) - - # 4. Scanning Parse Beam - pygraphics.hline(display, 12, int(self.scan_line_y), w - 24, _color("#38BDF8")) - - # 5. Bottom Generation Telemetry Box - bot_y = 135 - pygraphics.round_rect(display, 10, bot_y, w - 20, 94, 8, _color("#0F172A"), True) - pygraphics.round_rect(display, 10, bot_y, w - 20, 94, 8, _color("#1E293B")) - - # Telemetry Labels - _text(display, "TOKENS PARSED", 18, bot_y + 16, "#94A3B8") - _text(display, "TARGETS", 18, bot_y + 40, "#94A3B8") - _text(display, "HEADER SOT", 18, bot_y + 64, "#94A3B8") - _text(display, f"{self.tokens_parsed:,}", w - 18, bot_y + 16, "#F8FAFC", "right") - _text(display, "CPython / MP / CP", w - 18, bot_y + 40, "#818CF8", "right") - _text(display, "LVGL v9.2.2 C", w - 18, bot_y + 64, "#34D399", "right") - - # Progress bar - pygraphics.round_rect(display, 18, bot_y + 76, w - 36, 6, 3, _color("#1E293B"), True) - prog_w = int((w - 36) * ((self.tokens_parsed % 500) / 500.0)) - pygraphics.round_rect(display, 18, bot_y + 76, max(6, prog_w), 6, 3, _color("#38BDF8"), True) - - if hasattr(self.drv, "show"): - self.drv.show() - - -_ast_app = AstParserHero(size=min(display_drv.width, display_drv.height)) diff --git a/assets/apps/circuit_dial.py b/assets/apps/circuit_dial.py deleted file mode 100644 index eebc7d5..0000000 --- a/assets/apps/circuit_dial.py +++ /dev/null @@ -1,169 +0,0 @@ -""" -PyDevices CircuitPython Dial (Hero Canvas App for lvgl-circuitpython) -==================================================================== -Interactive NeoPixel-style RGB LED ring and capacitive touch dial: -- 16 individually illuminated virtual NeoPixel LED segments -- 360° rainbow chase and interactive touch hue positioning -- Real-time CircuitPython Feather / RP2040 telemetry readouts -""" - -import math -import time - -from board_config import display_drv -import board_config -import appdev -import events -import pygraphics - -app = appdev.App(board_config) - - -def _rgb565(red, green, blue): - return (int(red) & 0xF8) << 8 | (int(green) & 0xFC) << 3 | int(blue) >> 3 - - -def _color(value): - value = value.lstrip("#") - return _rgb565(int(value[:2], 16), int(value[2:4], 16), int(value[4:], 16)) - - -def _text(display, value, x, y, color, align="center"): - value = str(value) - if align == "center": x -= len(value) * 4 - elif align == "right": x -= len(value) * 8 - pygraphics.text8(display, value, int(x), int(y) - 8, color) - - -def hsl_to_rgb(h, s, l): - c = (1.0 - abs(2.0 * l - 1.0)) * s - x = c * (1.0 - abs((h / 60.0) % 2.0 - 1.0)) - m = l - c / 2.0 - if 0 <= h < 60: - r, g, b = c, x, 0 - elif 60 <= h < 120: - r, g, b = x, c, 0 - elif 120 <= h < 180: - r, g, b = 0, c, x - elif 180 <= h < 240: - r, g, b = 0, x, c - elif 240 <= h < 300: - r, g, b = x, 0, c - else: - r, g, b = c, 0, x - return int((r + m) * 255), int((g + m) * 255), int((b + m) * 255) - - -class CircuitDialHero: - def __init__(self, size=240): - self.size = size - self.w = size - self.h = size - self.cx = size // 2 - self.cy = size // 2 - - self.drv = display_drv - - self.num_leds = 16 - self.base_hue = 0.0 - self.selected_led = 0 - self.is_dragging = False - self.brightness = 0.85 - self.last_interaction_time = time.time() - - self.draw() - self._bind_events() - - self._tick_subscription = app.every(33, self._timer_tick) - - def _timer_tick(self, _timer): - self.tick() - - def _bind_events(self): - def update_from_pointer(event): - px = event.pos[0] - self.cx - py = event.pos[1] - self.cy - dist = math.sqrt(px * px + py * py) - if dist >= 25: - ang = (math.degrees(math.atan2(py, px)) + 360.0) % 360.0 - self.base_hue = ang - self.selected_led = int((ang / 360.0) * self.num_leds) % self.num_leds - self.last_interaction_time = time.time() - self.draw() - - def on_pointer_down(event): - self.is_dragging = True - update_from_pointer(event) - - def on_pointer_move(event): - if not self.is_dragging: - return - update_from_pointer(event) - - def on_pointer_up(event): - self.is_dragging = False - - app.on(events.MOUSEBUTTONDOWN, on_pointer_down) - app.on(events.MOUSEMOTION, on_pointer_move) - app.on(events.MOUSEBUTTONUP, on_pointer_up) - - def tick(self): - now = time.time() - if not self.is_dragging and (now - self.last_interaction_time) > 2.0: - self.base_hue = (self.base_hue + 1.2) % 360.0 - self.selected_led = int((self.base_hue / 360.0) * self.num_leds) % self.num_leds - self.draw() - - def draw(self): - display = self.drv - w, h, cx, cy = self.w, self.h, self.cx, self.cy - - # 1. Dark Circular Housing - display.fill(_color("#0A0D14")) - - # 2. Outer Bezel Track - pygraphics.circle(display, cx, cy, 106, _color("#111827"), True) - pygraphics.circle(display, cx, cy, 106, _color("#1F2937")) - - # 3. 16 NeoPixel LEDs - ring_r = 82 - for i in range(self.num_leds): - angle_rad = (i * (360.0 / self.num_leds) - 90.0) * (math.pi / 180.0) - lx = cx + math.cos(angle_rad) * ring_r - ly = cy + math.sin(angle_rad) * ring_r - - # LED Hue calculation - led_hue = (self.base_hue + i * (360.0 / self.num_leds)) % 360.0 - r, g, b = hsl_to_rgb(led_hue, 1.0, 0.55 * self.brightness) - - # Glow aura - is_active = (i == self.selected_led) - if is_active: - pygraphics.circle(display, int(lx), int(ly), 16, _rgb565(r // 3, g // 3, b // 3), True) - - # LED Bead - radius = 10 if is_active else 8 - pygraphics.circle(display, int(lx), int(ly), radius, _rgb565(r, g, b), True) - pygraphics.circle(display, int(lx), int(ly), radius, _color("#FFFFFF" if is_active else "#64748B")) - - # 4. Center Display Hub - hub_r = 54 - pygraphics.circle(display, cx, cy, hub_r, _color("#0D131F"), True) - pygraphics.circle(display, cx, cy, hub_r, _color("#2563EB")) - - # Hub Readouts - _text(display, "CIRCUITPYTHON", cx, cy - 22, _color("#38BDF8")) - - cur_r, cur_g, cur_b = hsl_to_rgb(self.base_hue, 1.0, 0.55) - _text(display, f"LED #{self.selected_led:02d}", cx, cy - 2, _color("#F8FAFC")) - - # Color Hex Badge - hex_str = f"#{cur_r:02X}{cur_g:02X}{cur_b:02X}" - _text(display, hex_str, cx, cy + 18, _rgb565(cur_r, cur_g, cur_b)) - _text(display, "TOUCH TO POSITION", cx, cy + 32, _color("#94A3B8")) - - if hasattr(self.drv, "show"): - self.drv.show() - - -_circuit_app = CircuitDialHero(size=min(display_drv.width, display_drv.height)) diff --git a/assets/apps/mp_console.py b/assets/apps/mp_console.py deleted file mode 100644 index 6f2814c..0000000 --- a/assets/apps/mp_console.py +++ /dev/null @@ -1,198 +0,0 @@ -""" -PyDevices MicroPython LVGL Console (Hero Canvas App for lvgl-micropython) -======================================================================== -Interactive round LVGL v9 micro-benchmark console: -- Animated sweeping spinner widget -- Interactive touch button cycling accent styles -- Live GC heap memory monitor and FPS telemetry -""" - -import math -import time - -import display_driver # wires LVGL display/input into the app -import lvgl as lv -from board_config import display_drv - - -def _color(hex_val): - r = (hex_val >> 16) & 0xFF - g = (hex_val >> 8) & 0xFF - b = hex_val & 0xFF - return lv.color_make(r, g, b) - - -def _font_for(size): - for s in (size, 14, 12, 10, 16, 20): - name = f"font_montserrat_{s}" - if hasattr(lv, name): - f = getattr(lv, name) - if callable(f): - f = f() - if f is not None: - return (f, s) - font = lv.font_default() if hasattr(lv, "font_default") else None - return (font, 14) if font is not None else (None, 0) - - -def _zero_styles(obj): - try: - obj.remove_style_all() - except AttributeError: - pass - parts = ( - 0, - getattr(lv.PART, "MAIN", 0), - getattr(lv.PART, "INDICATOR", 0), - getattr(lv.PART, "KNOB", 0), - getattr(lv.PART, "ITEMS", 0), - getattr(lv.PART, "ANY", 0), - ) - methods = ( - "set_style_pad_all", - "set_style_margin_all", - "set_style_border_width", - "set_style_outline_width", - ) - for part in parts: - for m in methods: - fn = getattr(obj, m, None) - if fn is not None: - try: - fn(0, part) - except (TypeError, AttributeError): - pass - try: - obj.remove_flag(lv.obj.FLAG.SCROLLABLE) - except AttributeError: - pass - return obj - - -THEME_COLORS = [0x38BDF8, 0x10B981, 0xF59E0B, 0xEC4899, 0x8B5CF6] - - -class MPConsoleHero: - def __init__(self, parent=None, size=240): - self.size = size - self.theme_idx = 0 - self.heap_free_kb = 142 - self.tap_count = 0 - - if parent is None: - parent = lv.screen_active() if hasattr(lv, "screen_active") else lv.scr_act() - self.parent = parent - _zero_styles(self.parent) - - self._build_ui() - - def _build_ui(self): - size = self.size - # 1. Bezel - self.bezel = lv.obj(self.parent) - _zero_styles(self.bezel) - self.bezel.set_size(size, size) - self.bezel.center() - self.bezel.set_style_radius(lv.RADIUS_CIRCLE, 0) - self.bezel.set_style_bg_color(_color(0x090D14), 0) - self.bezel.set_style_bg_opa(lv.OPA.COVER, 0) - self.bezel.remove_flag(lv.obj.FLAG.CLICKABLE) - - # 2. Main Dial - dial_size = size - 16 - self.dial = lv.obj(self.bezel) - _zero_styles(self.dial) - self.dial.set_size(dial_size, dial_size) - self.dial.center() - self.dial.set_style_radius(lv.RADIUS_CIRCLE, 0) - self.dial.set_style_bg_color(_color(0x111827), 0) - self.dial.set_style_bg_opa(lv.OPA.COVER, 0) - self.dial.set_style_border_color(_color(0x1F2937), 0) - self.dial.set_style_border_width(1, 0) - self.dial.remove_flag(lv.obj.FLAG.CLICKABLE) - - # 3. Header Label - font_sm, _ = _font_for(10) - font_xs, _ = _font_for(8) - font_md, _ = _font_for(14) - - self.lbl_head = lv.label(self.dial) - _zero_styles(self.lbl_head) - if font_sm: - self.lbl_head.set_style_text_font(font_sm, 0) - self.lbl_head.set_style_text_color(_color(0x38BDF8), 0) - self.lbl_head.set_style_text_align(lv.TEXT_ALIGN.CENTER, 0) - self.lbl_head.set_text("MICROPYTHON C") - self.lbl_head.align(lv.ALIGN.TOP_MID, 0, 24) - - # 4. Animated Spinner Arc - self.spinner = lv.spinner(self.dial) - _zero_styles(self.spinner) - self.spinner.set_size(84, 84) - self.spinner.center() - self.spinner.set_style_arc_width(6, lv.PART.MAIN) - self.spinner.set_style_arc_color(_color(0x1F2937), lv.PART.MAIN) - self.spinner.set_style_arc_width(6, lv.PART.INDICATOR) - self.spinner.set_style_arc_color(_color(THEME_COLORS[self.theme_idx]), lv.PART.INDICATOR) - self.spinner.set_style_arc_rounded(True, lv.PART.INDICATOR) - self.spinner.remove_flag(lv.obj.FLAG.CLICKABLE) - - # 5. Interactive Center Button - btn_cls = getattr(lv, "button", None) or getattr(lv, "btn", None) or lv.obj - self.btn = btn_cls(self.dial) - _zero_styles(self.btn) - self.btn.set_size(56, 56) - self.btn.center() - self.btn.set_style_radius(lv.RADIUS_CIRCLE, 0) - self.btn.set_style_bg_color(_color(0x1F2937), 0) - self.btn.set_style_bg_opa(lv.OPA.COVER, 0) - self.btn.set_style_border_color(_color(THEME_COLORS[self.theme_idx]), 0) - self.btn.set_style_border_width(2, 0) - self.btn.add_flag(lv.obj.FLAG.CLICKABLE) - - self.lbl_btn = lv.label(self.btn) - _zero_styles(self.lbl_btn) - if font_xs: - self.lbl_btn.set_style_text_font(font_xs, 0) - self.lbl_btn.set_style_text_color(_color(0xF9FAFB), 0) - self.lbl_btn.set_style_text_align(lv.TEXT_ALIGN.CENTER, 0) - self.lbl_btn.set_text("TAP ME") - self.lbl_btn.center() - self.lbl_btn.remove_flag(lv.obj.FLAG.CLICKABLE) - - def on_tap(e): - self.cycle_theme() - - self.btn.add_event_cb(on_tap, lv.EVENT.CLICKED, None) - - # 6. Bottom Heap & GC Readout - self.lbl_heap = lv.label(self.dial) - _zero_styles(self.lbl_heap) - if font_xs: - self.lbl_heap.set_style_text_font(font_xs, 0) - self.lbl_heap.set_style_text_color(_color(0x10B981), 0) - self.lbl_heap.set_style_text_align(lv.TEXT_ALIGN.CENTER, 0) - self.lbl_heap.set_text(f"GC HEAP: {self.heap_free_kb} KB") - self.lbl_heap.align(lv.ALIGN.BOTTOM_MID, 0, -32) - - self.lbl_fps = lv.label(self.dial) - _zero_styles(self.lbl_fps) - if font_xs: - self.lbl_fps.set_style_text_font(font_xs, 0) - self.lbl_fps.set_style_text_color(_color(0x9CA3AF), 0) - self.lbl_fps.set_style_text_align(lv.TEXT_ALIGN.CENTER, 0) - self.lbl_fps.set_text("60 FPS | USERMOD") - self.lbl_fps.align(lv.ALIGN.BOTTOM_MID, 0, -18) - - def cycle_theme(self): - self.tap_count += 1 - self.theme_idx = (self.theme_idx + 1) % len(THEME_COLORS) - col = THEME_COLORS[self.theme_idx] - self.spinner.set_style_arc_color(_color(col), lv.PART.INDICATOR) - self.btn.set_style_border_color(_color(col), 0) - self.lbl_head.set_style_text_color(_color(col), 0) - self.heap_free_kb = 120 + (self.tap_count * 7) % 60 - self.lbl_heap.set_text(f"GC HEAP: {self.heap_free_kb} KB") - -_scr = lv.screen_active() if hasattr(lv, "screen_active") else lv.scr_act() -_mp_app = MPConsoleHero(_scr, size=min(display_drv.width, display_drv.height)) diff --git a/assets/apps/thermostat.py b/assets/apps/thermostat.py index b890797..2e662a0 100644 --- a/assets/apps/thermostat.py +++ b/assets/apps/thermostat.py @@ -1,5 +1,5 @@ """ -PyDevices LVGL Smart Thermostat (Hero Canvas App for lvgl-python) +PyDevices LVGL Smart Thermostat (Hero Canvas App for omnipython-lvgl) ================================================================= Modern LVGL v9 circular climate dial featuring an interactive target temperature arc, touch-draggable knob, ambient status readout, and multi-state ECO leaf badge. diff --git a/assets/js/site-chrome.js b/assets/js/site-chrome.js index 6e3bed2..dc41b53 100644 --- a/assets/js/site-chrome.js +++ b/assets/js/site-chrome.js @@ -170,40 +170,13 @@ color: "var(--tier-3-blue, #3b82f6)", repos: [ { - id: "lvgl-bindings", - name: "lvgl-bindings", - path: "/lvgl-bindings/", - url: ROOT + "/lvgl-bindings/", - tag: "Generator", - desc: "C header AST parser & zero-copy binding generator", + id: "omnipython-lvgl", + name: "omnipython-lvgl", + path: "/omnipython-lvgl/", + url: ROOT + "/omnipython-lvgl/", + tag: "LVGL", + desc: "LVGL v9 for MicroPython, CircuitPython and CPython", icon: '' - }, - { - id: "lvgl-micropython", - name: "lvgl-micropython", - path: "/lvgl-micropython/", - url: ROOT + "/lvgl-micropython/", - tag: "MicroPython", - desc: "Precompiled LVGL v9 usermod bindings for MicroPython", - icon: '' - }, - { - id: "lvgl-python", - name: "lvgl-python", - path: "/lvgl-python/", - url: ROOT + "/lvgl-python/", - tag: "CPython / WASM", - desc: "LVGL Python wheels for Linux, Windows & WebAssembly", - icon: '' - }, - { - id: "lvgl-circuitpython", - name: "lvgl-circuitpython", - path: "/lvgl-circuitpython/", - url: ROOT + "/lvgl-circuitpython/", - tag: "CircuitPython", - desc: "Custom firmware builds with LVGL for CircuitPython", - icon: '' } ] }, diff --git a/data/repos_db.json b/data/repos_db.json index 7575f9a..427072e 100644 --- a/data/repos_db.json +++ b/data/repos_db.json @@ -35,7 +35,11 @@ "displayif": "now [`modules/displayif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/displayif) in micropython-pydevices. The old repository is archived.", "audioif": "now [`modules/audioif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/audioif) in micropython-pydevices. The old repository is archived.", "cameraif": "now [`modules/cameraif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/cameraif) in micropython-pydevices. The old repository is archived.", - "usbif": "the C module is now [`modules/usbhost`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/usbhost) in micropython-pydevices; the Python USB packages are in [pydevices](https://github.com/PyDevices/pydevices/blob/main/docs/guides/usb.md). The old repository is archived." + "usbif": "the C module is now [`modules/usbhost`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/usbhost) in micropython-pydevices; the Python USB packages are in [pydevices](https://github.com/PyDevices/pydevices/blob/main/docs/guides/usb.md). The old repository is archived.", + "lvgl-bindings": "now [`binding`](https://github.com/PyDevices/omnipython-lvgl/tree/main/binding) in omnipython-lvgl. The old repository is archived.", + "lvgl-micropython": "now [`ports/micropython`](https://github.com/PyDevices/omnipython-lvgl/tree/main/ports/micropython) in omnipython-lvgl. The old repository is archived.", + "lvgl-python": "now [`ports/cpython`](https://github.com/PyDevices/omnipython-lvgl/tree/main/ports/cpython) in omnipython-lvgl. The old repository is archived.", + "lvgl-circuitpython": "now [`ports/circuitpython`](https://github.com/PyDevices/omnipython-lvgl/tree/main/ports/circuitpython) in omnipython-lvgl. The old repository is archived." } }, "pydevices": { @@ -402,177 +406,173 @@ }, "omnipython-lvgl": { "tier": 3, - "page": "none", - "portal_grid": false, + "page": "portal-subdir", "tier_name": "LVGL Native Extensions & Binding Generator", "theme_color": "var(--tier-3-blue)", "eyebrow": "omnipython-lvgl", "headline": "omnipython-lvgl — LVGL v9 for MicroPython, CircuitPython and CPython.", - "description": "LVGL v9 for MicroPython, CircuitPython and CPython from one binding generator, which parses LVGL's C headers into a MicroPython user C module, a CircuitPython module and a CPython extension (the `pydevices-lvgl` wheels).", + "description": "LVGL v9 for Python: one binding generator turns LVGL's C headers into a MicroPython module, a CircuitPython module and a CPython wheel, so a program imports lvgl the same way on a desktop and on both kinds of board.", + "hero_canvas": { + "app": "thermostat", + "width": 240, + "height": 240, + "shape": "round", + "app_url": "https://PyDevices.github.io/assets/apps/thermostat.py" + }, "buttons": [ { "label": "GitHub Repo", "href": "https://github.com/PyDevices/omnipython-lvgl", "primary": true + }, + { + "label": "Docs", + "href": "https://github.com/PyDevices/omnipython-lvgl/blob/main/docs/index.md", + "tier_color": true + }, + { + "label": "TestPyPI", + "href": "https://test.pypi.org/project/pydevices-lvgl/", + "tier_color": true + }, + { + "label": "Gallery", + "href": "https://pydevices.github.io/gallery/pyscript/", + "tier_color": true } - ], - "ecosystem_map": true + ] }, "lvgl-bindings": { "tier": 3, "page": "portal-subdir", + "portal_grid": false, + "title": "PyDevices - lvgl-bindings (moved)", "tier_name": "LVGL Native Extensions & Binding Generator", "theme_color": "var(--tier-3-blue)", - "eyebrow": "lvgl-bindings", - "headline": "lvgl-bindings — Automated C header parser & binding generator.", - "description": "Automated binding generator parsing LVGL C headers into native CPython extensions, MicroPython usermods, and CircuitPython modules.", - "hero_canvas": { - "app": "ast_parser", - "width": 240, - "height": 240, - "shape": "square", - "app_url": "https://PyDevices.github.io/assets/apps/ast_parser.py" - }, + "eyebrow": "lvgl-bindings · moved", + "headline": "lvgl-bindings has moved into omnipython-lvgl.", + "description": "Moved to omnipython-lvgl as binding/, the generator that parses LVGL's C headers into the MicroPython, CircuitPython and CPython modules, with its history. Your code doesn't change. The old repository is archived.", "buttons": [ { - "label": "GitHub Repo", - "href": "https://github.com/PyDevices/lvgl-bindings", + "label": "omnipython-lvgl", + "href": "https://github.com/PyDevices/omnipython-lvgl", "primary": true }, { - "label": "MicroPython Module", - "href": "https://pydevices.github.io/lvgl-micropython/", + "label": "How the generator works", + "href": "https://github.com/PyDevices/omnipython-lvgl/blob/main/docs/how-it-works/generator-architecture.md", "tier_color": true }, { - "label": "CPython Wheel", - "href": "https://pydevices.github.io/lvgl-python/", + "label": "Docs", + "href": "https://github.com/PyDevices/omnipython-lvgl/blob/main/docs/index.md", "tier_color": true }, { - "label": "CircuitPython Module", - "href": "https://pydevices.github.io/lvgl-circuitpython/", + "label": "Archived repo", + "href": "https://github.com/PyDevices/lvgl-bindings", "tier_color": true } - ], - "ecosystem_map": false + ] }, "lvgl-micropython": { "tier": 3, "page": "portal-subdir", + "portal_grid": false, + "title": "PyDevices - lvgl-micropython (moved)", "tier_name": "LVGL Native Extensions & Binding Generator", "theme_color": "var(--tier-3-blue)", - "eyebrow": "lvgl-micropython", - "headline": "lvgl-micropython — MicroPython C usermod for LVGL v9.", - "description": "Native MicroPython C module integrating LVGL v9 graphics engine with displayif bus drivers on ESP32 targets.", - "hero_canvas": { - "app": "mp_console", - "width": 240, - "height": 240, - "shape": "round", - "app_url": "https://PyDevices.github.io/assets/apps/mp_console.py" - }, + "eyebrow": "lvgl-micropython · moved", + "headline": "lvgl-micropython has moved into omnipython-lvgl.", + "description": "Moved to omnipython-lvgl as its MicroPython port: build it into your firmware from the same repository that holds the generator. Your code doesn't change. The old repository is archived.", "buttons": [ { - "label": "GitHub Repo", - "href": "https://github.com/PyDevices/lvgl-micropython", + "label": "omnipython-lvgl", + "href": "https://github.com/PyDevices/omnipython-lvgl", "primary": true }, { - "label": "Get started", - "href": "https://github.com/PyDevices/lvgl-bindings/blob/main/docs/get-started/install.md#micropython-compatible-firmware-with-lvgl-micropython", + "label": "Build MicroPython with LVGL", + "href": "https://github.com/PyDevices/omnipython-lvgl/blob/main/docs/guides/build-micropython-firmware-with-lvgl.md", "tier_color": true }, { - "label": "lvgl-bindings", - "href": "https://pydevices.github.io/lvgl-bindings/", + "label": "Install", + "href": "https://github.com/PyDevices/omnipython-lvgl/blob/main/docs/get-started/install.md", "tier_color": true }, { - "label": "pydevices Core", - "href": "https://pydevices.github.io/pydevices/", + "label": "Archived repo", + "href": "https://github.com/PyDevices/lvgl-micropython", "tier_color": true } - ], - "ecosystem_map": false + ] }, "lvgl-python": { "tier": 3, "page": "portal-subdir", + "portal_grid": false, + "title": "PyDevices - lvgl-python (moved)", "tier_name": "LVGL Native Extensions & Binding Generator", "theme_color": "var(--tier-3-blue)", - "eyebrow": "lvgl-python", - "headline": "lvgl-python — CPython & Pyodide WASM extension wheels.", - "description": "Pre-built CPython extension wheels and Pyodide WASM packages bringing LVGL v9 to Linux, Windows, Android, and web browsers.", - "hero_canvas": { - "app": "thermostat", - "width": 240, - "height": 240, - "shape": "round", - "app_url": "https://PyDevices.github.io/assets/apps/thermostat.py" - }, + "eyebrow": "lvgl-python · moved", + "headline": "lvgl-python has moved into omnipython-lvgl.", + "description": "Moved to omnipython-lvgl as its CPython port. The wheels are still pydevices-lvgl on TestPyPI. Your code doesn't change. The old repository is archived.", "buttons": [ { - "label": "GitHub Repo", - "href": "https://github.com/PyDevices/lvgl-python", + "label": "omnipython-lvgl", + "href": "https://github.com/PyDevices/omnipython-lvgl", "primary": true }, { - "label": "TestPyPI", - "href": "https://test.pypi.org/project/pydevices-lvgl/", + "label": "Install the wheel", + "href": "https://github.com/PyDevices/omnipython-lvgl/blob/main/docs/get-started/install.md", "tier_color": true }, { - "label": "Gallery", - "href": "https://pydevices.github.io/gallery/gallery/", + "label": "TestPyPI", + "href": "https://test.pypi.org/project/pydevices-lvgl/", "tier_color": true }, { - "label": "pydevices Core", - "href": "https://pydevices.github.io/pydevices/", + "label": "Archived repo", + "href": "https://github.com/PyDevices/lvgl-python", "tier_color": true } - ], - "ecosystem_map": false + ] }, "lvgl-circuitpython": { "tier": 3, "page": "portal-subdir", + "portal_grid": false, + "title": "PyDevices - lvgl-circuitpython (moved)", "tier_name": "LVGL Native Extensions & Binding Generator", "theme_color": "var(--tier-3-blue)", - "eyebrow": "lvgl-circuitpython", - "headline": "lvgl-circuitpython — CircuitPython native LVGL C module.", - "description": "CircuitPython native C module providing LVGL v9 bindings and displayif integration for the Adafruit Feather RP2040 and ESP32 boards.", - "hero_canvas": { - "app": "circuit_dial", - "width": 240, - "height": 240, - "shape": "round", - "app_url": "https://PyDevices.github.io/assets/apps/circuit_dial.py" - }, + "eyebrow": "lvgl-circuitpython · moved", + "headline": "lvgl-circuitpython has moved into omnipython-lvgl.", + "description": "Moved to omnipython-lvgl as its CircuitPython port: build it into your firmware from the same repository that holds the generator. Your code doesn't change. The old repository is archived.", "buttons": [ { - "label": "GitHub Repo", - "href": "https://github.com/PyDevices/lvgl-circuitpython", + "label": "omnipython-lvgl", + "href": "https://github.com/PyDevices/omnipython-lvgl", "primary": true }, { - "label": "Get started", - "href": "https://github.com/PyDevices/lvgl-bindings/blob/main/docs/get-started/install.md#circuitpython-compatible-firmware-with-lvgl-circuitpython", + "label": "Build CircuitPython with LVGL", + "href": "https://github.com/PyDevices/omnipython-lvgl/blob/main/docs/guides/build-circuitpython-firmware-with-lvgl.md", "tier_color": true }, { - "label": "lvgl-bindings", - "href": "https://pydevices.github.io/lvgl-bindings/", + "label": "Install", + "href": "https://github.com/PyDevices/omnipython-lvgl/blob/main/docs/get-started/install.md", "tier_color": true }, { - "label": "pydevices Core", - "href": "https://pydevices.github.io/pydevices/", + "label": "Archived repo", + "href": "https://github.com/PyDevices/lvgl-circuitpython", "tier_color": true } - ], - "ecosystem_map": false + ] }, "pyscript-template": { "tier": 4, diff --git a/profile/README.md b/profile/README.md index b7013d7..03f838f 100644 --- a/profile/README.md +++ b/profile/README.md @@ -39,7 +39,7 @@ Pure Python on any Python 3 host; pygraphics adds native wheels for Linux x86_64 Single-source LVGL C header binding generator and native interpreter modules. -- [`omnipython-lvgl`](https://github.com/PyDevices/omnipython-lvgl) — LVGL v9 for MicroPython, CircuitPython and CPython from one binding generator, which parses LVGL's C headers into a MicroPython user C module, a CircuitPython module and a CPython extension (the `pydevices-lvgl` wheels). +- [`omnipython-lvgl`](https://github.com/PyDevices/omnipython-lvgl) — LVGL v9 for Python: one binding generator turns LVGL's C headers into a MicroPython module, a CircuitPython module and a CPython wheel, so a program imports lvgl the same way on a desktop and on both kinds of board. ### Tier 4: App Hosts & Mobile @@ -64,6 +64,10 @@ MIP package indexing, multi-usermod builds, and serial/FTP IDE extensions. - **audioif** — now [`modules/audioif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/audioif) in micropython-pydevices. The old repository is archived. - **cameraif** — now [`modules/cameraif`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/cameraif) in micropython-pydevices. The old repository is archived. - **usbif** — the C module is now [`modules/usbhost`](https://github.com/PyDevices/micropython-pydevices/tree/main/modules/usbhost) in micropython-pydevices; the Python USB packages are in [pydevices](https://github.com/PyDevices/pydevices/blob/main/docs/guides/usb.md). The old repository is archived. +- **lvgl-bindings** — now [`binding`](https://github.com/PyDevices/omnipython-lvgl/tree/main/binding) in omnipython-lvgl. The old repository is archived. +- **lvgl-micropython** — now [`ports/micropython`](https://github.com/PyDevices/omnipython-lvgl/tree/main/ports/micropython) in omnipython-lvgl. The old repository is archived. +- **lvgl-python** — now [`ports/cpython`](https://github.com/PyDevices/omnipython-lvgl/tree/main/ports/cpython) in omnipython-lvgl. The old repository is archived. +- **lvgl-circuitpython** — now [`ports/circuitpython`](https://github.com/PyDevices/omnipython-lvgl/tree/main/ports/circuitpython) in omnipython-lvgl. The old repository is archived. **Deliberately absent from this map:** diff --git a/scripts/generate_sites.py b/scripts/generate_sites.py index d613719..5edf3bc 100755 --- a/scripts/generate_sites.py +++ b/scripts/generate_sites.py @@ -53,6 +53,7 @@ def get_card_icon(repo_name): 'pdwidgets': '', 'palettes': '', 'lvgl-bindings': '', + 'omnipython-lvgl': '', 'lvgl-micropython': '', 'lvgl-python': '', 'lvgl-circuitpython': '', @@ -82,6 +83,7 @@ def get_tag_label(repo_name): 'pygraphics': '0-Dependency', 'pdwidgets': 'Pure-Python UI', 'palettes': 'Color Engine', + 'omnipython-lvgl': 'LVGL for Python', 'lvgl-bindings': 'LVGL Generator', 'lvgl-micropython': 'MicroPython C', 'lvgl-python': 'CPython / Pyodide', diff --git a/tests/test_generate_sites.py b/tests/test_generate_sites.py index 73eee01..4c68917 100644 --- a/tests/test_generate_sites.py +++ b/tests/test_generate_sites.py @@ -136,6 +136,18 @@ def test_moved_repos_keep_their_page_but_leave_the_grid(self) -> None: self.assertNotEqual(self.gen.page_destination(entry), "none", name) self.assertNotIn(f'href="/{name}/"', self.gen.build_portal_grids_html(self.db)) + def test_the_four_lvgl_repos_give_way_to_omnipython_lvgl(self) -> None: + moved = self.db["_meta"]["moved"] + grid = self.gen.build_portal_grids_html(self.db) + entry = self.db["omnipython-lvgl"] + self.assertNotEqual(self.gen.page_destination(entry), "none") + self.assertIn('href="/omnipython-lvgl/"', grid) + for old in ("lvgl-bindings", "lvgl-micropython", "lvgl-python", "lvgl-circuitpython"): + self.assertIn(old, moved) + self.assertNotIn(f'href="/{old}/"', grid) + block = self.gen.build_ecosystem_markdown(self.db) + self.assertIn("[`omnipython-lvgl`](https://github.com/PyDevices/omnipython-lvgl)", block) + if __name__ == "__main__": unittest.main()