Skip to content
Open
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
10 changes: 5 additions & 5 deletions .cproject
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.1316473902" name="Debug" parent="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug" postbuildStep="arm-none-eabi-objcopy -O binary &quot;${BuildArtifactFileBaseName}.elf&quot; &quot;UserApp.bin&quot; &amp;&amp; arm-none-eabi-size &quot;${BuildArtifactFileName}&quot;" prebuildStep="../prebuild.sh">
<configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="rm -rf" description="" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.1316473902" name="Debug" parent="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug" postbuildStep="arm-none-eabi-objcopy -O binary &quot;${BuildArtifactFileBaseName}.elf&quot; &quot;UserApp.bin&quot; &amp;&amp; arm-none-eabi-size &quot;${BuildArtifactFileName}&quot; &amp;&amp; cp &quot;UserApp.bin&quot; &quot;../Deploy/Firmware_As_Built/UserApp.bin&quot;" prebuildStep="../prebuild.sh">
<folderInfo id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.debug.1316473902." name="/" resourcePath="">
<toolChain id="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.debug.569694880" name="MCU ARM GCC" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.debug">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu.373619157" name="MCU" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu" useByScannerDiscovery="true" value="STM32WB5MMGHx" valueType="string"/>
Expand All @@ -25,7 +25,7 @@
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.1368736295" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.369744518" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Debug || true || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32WB5MMGHx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32WBxx_HAL_Driver/Inc | ../Drivers/STM32WBxx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32WBxx/Include | ../Drivers/CMSIS/Include | ../FATFS/Target | ../FATFS/App | ../STM32_WPAN/App | ../USB_Device/App | ../USB_Device/Target | ../Utilities/lpm/tiny_lpm | ../Middlewares/Third_Party/FatFs/src | ../Middlewares/ST/STM32_WPAN | ../Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread | ../Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl | ../Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/shci | ../Middlewares/ST/STM32_WPAN/utilities | ../Middlewares/ST/STM32_WPAN/ble/core | ../Middlewares/ST/STM32_WPAN/ble/core/auto | ../Middlewares/ST/STM32_WPAN/ble/core/template | ../Middlewares/ST/STM32_WPAN/ble/svc/Inc | ../Middlewares/ST/STM32_WPAN/ble/svc/Src | ../Middlewares/ST/STM32_USB_Device_Library/Core/Inc | ../Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Inc | ../Utilities/sequencer | ../Middlewares/ST/STM32_WPAN/ble || || || USE_HAL_DRIVER | STM32WB5Mxx || || USB_Device | Utilities | Drivers | STM32_WPAN | Core/Startup | Middlewares | Core | FATFS || || || ${workspace_loc:/${ProjName}/STM32WB5MMGHX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || || || " valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.589475122" name="Cpu clock frequence" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="64" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat.1943016217" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat" value="true" valueType="boolean"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat.1943016217" name="Use float with printf from newlib-nano (-u _printf_float)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.1132392883" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
<builder buildPath="${workspace_loc:/flysight-2-firmware}/Debug" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.307986665" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.1599855123" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">
Expand Down Expand Up @@ -124,7 +124,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.1591110137" name="Release" parent="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release" postbuildStep="arm-none-eabi-objcopy -O binary &quot;${BuildArtifactFileBaseName}.elf&quot; &quot;UserApp.bin&quot; &amp;&amp; arm-none-eabi-size &quot;${BuildArtifactFileName}&quot;" prebuildStep="..\prebuild.bat">
<configuration artifactExtension="elf" artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.1591110137" name="Release" parent="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release" postbuildStep="arm-none-eabi-objcopy -O binary &quot;${BuildArtifactFileBaseName}.elf&quot; &quot;UserApp.bin&quot; &amp;&amp; arm-none-eabi-size &quot;${BuildArtifactFileName}&quot;" prebuildStep="../prebuild.sh">
<folderInfo id="com.st.stm32cube.ide.mcu.gnu.managedbuild.config.exe.release.1591110137." name="/" resourcePath="">
<toolChain id="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.release.1963239428" name="MCU ARM GCC" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.exe.release">
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu.931808695" name="MCU" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_mcu" useByScannerDiscovery="true" value="STM32WB5MMGHx" valueType="string"/>
Expand All @@ -135,7 +135,7 @@
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.851921181" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.1662089201" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32WB5MMGHx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32WBxx_HAL_Driver/Inc | ../Drivers/STM32WBxx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32WBxx/Include | ../Drivers/CMSIS/Include | ../FATFS/Target | ../FATFS/App | ../STM32_WPAN/App | ../USB_Device/App | ../USB_Device/Target | ../Utilities/lpm/tiny_lpm | ../Middlewares/Third_Party/FatFs/src | ../Middlewares/ST/STM32_WPAN | ../Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread | ../Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl | ../Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/shci | ../Middlewares/ST/STM32_WPAN/utilities | ../Middlewares/ST/STM32_WPAN/ble/core | ../Middlewares/ST/STM32_WPAN/ble/core/auto | ../Middlewares/ST/STM32_WPAN/ble/core/template | ../Middlewares/ST/STM32_WPAN/ble/svc/Inc | ../Middlewares/ST/STM32_WPAN/ble/svc/Src | ../Middlewares/ST/STM32_USB_Device_Library/Core/Inc | ../Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Inc | ../Utilities/sequencer | ../Middlewares/ST/STM32_WPAN/ble || || || USE_HAL_DRIVER | STM32WB5Mxx || || USB_Device | Utilities | Drivers | STM32_WPAN | Core/Startup | Middlewares | Core | FATFS || || || ${workspace_loc:/${ProjName}/STM32WB5MMGHX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || || || " valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.1897362676" name="Cpu clock frequence" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="64" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat.704960018" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat" value="true" valueType="boolean"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat.704960018" name="Use float with printf from newlib-nano (-u _printf_float)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.928917703" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
<builder buildPath="${workspace_loc:/flysight-2-firmware}/Release" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.248188091" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.2040549644" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">
Expand Down Expand Up @@ -241,4 +241,4 @@
<resource resourceType="PROJECT" workspacePath="/flysight-2-firmware"/>
</configuration>
</storageModule>
</cproject>
</cproject>
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ Deploy/Firmware_To_Deploy/*
*.launch

# Test build products
Tests/*.exe
Tests/*.exe

# OS artifacts
.DS_Store

# Python
__pycache__/
*.pyc
94 changes: 94 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# FlySight 2 Firmware

## Project Overview

FlySight 2 is a high-precision GPS data logger for skydiving and BASE jumping by Bionic Avionics Inc. The firmware runs on an STM32WB5MMGHx dual-core MCU (Cortex-M4 application + Cortex-M0+ BLE radio). It provides real-time audio feedback during freefall, multi-sensor data logging, BLE connectivity, USB mass storage, and an ActiveLook HUD display on Engo smart glasses.

### Key Features
- GNSS/GPS tracking at up to 25 Hz (u-blox MAX-M8)
- 6-axis IMU (LSM6DSO), barometer, magnetometer, humidity sensor
- Real-time audio tone/speech feedback based on flight parameters
- Data logging to SD card via FatFS
- BLE connectivity (STM32 WPAN stack) for phone app and ActiveLook glasses
- USB mass storage for file transfer
- ActiveLook HUD display: 2x2 grid layout with icons, B612 aviation font

### Build System
- **IDE**: STM32CubeIDE (Eclipse-based, ARM GCC toolchain)
- **MCU**: STM32WB5MMGHx (dual-core M4+M0+, BLE 5.x)
- **No Makefile/CMake** -- build is defined in `.cproject`/`.project` files
- **Pre-build**: `prebuild.sh` generates `version.h` from git tag
- **Post-build**: generates `UserApp.bin` and copies to `Deploy/Firmware_As_Built/`

### Branch Structure
- `master` -- stable releases
- `develop` -- active development (ActiveLook integration, new features)

## Rules for Claude Code

### Language Server Protocol (LSP)
- **ALWAYS use LSP** (documentSymbol, hover, goToDefinition, findReferences, callHierarchy) when analyzing or reading C/C++ source files
- Prefer LSP over Read tool or grep for understanding code structure
- Only fall back to Read for non-code files (configs, scripts, docs) or when LSP can't resolve symbols due to missing STM32 HAL headers
- Use LSP for Python files as well when available

### ActiveLook Development
- **ALWAYS consult the ActiveLook API documentation** before any implementation: https://github.com/ActiveLook/Activelook-API-Documentation/blob/main/ActiveLook_API.md
- **Never guess coordinates or protocol details** -- read the documentation first
- ActiveLook display coordinate system: (0,0) = bottom-right visually (optical mirror flips both axes)
- High X = visually LEFT, Low X = visually RIGHT
- High Y = visually TOP, Low Y = visually BOTTOM
- Rotation 4 = normal readable text with centered anchor
- Page coordinates are NOT mirrored (standard: x=0 left, higher y = higher on screen)
- Layout-internal coordinates (extra sub-commands) ARE mirrored
- Images must be rotated 180 degrees before upload to compensate for optical mirror
- Config names use NUL-terminated strings (NOT padded to 12 bytes) when used with Config-Generator, but FlySight firmware pads to 12 bytes
- `cfgWrite` requires the correct password if config already exists (FlySight uses password `0x01020304`)
- `cfgSet` must be called to activate a config before its fonts/images are available
- Font upload uses `fontSave` with header `[id, size_hi, size_lo]` then data chunks
- Image upload uses `imgSave` with header `[id, size_u32, width_u16, format]` then data chunks
- Maximum BLE write payload = MTU - 3 (currently 253 bytes with MTU=256)
- Reference the ActiveLook Visual Assets for pre-loaded icons: https://github.com/ActiveLook/Activelook-Visual-Assets
- Reference the ActiveLook Config-Generator for font/image conversion: https://github.com/ActiveLook/Config-Generator

### STM32/Embedded Best Practices
- Follow existing code patterns -- the project uses STM32 HAL, WPAN middleware, and a cooperative scheduler (UTIL_SEQ), not FreeRTOS
- One BLE command per scheduler task invocation -- never send multiple BLE writes in a tight loop
- Use `UTIL_SEQ_SetTask()` to schedule the next step, not blocking delays
- Respect the watchdog timer (IWDG, 3-second timeout)
- All sensor I/O is DMA-based and interrupt-driven -- never block in ISR context
- Stack is limited (0x400 bytes) -- avoid large local arrays; use static buffers
- Flash is limited to 454 KB for the application (bootloader occupies lower flash)
- RAM1 is 256 KB, RAM_SHARED is 10 KB (BLE radio)
- Use `static` for file-scope variables and functions
- The project uses `newlib-nano` with float printf enabled (`-u _printf_float`)

### C Language Style
- Follow existing project conventions (Bionic Avionics coding style)
- Prefix all public functions with `FS_` (FlySight namespace)
- Use `typedef enum` and `typedef struct` with `_t` suffix
- State machines use function pointer tables (see `mode.c`, `crs.c`, `activelook.c`)
- Ring buffers for producer/consumer patterns (see `log.c`, `sensor.c`)
- No dynamic memory allocation (`malloc`/`free`) -- use static arrays
- Error handling: log events via `FS_Log_WriteEvent()`, set LED color for health status
- Configuration is file-based (text config on SD card, parsed at startup)

### Code Quality
- Do not add unnecessary comments -- the code should be self-documenting
- Do not add features beyond what was requested
- Do not guess at protocol details -- verify against documentation or test empirically
- When modifying ActiveLook layout code, make one change at a time and test
- The clangd LSP will show false errors for STM32 HAL symbols (can't resolve `main.h`) -- these are expected and don't affect the actual STM32CubeIDE build

### Deployment
- Build with STM32CubeIDE (Debug or Release configuration)
- Deploy via encrypted `.sfb` firmware update files (see `Deploy/deploy_firmware.py`)
- Each device batch has a specific public key -- check `flysight.txt` on device for `Pubkey_X`
- ActiveLook config (fonts/images) uploaded separately via `Config-Generator/upload_ble.py`

### Key Directories
- `FlySight/` -- main application code (sensors, audio, logging, modes, ActiveLook)
- `Core/Src/` -- STM32 HAL initialization, main loop, interrupt handlers
- `STM32_WPAN/App/` -- BLE application layer (app_ble.c, custom services, ActiveLook client)
- `Deploy/` -- firmware deployment scripts and tools
- `Config-Generator/` (external, at `~/Projects/Config-Generator/`) -- ActiveLook font/image preparation tool
Loading