> ## Documentation Index
> Fetch the complete documentation index at: https://totem-cb8b3887.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Module reference

> All 94 frozen MicroPython modules in the v5.0.3 image, with a per-module decode-coverage rating.

Every module below is frozen into the firmware. Names are exact, taken from the frozen module
registry. **Roles are not all equally trustworthy**, so each one carries a status marker saying
how it was established.

## How much of this firmware is actually decoded?

<Note>
  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`.
</Note>

| Status        | Meaning                                                                                                                                                                |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **DECODED**   | Someone read the bytecode and documented actual behaviour — named functions, constant *values*, control flow. Trust it.                                                |
| **PARTIAL**   | Real internals are documented and verified, but the module's main logic is not. Usually one surface (a wire format, a v5.0.3 delta) was decoded and the rest was left. |
| **NAME-ONLY** | The role is a guess from the module name and a few strings. **Nothing here has been verified against bytecode.** Treat as a hypothesis.                                |
| **STOCK**     | Upstream MicroPython or `micropython-lib`, not Totem code. Decoding it would just re-document MicroPython.                                                             |

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:

| Status    | Modules | Share of modules | Lines of disassembly | Share of bytecode |
| --------- | ------- | ---------------- | -------------------- | ----------------- |
| DECODED   | 46      | 68%              | 68,314               | 74%               |
| PARTIAL   | 22      | 32%              | 23,865               | 26%               |
| NAME-ONLY | 0       | 0%               | 0                    | 0%                |

<Note>
  **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.
</Note>

<Warning>
  **"Decoded" still does not mean "correct".** The same audit that produced these ratings
  found roughly sixty-five false claims across these pages, several of them stamped
  **confirmed** — a driver that is dead code, a deep-sleep mode that does not exist, a
  BLE central role the firmware does not compile, and an OTA hash that is never computed.
  Every rating here is a statement about how much was read, not a warranty on every
  sentence. Where a page marks a claim *inferred* or *not recoverable*, that is the
  honest state of it.
</Warning>

The counts above are module counts and raw disassembly line counts, which are a proxy for
volume, not for importance. The ranked gap list below weights by how much other code
depends on each module.

## 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.

| # | Module              | Lines | Importers | Status  | What is still missing                                                                                                                    |
| - | ------------------- | ----- | --------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | `project_data.py`   | 2,642 | 27        | PARTIAL | The global config/constants object. The `config.json` shape and many constants are documented; the `ActiveModes` mutation paths are not. |
| 2 | `ubx_gnss.py`       | 3,060 | 1         | PARTIAL | The fix pipeline, CFG-VALSET frames and AssistNow transfer are now documented; the remaining UBX message handlers are not.               |
| 3 | `compassing.py`     | 1,956 | 3         | PARTIAL | The dial rendering and peer-proximity mapping are documented; `start_rotation`'s full frame loop is not.                                 |
| 4 | `espnow_conn_v2.py` | —     | —         | PARTIAL | The frame formats, radio windows and light-sleep rules are documented; the supervisor and outbox internals only partly.                  |
| 5 | `compass.py`        | —     | —         | PARTIAL | The largest module in the image. Most subsystems' entry points are decoded through it; it has never been read end to end.                |

Everything else is either DECODED or stock MicroPython. The per-module tables below
carry the rating for each.

<Note>
  **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\_lib](/reference/f-lib)
  * `f_lib/requests.py`, `f_lib/wifi.py` → [networking](/reference/networking)
  * `f_ota/hotspot.py` → [hotspot server](/firmware/hotspot-server)
  * `ble_controller.py` → [BLE](/protocols/ble)
  * `imu_fusion_auto.py` → [navigation](/subsystems/navigation)
  * `debugger.py`, `peer_auto_bond.py` → [telemetry](/subsystems/telemetry)
</Note>

## Registry notes

<Note>
  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`).
</Note>

<Note>
  **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](/firmware/boot-flow). *(CONFIRMED: the
  `IMPORT_NAME` opcodes are in `project_main.dis`; no matching module exists in the 94.)*
</Note>

## Top-level application

| Module            | Status  | Role                                                                                                                                                                                                                                                        |
| ----------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `main.py`         | DECODED | Entire file is `try: from ota_daemon import *` / `except ImportError: pass`. Nothing else.                                                                                                                                                                  |
| `ota_daemon.py`   | DECODED | Defines `start_ota(cmd, version, url, networks)`, calls `firmware_rollback.cancel()` to mark the running slot valid, then `from project_main import *` inside a `try` that prints `Project Exception Occurred` on failure                                   |
| `project_main.py` | DECODED | Module body ends with `rtc_mem.reload()` then `start(1)`; `start(cmd, opt)` dispatches the boot modes. See [boot flow](/firmware/boot-flow)                                                                                                                 |
| `project_data.py` | PARTIAL | Project constants / configuration data; `ActiveModes` flags (v5.0.3 adds `ble_ticks_app_internet`, `is_ble_log_upload`, `is_file_upload_test`, `is_nav_log_fast_rotate`). Also owns the RTC device snapshot (`get_device_snapshot` / `set_device_snapshot`) |
| `compass.py`      | DECODED | Top-level compass state machine — the largest application module after `espnow_conn_v2`                                                                                                                                                                     |
| `compassing.py`   | PARTIAL | Compass math (heading, 2D/3D, bias) and peer-proximity LED mapping                                                                                                                                                                                          |
| `new_vibe.py`     | DECODED | Vibe Mode — microphone-driven sound-reactive ring LED effect (`mic.read_u16` → `ring.buf`; `newvibe-1.10`, v5.0.2: `newvibe-1.9`). Not magnetometer calibration                                                                                             |
| `chat_msg.py`     | PARTIAL | Peer-to-peer chat messages (`Messenger`, `gen_msg_uid`, `MSG_IN_BUFF`, `MSG_OUT_BUFF`). **Imported by no module in v5.0.3**                                                                                                                                 |
| `stats.py`        | PARTIAL | Runtime statistics counters                                                                                                                                                                                                                                 |
| `debugger.py`     | DECODED | On-device telemetry recorder with its own log writer and rotation — *not* decoded                                                                                                                                                                           |
| `demi_god.py`     | DECODED | Privileged broadcast command system                                                                                                                                                                                                                         |

## Boot & filesystem

| Module         | Status  | Role                                                                                                                                                                                                      |
| -------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `_boot.py`     | STOCK   | Stock esp32 `_boot`: mounts `bdev` at `/`, falls back to `inisetup.setup()` on `OSError`                                                                                                                  |
| `inisetup.py`  | STOCK\* | Stock esp32 `inisetup`, **with one Totem change**: `setup()` formats LittleFS2 and then writes *both* `boot.py` (stock template) and `main.py` (the `ota_daemon` snippet). Upstream writes only `boot.py` |
| `flashbdev.py` | STOCK   | Flash block device for the VFS                                                                                                                                                                            |

## Navigation

| Module                    | Status  | Role                                                                                                                                                                                                                     |
| ------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `ubx_gnss.py`             | PARTIAL | u-blox UBX GNSS driver                                                                                                                                                                                                   |
| `nav_helpers.py`          | DECODED | Navigation math helpers (`get_azimuth`, `get_heading_mot`, distance, odometer)                                                                                                                                           |
| `nav_logger.py`           | PARTIAL | Navigation event logging (v5.0.3: fast `events.bin` rotation at ≥1024 B when `is_nav_log_fast_rotate`)                                                                                                                   |
| `imu_fusion_auto.py`      | DECODED | **Madgwick fusion** over an ICM-20948, plus the 2D/3D magnetometer calibration state machine; the sole fusion module in v5.0.3 (byte-identical to v5.0.2), defines `_spin_deg`. See [navigation](/subsystems/navigation) |
| `mag_wmm_data.py`         | DECODED | World Magnetic Model data — a single constant, `WMM_2025`. Pure data, nothing to decode                                                                                                                                  |
| `task_mag_declination.py` | PARTIAL | Periodic declination recompute against `WMM_2025`                                                                                                                                                                        |

## LEDs

| Module                 | Status           | Role                                                                                                                                           |
| ---------------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `leds.py`              | DECODED          | LED behaviour / status mapping (`LightStrip`). **This is the live LED path**: it imports `NeoPixel` from `f_lib/neopixel_v2.py`                |
| `animations.py`        | PARTIAL          | Animation definitions                                                                                                                          |
| `f_lib/neopixel_v2.py` | PARTIAL          | The addressable-LED driver actually used, via `leds.py`                                                                                        |
| `neopixel.py`          | STOCK / **DEAD** | Stock MicroPython NeoPixel driver. Imported only by `apa106.py`; nothing else in the image imports it                                          |
| `apa106.py`            | STOCK / **DEAD** | Stock esp32 `apa106`: 49 lines, `class APA106(NeoPixel)` overriding only `ORDER = (0, 1, 2, 3)`. **No module imports it.** Dead code in v5.0.3 |

<Note>
  **`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.
</Note>

## Input & sensors

| Module               | Status  | Role                                                                                                                                 |
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `button.py`          | DECODED | Both physical buttons, power and SOS (`AsyncButton`); v5.0.3 replaces the 50 ms `debounce` coroutine with a 30 ms `_edge_ms` lockout |
| `touch_button_v2.py` | PARTIAL | Capacitive Touch Crystal                                                                                                             |
| `peripherals.py`     | DECODED | Peripheral bring-up (`DeviceLeds`, `pwr_gate_pin`, `get_batt_pct`)                                                                   |
| `ds18x20.py`         | STOCK   | Stock DS18B20 temperature sensor driver                                                                                              |
| `onewire.py`         | STOCK   | Stock 1-Wire bus driver                                                                                                              |

## Bluetooth LE

| Module                | Status  | Role                                                                                                                                                                                             |
| --------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `ble_controller.py`   | DECODED | BLE enable/disable blocker engine. The class is `BleController`; `BleBlockers` is real. **`BleCtrl` is only a log-line prefix, not a class** — an earlier revision of this page listed it as one |
| `ble_core.py`         | DECODED | Core BLE glue — characteristic/service registration, secrets                                                                                                                                     |
| `ble_manager.py`      | DECODED | Connection/session manager (`BleManager`, `send_data_v2`, `gen_live_data`, `execute_cmd`)                                                                                                        |
| `svc_ble_transfer.py` | PARTIAL | Chunked transfer GATT service; entered at boot via the RTC category-0 handoff                                                                                                                    |
| `ota_ble.py`          | DECODED | OTA over BLE (v5.0.3 imports `CHUNK_HDR_FMT` / `CHUNK_HDR_SZ` from `f_ble.chunking`)                                                                                                             |

## ESP-NOW mesh & peers

| Module               | Status  | Role                                                                                                                                                                                                                                                                      |
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `espnow.py`          | STOCK   | Stock MicroPython esp32 `espnow.py`: `from _espnow import *`, then `class ESPNow(ESPNowBase)` adding `irecv`/`recv`/`irq`/`__iter__`. *(This resolves the "origin uncertain" note in earlier revisions — it is the upstream Python wrapper over the `_espnow` C module.)* |
| `espnow_conn_v2.py`  | DECODED | Connection/session layer; message schema maps (`TOTEM_MSG_MAP`, `EXTENDED`, `COMM_SPEED`). Largest module in the image; the protocol surface is decoded, the radio queue internals less so                                                                                |
| `espnow_msg.py`      | DECODED | ESP-NOW message builders (`*_gen_*` payload generators, `pack_flags`, `rot13`)                                                                                                                                                                                            |
| `aioespnow.py`       | STOCK   | Stock asyncio ESP-NOW wrapper (`AIOESPNow`)                                                                                                                                                                                                                               |
| `peer_auto_bond.py`  | DECODED | One function, `bond_to_group`. No module imports it                                                                                                                                                                                                                       |
| `peer_helpers.py`    | PARTIAL | Peer utilities (`is_peer_stale`: 7200 s in v5.0.3, v5.0.2: 14400 s)                                                                                                                                                                                                       |
| `peer_management.py` | PARTIAL | Peer registry / lifecycle; `auto_bond_to_peers` is decoded, the rest is not                                                                                                                                                                                               |

## Upload & OTA

| Module                | Status  | Role                                                                                        |
| --------------------- | ------- | ------------------------------------------------------------------------------------------- |
| `data_upload_v2.py`   | PARTIAL | App data upload over WiFi/HTTP (`UploadData`, `upload_file`, `API_ENDPOINT`)                |
| `ota_block_writer.py` | DECODED | Write image chunks to the OTA slot (`OtaWriter`, `BlockDev`)                                |
| `ota_callback.py`     | DECODED | OTA progress/state callbacks and their LED colours (`PROGRESS_RGB`, `ERROR_RGB`, `LOG_RGB`) |
| `ota_daemon.py`       | DECODED | Background OTA entry — see *Top-level application* above                                    |

## Power & system

| Module             | Status  | Role                                                                                                                                                |
| ------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `device_power.py`  | DECODED | Power state machine, battery health, and `shut_down_tasks(method, is_save_config)` — the only power-down path. See [boot flow](/firmware/boot-flow) |
| `wdt_manager.py`   | DECODED | Watchdog management (conditions/blockers; v5.0.3 adds the `WLAN_KICK` blocker)                                                                      |
| `event_manager.py` | PARTIAL | Pub/sub event bus (`block` / `unblock`)                                                                                                             |

## `f_ble/` package

| Module                 | Status  | Role                                                                     |
| ---------------------- | ------- | ------------------------------------------------------------------------ |
| `f_ble/__init__.py`    | —       | Empty package init (15 lines)                                            |
| `f_ble/peripheral.py`  | DECODED | GATT peripheral + advertising (`gen_advertise_payload`)                  |
| `f_ble/ble_lite.py`    | DECODED | Lightweight GATT peripheral (`BleLite`)                                  |
| `f_ble/ble_data.py`    | DECODED | Message (de)serialisation; `Characteristic`, `Service`, `Conn`, `BleErr` |
| `f_ble/chunking.py`    | DECODED | Payload fragmentation (`CHUNK_HDR_FMT = '<HHiH'`, `CHUNK_HDR_SZ = 12`)   |
| `f_ble/file_upload.py` | DECODED | Resumable chunked file transfer (`FileUploader`, `RES_*` result codes)   |

## `f_ota/` package

| Module                 | Status  | Role                                                                                                                                                                                    |
| ---------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `f_ota/__init__.py`    | —       | Empty package init (15 lines)                                                                                                                                                           |
| `f_ota/main.py`        | PARTIAL | OTA orchestration (`install_firmware_update`, `get_release_from_api`)                                                                                                                   |
| `f_ota/hotspot.py`     | DECODED | An HTTP + WebSocket server, not just a "hotspot updater". **Nothing imports it and its one entry point is retired**, so it is dead code. See [hotspot server](/firmware/hotspot-server) |
| `f_ota/install_ota.py` | PARTIAL | Write + activate new slot                                                                                                                                                               |
| `f_ota/config.py`      | PARTIAL | OTA configuration and status (`OtaStatus`, `OtaErr`)                                                                                                                                    |
| `f_ota/system.py`      | DECODED | System helpers; `release_code` `5.0.3`, `release_id` 339 (v5.0.2: 335)                                                                                                                  |
| `f_ota/f_assets.py`    | PARTIAL | Asset fetch/apply                                                                                                                                                                       |

## `f_lib/` package

| Module                       | Status  | Role                                                                                                                                                                                                                         |
| ---------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `f_lib/__init__.py`          | —       | Empty package init (15 lines)                                                                                                                                                                                                |
| `f_lib/wifi.py`              | DECODED | `WiFi` class: `connect`, `connect_to_known`, `scan`, `get_nearby_networks`, `power_on`. Used by `f_ota/`                                                                                                                     |
| `f_lib/wifi_v2.py`           | PARTIAL | Station/AP control with power/protocol modes (`MODE_ESP_NOW_WIFI`, `PM_PERF`, `PM_PWRSAVE`)                                                                                                                                  |
| `f_lib/requests.py`          | DECODED | Async HTTP client: `Response`, `SocketWrapper`, `Downloader`, and `get`/`post`/`put`/`patch`/`delete`/`head`/`rest`                                                                                                          |
| `f_lib/task_mgr.py`          | DECODED | asyncio task manager, 28 importers. **A task that raises is killed permanently and never reaches `errors.log`.** See [f\_lib](/reference/f-lib)                                                                              |
| `f_lib/async_helpers.py`     | DECODED | `EventTimeout` (a context manager with `_countdown`) and `AsyncDeque`                                                                                                                                                        |
| `f_lib/generators.py`        | PARTIAL | Generator helpers (`breathe_effect`, `sos_timing`)                                                                                                                                                                           |
| `f_lib/rtc_mem.py`           | DECODED | **The RTC-memory allocator.** `RtcMem` over `machine.RTC().memory()`. See the frame format below                                                                                                                             |
| `f_lib/rtc_v2.py`            | DECODED | **Not RTC-memory storage.** `class RTCv2(machine.RTC)` adding calendar/timestamp maths. See [f\_lib](/reference/f-lib)                                                                                                       |
| `f_lib/file_mgr.py`          | DECODED | File management. `save_obj` is a plain write, **not** the atomic `.tmp`+rename — that lives in `project_data.update_config`. v5.0.3 adds async SHA-256 `gen_file_hash` and `get_oldest_file`. See [f\_lib](/reference/f-lib) |
| `f_lib/gzip.py`              | DECODED | gzip decompression for `.tgz` OTA                                                                                                                                                                                            |
| `f_lib/tarfile.py`           | DECODED | `TarFile` / `TarInfo` / `FileSection` reader                                                                                                                                                                                 |
| `f_lib/unpack.py`            | DECODED | `unzip_tar` / `unpack_tar` — glues `gzip` to `tarfile`                                                                                                                                                                       |
| `f_lib/firmware_ota.py`      | PARTIAL | OTA slot writing (`BlockDevWriter`, `from_firmware_file`)                                                                                                                                                                    |
| `f_lib/firmware_rollback.py` | DECODED | Rollback logic (`mark_app_valid_cancel_rollback`, `OTA_MIN`/`OTA_MAX`)                                                                                                                                                       |
| `f_lib/firmware_helpers.py`  | DECODED | `running_partition`                                                                                                                                                                                                          |
| `f_lib/neopixel_v2.py`       | PARTIAL | The LED driver `leds.py` actually uses                                                                                                                                                                                       |
| `f_lib/bitwise.py`           | DECODED | Bit manipulation — see below                                                                                                                                                                                                 |
| `f_lib/helpers.py`           | PARTIAL | Misc utilities (`rot13`, `fallback`)                                                                                                                                                                                         |
| `f_lib/logger.py`            | DECODED | Structured logging — see below                                                                                                                                                                                               |

### `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**:

```text theme={null}
offset  size  meaning
  +0      2   magic, b'\xa7t'
  +2      1   category id
  +3      1   category-specific byte
  +4      1   payload length N
  +5      N   payload
```

The walk is `i += 5 + mem[i+4]`, stopping at `mem_size` or the end of the buffer.

Three category ids are in use — not two:

| Cat   | Written by                         | Read by                            | Contents                                                                                                                                                                                                                                                     |
| ----- | ---------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **0** | `ble_manager.execute_cmd`          | `project_main.start`               | Reboot-into-service handoff. BLE command 3 or 4 writes a 5-byte frame with `frame[3]` set to 1 or 2 and zero payload, then soft-resets. On the next boot `start` reads it, deletes it, and runs `asyncio.run(svc_ble_transfer.svc_manager(cmd_id=frame[3]))` |
| **1** | `device_power.save_ble_secrets`    | `ble_core`, `device_power`         | A raw mirror of `ble_keys.bin` — the BLE pairing secrets, so they survive a reset without a VFS write                                                                                                                                                        |
| **2** | `project_data.set_device_snapshot` | `project_data.get_device_snapshot` | A 7-byte device snapshot: 5-byte header plus a 2-byte payload whose second byte is `pack_flags(...)`. Bit 0 = BLE active or disconnect scheduled; bit 2 = GNSS location available or phone GNSS in use                                                       |

### `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
  by `set_print_level`.
* **`ErrCode` members**: `InvalidAuth`, `LimitReached`, `OperationFailed`, `ParamMissing`,
  `ParamInvalid`, `HardwareErr`, `InvalidLength`, `InvalidValue`.
* **On-flash log file**: `errors.log`. `print_logs` brackets its output with
  `--- Logged Events ---` / `--- End Logged Events ---`, and reports
  `No log file on device` when 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](/protocols/overview) 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.
