Skip to content

joeynotion/Trackball_AMOLED_Demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

15 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

ESP32-S3-AMOLED Platform

PlatformIO ESP32 Display LVGL

A reference implementation for the Waveshare ESP32-S3-AMOLED-1.91 development board integrated with the Pimoroni Trackball Breakout. This project standardizes the drivers, power management, and UI architecture to serve as a foundation for future derived systems.


โœจ Features

  • Low Power Mode: Polled esp_light_sleep implementation for low idle consumption with instant wake-on-input.
  • Graphics: Dual-buffered LVGL 9 rendering on the RM67162 AMOLED controller using OPI PSRAM.
  • Input Handling: Support for RGBW LED control and unified I2C bus driver with coordinate rotation.
  • Build Configuration: Verified partition tables and build scripts to address common Xtensa/ARM assembly conflicts.
  • Embedded Drivers: Custom implementations for the QSPI display and I2C trackball to support specific power states and peripheral configurations.

๐ŸŽฎ About the Demo

This project compiles into a complete interactive reference application that demonstrates:

  1. Smooth UI: A responsive LVGL interface running on the AMOLED screen.
  2. Trackball Navigation: Use the trackball to move focus between UI elements (rotated 90ยฐ to match the screen).
  3. Smart Power Saving:
    • Uses a 4-state machine: AWAKE -> FADE_OUT -> LIGHT_SLEEP -> FADE_IN.
    • Idle: Dimming after 10s of inactivity, then entering Light Sleep.
    • Sleep: Display & LED off. Polled wake-up every 100ms (Light Sleep).
    • Wake: Instant wake-up by rolling or clicking the trackball.
  4. Feedback: Click the on-screen color buttons to set the trackball's RGBW LED to the corresponding color.

๐Ÿš€ Getting Started

Prerequisites

  • VSCode with PlatformIO extension.
  • Python 3 (for build scripts).

Installation

  1. Clone the repository
  2. Verify platformio.ini: Ensure board_build.arduino.memory_type = qio_opi is set.
  3. Build & Flash: Connect via USB-C (ensure you hold BOOT if it's the first flash).

๐Ÿ› ๏ธ Hardware Specification

Component Detail
MCU ESP32-S3R8 (Dual Core 240MHz)
PSRAM 8MB OPI (Octal SPI)
Flash 16MB (External)
Display 1.91" AMOLED (240x536) @ 60Hz
IMU QMI8658 (6-Axis)
Input Pimoroni Trackball Breakout (RGBW LED, Nuvoton MCU)

๐Ÿ”Œ Pinout Reference

Function Pin (GPIO) Notes
QSPI SCK 47 Shared with SD Card CLK
QSPI CS 6 Display Chip Select
I2C SDA 40 Trackball & IMU Shared
I2C SCL 39 Trackball & IMU Shared
Display RST - Internal/Shared
Battery ADC 1 Voltage Monitor

๐Ÿง  System Architecture

1. Display (RM67162)

Driven via QSPI at 40MHz. Requires specific initialization for the AMOLED panel:

  • Color Inversion: INVON (0x21) is mandatory for correct black levels.
  • Orientation: MADCTL (0x36) set to 0x20 | 0x80 for landscape.
  • Buffering: Uses two MALLOC_CAP_SPIRAM buffers in PSRAM for smooth partial rendering.

2. Power Management

Uses a Polled Light Sleep loop:

  1. Enter esp_light_sleep_start() for 100ms.
  2. Wake & Poll Trackball I2C.
  3. If no activity -> Sleep.
  4. If activity -> Wake Display -> lv_obj_invalidate() -> Fade In.

3. Memory Layout

  • App Partition: 3MB (via partitions.csv)
  • Filesystem: ~9.9MB FATFS/LittleFS
  • PSRAM: 8MB OPI (Critical: qio_opi mode)

๐Ÿ—๏ธ Technical Implementations

The project uses custom-built drivers located in src/ to handle specific hardware requirements:

  1. RM67162 AMOLED Driver (qspi_display.cpp/h):
    • Configures the ESP32-S3 QSPI peripheral at 40MHz.
    • Uses manual memory-mapped addressing for frame data transfers.
    • Implements the hardware-level sleep/wake commands for the display controller.
  2. Pimoroni Trackball Driver (trackball.h):
    • Header-only I2C implementation for the Nuvoton-based breakout.
    • Supports RGBW LED control and directional polling.
  3. LVGL Input Bridge (input.cpp/h):
    • Maps the physical trackball to the LVGL KEYPAD input system.
    • Implements coordinate rotation and software debouncing.

๐Ÿ› Troubleshooting & Tips

  • Display is Negative? -> You missed the INVON (0x21) command in init.
  • Build Error (Neon/Helium)? -> Run the fix_lvgl_9.py script to remove ARM assembly.
  • No Serial Output? -> Set ARDUINO_USB_CDC_ON_BOOT=1 in platformio.ini.
  • Serial Stops after Sleep? -> This is normal behavior. It automatically reconnects 50ms after wake.
  • Input Lag? -> Check NAVIGATION_THRESHOLD in input.cpp.

๐Ÿ“š Appendices

A. Partition Table (partitions.csv)

# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x5000,
otadata,  data, ota,     0xe000,  0x2000,
app0,     app,  ota_0,   0x10000, 0x300000,
app1,     app,  ota_1,   0x310000,0x300000,
spiffs,   data, spiffs,  0x610000, 0x9E0000,

B. Display Init Sequence (qspi_display.cpp)

// 1. SlpOut & Wait
writeCommand(0x11); delay(120);
// 2. Color Mode 16-bit
writeC8D8(0x3A, 0x55); 
// 3. Orientation
writeC8D8(0x36, 0x20 | 0x80 | 0x00); 
// 4. Brightness
writeC8D8(0x51, 0x00); 
// 5. Display ON
writeCommand(0x29); 
// 6. Color Inversion (CRITICAL)
writeCommand(0x21); delay(20);

C. Build Patch (fix_lvgl_9.py)

# Removes ARM assembly from LVGL which breaks ESP32 builds
import os
import shutil
Import("env")

try:
    # Get the library dependencies directory
    libdeps_dir = env.subst("$PROJECT_LIBDEPS_DIR")
    env_name = env.subst("$PIOENV")
    lvgl_dir = os.path.join(libdeps_dir, env_name, "lvgl")

    if os.path.exists(lvgl_dir):
        problematic_dirs = [
            os.path.join(lvgl_dir, "src", "draw", "sw", "blend", "helium"),
            os.path.join(lvgl_dir, "src", "draw", "sw", "blend", "neon"),
            os.path.join(lvgl_dir, "src", "draw", "convert", "helium"),
            os.path.join(lvgl_dir, "src", "draw", "convert", "neon"),
        ]
        
        for d in problematic_dirs:
            if os.path.exists(d):
                print(f"Removing problematic LVGL 9 directory: {d}")
                shutil.rmtree(d)
except Exception as e:
    print(f"Error in fix_lvgl_9.py: {e}")

About

A reference implementation for the Waveshare ESP32-S3-AMOLED-1.91 development board integrated with the Pimoroni Trackball Breakout. This project standardizes the drivers, power management, and UI architecture to serve as a foundation for future derived systems.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors