Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion Buildscripts/DevicetreeCompiler/source/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from textwrap import dedent
from source.models import *
from .exception import DevicetreeException
from .printing import print_warning

def write_include(file, include: IncludeC, verbose: bool):
if verbose:
Expand Down Expand Up @@ -59,6 +60,35 @@ def find_phandle(devices: list[Device], phandle: str):
return f"&{get_device_node_name_safe(device)}"
raise DevicetreeException(f"phandle '{phandle}' not found in devicetree")

def parse_number(text: str):
try:
return int(text, 0)
except ValueError:
return None

def get_device_address(device: Device) -> str:
"""The node's unit address (e.g. "display@0"), or else the first value of its "reg" property (e.g. an I2C address)."""
reg_property = find_device_property(device, "reg")
reg_value = None
if reg_property is not None:
if reg_property.type == "value":
reg_value = reg_property.value
elif reg_property.type == "values" and len(reg_property.value) > 0:
reg_value = str(reg_property.value[0])
if device.node_address is None:
return reg_value if reg_value is not None else "0"
# Unit addresses are hexadecimal, like in Linux
try:
unit_address = int(device.node_address, 16)
except ValueError:
raise DevicetreeException(f"Unit address of {device.node_name}@{device.node_address} isn't a hexadecimal number")
# Like Linux's dtc, the unit address should match the first "reg" value
if reg_value is not None:
reg_number = parse_number(reg_value)
if reg_number is not None and unit_address != reg_number:
print_warning(f"{device.node_name}@{device.node_address} has a different reg value: {reg_value}")
return str(unit_address)

def property_to_string(property: DeviceProperty, devices: list[Device]) -> str:
type = property.type
if type == "value" or type == "int":
Expand Down Expand Up @@ -277,7 +307,7 @@ def write_device_structs(file, device: Device, parent_device: Device, bindings:
# Write config struct
write_config(file, device, bindings, devices, type_name)
# Write device struct
address_value = device.node_address if device.node_address is not None else "0"
address_value = get_device_address(device)
file.write(f"static struct Device {node_name}" " = {\n")
file.write(f"\t.address = {address_value},\n")
file.write(f"\t.name = \"{device.node_name}\",\n") # Use original name
Expand Down
84 changes: 83 additions & 1 deletion Buildscripts/DevicetreeCompiler/tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,86 @@ def test_array_property_defaults_to_null_when_absent():
print("PASSED")
return True

def write_reg_config(tmp_dir, node):
config_dir = os.path.join(tmp_dir, "reg_data")
bindings_dir = os.path.join(config_dir, "bindings")
os.makedirs(bindings_dir)

with open(os.path.join(config_dir, "module.yaml"), "w") as f:
f.write("dts: test.dts\nbindings: bindings")

with open(os.path.join(config_dir, "test.dts"), "w") as f:
f.write(f"""/dts-v1/;

/ {{
compatible = "test,root";
model = "Test Model";

{node} {{
compatible = "test,reg-device";
reg = <0x5D>;
}};
}};
""")

with open(os.path.join(bindings_dir, "test,root.yaml"), "w") as f:
f.write("description: Test root binding\ncompatible: \"test,root\"\nproperties:\n model:\n type: string\n")

with open(os.path.join(bindings_dir, "test,reg-device.yaml"), "w") as f:
f.write("description: Test reg binding\ncompatible: \"test,reg-device\"\nproperties:\n reg:\n type: int\n")

return config_dir

def test_reg_is_address_without_unit_address():
print("Running test_reg_is_address_without_unit_address...")
with tempfile.TemporaryDirectory() as tmp_dir:
config_dir = write_reg_config(tmp_dir, "touch")
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)

result = run_compiler(config_dir, output_dir)

if result.returncode != 0:
print(f"FAILED: Compilation should have succeeded: {result.stderr} {result.stdout}")
return False

with open(os.path.join(output_dir, "devicetree.c")) as f:
generated = f.read()

if ".address = 0x5D," not in generated:
print(f"FAILED: Expected the reg value as address:\n{generated}")
return False

print("PASSED")
return True

def test_unit_address_mismatch_warns():
print("Running test_unit_address_mismatch_warns...")
with tempfile.TemporaryDirectory() as tmp_dir:
config_dir = write_reg_config(tmp_dir, "touch@10")
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)

result = run_compiler(config_dir, output_dir)

if result.returncode != 0:
print(f"FAILED: Compilation should have succeeded: {result.stderr} {result.stdout}")
return False

if "different reg value" not in result.stdout:
print(f"FAILED: Expected a warning, got: {result.stdout}")
return False

with open(os.path.join(output_dir, "devicetree.c")) as f:
generated = f.read()

if ".address = 16," not in generated:
print(f"FAILED: Expected the unit address as address:\n{generated}")
return False

print("PASSED")
return True

def test_compile_missing_config():
print("Running test_compile_missing_config...")
with tempfile.TemporaryDirectory() as output_dir:
Expand Down Expand Up @@ -322,7 +402,9 @@ def test_compile_missing_config():
test_minmax_out_of_range_default_fails,
test_minmax_symbolic_value_skips_validation,
test_array_property_generates_static_array_and_length,
test_array_property_defaults_to_null_when_absent
test_array_property_defaults_to_null_when_absent,
test_reg_is_address_without_unit_address,
test_unit_address_mismatch_warns
]

failed = 0
Expand Down
2 changes: 1 addition & 1 deletion Devices/m5stack-tab5/Source/devices/devices_v1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void tab5_create_devices_v1(Device* i2c0) {
.dsi_bus_id = 0,
.num_data_lanes = 2,
.lane_bit_rate_mbps = 1000,
.dpi_clock_freq_mhz = 60,
.dpi_clock_freq_mhz = 80,
.hsync_pulse_width = 40,
.hsync_back_porch = 140,
.hsync_front_porch = 40,
Expand Down
1 change: 1 addition & 0 deletions Documentation/ideas.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

## Higher Priority

- Wi-Fi and Bluetooth settings app: scanning should start and gather results, then it should stop refreshing the scan results automatically. When scanning is finished, a paginated view should be shown with the results (as many as fit on the screen, but not more). There should be an icon on the toolbar to refresh scanning (looking glass? something else?) and this icon is only visible when the radio is enabled. When radio is enabled by the user, automatically start a scan. If the radio was already enabled and the app starts, start scanning.
- Update to LVGL 9.6.x (ESP-IDF and POSIX)
- Terminal app: on devices with pointer device: LVGL rendering mode should hide the toolbar by default, but tapping the terminal should toggle the visibility of the toolbar.
- Terminal app: should always run in non-LVGL mode if no PSRAM is present.
Expand Down
1 change: 1 addition & 0 deletions Modules/cpp-symbols-module/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ESP_PLATFORM` in `source/module.cpp`; symbols outside that gate (e.g. `__cxa_pur

- `operator new(unsigned int)` / `operator delete(void*, unsigned int)` (`_Znwj` / `_ZdlPvj`)
- `operator new[](unsigned int)` / `operator delete[](void*, unsigned int)` (`_Znaj` / `_ZdaPvj`)
- `operator new[](unsigned int, std::nothrow_t const&)` (`_ZnajRKSt9nothrow_t`)
- `operator delete(void*)` / `operator delete[](void*)` (`_ZdlPv` / `_ZdaPv`) - the unsized forms,
used instead of the above when the compiler determines no size is needed
- `std::nothrow`
Expand Down
2 changes: 2 additions & 0 deletions Modules/cpp-symbols-module/source/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ extern "C" {
extern void* _Znwj(uint32_t size); // operator new(unsigned int)
extern void _ZdlPvj(void* p, uint64_t size); // operator delete(void*, unsigned int)
extern void* _Znaj(uint32_t size); // operator new[](unsigned int)
extern void* _ZnajRKSt9nothrow_t(uint32_t size, const std::nothrow_t& tag); // operator new[](unsigned int, std::nothrow_t const&)
extern void _ZdaPvj(void* p, uint64_t size); // operator delete[](void*, unsigned int)
// Unsized forms: the compiler picks these over the sized ones above depending on context
// (e.g. trivially-destructible types needing no array cookie), so both must be exported.
Expand Down Expand Up @@ -572,6 +573,7 @@ static const ModuleSymbol SYMBOLS[] = {
DEFINE_MODULE_SYMBOL(_Znwj), // operator new(unsigned int)
DEFINE_MODULE_SYMBOL(_ZdlPvj), // operator delete(void*, unsigned int)
DEFINE_MODULE_SYMBOL(_Znaj), // operator new[](unsigned int)
DEFINE_MODULE_SYMBOL(_ZnajRKSt9nothrow_t), // operator new[](unsigned int, std::nothrow_t const&)
DEFINE_MODULE_SYMBOL(_ZdaPvj), // operator delete[](void*, unsigned int)
DEFINE_MODULE_SYMBOL(_ZdlPv), // operator delete(void*)
DEFINE_MODULE_SYMBOL(_ZdaPv), // operator delete[](void*)
Expand Down
5 changes: 5 additions & 0 deletions Modules/lvgl-module/generate-icons.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,18 @@ def generate_icon_names(codepoint_map: dict, codepoint_names: list, variable_nam
"download",
"forum", # Chat app
"gamepad",
"hard_disk", # System Info
"help", # Diceware help
"hub", # App Hub
"info", # System Info
"image", # Screenshot app
"keyboard_arrow_up",
"lightbulb",
"language", # Globe
"lists", # Chat app toolbar
"mail",
"menu",
"memory", # System Info
"mop",
"more_vert",
"music_note",
Expand All @@ -166,6 +169,7 @@ def generate_icon_names(codepoint_map: dict, codepoint_names: list, variable_nam
"power_settings_new", # Power off for T-Lora Pager
"refresh", # e.g. App Hub reload button
"search",
"select_window_2", # System Info
"settings",
"toolbar", # Apps without custom icon
"navigation", # GPS (settings) app
Expand All @@ -177,6 +181,7 @@ def generate_icon_names(codepoint_map: dict, codepoint_names: list, variable_nam
"logo_dev",
"camera",
"lightstrip",
"phone_android", # Display settings: orientation
]

# Get more from https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded
Expand Down
2 changes: 1 addition & 1 deletion Modules/lvgl-module/include/lvgl/icons/names.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ extern "C" {
#endif

/** Changes whenever the icon TTF subset, its codepoints file or the icon name lists change */
#define LVGL_ICON_FONT_VERSION 0x1B608834u
#define LVGL_ICON_FONT_VERSION 0xC28E1A92u

// Icon names per icon font, resolved through the .codepoints file next to the TTF
extern const char* const lvgl_icon_shared_names[];
Expand Down
5 changes: 5 additions & 0 deletions Modules/lvgl-module/include/lvgl/icons/shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,18 @@
#define LVGL_ICON_SHARED_DOWNLOAD "\xEF\x82\x90"
#define LVGL_ICON_SHARED_FORUM "\xEE\xA2\xAF"
#define LVGL_ICON_SHARED_GAMEPAD "\xEE\x8C\x8F"
#define LVGL_ICON_SHARED_HARD_DISK "\xEF\x8F\x9A"
#define LVGL_ICON_SHARED_HELP "\xEE\xA3\xBD"
#define LVGL_ICON_SHARED_HUB "\xEE\xA7\xB4"
#define LVGL_ICON_SHARED_INFO "\xEE\xA2\x8E"
#define LVGL_ICON_SHARED_IMAGE "\xEE\x8F\xB4"
#define LVGL_ICON_SHARED_KEYBOARD_ARROW_UP "\xEE\x8C\x96"
#define LVGL_ICON_SHARED_LIGHTBULB "\xEE\xA4\x8F"
#define LVGL_ICON_SHARED_LANGUAGE "\xEE\xA8\x87"
#define LVGL_ICON_SHARED_LISTS "\xEE\xA6\xB9"
#define LVGL_ICON_SHARED_MAIL "\xEE\x85\x99"
#define LVGL_ICON_SHARED_MENU "\xEE\x97\x92"
#define LVGL_ICON_SHARED_MEMORY "\xEE\x8C\xA2"
#define LVGL_ICON_SHARED_MOP "\xEE\x8A\x8D"
#define LVGL_ICON_SHARED_MORE_VERT "\xEE\x97\x94"
#define LVGL_ICON_SHARED_MUSIC_NOTE "\xEE\x90\x85"
Expand All @@ -39,6 +42,7 @@
#define LVGL_ICON_SHARED_POWER_SETTINGS_NEW "\xEF\xA3\x87"
#define LVGL_ICON_SHARED_REFRESH "\xEE\x97\x95"
#define LVGL_ICON_SHARED_SEARCH "\xEE\xBD\xBA"
#define LVGL_ICON_SHARED_SELECT_WINDOW_2 "\xEF\x93\x88"
#define LVGL_ICON_SHARED_SETTINGS "\xEE\xA2\xB8"
#define LVGL_ICON_SHARED_TOOLBAR "\xEE\xA7\xB7"
#define LVGL_ICON_SHARED_NAVIGATION "\xEE\x95\x9D"
Expand All @@ -50,3 +54,4 @@
#define LVGL_ICON_SHARED_LOGO_DEV "\xEE\xAB\x96"
#define LVGL_ICON_SHARED_CAMERA "\xEE\x8E\xAF"
#define LVGL_ICON_SHARED_LIGHTSTRIP "\xF3\xBF\xBD\xB5"
#define LVGL_ICON_SHARED_PHONE_ANDROID "\xEF\x8B\x9B"
6 changes: 3 additions & 3 deletions Modules/lvgl-module/include/lvgl/lvgl.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ void lvgl_unlock(void);
bool lvgl_is_running(void);

/**
* @brief Gets the desired UI density for the target hardware.
* The density is defined in the `device.properties` of a hardware device.
* This setting is read by CMakeLists.txt and passed as a target compile definition of the LVGL module.
* @brief Gets the UI density of the theme settings.
* @deprecated Use lvgl_theme_is_compact() from <lvgl/theme.h>
* @return the UI density
*/
__attribute__((deprecated("Use lvgl_theme_is_compact()")))
enum UiDensity lvgl_get_ui_density(void);

#ifdef __cplusplus
Expand Down
12 changes: 12 additions & 0 deletions Modules/lvgl-module/include/lvgl/theme.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ typedef struct {
lv_color_t color_primary;
lv_color_t color_secondary;
lv_color_t color_error;
/** Smaller spacing and controls, for small screens (see lvgl_theme_is_compact()) */
bool is_compact;
/** Use color_surface as the surface (screen background) colour, instead of the theme's own. Not used by the monochrome theme. */
bool surface_override;
lv_color_t color_surface;
} LvglThemeSettings;

/**
Expand All @@ -37,6 +42,13 @@ void lvgl_theme_get_default_settings(LvglThemeSettings* settings);
*/
bool lvgl_theme_is_mono(void);

/**
* @brief Checks whether the theme settings use the compact UI density: smaller spacing and controls, for small screens.
* The device's default density is defined in its `device.properties`.
* @return true when the UI is compact
*/
bool lvgl_theme_is_compact(void);

/**
* @brief Sets the theme settings. They are used for displays that are added afterwards, e.g. when LVGL (re)starts.
* @param[in] settings the theme settings
Expand Down
Loading
Loading