# shockwav3/multifunctionalknob architecture

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

- Interactive diagram: https://gitdiagram.com/shockwav3/multifunctionalknob
- Repository: https://github.com/shockwav3/multifunctionalknob

## Overview

1. This repository has two distinct layers: the firmware for an ESP32-C3 peripheral, and a large set of AI/workflow/documentation assets around that firmware. For an architecture diagram of the product itself, the important runtime boundary is the firmware under `src/`, `include/`, `lib/`, plus the PlatformIO build config.

2. The device is a Bluetooth HID rotary controller named “KnobKoKy.” Its core responsibility is to translate physical inputs from a rotary encoder and button into either HID actions or menu-driven configuration changes, while showing state on a small OLED display and persisting settings in NVS.

3. `src/main.cpp` is the composition root. It wires together configuration, event dispatchers/handlers, encoder mode management, menu control, display output, BLE HID services, macro behavior, and power management. This is the main place where subsystems are connected into one event-driven runtime.

4. Hardware input is split across custom drivers in `lib/`: `ButtonDriver` and `EncoderDriver`. These feed the application through the event layer in `src/Event/`, which is organized into dispatchers and handlers for button, encoder, menu, and app-level events. This is the main asynchronous boundary in the system.

5. The event pipeline is the central data flow: physical input -> driver -> event type -> dispatcher -> handler -> subsystem action. Shared event contracts live in `include/Type/` and `include/Enum/`, which keeps the subsystems loosely coupled and makes the control flow explicit for diagramming.

6. Encoder behavior is abstracted as a mode system under `src/EncoderMode/`. There are separate handlers for scroll, volume, and zoom, plus a manager/selector layer that decides which behavior is active. This is the primary behavioral switch for the rotary knob.

7. The menu subsystem under `src/Menu/` is the user-facing configuration boundary. It has a controller, tree/model objects, and action classes such as wheel mode selection, wheel direction selection, button behavior, display power, Bluetooth pair/disconnect, and status/about screens. Menu actions are the bridge from UI navigation to system state changes.

8. Bluetooth HID is encapsulated under `src/BLE/`. The BLE callback handler and keyboard service provide the external device interface that turns internal input events into wireless keyboard/mouse-like behavior. In diagram terms, this is the outbound hardware/service boundary to the host computer.

9. Display output is abstracted under `src/Display/`. A common `DisplayInterface` is implemented by both `OLEDDisplay` and `SerialDisplay`, and a `DisplayTask` processes `DisplayRequest` objects. This makes the display a separate consumer of application state rather than something the rest of the system writes to directly.

10. Configuration and persistence live under `src/Config/`, with `ConfigManager` and `FactoryReset` handling runtime settings and recovery. The `include/Config/` headers define the device constants, pin mapping, and feature limits, while NVS persistence is the storage boundary for user settings like wheel direction, behavior, and other menu-driven options.

11. System behavior beyond input/output is handled by `src/System/PowerManager.cpp`, which supports inactivity-based sleep and wake behavior. This subsystem interacts with the event flow because user input resets timers and can wake the device, making power state part of the same control loop rather than a separate concern.

12. `src/Macro/` adds another behavioral layer for programmable button actions, letting the device do more than simple HID passthrough. This subsystem is important because it expands the button from a single input into a configurable action trigger.

13. The build/runtime environment is PlatformIO for Arduino on ESP32-C3, with NimBLE used for the Bluetooth stack in the preferred build environment. The hardware target is the ESP32-C3 Super Mini with a rotary encoder and SSD1306 OLED on I2C; `boards/nologo_esp32c3_super_mini.json` and `platformio.ini` define the board/build boundary.

14. The extensive `_bmad-output/`, `.claude/`, `.gemini/`, `.opencode/`, `.roo/`, and `_bmad/` trees are not part of firmware execution. They are documentation, planning, and AI-agent orchestration assets that describe the product, track epics/stories, and generate diagrams/specs; useful for understanding the project lifecycle, but separate from the runtime architecture.

Main entry points: [`src/main.cpp`](https://github.com/shockwav3/multifunctionalknob/blob/main/src/main.cpp) (Main), [`src/Event/Handler`](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Event/Handler) (Handlers), [`src/Menu/Action`](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Menu/Action) (Menu actions), [`src/Menu`](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Menu) (Menu system)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_firmware["Firmware runtime"]
  node_main["Main<br/>composition root<br/>[main.cpp]"]
  node_event_dispatchers["Dispatchers<br/>event routing"]
  node_event_handlers["Handlers<br/>event handling"]
  node_input_drivers["Input drivers<br/>hardware drivers"]
  node_event_types["Event types<br/>shared contracts"]
  node_enum_types["Enums<br/>shared contracts"]
  node_encoder_modes["Encoder modes<br/>behavior modes"]
  node_mode_manager["Mode manager<br/>mode coordination"]
  node_mode_handlers["Mode handlers<br/>encoder actions"]
  node_menu_system["Menu system<br/>ui configuration"]
  node_menu_controller["Menu controller<br/>menu state"]
  node_menu_actions["Menu actions<br/>config actions"]
  node_ble_hid["BLE HID<br/>wireless output"]
  node_display_system["Display system<br/>output rendering"]
  node_display_task["Display task<br/>display worker"]
  node_config_system["Config system<br/>settings persistence"]
  node_power_manager["Power manager<br/>sleep control<br/>[PowerManager.cpp]"]
  node_macro_manager["Macro manager<br/>programmable actions"]
  node_build_target["PlatformIO build<br/>build/runtime target<br/>[platformio.ini]"]
end

subgraph group_docs["Docs and agents"]
  node_docs_assets["Docs assets<br/>documentation tooling"]
end

node_input_drivers -->|"input events"| node_event_dispatchers
node_event_dispatchers -->|"route"| node_event_handlers
node_event_handlers -->|"select mode"| node_encoder_modes
node_event_handlers -->|"open menu"| node_menu_system
node_event_handlers -->|"hid output"| node_ble_hid
node_event_handlers -->|"update ui"| node_display_system
node_event_handlers -->|"persist settings"| node_config_system
node_event_handlers -->|"reset timer"| node_power_manager
node_event_handlers -->|"trigger macro"| node_macro_manager
node_encoder_modes -->|"coordinate"| node_mode_manager
node_mode_manager -->|"delegate"| node_mode_handlers
node_menu_system -->|"navigate"| node_menu_controller
node_menu_system -->|"invoke actions"| node_menu_actions
node_menu_actions -->|"change config"| node_config_system
node_menu_actions -->|"pair/disconnect"| node_ble_hid
node_menu_actions -->|"screen modes"| node_display_system
node_display_system -->|"render requests"| node_display_task
node_config_system -.->|"device limits"| node_build_target
node_main -->|"compose"| node_event_dispatchers
node_main -->|"compose"| node_event_handlers
node_main -->|"compose"| node_encoder_modes
node_main -->|"compose"| node_menu_system
node_main -->|"compose"| node_ble_hid
node_main -->|"compose"| node_display_system
node_main -->|"compose"| node_config_system
node_main -->|"compose"| node_power_manager
node_main -->|"compose"| node_macro_manager
node_main -->|"init hardware"| node_input_drivers
node_docs_assets -.->|"separate from runtime"| node_main

click node_main "https://github.com/shockwav3/multifunctionalknob/blob/main/src/main.cpp"
click node_event_dispatchers "https://github.com/shockwav3/multifunctionalknob/tree/main/src/Event/Dispatcher"
click node_event_handlers "https://github.com/shockwav3/multifunctionalknob/tree/main/src/Event/Handler"
click node_input_drivers "https://github.com/shockwav3/multifunctionalknob/tree/main/lib"
click node_event_types "https://github.com/shockwav3/multifunctionalknob/tree/main/include/Type"
click node_enum_types "https://github.com/shockwav3/multifunctionalknob/tree/main/include/Enum"
click node_encoder_modes "https://github.com/shockwav3/multifunctionalknob/tree/main/src/EncoderMode"
click node_mode_manager "https://github.com/shockwav3/multifunctionalknob/tree/main/src/EncoderMode/Manager"
click node_mode_handlers "https://github.com/shockwav3/multifunctionalknob/tree/main/src/EncoderMode/Handler"
click node_menu_system "https://github.com/shockwav3/multifunctionalknob/tree/main/src/Menu"
click node_menu_controller "https://github.com/shockwav3/multifunctionalknob/tree/main/src/Menu/Controller"
click node_menu_actions "https://github.com/shockwav3/multifunctionalknob/tree/main/src/Menu/Action"
click node_ble_hid "https://github.com/shockwav3/multifunctionalknob/tree/main/src/BLE"
click node_display_system "https://github.com/shockwav3/multifunctionalknob/tree/main/src/Display"
click node_display_task "https://github.com/shockwav3/multifunctionalknob/tree/main/src/Display/Task"
click node_config_system "https://github.com/shockwav3/multifunctionalknob/tree/main/src/Config"
click node_power_manager "https://github.com/shockwav3/multifunctionalknob/blob/main/src/System/PowerManager.cpp"
click node_macro_manager "https://github.com/shockwav3/multifunctionalknob/tree/main/src/Macro/Manager"
click node_build_target "https://github.com/shockwav3/multifunctionalknob/blob/main/platformio.ini"
click node_docs_assets "https://github.com/shockwav3/multifunctionalknob/tree/main/_bmad-output"

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_main,node_event_dispatchers,node_event_handlers,node_input_drivers,node_event_types,node_enum_types,node_encoder_modes,node_mode_manager,node_mode_handlers,node_menu_system,node_menu_controller,node_menu_actions,node_ble_hid,node_display_system,node_display_task,node_config_system,node_power_manager,node_macro_manager,node_build_target toneBlue
class node_docs_assets toneAmber
```

## Components

### Firmware runtime

ESP32-C3 device code that runs KnobKoKy.

- [Main](https://github.com/shockwav3/multifunctionalknob/blob/main/src/main.cpp): composition root · Wires the device runtime together and starts the event-driven loop. · `src/main.cpp`
- [Dispatchers](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Event/Dispatcher): event routing · Routes button, encoder, menu, and app events to their handlers. · `src/Event/Dispatcher`
- [Handlers](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Event/Handler): event handling · Converts dispatched events into subsystem actions and state changes. · `src/Event/Handler`
- [Input drivers](https://github.com/shockwav3/multifunctionalknob/tree/main/lib): hardware drivers · Reads the rotary encoder and button from GPIO hardware. · `lib`
- [Event types](https://github.com/shockwav3/multifunctionalknob/tree/main/include/Type): shared contracts · Shared event and status contracts used across subsystems. · `include/Type`
- [Enums](https://github.com/shockwav3/multifunctionalknob/tree/main/include/Enum): shared contracts · Core mode, direction, power, and error enums shared by the runtime. · `include/Enum`
- [Encoder modes](https://github.com/shockwav3/multifunctionalknob/tree/main/src/EncoderMode): behavior modes · Selects rotary behavior such as scroll, volume, and zoom. · `src/EncoderMode`
- [Mode manager](https://github.com/shockwav3/multifunctionalknob/tree/main/src/EncoderMode/Manager): mode coordination · Tracks the active encoder behavior and switches between modes. · `src/EncoderMode/Manager`
- [Mode handlers](https://github.com/shockwav3/multifunctionalknob/tree/main/src/EncoderMode/Handler): encoder actions · Implements the concrete rotary behaviors for scroll, volume, and zoom. · `src/EncoderMode/Handler`
- [Menu system](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Menu): ui configuration · Navigates device settings and invokes configuration actions. · `src/Menu`
- [Menu controller](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Menu/Controller): menu state · Controls menu navigation state and selection flow. · `src/Menu/Controller`
- [Menu actions](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Menu/Action): config actions · Applies wheel, button, Bluetooth, display, and info actions from the menu. · `src/Menu/Action`
- [BLE HID](https://github.com/shockwav3/multifunctionalknob/tree/main/src/BLE): wireless output · Exports device actions to the host computer over Bluetooth HID. · `src/BLE`
- [Display system](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Display): output rendering · Builds and serves OLED or serial display output as requests. · `src/Display`
- [Display task](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Display/Task): display worker · Consumes display requests and updates the active display implementation. · `src/Display/Task`
- [Config system](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Config): settings persistence · Loads, stores, and resets runtime settings backed by NVS. · `src/Config`
- [Power manager](https://github.com/shockwav3/multifunctionalknob/blob/main/src/System/PowerManager.cpp): sleep control · Handles inactivity-based sleep and wake behavior. · `src/System/PowerManager.cpp`
- [Macro manager](https://github.com/shockwav3/multifunctionalknob/tree/main/src/Macro/Manager): programmable actions · Expands button input into configurable macro behaviors. · `src/Macro/Manager`
- [PlatformIO build](https://github.com/shockwav3/multifunctionalknob/blob/main/platformio.ini): build/runtime target · Defines the ESP32-C3 Arduino build environment and board target. · `platformio.ini`

### Docs and agents

Planning, documentation, and AI workflow assets separate from runtime.

- [Docs assets](https://github.com/shockwav3/multifunctionalknob/tree/main/_bmad-output): documentation tooling · Project planning, agent workflows, and generated documentation that support development but are outside firmware execution. · `_bmad-output`

## Connections

- Input drivers → Dispatchers: input events · Physical button and encoder changes become application events.
- Dispatchers → Handlers: route · Dispatchers forward typed events to their handlers.
- Handlers → Encoder modes: select mode · Handlers choose or update rotary behavior.
- Handlers → Menu system: open menu · Events drive menu navigation and selection.
- Handlers → BLE HID: hid output · Input events can be translated into host-facing HID actions.
- Handlers → Display system: update ui · Handlers enqueue display state changes and requests.
- Handlers → Config system: persist settings · Menu and app events update stored configuration.
- Handlers → Power manager: reset timer · User activity affects idle and sleep control.
- Handlers → Macro manager: trigger macro · Button actions can invoke programmable macro behavior.
- Encoder modes → Mode manager: coordinate · The manager tracks and switches the active encoder behavior.
- Mode manager → Mode handlers: delegate · Active mode is executed by a concrete handler.
- Menu system → Menu controller: navigate · The controller manages the current menu state.
- Menu system → Menu actions: invoke actions · Menu selections map to concrete device actions.
- Menu actions → Config system: change config · Actions update runtime settings and NVS-backed values.
- Menu actions → BLE HID: pair/disconnect · Menu actions manage Bluetooth host connection state.
- Menu actions → Display system: screen modes · Actions can switch display content such as status or about screens.
- Display system → Display task: render requests · Display implementations are driven through request processing.
- Config system → PlatformIO build: device limits · Build and board configuration constrain runtime settings and hardware mappings.
- Main → Dispatchers: compose · Main wires dispatchers into the application runtime.
- Main → Handlers: compose · Main wires handlers into the application runtime.
- Main → Encoder modes: compose · Main initializes the encoder mode subsystem.
- Main → Menu system: compose · Main initializes menu navigation and actions.
- Main → BLE HID: compose · Main sets up Bluetooth HID services and callbacks.
- Main → Display system: compose · Main selects and starts the display pipeline.
- Main → Config system: compose · Main loads configuration and recovery behavior.
- Main → Power manager: compose · Main connects sleep and wake control into the loop.
- Main → Macro manager: compose · Main includes macro behavior in the runtime wiring.
- Main → Input drivers: init hardware · Main initializes the physical input drivers.
- Docs assets → Main: separate from runtime · Documentation and agent assets describe the project but do not participate in device execution.
