From 003128c3b6276927106559f548fc918029f21705 Mon Sep 17 00:00:00 2001 From: lucas lelievre Date: Tue, 4 Nov 2025 01:26:52 +0100 Subject: [PATCH] Add full support for sensor list in preprocessor (#483) * Add support for sensor list in preprocessor * Fix quotes --- board-defaults.json | 1 + board-defaults.schema.json | 6 +- scripts/preprocessor.py | 122 ++++++++++++++++++++++--------------- 3 files changed, 78 insertions(+), 51 deletions(-) diff --git a/board-defaults.json b/board-defaults.json index fb41e43..fba0b1c 100644 --- a/board-defaults.json +++ b/board-defaults.json @@ -48,6 +48,7 @@ "protocol": "SPI", "imu": "IMU_AUTO", "int": "2", + "cs": "15", "rotation": "DEG_270" }, { diff --git a/board-defaults.schema.json b/board-defaults.schema.json index 227064f..a46d093 100644 --- a/board-defaults.schema.json +++ b/board-defaults.schema.json @@ -81,9 +81,10 @@ "rotation": { "$ref": "#/$defs/IMU_ROTATION", "description": "IMU Rotation" - } + }, + "cs": { "$ref": "#/$defs/pin", "description": "CS Pin" } }, - "required": ["protocol", "imu"] + "required": ["protocol", "imu", "cs"] }, "IMU": { @@ -171,7 +172,6 @@ "SENSORS": { "type": "array", "items": { "$ref": "#/$defs/IMU" }, - "maxItems": 2, "minItems": 1, "description": "Sensors List" }, diff --git a/scripts/preprocessor.py b/scripts/preprocessor.py index 8692deb..3a49aa6 100644 --- a/scripts/preprocessor.py +++ b/scripts/preprocessor.py @@ -7,7 +7,7 @@ from typing import Union, Optional, Dict, Any, List Import("env") try: - import jsonschema + import jsonschema except: env.Execute( env.VerboseAction( @@ -37,6 +37,19 @@ def _format_raw_value(value: Any) -> str: return "true" if value else "false" return str(value) +def format_value(val: Any, typ: str) -> str: + if typ == "pin": + if isinstance(val, str) and re.search(r"[AD]", val): + return f'{val}' + else: + return _format_raw_value(val) + elif typ == "string": + return f'{val}' + elif typ in ("raw", "number"): + return _format_raw_value(val) + else: + raise ValueError(f"Value type is not supported") + def _build_board_flags(defaults: dict, board_name: str) -> List[str]: """Construct list of -D flags for one board.""" @@ -54,52 +67,65 @@ def _build_board_flags(defaults: dict, board_name: str) -> List[str]: if value is not None: args[key] = {"value": value, "type": value_type} - add("BOARD", board_name, "raw") - add("LED_PIN", values.get("LED").get("LED_PIN"), "pin") - add("LED_INVERTED", values.get("LED").get("LED_INVERTED"), "raw") + add('BOARD', board_name, 'raw') + add('LED_PIN', values.get('LED').get('LED_PIN'), 'pin') + add('LED_INVERTED', values.get('LED').get('LED_INVERTED'), 'raw') - sensors = values.get("SENSORS") + sensors = values.get('SENSORS') if sensors: + sensor_list = [] + + add('PIN_IMU_SDA', 255, 'pin') # FIXME fix the I2C Scanner so it use the sensor list and not be called when no I2C sensor + add('PIN_IMU_SCL', 255, 'pin') + add('PIN_IMU_INT_2', 255, 'pin') # FIXME: fix the CONFIG serial command so it use the sensor list + for index, sensor in enumerate(sensors): - if index == 0: - add("IMU", sensor.get("imu"), "raw") - add("PIN_IMU_INT", sensor.get("int"), "pin") - add("IMU_ROTATION", sensor.get("rotation"), "raw") - if sensor.get("protocol") == "I2C": - add("PRIMARY_IMU_ADDRESS_ONE", sensor.get("address"), "number") - if index == 1: - add("SECOND_IMU", sensor.get("imu"), "raw") - add("PIN_IMU_INT_2", sensor.get("int"), "pin") - add("SECOND_IMU_ROTATION", sensor.get("rotation"), "raw") - if sensor.get("protocol") == "I2C": - add("SECONDARY_IMU_ADDRESS_TWO", sensor.get("address"), "number") + if sensor.get('protocol') == 'I2C': + params = [ + format_value(sensor.get('imu'), 'raw'), + format_value(sensor.get('address', 'PRIMARY_IMU_ADDRESS_ONE'), 'number'), + format_value(sensor.get('rotation'), 'raw'), + f'DIRECT_WIRE({format_value(sensor.get('scl'), 'pin')}, {format_value(sensor.get('sda'), 'pin')})', + 'false' if index == 0 else 'true', + f'DIRECT_PIN({format_value(sensor.get('int', 255), 'pin')})', + '0' + ] + sensor_list.append(f'SENSOR_DESC_ENTRY({','.join(params)})') + add('PIN_IMU_SDA', sensor.get('sda'), 'pin') + add('PIN_IMU_SCL', sensor.get('scl'), 'pin') - if sensor.get("protocol") == "I2C": - add("PIN_IMU_SDA", sensor.get("sda"), "pin") - add("PIN_IMU_SCL", sensor.get("scl"), "pin") + if sensor.get('protocol') == 'SPI': + params = [ + format_value(sensor.get('imu'), 'raw'), + f'DIRECT_PIN({format_value(sensor.get('cs'), 'pin')})', + format_value(sensor.get('rotation'), 'raw'), + "DIRECT_SPI(24'000'000, MSBFIRST, SPI_MODE3)", + 'false' if index == 0 else 'true', + f'DIRECT_PIN({format_value(sensor.get('int', 255), 'pin')})', + '0' + ] + sensor_list.append(f'SENSOR_DESC_ENTRY({','.join(params)})') - battery = values.get("BATTERY") + if index == 0: # FIXME: fix the CONFIG serial command so it use the sensor list + add('PIN_IMU_INT', sensor.get('int'), 'pin') + elif index == 1: + add('PIN_IMU_INT_2', sensor.get('int'), 'pin') + add('SENSOR_DESC_LIST', f"'{' '.join(sensor_list)}'", 'raw') + + + battery = values.get('BATTERY') if battery: - add("BATTERY_MONITOR", battery.get("type"), "raw") - add("PIN_BATTERY_LEVEL", battery.get("pin", 255), "pin") - add("BATTERY_SHIELD_RESISTANCE", battery.get("shieldR", 180), "number") - add("BATTERY_SHIELD_R1", battery.get("r1", 100), "number") - add("BATTERY_SHIELD_R2", battery.get("r2", 220), "number") + add('BATTERY_MONITOR', battery.get('type'), 'raw') + add('PIN_BATTERY_LEVEL', battery.get('pin', 255), 'pin') + add('BATTERY_SHIELD_RESISTANCE', battery.get('shieldR', 180), 'number') + add('BATTERY_SHIELD_R1', battery.get('r1', 100), 'number') + add('BATTERY_SHIELD_R2', battery.get('r2', 220), 'number') parts: List[str] = [] for key, meta in args.items(): val = meta["value"] typ = meta["type"] - - if typ == "pin": - if isinstance(val, str) and re.search(r"[AD]", val): - parts.append(f"-D{key}='{val}'") - else: - parts.append(f"-D{key}={_format_raw_value(val)}") - elif typ == "string": - parts.append(f"-D{key}='{val}'") - elif typ in ("raw", "number"): - parts.append(f"-D{key}={_format_raw_value(val)}") + parts.append(f"-D{key}={format_value(val, typ)}") return parts @@ -140,18 +166,18 @@ schema_obj = _load_json("./board-defaults.schema.json") defaults_obj = _load_json("./board-defaults.json") slime_board = env.GetProjectOption("custom_slime_board", None) if slime_board: - if 'SLIMEVR_OVERRIDE_DEFAULTS' in os.environ and slime_board in defaults_obj['defaults']: - print(">>> OVERIDING BOARD DEFAULTS ", os.environ['SLIMEVR_OVERRIDE_DEFAULTS']) - defaults_obj['defaults'][slime_board]['values'] = json.loads(os.environ['SLIMEVR_OVERRIDE_DEFAULTS']) + if 'SLIMEVR_OVERRIDE_DEFAULTS' in os.environ and slime_board in defaults_obj['defaults']: + print(">>> OVERIDING BOARD DEFAULTS ", os.environ['SLIMEVR_OVERRIDE_DEFAULTS']) + defaults_obj['defaults'][slime_board]['values'] = json.loads(os.environ['SLIMEVR_OVERRIDE_DEFAULTS']) - output_flags = build_boards( - schema_obj, - defaults_obj, - slime_board, - ) - output_flags = output_flags.get(slime_board, []) if isinstance(output_flags, dict) else [] + output_flags = build_boards( + schema_obj, + defaults_obj, + slime_board, + ) + output_flags = output_flags.get(slime_board, []) if isinstance(output_flags, dict) else [] - print(">>> Appending build flags:", output_flags) - env.Append(BUILD_FLAGS=output_flags) + print(f">>> Appending build flags:\n {'\n '.join(output_flags)}") + env.Append(BUILD_FLAGS=output_flags) else: - print(">>> custom_slime_board not set - skipping") + print(">>> custom_slime_board not set - skipping")