How much of this firmware is actually decoded?
This page used to say roles were “inferred from symbols, string constants, and log lines”
without saying which ones. That understated some modules and overstated others. The table
below is the result of an explicit audit: every module was checked against its
disassembly in
re/v5.0.3/mpy/*.dis.
The 94 modules split into 68 Totem application modules, 23 stock MicroPython
modules, and 3 empty package
__init__.py files. Coverage of the Totem code —
the only part worth decoding — is:
No module is documented by name alone any more. When this audit first ran the
split was 28 / 27 / 13 — 55% of the bytecode decoded, and thirteen modules, 9,534
lines, never read at all. Those thirteen have since been read, and five modules moved
from PARTIAL to DECODED with them.What remains is 22 PARTIAL modules, 23,865 lines: real internals documented and
verified, main logic not. That is a different and smaller claim than “not decoded”,
and the per-module tables below say which is which.
What is left to do, in priority order
Every module that was documented by name alone has now been read. What remains is PARTIAL: modules where a surface was decoded and the main body was not. Ranked by disassembly size × number of importing modules — how much of the rest of the firmware rests on code nobody has read through.
Everything else is either DECODED or stock MicroPython. The per-module tables below
carry the rating for each.
What closed, and where it went. Thirteen modules moved from NAME-ONLY to DECODED,
and five from PARTIAL to DECODED:
f_lib/logger.py,f_lib/bitwise.py,f_lib/task_mgr.py,f_lib/file_mgr.py,f_lib/rtc_v2.py,f_lib/rtc_mem.py,f_lib/async_helpers.py,f_lib/tarfile.py,f_lib/gzip.py,f_lib/unpack.py,f_lib/firmware_helpers.py→ f_libf_lib/requests.py,f_lib/wifi.py→ networkingf_ota/hotspot.py→ hotspot serverble_controller.py→ BLEimu_fusion_auto.py→ navigationdebugger.py,peer_auto_bond.py→ telemetry
Registry notes
The v5.0.3 frozen-module registry (
mp_frozen_names) holds exactly 94 entries — the
modules listed on this page. Two more .py files, boot.py and webrepl_cfg.py,
exist only as on-flash VFS filesystem paths (./boot.py, ./webrepl_cfg.py), and are
not frozen, which is why some tallies of the image reach 96.v5.0.2 had 96 frozen modules (98 with the two VFS files). v5.0.3 removed two that
nothing imported: imu_fusion.py (an older, unused Madgwick Fusion/Cal
implementation) and io_mgr.py (only import io).Five more modules are imported but not present.
project_main.start imports
mpy_dev.dev_comms, mpy_dev.dev_imu, mpy_dev.dev_leds, mpy_dev.dev_rest,
mpy_dev.dev_mem_release and web_bluetooth. None of them is frozen into the image
and none is on the VFS, so those branches raise ImportError on a production device.
They are developer bench paths — see boot flow. (CONFIRMED: the
IMPORT_NAME opcodes are in project_main.dis; no matching module exists in the 94.)Top-level application
Boot & filesystem
Navigation
LEDs
apa106.py is not the LED driver. (CONFIRMED) leds.py opens with
IMPORT_NAME f_lib.neopixel_v2 / IMPORT_FROM NeoPixel. apa106.py imports
neopixel, and a search of all 94 disassemblies for IMPORT_NAME apa106 and
IMPORT_NAME neopixel returns only apa106.dis itself. Both modules are unreachable
in v5.0.3. Earlier revisions of these docs presented apa106.py as the driver; that
was wrong.Input & sensors
Bluetooth LE
ESP-NOW mesh & peers
Upload & OTA
Power & system
f_ble/ package
f_ota/ package
f_lib/ package
f_lib/rtc_mem.py — RTC-memory frame format (CONFIRMED)
RtcMem packs variable-length frames into machine.RTC().memory(). _rebuild_contents
walks the buffer and builds contents, a dict mapping category id → list of byte
offsets:
i += 5 + mem[i+4], stopping at mem_size or the end of the buffer.
Three category ids are in use — not two:
f_lib/logger.py — what is actually in it (CONFIRMED from obj_table)
Not decoded as a module, but its constants are readable directly and are worth recording,
because every log line quoted elsewhere on this site is produced here:
- Levels, in order:
('NOT', 'DBG', 'INF', 'WAR', 'ERR', 'EXC')— index 0–5, selected byset_print_level. ErrCodemembers:InvalidAuth,LimitReached,OperationFailed,ParamMissing,ParamInvalid,HardwareErr,InvalidLength,InvalidValue.- On-flash log file:
errors.log.print_logsbrackets its output with--- Logged Events ---/--- End Logged Events ---, and reportsNo log file on devicewhen absent. - Record format:
'{} | {} | {} | {} | {}'(five fields). - Public API:
debug,info,warn,err,exc,print_logs,set_print_level, plus internal_log/_write.
f_lib/bitwise.py — the packing primitives (function list CONFIRMED)
Every wire format documented under protocols is built from these,
but the functions themselves have not been decoded:
bin_to_hex, bin_to_str, get_mac_addr, hex_to_bin, pack_2bit_value, pack_bits,
pack_flags, pack_utf8_str, str_to_bin, unpack_2bit_value, unpack_bits,
unpack_flags, unpack_utf8_str.
Standard / vendored MicroPython
Frozen library modules that ship with, or are vendored into, MicroPython. Not Totem code, and out of scope for decoding. Status STOCK is inferred from structure — the class and method sets match the documented upstream APIs and the modules import the corresponding C modules (_espnow, bdev) — rather than from a byte-for-byte diff against an upstream
tree.
asyncio/ (__init__, core, event, funcs, lock, stream), uasyncio.py,
requests/__init__.py, urequests.py, mip/__init__.py, ssl.py, upysh.py,
webrepl.py, webrepl_setup.py, onewire.py, ds18x20.py, neopixel.py, apa106.py,
espnow.py, aioespnow.py, flashbdev.py, _boot.py, inisetup.py.
Of these, inisetup.py carries a Totem modification (it writes main.py as well as
boot.py), and neopixel.py / apa106.py are dead code.