From 9bcfe9f97c30cb5d5fff19b947fe88f6ac5fd1df Mon Sep 17 00:00:00 2001 From: Cooper Dalrymple Date: Tue, 5 Aug 2025 08:39:47 -0500 Subject: [PATCH 1/5] Support 4:3 aspect ratio with `FRUIT_JAM_OS_4x3` environment variable --- src/code.py | 27 +++++++++++++++++++++------ src/settings.toml | 1 + 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/code.py b/src/code.py index d0671f7..f98e3bf 100644 --- a/src/code.py +++ b/src/code.py @@ -9,6 +9,7 @@ import atexit import json import math import displayio +import os import supervisor import sys import terminalio @@ -52,7 +53,13 @@ if args is not None and len(args) > 0: print(f"launching: {next_code_file}") supervisor.reload() -request_display_config(720, 400) +# read environment variables +aspect_ratio_4x3 = os.getenv("FRUIT_JAM_OS_4x3", 0) + +if aspect_ratio_4x3: + request_display_config(640, 480) +else: + request_display_config(720, 400) display = supervisor.runtime.display scale = 1 @@ -135,8 +142,12 @@ if "use_mouse" in launcher_config and launcher_config["use_mouse"]: mouse_buf = array.array("b", [0] * 8) -WIDTH = 280 -HEIGHT = 182 +if aspect_ratio_4x3: + WIDTH = 248 + HEIGHT = 218 +else: + WIDTH = 280 + HEIGHT = 182 config = { "menu_title": "Launcher Menu", @@ -177,10 +188,13 @@ config = { } cell_width = WIDTH // config["width"] +cell_height = HEIGHT // config["height"] default_icon_bmp, default_icon_palette = adafruit_imageload.load("launcher_assets/default_icon.bmp") default_icon_palette.make_transparent(0) -menu_grid = GridLayout(x=40, y=16, width=WIDTH, height=HEIGHT, grid_size=(config["width"], config["height"]), +menu_grid = GridLayout(x=(display.width // scale - WIDTH) // 2, + y=(display.height // scale - HEIGHT) // 2, + width=WIDTH, height=HEIGHT, grid_size=(config["width"], config["height"]), divider_lines=False) scaled_group.append(menu_grid) @@ -267,8 +281,9 @@ def _create_cell_group(app): cell_group.append(icon_tg) icon_tg.x = cell_width // 2 - icon_tg.tile_width // 2 - title_txt = TextBox(font, text=app["title"], width=WIDTH // config["width"], height=18, + title_txt = TextBox(font, text=app["title"], width=cell_width, height=18, align=TextBox.ALIGN_CENTER) + icon_tg.y = (cell_height - icon_tg.tile_height - title_txt.height) // 2 cell_group.append(title_txt) title_txt.anchor_point = (0, 0) title_txt.anchored_position = (0, icon_tg.y + icon_tg.tile_height) @@ -288,7 +303,7 @@ def _reuse_cell_group(app, cell_group): icon_tg.pixel_shader = icon_palette icon_tg.x = cell_width // 2 - icon_tg.tile_width // 2 - # title_txt = TextBox(font, text=app["title"], width=WIDTH // config["width"], height=18, + # title_txt = TextBox(font, text=app["title"], width=cell_width, height=18, # align=TextBox.ALIGN_CENTER) # cell_group.append(title_txt) title_txt = cell_group[1] diff --git a/src/settings.toml b/src/settings.toml index a5eb1f8..e8f251b 100755 --- a/src/settings.toml +++ b/src/settings.toml @@ -1 +1,2 @@ CIRCUITPY_PYSTACK_SIZE=4000 +# FRUIT_JAM_OS_4x3=1 From ebbd201a3a6a12a27eaa8870d2bb4aca0ce83a62 Mon Sep 17 00:00:00 2001 From: Cooper Dalrymple Date: Tue, 5 Aug 2025 09:28:38 -0500 Subject: [PATCH 2/5] Support `CIRCUITPY_DISPLAY_WIDTH` environment variable --- src/code.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/code.py b/src/code.py index f98e3bf..4fb6f15 100644 --- a/src/code.py +++ b/src/code.py @@ -24,7 +24,7 @@ from adafruit_anchored_tilegrid import AnchoredTileGrid import adafruit_imageload import adafruit_usb_host_descriptors from adafruit_anchored_group import AnchoredGroup -from adafruit_fruitjam.peripherals import request_display_config +from adafruit_fruitjam.peripherals import request_display_config, VALID_DISPLAY_SIZES from adafruit_argv_file import read_argv, write_argv """ @@ -53,14 +53,18 @@ if args is not None and len(args) > 0: print(f"launching: {next_code_file}") supervisor.reload() -# read environment variables -aspect_ratio_4x3 = os.getenv("FRUIT_JAM_OS_4x3", 0) - -if aspect_ratio_4x3: - request_display_config(640, 480) -else: - request_display_config(720, 400) display = supervisor.runtime.display +if display is None: + width_config = os.getenv("CIRCUITPY_DISPLAY_WIDTH") + if width_config is None: + request_display_config(720, 400) + elif width_config in [x[0] for x in VALID_DISPLAY_SIZES]: + for display_size in VALID_DISPLAY_SIZES: + if display_size[0] == width_config: + request_display_config(*display_size) + break + else: + raise ValueError(f"Invalid display size. Must be one of: {VALID_DISPLAY_SIZES}") scale = 1 if display.width > 360: @@ -142,12 +146,8 @@ if "use_mouse" in launcher_config and launcher_config["use_mouse"]: mouse_buf = array.array("b", [0] * 8) -if aspect_ratio_4x3: - WIDTH = 248 - HEIGHT = 218 -else: - WIDTH = 280 - HEIGHT = 182 +WIDTH = int(280 / 360 * display.width // scale) +HEIGHT = int(182 / 200 * display.height // scale) config = { "menu_title": "Launcher Menu", From 7b98eec44c4a3ef7dfb6cf4cd790ed16167fa151 Mon Sep 17 00:00:00 2001 From: Cooper Dalrymple Date: Tue, 5 Aug 2025 10:28:06 -0500 Subject: [PATCH 3/5] Force display configuration --- src/code.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/code.py b/src/code.py index 379d3fe..6cf370e 100644 --- a/src/code.py +++ b/src/code.py @@ -62,17 +62,15 @@ color_palette = { } display = supervisor.runtime.display -if display is None: - width_config = os.getenv("CIRCUITPY_DISPLAY_WIDTH") - if width_config is None: - request_display_config(720, 400) - elif width_config in [x[0] for x in VALID_DISPLAY_SIZES]: - for display_size in VALID_DISPLAY_SIZES: - if display_size[0] == width_config: - request_display_config(*display_size) - break - else: +if (width_config := os.getenv("CIRCUITPY_DISPLAY_WIDTH")) is not None: + if width_config not in [x[0] for x in VALID_DISPLAY_SIZES]: raise ValueError(f"Invalid display size. Must be one of: {VALID_DISPLAY_SIZES}") + for display_size in VALID_DISPLAY_SIZES: + if display_size[0] == width_config: + break +else: + display_size = (720, 400) +request_display_config(*display_size) scale = 1 if display.width > 360: From 0f12a36ff61e76a62c45d341b39a977526dc249a Mon Sep 17 00:00:00 2001 From: Cooper Dalrymple Date: Tue, 5 Aug 2025 10:34:13 -0500 Subject: [PATCH 4/5] Fix page indicator size when `scale=1` --- src/code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code.py b/src/code.py index 6cf370e..2d4fa79 100644 --- a/src/code.py +++ b/src/code.py @@ -359,7 +359,7 @@ def display_page(page_index): print(f"{grid_index} | {grid_index % config["width"], grid_index // config["width"]}") -page_txt = Label(terminalio.FONT, text="", scale=2, color=color_palette["fg"]) +page_txt = Label(terminalio.FONT, text="", scale=scale, color=color_palette["fg"]) page_txt.anchor_point = (1.0, 1.0) page_txt.anchored_position = (display.width - 2, display.height - 2) main_group.append(page_txt) From 4cd27e78b6c8c1e8fec538067a265dcb6e3b0527 Mon Sep 17 00:00:00 2001 From: Cooper Dalrymple Date: Tue, 5 Aug 2025 11:03:16 -0500 Subject: [PATCH 5/5] Fix `display=None` error --- src/code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code.py b/src/code.py index 2d4fa79..2bdf1d0 100644 --- a/src/code.py +++ b/src/code.py @@ -61,7 +61,6 @@ color_palette = { "arrow": os.getenv("FRUIT_JAM_OS_ARROW"), } -display = supervisor.runtime.display if (width_config := os.getenv("CIRCUITPY_DISPLAY_WIDTH")) is not None: if width_config not in [x[0] for x in VALID_DISPLAY_SIZES]: raise ValueError(f"Invalid display size. Must be one of: {VALID_DISPLAY_SIZES}") @@ -71,6 +70,7 @@ if (width_config := os.getenv("CIRCUITPY_DISPLAY_WIDTH")) is not None: else: display_size = (720, 400) request_display_config(*display_size) +display = supervisor.runtime.display scale = 1 if display.width > 360: