# Multi-Functional Controller (MFC) [![ESP-IDF](https://img.shields.io/badge/ESP--IDF-v5.x-E7352C?style=for-the-badge&logo=espressif&logoColor=white)](https://github.com/espressif/esp-idf) [![Target MCU](https://img.shields.io/badge/MCU-ESP32--S3--N16R8-red?style=for-the-badge&logo=espressif)](https://www.espressif.com/en/products/socs/esp32-s3) [![KiCad](https://img.shields.io/badge/EDA-KiCad%2010-314CB0?style=for-the-badge&logo=kicad&logoColor=white)](https://www.kicad.org/) [![Language](https://img.shields.io/badge/Firmware-C99%20%2F%20C%2B%2B-00599C?style=for-the-badge&logo=c)](https://en.wikipedia.org/wiki/C_(programming_language)) [![RTOS](https://img.shields.io/badge/OS-FreeRTOS-008080?style=for-the-badge)](https://www.freertos.org/) [![Status](https://img.shields.io/badge/Status-Active%20Prototype-success?style=for-the-badge)](#roadmap--milestones) A custom, high-performance handheld remote controller engineered from scratch for dual-role applications: **long-range, low-latency RC vehicle control** and **USB/Bluetooth HID gaming**. Built around the **ESP32-S3-N16R8 (Xtensa® 32-bit LX7 dual-core @ 240 MHz)**, this project bridges hardware and software engineering—combining analog/Hall-effect sensing on `ADC1`, 2.4 GHz nRF24L01+ RF telemetry, hardware pulse-counted (`pulse_cnt`) rotary inputs, and a shared high-speed `SPI2_HOST` (FSPI) bus driving both the 1.3" SH1106 OLED display and radio transceiver without bus collisions. --- ## Prototype Showcase

Multi-Functional Controller Top View
Figure 1: Top assembly layout — ESP32-S3-N16R8 module, analog joystick, quadrature rotary encoder, 1.3" SH1106 SPI OLED display, and nRF24L01+ RF transceiver.

Multi-Functional Controller Profile & RF Antenna
Figure 2: Ergonomic profile — 2.4 GHz external dipole antenna connected to the nRF24L01+ transceiver, rotary dial, and dual USB-C ports.

Multi-Functional Controller Perfboard Soldering
Figure 3: Underbody point-to-point bus routing — 6×9 cm perfboard with dedicated decoupled power rails (100 µF smoothing capacitor across nRF24L01+ VCC/GND) and direct FSPI signal lines.

--- ## Key Hardware & Firmware Architecture - **Microcontroller Core:** Espressif **ESP32-S3-N16R8** (16 MB Quad SPI Flash, 8 MB Octal PSRAM) running FreeRTOS. - **Collision-Free Shared FSPI (`SPI2_HOST`) Bus:** - Shares `MOSI` (`GPIO 11`), `MISO` (`GPIO 13`), and `SCK` (`GPIO 12`) between the **1.3" SH1106 OLED** (10 MHz clock) and the **nRF24L01+ 2.4 GHz Transceiver** (1 MHz clock) via independent hardware Chip Select lines (`GPIO 10` and `GPIO 14`). - **Bare-Metal 5×8 OLED Graphics Engine & Multi-Screen UI State Machine:** - Direct register-level driver for the 1.3" SH1106 controller (handling the 132×64 internal RAM 2-pixel column offset) with a complete 5×8 bitmap font table (`A–Z`, `0–9`, `<`, `>`, `[`, `]`, `(`, `)`, `/`, `-`, `:`, `.`). - **4 Interactive Screens:** 1. `DRIVE VEHICLE`: Real-time One-Shot `ADC1` joystick acquisition (`VRx` / `VRy`) and live 2.4 GHz packet broadcasting (`rc_packet_t`). 2. `RADIO CONFIG`: Verifies physical nRF24L01+ SPI link (`SETUP_AW` register `0x03`) and tunes `RF_CH` (register `0x05`) live across channels `0–125` (`2.400–2.525 GHz`) using the rotary dial. 3. `CALIBRATE`: Live raw `ADC1` readout (`0–4095`) with one-click neutral center-point capture. 4. `SYSTEM INFO`: Displays target silicon (`ESP32-S3`) and real-time free RTOS heap memory (`esp_get_free_heap_size()`). - **Hardware Quadrature Rotary Decoder (`pulse_cnt`):** - Uses the ESP32-S3 hardware Pulse Counter peripheral on `GPIO 15` (`CLK`) and `GPIO 16` (`DT`) with a `1000 ns` hardware glitch filter and full 4× quadrature edge/level state decoding, paired with a `300 ms` debounced push-switch (`GPIO 17`). - **Wi-Fi-Safe Analog Joystick Acquisition (`ADC1`):** - Routes `VRx` (`GPIO 4`, `ADC1_CH3`) and `VRy` (`GPIO 5`, `ADC1_CH4`) with `12 dB` attenuation (`0–3.3V` full-scale) on `ADC_UNIT_1` to avoid `ADC2` Wi-Fi/RF arbitration conflicts. - **Power Subsystem:** - Dual parallel 18650 Li-ion cells delivering **4800 mAh** combined capacity. - 100 µF low-ESR electrolytic bulk decoupling capacitor suppressing nRF24L01+ TX current spikes. --- ## GPIO Pinout & Peripheral Mapping (ESP32-S3 Hardware Specification) The physical controller uses a shared high-speed **SPI2_HOST** (FSPI) bus for both the 1.3" SH1106 OLED and the nRF24L01+ RF transceiver, alongside dedicated `ADC1` channels and hardware pulse-counter inputs: | Peripheral / Signal | GPIO | Hardware Interface | Description | | :--- | :---: | :--- | :--- | | **SPI Bus: MOSI** | `GPIO 11` | SPI Master Output (`SPI2_HOST`) | Shared data line for nRF24L01+ and OLED (`SDA` / `D1`) | | **SPI Bus: MISO** | `GPIO 13` | SPI Master Input (`SPI2_HOST`) | Data line from nRF24L01+ radio module | | **SPI Bus: SCK (Clock)** | `GPIO 12` | SPI Master Clock (`SPI2_HOST`) | Shared clock line for nRF24L01+ and OLED (`CLK` / `D0`) | | **nRF24L01+ Chip Select (CS)** | `GPIO 14` | SPI Device Select | Dedicated radio bus enable | | **nRF24L01+ Chip Enable (CE)** | `GPIO 21` | Digital Output | Radio TX/RX power state activation line | | **OLED Chip Select (CS)** | `GPIO 10` | SPI Device Select | Display SPI bus enable | | **OLED Data/Command (DC)** | `GPIO 9` | Digital Output | 1.3" OLED command vs. data selection | | **OLED Reset (RES)** | `GPIO 8` | Digital Output | Hardware display reset line | | **Joystick VRx (X-Axis)** | `GPIO 4` | `ADC1` Channel 3 (`12 dB` Atten) | Analog X-axis potentiometer input (`0–3.3V` safe) | | **Joystick VRy (Y-Axis)** | `GPIO 5` | `ADC1` Channel 4 (`12 dB` Atten) | Analog Y-axis potentiometer input (`0–3.3V` safe) | | **Rotary Encoder CLK** | `GPIO 15` | ESP-IDF `pulse_cnt` Unit | Quadrature channel A (hardware edge counter) | | **Rotary Encoder DT** | `GPIO 16` | ESP-IDF `pulse_cnt` Unit | Quadrature channel B (direction sensing) | | **Rotary Encoder Switch (SW)**| `GPIO 17` | Digital Input (`PULLUP`) | Push-button (menu enter/select mode) | ### Silicon Multiplexing Notes (ESP32-S3-N16R8 vs. Classic ESP32) 1. **Octal PSRAM & Flash Reservation (`GPIO 26 – GPIO 37`):** On the **ESP32-S3-N16R8** (8 MB Octal PSRAM), `GPIO 26` through `GPIO 37` are wired internally to the Octal SPI Flash/PSRAM bus. Accessing `GPIO 26, 27, 32, 33` triggers an immediate *Guru Meditation Error / Cache Disabled Panic* on boot. 2. **Unbonded Silicon Pins (`GPIO 22 – GPIO 25`):** `GPIO 22, 23, 24, 25` do not exist on the ESP32-S3 pin multiplexing matrix. 3. **FSPI (`SPI2_HOST`) Default Matrix:** Uses native ESP32-S3 FSPI pins (`GPIO 10, 11, 12, 13`) for zero-penalty IOMUX/GPIO matrix routing rather than legacy 2016 ESP32 VSPI defaults (`GPIO 5, 18, 23`). --- ## Repository Structure ```text multi-functional-controller/ ├── firmware/ # ESP-IDF C99 Firmware Project (ESP32-S3) │ ├── CMakeLists.txt # Top-level CMake project configuration │ ├── sdkconfig # ESP32-S3 target configuration │ └── main/ │ ├── CMakeLists.txt # Component registration │ └── mmcontroller.c # Master firmware: Shared SPI2, SH1106 5x8 UI, nRF24L01+, PCNT, ADC1 ├── hardware/ # KiCad 10 Electronic Design Automation (EDA) │ ├── mfc-1.kicad_pro # KiCad project file │ ├── mfc-1.kicad_sch # Complete schematic design & component symbols │ └── mfc-1.kicad_pcb # Board layout & routing rules ├── images/ # High-resolution prototype photography │ ├── TOP_VIEW.png # Front control surface overview │ ├── SIDE_VIEW_WITH_ANTENNA.png # RF antenna and profile perspective │ └── BOTTOM_VIEW.png # Perfboard underside bus wiring ├── .gitignore # Clean repository filter (builds, caches, local configs) ├── LICENSE # MIT License └── README.md # Master engineering documentation ``` --- ## Getting Started: Building the Firmware ### Prerequisites - [ESP-IDF v5.1+](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/get-started/) installed and exported into your environment: ```bash . $HOME/esp/esp-idf/export.sh ``` ### Build & Flash 1. Navigate to the firmware directory: ```bash cd firmware ``` 2. Set target to ESP32-S3: ```bash idf.py set-target esp32s3 ``` 3. Compile the firmware: ```bash idf.py build ``` 4. Flash to the controller and open serial monitoring: ```bash idf.py -p /dev/ttyACM0 flash monitor ``` --- ## Hardware CAD & Schematic Editing The electronic schematic is developed in **KiCad 10**: 1. Open the project: ```bash kicad hardware/mfc-1.kicad_pro ``` 2. Inspect or modify the schematic in `eeschema` (`hardware/mfc-1.kicad_sch`). 3. To generate vector schematics for documentation or web publication: - Select **File $\rightarrow$ Plot $\rightarrow$ SVG** or **PDF**. --- ## Roadmap & Milestones - [x] Initial hardware breadboard and perfboard prototype (6×9 cm assembly). - [x] Shared `SPI2_HOST` bus driving both 1.3" SH1106 OLED and nRF24L01+ without bus collisions. - [x] Full 5×8 bare-metal font renderer (`A–Z`, `0–9`, and UI punctuation/symbols). - [x] Hardware pulse-counter (`pulse_cnt`) quadrature decoder with 1000 ns glitch filter & 300 ms debounced state machine. - [x] Live nRF24L01+ SPI register verification (`0x03`) and channel tuning (`0–125`) with `ADC1` joystick packet transmission. - [ ] Custom multi-layer printed circuit board (PCB) design in KiCad. - [ ] 3D-printable ergonomic handheld enclosure (PETG / Resin). - [ ] Bidirectional ACK-payload telemetry from target RC vehicle. - [ ] Native USB Gamepad HID descriptor integration on ESP32-S3 USB-OTG port. --- ## Author & Project Notebook - **Author:** [Ertunç Özbay](https://github.com/ertunc-ozbay) - **Personal Workshop & Portfolio:** [ertuncozbay.dev](https://ertuncozbay.dev) - **Project Detail Page:** [ertuncozbay.dev/projects/multi-functional-controller.html](https://ertuncozbay.dev/projects/multi-functional-controller.html) - **License:** [MIT License](LICENSE)