# joshua12-5/macropad architecture

> Architecture diagram of the GitHub repository joshua12-5/macropad, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-10-01). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/joshua12-5/macropad
- Repository: https://github.com/joshua12-5/macropad

## Overview

RP2040 Macropad combines a desktop configurator with USB HID firmware for a programmable 12-key pad. The user edits profiles, macros, or idle animations in the configurator, then connects to the device to upload or manage configuration; the firmware stores it and runs the pad as a keyboard, with an OLED menu and optional app-driven profile switching. The graph includes the documented editing, backup, animation, and auto-switch capabilities. Some feature modules were not sampled, so their internal call relationships are omitted; README-supported links are identified as such.

Main entry points: [`firmware/src/main.c`](https://github.com/joshua12-5/macropad/blob/main/firmware/src/main.c) (Firmware loop), [`configurator/macropad_config/protocol/device.py`](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/protocol/device.py) (Device API), [`configurator/macropad_config/widgets`](https://github.com/joshua12-5/macropad/tree/main/configurator/macropad_config/widgets) (Task editors), [`configurator/macropad_config/protocol/frames.py`](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/protocol/frames.py) (Protocol frames)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_desktop["Desktop configurator"]
  node_app["App entry<br/>[app.py]"]
  node_workspace["Configurator window<br/>[main_window.py]"]
  node_editors["Task editors"]
  node_preview["Pad preview<br/>[pad_preview.py]"]
  node_autoswitch["Auto-switch"]
  node_backup["Device backup<br/>[device_backup.py]"]
end

subgraph group_config_data["Configuration data"]
  node_profiles["Profile model<br/>[profile.py]"]
  node_macros["Macro model<br/>[macro.py]"]
  node_schema["Data schema<br/>[schema.py]"]
  node_anim_tools["Animation tools"]
  node_profile_blob["Profile encoding<br/>[profile_blob.py]"]
  node_macro_blob["Macro encoding<br/>[macro_blob.py]"]
  node_anim_codec["Animation encoding<br/>[codec.py]"]
  node_frames["Protocol frames<br/>[frames.py]"]
  node_device_api["Device API<br/>[device.py]"]
end

subgraph group_firmware_core["Firmware runtime"]
  node_firmware_loop["Firmware loop<br/>[main.c]"]
  node_config_protocol["Config protocol<br/>[config_protocol.c]"]
  node_storage[("Flash storage<br/>[storage.c]")]
  node_profile_runtime["Profile runtime<br/>[profiles.c]"]
  node_macro_runtime["Macro engine<br/>[macros.c]"]
  node_actions["Action engine<br/>[actions.c]"]
  node_usb_keyboard["USB keyboard<br/>[usb_hid_app.c]"]
  node_matrix_encoder["Keys and encoder<br/>[matrix.c]"]
end

subgraph group_device_features["On-device features"]
  node_oled_menu["OLED menu<br/>[device_menu.c]"]
  node_oled_ui["OLED display<br/>[oled_ui.c]"]
  node_animation["Idle animation<br/>[anim.c]"]
end

node_user(("User"))
node_hid_device[("USB HID device")]
node_flash[("Device flash")]

node_user -->|"starts"| node_app
node_app -->|"opens GUI"| node_workspace
node_user -->|"edits configuration"| node_editors
node_workspace -->|"presents tasks"| node_editors
node_workspace -->|"shows layout"| node_preview
node_editors -.->|"edits profiles"| node_profiles
node_editors -.->|"edits macros"| node_macros
node_editors -.->|"edits animations"| node_anim_tools
node_autoswitch -->|"sets active profile"| node_device_api
node_autoswitch -->|"switches profile"| node_hid_device
node_backup -.->|"backs up device"| node_device_api
node_profiles -->|"validates against"| node_schema
node_macros -->|"validates against"| node_schema
node_profile_blob -.->|"uses framing"| node_frames
node_macro_blob -->|"uses framing"| node_frames
node_anim_codec -->|"uses frame format"| node_frames
node_device_api -->|"exchanges frames"| node_frames
node_device_api -->|"transfers profiles"| node_profile_blob
node_device_api -->|"transfers macros"| node_macro_blob
node_device_api -->|"transfers animations"| node_anim_codec
node_device_api -->|"communicates over HID"| node_hid_device
node_hid_device -->|"sends configuration"| node_config_protocol
node_firmware_loop -->|"runs protocol"| node_config_protocol
node_firmware_loop -->|"polls inputs"| node_matrix_encoder
node_firmware_loop -->|"runs actions"| node_actions
node_firmware_loop -->|"runs macros"| node_macro_runtime
node_firmware_loop -->|"runs menu"| node_oled_menu
node_firmware_loop -->|"updates display"| node_oled_ui
node_firmware_loop -->|"runs animation"| node_animation
node_firmware_loop -->|"persists state"| node_storage
node_matrix_encoder -.->|"triggers actions"| node_actions
node_actions -.->|"emits key actions"| node_usb_keyboard
node_config_protocol -.->|"reads and writes"| node_storage
node_storage -->|"persists configuration"| node_flash
node_oled_menu -.->|"switches profiles"| node_profile_runtime
node_animation -->|"stores animation frames"| node_flash
node_firmware_loop -->|"updates HID reports"| node_usb_keyboard

click node_app "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/app.py"
click node_workspace "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/main_window.py"
click node_editors "https://github.com/joshua12-5/macropad/tree/main/configurator/macropad_config/widgets"
click node_preview "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/widgets/pad_preview.py"
click node_autoswitch "https://github.com/joshua12-5/macropad/tree/main/configurator/macropad_config/autoswitch"
click node_backup "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/device_backup.py"
click node_profiles "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/models/profile.py"
click node_macros "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/models/macro.py"
click node_schema "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/models/schema.py"
click node_anim_tools "https://github.com/joshua12-5/macropad/tree/main/configurator/macropad_config/animation"
click node_profile_blob "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/protocol/profile_blob.py"
click node_macro_blob "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/protocol/macro_blob.py"
click node_anim_codec "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/animation/codec.py"
click node_frames "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/protocol/frames.py"
click node_device_api "https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/protocol/device.py"
click node_firmware_loop "https://github.com/joshua12-5/macropad/blob/main/firmware/src/main.c"
click node_config_protocol "https://github.com/joshua12-5/macropad/blob/main/firmware/src/config_protocol.c"
click node_storage "https://github.com/joshua12-5/macropad/blob/main/firmware/src/storage.c"
click node_profile_runtime "https://github.com/joshua12-5/macropad/blob/main/firmware/src/profiles.c"
click node_macro_runtime "https://github.com/joshua12-5/macropad/blob/main/firmware/src/macros.c"
click node_actions "https://github.com/joshua12-5/macropad/blob/main/firmware/src/actions.c"
click node_usb_keyboard "https://github.com/joshua12-5/macropad/blob/main/firmware/src/usb_hid_app.c"
click node_matrix_encoder "https://github.com/joshua12-5/macropad/blob/main/firmware/src/matrix.c"
click node_oled_menu "https://github.com/joshua12-5/macropad/blob/main/firmware/src/device_menu.c"
click node_oled_ui "https://github.com/joshua12-5/macropad/blob/main/firmware/src/oled_ui.c"
click node_animation "https://github.com/joshua12-5/macropad/blob/main/firmware/src/anim.c"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_app,node_workspace,node_editors,node_preview,node_autoswitch,node_backup,node_user toneBlue
class node_profiles,node_macros,node_schema,node_anim_tools,node_profile_blob,node_macro_blob,node_anim_codec,node_frames,node_device_api,node_hid_device,node_flash toneAmber
class node_firmware_loop,node_config_protocol,node_storage,node_profile_runtime,node_macro_runtime,node_actions,node_usb_keyboard,node_matrix_encoder toneMint
class node_oled_menu,node_oled_ui,node_animation toneRose
```

## Components

### Desktop configurator

- [App entry](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/app.py): `configurator/macropad_config/app.py`
- [Configurator window](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/main_window.py): `configurator/macropad_config/main_window.py`
- [Task editors](https://github.com/joshua12-5/macropad/tree/main/configurator/macropad_config/widgets): `configurator/macropad_config/widgets`
- [Pad preview](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/widgets/pad_preview.py): `configurator/macropad_config/widgets/pad_preview.py`
- [Auto-switch](https://github.com/joshua12-5/macropad/tree/main/configurator/macropad_config/autoswitch): `configurator/macropad_config/autoswitch`
- [Device backup](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/device_backup.py): `configurator/macropad_config/device_backup.py`

### Configuration data

- [Profile model](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/models/profile.py): `configurator/macropad_config/models/profile.py`
- [Macro model](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/models/macro.py): `configurator/macropad_config/models/macro.py`
- [Data schema](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/models/schema.py): `configurator/macropad_config/models/schema.py`
- [Animation tools](https://github.com/joshua12-5/macropad/tree/main/configurator/macropad_config/animation): `configurator/macropad_config/animation`
- [Profile encoding](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/protocol/profile_blob.py): `configurator/macropad_config/protocol/profile_blob.py`
- [Macro encoding](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/protocol/macro_blob.py): `configurator/macropad_config/protocol/macro_blob.py`
- [Animation encoding](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/animation/codec.py): `configurator/macropad_config/animation/codec.py`
- [Protocol frames](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/protocol/frames.py): `configurator/macropad_config/protocol/frames.py`
- [Device API](https://github.com/joshua12-5/macropad/blob/main/configurator/macropad_config/protocol/device.py): `configurator/macropad_config/protocol/device.py`

### Firmware runtime

- [Firmware loop](https://github.com/joshua12-5/macropad/blob/main/firmware/src/main.c): `firmware/src/main.c`
- [Config protocol](https://github.com/joshua12-5/macropad/blob/main/firmware/src/config_protocol.c): `firmware/src/config_protocol.c`
- [Flash storage](https://github.com/joshua12-5/macropad/blob/main/firmware/src/storage.c): `firmware/src/storage.c`
- [Profile runtime](https://github.com/joshua12-5/macropad/blob/main/firmware/src/profiles.c): `firmware/src/profiles.c`
- [Macro engine](https://github.com/joshua12-5/macropad/blob/main/firmware/src/macros.c): `firmware/src/macros.c`
- [Action engine](https://github.com/joshua12-5/macropad/blob/main/firmware/src/actions.c): `firmware/src/actions.c`
- [USB keyboard](https://github.com/joshua12-5/macropad/blob/main/firmware/src/usb_hid_app.c): `firmware/src/usb_hid_app.c`
- [Keys and encoder](https://github.com/joshua12-5/macropad/blob/main/firmware/src/matrix.c): `firmware/src/matrix.c`

### On-device features

- [OLED menu](https://github.com/joshua12-5/macropad/blob/main/firmware/src/device_menu.c): `firmware/src/device_menu.c`
- [OLED display](https://github.com/joshua12-5/macropad/blob/main/firmware/src/oled_ui.c): `firmware/src/oled_ui.c`
- [Idle animation](https://github.com/joshua12-5/macropad/blob/main/firmware/src/anim.c): `firmware/src/anim.c`

### Other components

- **User**
- **USB HID device**
- **Device flash**

## Connections

- User → App entry: starts (evidence: `README.md`)
- App entry → Configurator window: opens GUI (evidence: `README.md`)
- User → Task editors: edits configuration (evidence: `README.md`)
- Configurator window → Task editors: presents tasks (evidence: `README.md`)
- Configurator window → Pad preview: shows layout (evidence: `configurator/macropad_config/main_window.py`)
- Task editors → Profile model: edits profiles (evidence: `configurator/macropad_config/widgets/pad_preview.py`)
- Task editors → Macro model: edits macros (evidence: `configurator/macropad_config/widgets/pad_preview.py`)
- Task editors → Animation tools: edits animations (evidence: `configurator/macropad_config/widgets/pad_preview.py`)
- Auto-switch → Device API: sets active profile (evidence: `configurator/macropad_config/autoswitch/service.py`)
- Auto-switch → USB HID device: switches profile (evidence: `README.md`)
- Device backup → Device API: backs up device
- Profile model → Data schema: validates against (evidence: `configurator/macropad_config/models/profile.py`)
- Macro model → Data schema: validates against (evidence: `configurator/macropad_config/models/macro.py`)
- Profile encoding → Protocol frames: uses framing (evidence: `configurator/macropad_config/protocol/profile_blob.py`)
- Macro encoding → Protocol frames: uses framing (evidence: `configurator/macropad_config/protocol/macro_blob.py`)
- Animation encoding → Protocol frames: uses frame format (evidence: `configurator/macropad_config/animation/codec.py`)
- Device API → Protocol frames: exchanges frames (evidence: `configurator/macropad_config/protocol/device.py`)
- Device API → Profile encoding: transfers profiles (evidence: `configurator/macropad_config/protocol/device.py`)
- Device API → Macro encoding: transfers macros (evidence: `configurator/macropad_config/protocol/device.py`)
- Device API → Animation encoding: transfers animations (evidence: `configurator/macropad_config/protocol/device.py`)
- Device API → USB HID device: communicates over HID (evidence: `configurator/macropad_config/protocol/device.py`)
- USB HID device → Config protocol: sends configuration (evidence: `README.md`)
- Firmware loop → Config protocol: runs protocol (evidence: `firmware/src/main.c`)
- Firmware loop → Keys and encoder: polls inputs (evidence: `firmware/src/main.c`)
- Firmware loop → Action engine: runs actions (evidence: `firmware/src/main.c`)
- Firmware loop → Macro engine: runs macros (evidence: `firmware/src/main.c`)
- Firmware loop → OLED menu: runs menu (evidence: `firmware/src/main.c`)
- Firmware loop → OLED display: updates display (evidence: `firmware/src/main.c`)
- Firmware loop → Idle animation: runs animation (evidence: `firmware/src/main.c`)
- Firmware loop → Flash storage: persists state (evidence: `firmware/src/main.c`)
- Keys and encoder → Action engine: triggers actions
- Action engine → USB keyboard: emits key actions
- Config protocol → Flash storage: reads and writes
- Flash storage → Device flash: persists configuration (evidence: `firmware/src/storage.c`)
- OLED menu → Profile runtime: switches profiles
- Idle animation → Device flash: stores animation frames
- Firmware loop → USB keyboard: updates HID reports (evidence: `firmware/src/main.c`)
