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.

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.