Architecture ============ This page is for people who want to understand or hack on the firmware. For build and test commands see :doc:`building-and-testing`. The firmware is written in Rust, targeting ``xtensa-esp32-espidf`` on the ESP-IDF framework. At its heart is a state-machine loop with a dual-core design. Dual-core design ---------------- - **Core 1 (main):** runs the ATM state machine — ``Idle → CountingCoins → WithdrawReady``. - **Core 0 (background):** runs the BlockClock/OrangeClock mempool data fetcher when enabled, spawned via the FreeRTOS ``xTaskCreatePinnedToCore`` API. The application state is the ``AppState`` enum (``state.rs``): ``Idle``, ``CountingCoins(u64)`` and ``WithdrawReady(u64)``. Modules ------- .. list-table:: :header-rows: 1 :widths: 26 74 * - Module - Responsibility * - ``state.rs`` - The ``AppState`` enum that drives the main loop. * - ``lnurl.rs`` - Offline LNURL-withdraw generation — the core crypto. Implements the LNbits FOSSA protocol: AES-256-CBC encryption with EVP_BytesToKey-style key derivation (MD5 rounds) and bech32-encoded output. * - ``display.rs`` - The ``AtmDisplay`` trait with per-resolution implementations for the 1.54", 2.13" and 2.7" Waveshare e-paper displays (``epd-waveshare`` + ``embedded-graphics``). Also renders the BlockClock screens. * - ``board.rs`` - The ``BoardType`` enum (``Generic`` / ``Waveshare``) mapping to the GPIO pin assignments — the source of truth for :doc:`../hardware/wiring`. * - ``coins.rs`` - Pulse-counting coin detection via a debounced GPIO interrupt. ``COIN_MAP`` maps a pulse count to a cent value; the ISR uses an ``AtomicU32`` for lock-free pulse counting. * - ``config.rs`` - NVS (non-volatile storage) persistence for board type, display type, the LNbits connection and BlockClock settings. NVS keys must be ≤ 15 chars. * - ``util.rs`` - ``LNBitsConnection`` parsing from the device string and QR-code matrix generation. * - ``wifi.rs`` - The WiFi access-point configuration portal (HTML form via ``include_str!``) and ``WifiStation`` for the BlockClock's station-mode connection. * - ``mempool.rs`` - Fetches Bitcoin network data (block height, price, fees, difficulty, mempool stats) from the mempool.space API with a fallback endpoint. The background fetcher runs on Core 0 with ``Arc>>`` shared state. * - ``orangeclock_icons.rs`` - Bitmap icon data for the BlockClock display. * - ``lib.rs`` - Re-exports ``coins``, ``lnurl``, ``mempool``, ``state`` and ``util`` for host-side unit testing. Key design constraints ---------------------- - The ``esp`` feature flag gates all ESP32-specific dependencies. The ``[lib]`` target built with ``--no-default-features`` compiles the platform-independent modules for x86 testing (see :doc:`building-and-testing`). - The ``epd-waveshare`` crate is pinned to a specific git revision (``1e525bb``) for unreleased display-driver support. - The espflash runner erases the NVS config partition on every flash (``--erase-parts nvs`` in ``.cargo/config.toml``), so the device returns to the config portal after a flash. - The configuration portal is triggered by holding GPIO 0 (the BOOT button, physically inside the case) during startup.