Skip to main content

Layered view

Totem’s firmware is a MicroPython application organized into a small number of packages plus a set of top-level modules — 94 frozen modules in v5.0.3 (v5.0.2: 96; the unused imu_fusion.py and io_mgr.py were removed). From the bottom up:

Packages

f_lib/ — platform library

Reusable infrastructure used by everything above it.

f_ble/ — Bluetooth LE

f_ota/ — update engine

Top-level modules by subsystem

compass.py, compassing.py, ubx_gnss.py, nav_helpers.py, nav_logger.py, imu_fusion_auto.py, mag_wmm_data.py, task_mag_declination.py
The full list with one-line descriptions is on the module reference, which also rates each module DECODED / PARTIAL / NAME-ONLY so you can tell which of the roles above were read out of the bytecode and which are still guesses. Of the 68 Totem application modules, 28 are decoded, 27 are partial, and 13 have never been read.

Concurrency model

The application is asyncio-based. f_lib/task_mgr.py and the frozen asyncio package schedule long-running coroutines (BLE service loop, mesh outbox drain, GNSS polling, LED animation ticks, background checks). Many tasks wait on evt_* events from the event_manager bus before doing work, so subsystems can be paused and resumed — for example, evt_ble_active and evt_battery_usable gate BLE and battery-dependent tasks, and Vibe Mode (new_vibe) waits on events such as evt_non_eco_mode and evt_led_override_off. (The v5.0.2 log lines task started, waiting on enable events / task cancelled came from Vibe Mode’s _DBG telemetry and no longer exist in v5.0.3.) In v5.0.3 compass.start launches the ESP-NOW comms task through enow_v2.communicate_supervised, which restarts it if it crashes (v5.0.2 launched communicate_v2 directly). A separate async watchdog-feed loop (wdt_manager.py / WdtManager) runs alongside task_mgr and asyncio: it feeds the hardware WDT via wdt_feed_loop / feed_now, but is disabled while any WdtConditions condition or WdtBlockers blocker is active (_should_enable returns False). v5.0.3’s blockers are log rotate, vfs write, and the new wlan kick (WLAN_KICK = 2, set by ble_manager around its WiFi-driver kick). When the loop is running, a stalled event loop stops the feed and lets the watchdog fire.