243 lines
7.6 KiB
Python
243 lines
7.6 KiB
Python
import re
|
|
from dataclasses import dataclass, field
|
|
from enum import IntEnum, unique
|
|
|
|
from c3nav.api.utils import EnumSchemaByNameMixin
|
|
from c3nav.mesh.baseformats import (BoolFormat, EnumFormat, FixedHexFormat, FixedStrFormat, SimpleFormat, StructType,
|
|
VarArrayFormat, TwoNibblesEnumFormat, ChipRevFormat, SimpleConstFormat)
|
|
|
|
|
|
class MacAddressFormat(FixedHexFormat):
|
|
def __init__(self):
|
|
super().__init__(num=6, sep=':')
|
|
|
|
|
|
class MacAddressesListFormat(VarArrayFormat):
|
|
def __init__(self):
|
|
super().__init__(child_type=MacAddressFormat())
|
|
|
|
|
|
@unique
|
|
class LedType(IntEnum):
|
|
NONE = 0
|
|
SERIAL = 1
|
|
MULTIPIN = 2
|
|
|
|
@property
|
|
def pretty_name(self):
|
|
return self.name.lower()
|
|
|
|
|
|
@unique
|
|
class SerialLedType(IntEnum):
|
|
WS2812 = 1
|
|
SK6812 = 2
|
|
|
|
|
|
@dataclass
|
|
class LedConfig(StructType, union_type_field="led_type"):
|
|
"""
|
|
configuration for an optional connected status LED
|
|
"""
|
|
led_type: LedType = field(metadata={"format": EnumFormat(), "c_name": "type"})
|
|
|
|
|
|
@dataclass
|
|
class NoLedConfig(LedConfig, led_type=LedType.NONE):
|
|
pass
|
|
|
|
|
|
@dataclass
|
|
class SerialLedConfig(LedConfig, led_type=LedType.SERIAL):
|
|
serial_led_type: SerialLedType = field(metadata={"format": EnumFormat(), "c_name": "type"})
|
|
gpio: int = field(metadata={"format": SimpleFormat('B')})
|
|
|
|
|
|
@dataclass
|
|
class MultipinLedConfig(LedConfig, led_type=LedType.MULTIPIN):
|
|
gpio_red: int = field(metadata={"format": SimpleFormat('B')})
|
|
gpio_green: int = field(metadata={"format": SimpleFormat('B')})
|
|
gpio_blue: int = field(metadata={"format": SimpleFormat('B')})
|
|
|
|
|
|
@dataclass
|
|
class UWBConfig(StructType):
|
|
"""
|
|
configuration for the connection to the UWB module
|
|
"""
|
|
enable: bool = field(metadata={"format": BoolFormat()})
|
|
gpio_miso: int = field(metadata={"format": SimpleFormat('B')})
|
|
gpio_mosi: int = field(metadata={"format": SimpleFormat('B')})
|
|
gpio_clk: int = field(metadata={"format": SimpleFormat('B')})
|
|
gpio_cs: int = field(metadata={"format": SimpleFormat('B')})
|
|
gpio_irq: int = field(metadata={"format": SimpleFormat('B')})
|
|
gpio_rst: int = field(metadata={"format": SimpleFormat('B')})
|
|
gpio_wakeup: int = field(metadata={"format": SimpleFormat('B')})
|
|
gpio_exton: int = field(metadata={"format": SimpleFormat('B')})
|
|
|
|
|
|
@unique
|
|
class BoardType(EnumSchemaByNameMixin, IntEnum):
|
|
CUSTOM = 0x00
|
|
|
|
# devboards
|
|
ESP32_C3_DEVKIT_M_1 = 0x01
|
|
ESP32_C3_32S = 2
|
|
|
|
# custom boards
|
|
C3NAV_UWB_BOARD = 0x10
|
|
C3NAV_LOCATION_PCB_REV_0_1 = 0x11
|
|
C3NAV_LOCATION_PCB_REV_0_2 = 0x12
|
|
|
|
@property
|
|
def pretty_name(self):
|
|
if self.name.startswith('ESP32'):
|
|
return self.name.replace('_', '-').replace('DEVKIT-', 'DevKit')
|
|
if self.name.startswith('C3NAV'):
|
|
name = self.name.replace('_', ' ').lower()
|
|
name = name.replace('uwb', 'UWB').replace('pcb', 'PCB')
|
|
name = re.sub(r'[0-9]+( [0-9+])+', lambda s: s[0].replace(' ', '.'), name)
|
|
name = re.sub(r'rev.*', lambda s: s[0].replace(' ', ''), name)
|
|
return name
|
|
return self.name
|
|
|
|
|
|
@dataclass
|
|
class BoardConfig(StructType, union_type_field="board"):
|
|
board: BoardType = field(metadata={"format": EnumFormat(as_hex=True)})
|
|
|
|
|
|
@dataclass
|
|
class CustomBoardConfig(BoardConfig, board=BoardType.CUSTOM):
|
|
uwb: UWBConfig = field(metadata={"as_definition": True})
|
|
led: LedConfig = field(metadata={"as_definition": True})
|
|
|
|
|
|
@dataclass
|
|
class DevkitMBoardConfig(BoardConfig, board=BoardType.ESP32_C3_DEVKIT_M_1):
|
|
uwb: UWBConfig = field(metadata={"as_definition": True})
|
|
|
|
|
|
@dataclass
|
|
class Esp32SBoardConfig(BoardConfig, board=BoardType.ESP32_C3_32S):
|
|
uwb: UWBConfig = field(metadata={"as_definition": True})
|
|
|
|
|
|
@dataclass
|
|
class UwbBoardConfig(BoardConfig, board=BoardType.C3NAV_UWB_BOARD):
|
|
pass
|
|
|
|
|
|
@dataclass
|
|
class LocationPCBRev0Dot1BoardConfig(BoardConfig, board=BoardType.C3NAV_LOCATION_PCB_REV_0_1):
|
|
pass
|
|
|
|
|
|
@dataclass
|
|
class LocationPCBRev0Dot2BoardConfig(BoardConfig, board=BoardType.C3NAV_LOCATION_PCB_REV_0_2):
|
|
pass
|
|
|
|
|
|
@dataclass
|
|
class RangeResultItem(StructType):
|
|
peer: str = field(metadata={"format": MacAddressFormat()})
|
|
rssi: int = field(metadata={"format": SimpleFormat('b')})
|
|
distance: int = field(metadata={"format": SimpleFormat('H')})
|
|
|
|
|
|
@dataclass
|
|
class RawFTMEntry(StructType):
|
|
dlog_token: int = field(metadata={"format": SimpleFormat('B')})
|
|
rssi: int = field(metadata={"format": SimpleFormat('b')})
|
|
rtt: int = field(metadata={"format": SimpleFormat('I')})
|
|
t1: int = field(metadata={"format": SimpleFormat('Q')})
|
|
t2: int = field(metadata={"format": SimpleFormat('Q')})
|
|
t3: int = field(metadata={"format": SimpleFormat('Q')})
|
|
t4: int = field(metadata={"format": SimpleFormat('Q')})
|
|
|
|
|
|
@dataclass
|
|
class FirmwareAppDescription(StructType, existing_c_struct="esp_app_desc_t"):
|
|
magic_word: int = field(metadata={"format": SimpleConstFormat('I', 0xAB_CD_54_32)}, repr=False)
|
|
secure_version: int = field(metadata={"format": SimpleFormat('I')})
|
|
reserv1: list[int] = field(metadata={"format": SimpleFormat('2I')}, repr=False)
|
|
version: str = field(metadata={"format": FixedStrFormat(32)})
|
|
project_name: str = field(metadata={"format": FixedStrFormat(32)})
|
|
compile_time: str = field(metadata={"format": FixedStrFormat(16)})
|
|
compile_date: str = field(metadata={"format": FixedStrFormat(16)})
|
|
idf_version: str = field(metadata={"format": FixedStrFormat(32)})
|
|
app_elf_sha256: str = field(metadata={"format": FixedHexFormat(32)})
|
|
reserv2: list[int] = field(metadata={"format": SimpleFormat('20I')}, repr=False)
|
|
|
|
|
|
@unique
|
|
class SPIFlashMode(EnumSchemaByNameMixin, IntEnum):
|
|
QIO = 0
|
|
QOUT = 1
|
|
DIO = 2
|
|
DOUT = 3
|
|
|
|
|
|
@unique
|
|
class FlashSize(EnumSchemaByNameMixin, IntEnum):
|
|
SIZE_1MB = 0
|
|
SIZE_2MB = 1
|
|
SIZE_4MB = 2
|
|
SIZE_8MB = 3
|
|
SIZE_16MB = 4
|
|
SIZE_32MB = 5
|
|
SIZE_64MB = 6
|
|
SIZE_128MB = 7
|
|
|
|
|
|
@unique
|
|
class FlashFrequency(EnumSchemaByNameMixin, IntEnum):
|
|
FREQ_40MHZ = 0
|
|
FREQ_26MHZ = 1
|
|
FREQ_20MHZ = 2
|
|
FREQ_80MHZ = 0xf
|
|
|
|
|
|
@dataclass
|
|
class FlashSettings:
|
|
size: FlashSize
|
|
frequency: FlashFrequency
|
|
|
|
|
|
@unique
|
|
class ChipType(EnumSchemaByNameMixin, IntEnum):
|
|
ESP32_S2 = 2
|
|
ESP32_C3 = 5
|
|
|
|
@property
|
|
def pretty_name(self):
|
|
return self.name.replace('_', '-')
|
|
|
|
|
|
@dataclass
|
|
class FirmwareImageFileHeader(StructType):
|
|
magic_word: int = field(metadata={"format": SimpleConstFormat('B', 0xE9)}, repr=False)
|
|
num_segments: int = field(metadata={"format": SimpleFormat('B')})
|
|
spi_flash_mode: SPIFlashMode = field(metadata={"format": EnumFormat()})
|
|
flash_stuff: FlashSettings = field(metadata={"format": TwoNibblesEnumFormat()})
|
|
entry_point: int = field(metadata={"format": SimpleFormat('I')})
|
|
|
|
|
|
@dataclass
|
|
class FirmwareImageExtendedFileHeader(StructType):
|
|
wp_pin: int = field(metadata={"format": SimpleFormat('B')})
|
|
drive_settings: int = field(metadata={"format": SimpleFormat('3B')})
|
|
chip_id: ChipType = field(metadata={"format": EnumFormat('H')})
|
|
min_chip_rev_old: int = field(metadata={"format": SimpleFormat('B')})
|
|
min_chip_rev: tuple[int, int] = field(metadata={"format": ChipRevFormat()})
|
|
max_chip_rev: tuple[int, int] = field(metadata={"format": ChipRevFormat()})
|
|
reserv: int = field(metadata={"format": SimpleFormat('I')}, repr=False)
|
|
hash_appended: bool = field(metadata={"format": BoolFormat()})
|
|
|
|
|
|
@dataclass
|
|
class FirmwareImage(StructType):
|
|
header: FirmwareImageFileHeader
|
|
ext_header: FirmwareImageExtendedFileHeader
|
|
first_segment_headers: tuple[int, int] = field(metadata={"format": SimpleFormat('2I')}, repr=False)
|
|
app_desc: FirmwareAppDescription
|