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()