Skip to content

Repository structure

The repository has four numbered top-level folders: the two firmwares (flight controller, ACwing Flow bridge), the PC tools and the documentation assets. Names follow the ACwing convention of the hardware repository: ACwing_<part>_<what> (CubeIDE project ACwing_FC_FW, Python package acwing_tools, MATLAB viewer acwingLiveViewer, logs acwing_log_*). Names of the filter itself (iekf.c, iekfAttitude.m, …) keep the name of the algorithm.

ACwing_FW/
├── 00 - FC_FW/                     STM32CubeIDE project of the flight-controller firmware (import this folder)
│   ├── App/                        application code, hardware-independent where possible
│   │   ├── app/                    app_main (FreeRTOS tasks, IRQ glue), app_config.h (ALL parameters),
│   │   │                           est_pipeline (multi-rate attitude estimation), tlm_build (telemetry frames),
│   │   │                           app_task (protocol v2: commands, params, flash, v2 frames), params,
│   │   │                           cfg_store (A/B flash image), fc_shared (ImuTask <-> AppTask data),
│   │   │                           ext_sens (ExtTask: probe/poll the Qwiic ToF and flow, host-tested),
│   │   │                           batt_task (BattTask: battery monitor, signals the flight core),
│   │   │                           log_task (LogTask: flight log, USB log commands)
│   │   ├── filters/                state estimators (no HAL, no RTOS, host-testable)
│   │   │   ├── iekf/               attitude IEKF on SO(3): so3 (Exp/Log, orthonormalisation), iekf (filter),
│   │   │   │                       accwin (rotation-compensated acc mean), calib (static calibration window)
│   │   │   └── altitude_kf/        altitude Kalman filter (alt_est): height, climb rate, baro and acc bias
│   │   ├── control/                fc_core (arming, modes, TAKEOFF/LAND/HOLD, failsafes), alt_ctrl (height
│   │   │                           loop), calib_mgr (calibrations), checks (pre-flight), battery (estimator:
│   │   │                           cells, level, state of charge, time left), control hooks (weak,
│   │   │                           empty), motor PWM (disabled)
│   │   ├── log/                    flight log: log_format.h (on-flash format), log_store (sector ring),
│   │   │                           log_queue (producer rings), log_feed (record builders), log_flash_ram
│   │   ├── drivers/                chip drivers, portable (bus given as function pointers, host-testable):
│   │   │                           sensor_bus.h, imu_lsm6dsv16x (IMU, sensor hub with compass and barometer,
│   │   │                           FIFO parser), vl53l1x (ToF), flow_bridge (ACwing Flow), w25q (log flash)
│   │   ├── bsp/                    board support, tied to the STM32WB55 + HAL/RTOS: imu_i2c (HAL I²C + DMA
│   │   │                           binding, bus lock), ble_tlm_svc (GATT service + TX thread on STM32_WPAN),
│   │   │                           cfg_flash_wb (flash pages shared with CPU2), ext_i2c (HAL binding of the
│   │   │                           Qwiic devices for the vl53l1x / flow_bridge drivers), batt_adc (ADC1
│   │   │                           injected group), usb_cdc + usb/ (USB CDC device: usbd_conf, descriptors)
│   │   ├── telemetry/              frame format and CRC (telemetry.h), UART + DMA transport;
│   │   │                           tlm_ble: BLE queues HI/LO + link state; proto_v2 (app protocol ids and
│   │   │                           layouts), app_link (CMD receive side), ack_cache, usb_link (USB byte
│   │   │                           stream), spsc (all host-testable)
│   │   └── third_party/            ST lsm6dsv16x-pid driver (BSD-3), CMSIS-DSP headers and library,
│   │                               ST USB device library 2.11.6 (st_usb, SLA0044) and the HAL PCD/USB
│   │                               and LL ADC files (st_hal_usb_adc, BSD-3), kept out of CubeMX's reach
│   ├── Core/                       CubeMX-generated: main.c, interrupts, HAL MSP, FreeRTOS config, startup,
│   │                               radio-core infrastructure (app_entry, hw_timerserver, app_conf.h)
│   ├── Tests/host/                 host tests (make): flight core, failsafes, TAKEOFF/LAND, altitude filter,
│   │                               drivers, AppTask protocol, BLE rings; ExtTask end to end with the Flow
│   │                               bridge logic of 01 - FLOW_FW; battery (power_test); flight log (log_test)
│   ├── STM32_WPAN/App/             CubeMX-generated BLE application (app_ble.c with our 3 hooks, see BLE telemetry)
│   ├── Drivers/, Middlewares/      CubeMX-generated: STM32WB HAL, CMSIS, FreeRTOS, ST STM32_WPAN (BLE)
│   ├── Utilities/                  CubeMX-generated: low-power manager used by STM32_WPAN
│   ├── ACwing_FC_FW.ioc            CubeMX configuration (pins, clocks, DMA, FreeRTOS, BLE)
│   ├── ACwing_FC_FW.launch         STM32CubeIDE debug configuration (ST-LINK, SWD)
│   ├── .project, .cproject, .mxproject, .settings/   STM32CubeIDE project files
│   └── STM32WB55RGVX_FLASH.ld, ..._RAM.ld   linker scripts
├── 01 - FLOW_FW/                   ACwing Flow bridge firmware (STM32C011F4U6): PMW3901 over SPI -> I²C target
│                                   0x3B; Makefile, CMSIS only, host tests; see its README
├── 02 - Tools/                     PC tools (MATLAB and Python, equivalent) and the ACwing Pilot app
│   ├── 00 - Matlab/                MATLAB tools (R2019b+)
│   │   ├── initPath.m              adds every folder below to the path
│   │   ├── Viewer/                 acwingLiveViewer.m (live 3D triad + logging, USB or BLE), quat2rotmLocal.m
│   │   ├── Telemetry/              parseTelemetry, decode*, crc16ccitt, statusDiagnosis
│   │   ├── MagCalib/               calibMagAxes.m (axis map + hard-iron), fitHardIron.m, magCheck.m
│   │   ├── FlightLog/              acwingLogDownload.m (USB), acwingLogDecode.m (flight log format 1)
│   │   └── FiltersComparison/      tlmCapture, tlmSniffer, compareEmbeddedVsMatlab
│   │       ├── IEKF_originalVersion/   ORIGINAL filter developed in MATLAB: iekfAttitude.m, expSO3, logSO3, skewSym
│   │       └── IEKF_embeddedVersion/   EXTENDED filter: iekfAttitudeEmb.m + iekfCore*.m (MATLAB mirror of the C code)
│   ├── 01 - Python/                Python equivalents of the MATLAB tools (package acwing_tools, CLI acwing-tools)
│   │   ├── acwing_tools/           viewer, capture + sniffer, compare, magcalib, telemetry,
│   │   │                           ble_io (BLE link, bleak), filters/ (original + embedded mirror),
│   │   │                           logio (.mat logs), simulate, flightlog (flight log download + decode)
│   │   ├── tests/                  pytest suite: parity with the MATLAB outputs, recorded captures
│   │   ├── pyproject.toml, requirements.txt
│   │   └── README.md               installation, MATLAB ↔ Python map, commands
│   └── 02 - App/                   ACwing Pilot: flight/telemetry/settings/calibration app (web/PWA, iOS, Android)
│       ├── src/                    React + TypeScript; protocol/ (v2 frames and commands), sim/ (reference drone)
│       ├── HANDOVER_FW.md          drone ↔ app protocol v2: what the firmware must implement
│       └── README.md               run, simulator, native builds
├── 03 - Docs/                      documentation site sources (MkDocs Material): theory, firmware,
│   │                               tools, guides, decisions (ADR); renders on GitHub as well
│   ├── api/                        API reference landing page; Doxygen output goes to api/fc, api/flow
│   └── requirements.txt            pinned MkDocs versions
├── .github/workflows/docs.yml      CI: Doxygen + mkdocs build --strict, publish to GitHub Pages
├── mkdocs.yml                      site configuration (navigation, math, Mermaid, link checking)
├── Doxyfile.fc, Doxyfile.flow      API reference of the two firmwares (Doxygen + Graphviz)
├── .gitignore                      build outputs (Debug/, Release/, site/, api/fc, api/flow) are not versioned
└── README.md                       short entry point: what ACwing is, how to start, links to this site

Paths in this document. Short paths are relative to the folder they belong to:

Paths like Are relative to
App/…, Core/…, ACwing_FC_FW.ioc 00 - FC_FW/
Viewer/…, MagCalib/…, FiltersComparison/…, initPath.m 02 - Tools/00 - Matlab/
acwing_tools/…, tests/… 02 - Tools/01 - Python/

Three implementations of the same filter, each with its role:

Implementation Role
App/filters/iekf/ (C, float32) what flies
FiltersComparison/IEKF_originalVersion/ (MATLAB) the filter as first designed, kept unchanged as the reference of the equations
FiltersComparison/IEKF_embeddedVersion/ (MATLAB) MATLAB mirror of the C code, written line by line after iekf.c, with every improvement of IEKF on the microcontroller

acwing_tools/filters/ (Python) ports both MATLAB filters, matching them to ~1e-14.

Where to start: see the table on the home page.