# Display Refresh Mechanism This document explains the dual-core architecture used to handle USB keyboard input and e-Paper display updates efficiently on the Raspberry Pi Pico. ## Architecture Overview The system utilizes both cores of the RP2040 to ensure that the slow refresh rate of the e-Paper display does not block or lag the USB keyboard input. ### Core 0: Input Handling (Producer) * **Role:** Handles USB Host tasks, processes keyboard reports, and manages the text buffer. * **Behavior:** 1. Receives key presses via TinyUSB callbacks. 2. Updates the local text buffer (`g_entry_list`). 3. Triggers a display update via `send_display_update()`. * **Non-Blocking Transmission:** * When an update is needed, Core 0 allocates a `DisplayMessage` on the heap. * It attempts to push the message pointer to the Multicore FIFO. * **Critical Optimization:** It uses `multicore_fifo_wready()` to check if the FIFO has space. * **If Ready:** Pushes the message. * **If Full:** Immediately frees the message and skips the update. This ensures Core 0 never waits for Core 1, keeping typing responsive. ### Core 1: Display Driver (Consumer) * **Role:** Manages the e-Paper hardware and performs the actual drawing operations. * **Behavior:** 1. Initializes the e-Paper display. 2. Waits for messages in the Multicore FIFO. * **Smart Refresh (Accumulation):** * When Core 1 wakes up to process a message, it first checks if *more* messages have arrived while it was sleeping or busy. * **FIFO Draining:** It loops through the FIFO, popping and freeing all intermediate messages, keeping only the **latest** one. * This ensures that if the user types "Hello World" quickly, Core 1 might skip rendering "Hello " and jump straight to rendering "Hello World", preventing a queue of obsolete updates from slowing down the display. ## Data Flow Diagram ```mermaid sequenceDiagram participant User participant Core0 as Core 0 (USB/Input) participant FIFO as Multicore FIFO participant Core1 as Core 1 (Display) User->>Core0: Types 'A' Core0->>FIFO: Push Msg('A') User->>Core0: Types 'B' Core0->>FIFO: Push Msg('AB') Note over Core1: Busy refreshing... User->>Core0: Types 'C' alt FIFO is Full Core0->>Core0: Drop Msg('ABC') (Free memory) else FIFO has space Core0->>FIFO: Push Msg('ABC') end Core1->>FIFO: Pop Msg('A') Note over Core1: Checks FIFO for newer msgs FIFO->>Core1: Msg('AB') exists Core1->>Core1: Free Msg('A'), use Msg('AB') FIFO->>Core1: Msg('ABC') exists Core1->>Core1: Free Msg('AB'), use Msg('ABC') Core1->>Display: Render('ABC') ``` ## Key Functions * **`send_display_update(const char *entry, bool finish_line)`**: * Allocates memory. * Checks FIFO status. * Pushes or drops message. * **`core1_display_init()`**: * Main loop for Core 1. * Drains FIFO to find the latest message. * Calls e-Paper drawing functions. ## Memory Management * Messages are `malloc`'d by Core 0. * Messages are `free`'d by Core 1 (after processing or dropping). * If Core 0 drops a message because the FIFO is full, it `free`s it immediately.