640 lines
20 KiB
Markdown
640 lines
20 KiB
Markdown
# RP2350 TFT Display with Touch and SD Card Demo
|
||
|
||
A modular embedded application for RP2350 microcontrollers featuring display, touch, and SD card support with hardware abstraction layers. **Now includes a reactive game template architecture!**
|
||
|
||
## Features
|
||
|
||
- **Reactive Game Template** - Event-driven architecture optimized for e-ink displays and power efficiency
|
||
- **Display Abstraction Layer** - Support for multiple display types (ST7796, ST7789, E-Paper)
|
||
- **Touch Abstraction Layer** - Extensible touch controller support (FT6336U)
|
||
- **SD Card with FatFS** - File system support with board-aware initialization
|
||
- **Multi-Board Support** - Single-file board configuration system for easy board switching
|
||
- **1-bit Rendering** - Memory-efficient monochrome graphics with GUI widgets
|
||
- **Automated Build Scripts** - Build for one board or all boards with single commands
|
||
- **Hardware Abstraction** - Factory pattern for displays and touch controllers
|
||
|
||
## 🎮 Reactive Game Template
|
||
|
||
The project now uses a **clean, event-driven architecture** perfect for building games and interactive applications:
|
||
|
||
### Key Features
|
||
- ⚡ **Event-Driven**: Display only updates when input is received
|
||
- 🔋 **Power Efficient**: Uses `__wfi()` to sleep between inputs (< 1mA idle)
|
||
- 📄 **E-ink Optimized**: Minimizes screen refreshes for e-paper displays
|
||
- 🎯 **Interrupt-Driven**: Touch and button handling via hardware interrupts
|
||
- 🧩 **Modular**: Clear separation of input processing, game logic, and rendering
|
||
|
||
### Architecture Highlights
|
||
|
||
```
|
||
Interrupt → Set Flag → Wake CPU → Process Input → Update Game → Draw → Refresh → Sleep
|
||
```
|
||
|
||
**Before (Polling Loop):**
|
||
```cpp
|
||
while(1) {
|
||
if (touch_interrupt_flag) {
|
||
// Read touch data
|
||
// Process coordinates
|
||
// Draw directly
|
||
// Handle gestures inline
|
||
refresh_screen();
|
||
}
|
||
}
|
||
```
|
||
|
||
**After (Reactive Template):**
|
||
```cpp
|
||
while(1) {
|
||
__wfi(); // Sleep until interrupt
|
||
|
||
InputEvent input = process_button_input(config);
|
||
if (!input.valid) {
|
||
input = process_touch_input(config, &last_touch_time);
|
||
}
|
||
|
||
if (input.valid && game_update(&game_state, input, config, &renderer)) {
|
||
game_draw(&game_state, &renderer, &gui);
|
||
refresh_screen(bit_buffer, display);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Creating Your Own Game
|
||
|
||
1. **Modify GameState** - Define your game variables
|
||
2. **Implement game_init()** - Set initial values
|
||
3. **Implement game_update()** - Handle input and update state
|
||
4. **Implement game_draw()** - Render your game graphics
|
||
|
||
The reactive loop and input system work automatically!
|
||
|
||
**📖 [Read the Full Template Usage Guide](TEMPLATE_USAGE.md)** for detailed examples and patterns.
|
||
|
||
### Example Game (Included)
|
||
|
||
The template includes a **Button Navigation Game** demonstrating:
|
||
- Hardware button input handling (KEY0 switches focus, KEY1 clicks)
|
||
- GUI component usage (buttons, radio buttons, status bars)
|
||
- State management (click counters, focus tracking)
|
||
- Visual feedback (filled buttons show focus)
|
||
- E-ink optimized refreshes
|
||
|
||
Perfect starting point for your own game!
|
||
|
||
## Supported Hardware Configurations
|
||
|
||
### Available Board Configurations
|
||
|
||
1. **BOARD_FEATHER_TFT** - Adafruit Feather RP2350 with 4.0" TFT ST7796
|
||
- Display: ST7796 (480x320 RGB TFT)
|
||
- Touch: FT6336U capacitive touch
|
||
- Features: High-speed refresh, backlight control, SD card support
|
||
|
||
2. **BOARD_PICO2_TFT** - Raspberry Pi Pico 2 with 4.0" TFT ST7796
|
||
- Display: ST7796 (480x320 RGB TFT)
|
||
- Touch: FT6336U capacitive touch
|
||
- Features: High-speed refresh, backlight control, SD card support
|
||
|
||
3. **BOARD_PICO2_EINK** - Raspberry Pi Pico 2 with E-Ink Display
|
||
- Display: E-Paper (400x300 monochrome)
|
||
- Touch: None (uses hardware buttons KEY0/KEY1)
|
||
- Features: Ultra-low power, partial/full refresh modes
|
||
|
||
### Supported Displays
|
||
- **ST7796** - 480x320 RGB TFT LCD (Fully implemented)
|
||
- **E-Paper** - Various sizes, monochrome (Fully implemented)
|
||
- **ST7789** - Ready for driver implementation
|
||
|
||
### Supported Touch Controllers
|
||
- **FT6336U** - I2C capacitive touch with gesture support (Fully implemented)
|
||
- Extensible architecture for additional controllers
|
||
|
||
## Board Configuration System
|
||
|
||
### Switching Between Boards
|
||
|
||
The project uses a single-file configuration system. To switch boards, simply edit `board_config.h` and uncomment your target board:
|
||
|
||
```cpp
|
||
// ---- SELECT YOUR BOARD HERE ----
|
||
// #define BOARD_FEATHER_TFT // Feather RP2350 + 4.0" TFT ST7796
|
||
// #define BOARD_PICO2_TFT // Pico 2 + 4.0" TFT ST7796
|
||
#define BOARD_PICO2_EINK // Pico 2 + E-Ink Display
|
||
// --------------------------------
|
||
```
|
||
|
||
**Important:** Only one board should be uncommented at a time!
|
||
|
||
### What Gets Configured
|
||
|
||
Each board configuration includes:
|
||
- Display type and resolution
|
||
- All pin assignments (SPI, I2C, GPIO)
|
||
- Touch controller configuration
|
||
- Coordinate transformation (rotation/inversion)
|
||
- SD card pins
|
||
- Hardware button pins (e-ink boards)
|
||
- Communication speeds (SPI/I2C baud rates)
|
||
|
||
### Board-Specific Files
|
||
|
||
Board configurations are located in `board_configs/`:
|
||
- `board_feather_tft.h` - Feather RP2350 + TFT configuration
|
||
- `board_pico2_tft.h` - Pico 2 + TFT configuration
|
||
- `board_pico2_eink.h` - Pico 2 + E-Ink configuration
|
||
|
||
## Building and Flashing
|
||
|
||
### Method 1: Build for Currently Selected Board
|
||
|
||
The simplest method - builds for whatever board is selected in `board_config.h`:
|
||
|
||
```bash
|
||
./build_and_flash.sh
|
||
```
|
||
|
||
This script will:
|
||
1. Detect which board is selected in `board_config.h`
|
||
2. Configure CMake if needed
|
||
3. Build the project using Ninja
|
||
4. Flash to the board using picotool (if board is in BOOTSEL mode)
|
||
|
||
To build without flashing:
|
||
```bash
|
||
mkdir -p build
|
||
cd build
|
||
cmake -G Ninja ..
|
||
ninja
|
||
```
|
||
|
||
The output file will be `build/basic1.uf2`.
|
||
|
||
### Method 2: Build for All Boards
|
||
|
||
To create UF2 files for all supported boards in one command:
|
||
|
||
```bash
|
||
./build_all_boards.sh
|
||
```
|
||
|
||
This script will:
|
||
1. Backup your current `board_config.h`
|
||
2. Build each board configuration automatically
|
||
3. Generate board-specific output files:
|
||
- `basic1_feather_tft.uf2`
|
||
- `basic1_pico2_tft.uf2`
|
||
- `basic1_pico2_eink.uf2`
|
||
4. Restore your original `board_config.h`
|
||
|
||
This is useful for:
|
||
- Creating releases for multiple hardware variants
|
||
- Testing code on all board configurations
|
||
- Batch building without manual configuration changes
|
||
|
||
### Manual Flashing
|
||
|
||
1. Hold the **BOOTSEL** button while connecting USB
|
||
2. The board appears as a USB drive (e.g., `RPI-RP2`)
|
||
3. Copy the appropriate `.uf2` file to the drive:
|
||
```bash
|
||
cp basic1.uf2 /Volumes/RPI-RP2/
|
||
```
|
||
4. The board automatically reboots and runs the program
|
||
|
||
### Using picotool
|
||
|
||
If picotool is installed at `~/.pico-sdk/picotool/`:
|
||
|
||
```bash
|
||
# Load and auto-reboot
|
||
picotool load build/basic1.uf2 -fx
|
||
|
||
# Or load without auto-reboot
|
||
picotool load build/basic1.uf2
|
||
```
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
basic1/
|
||
├── basic1.cpp # Main application
|
||
├── board_config.h # Board selector (edit this to switch boards!)
|
||
├── board_configs/ # Board-specific configurations
|
||
│ ├── board_feather_tft.h # Feather RP2350 + TFT pin config
|
||
│ ├── board_pico2_tft.h # Pico 2 + TFT pin config
|
||
│ ├── board_pico2_eink.h # Pico 2 + E-Ink pin config
|
||
│ └── README.md # Board config documentation
|
||
│
|
||
├── CMakeLists.txt # Build configuration
|
||
├── build_all_boards.sh # Build all boards automatically
|
||
├── build_and_flash.sh # Build and flash current board
|
||
│
|
||
├── display/ # Display and GUI abstraction layer
|
||
│ ├── low_level_display.h # Display interface (factory pattern)
|
||
│ ├── low_level_display_st7796.cpp # ST7796 TFT implementation
|
||
│ ├── low_level_display_epaper.cpp # E-Paper implementation
|
||
│ ├── low_level_touch.h # Touch interface (factory pattern)
|
||
│ ├── low_level_touch_ft6336u.cpp # FT6336U touch implementation
|
||
│ ├── low_level_render.h/cpp # 1-bit rendering engine
|
||
│ └── low_level_gui.h/cpp # GUI widgets (buttons, gauges, etc.)
|
||
│
|
||
├── lib/ # Hardware drivers
|
||
│ ├── ft6336u/ # FT6336U capacitive touch driver
|
||
│ ├── st7796/ # ST7796 TFT display driver
|
||
│ ├── epaper/ # E-Paper display driver
|
||
│ ├── sd_card/ # SD card driver with FatFS test
|
||
│ └── fatfs/ # FatFS filesystem
|
||
│
|
||
├── fonts/ # 25+ bitmap font definitions (5x5 to 8x8)
|
||
└── fatfs_time.c # FatFS timestamp support
|
||
```
|
||
|
||
## Adding a New Board Configuration
|
||
|
||
1. Create a new config file in `board_configs/`:
|
||
```bash
|
||
cp board_configs/board_pico2_tft.h board_configs/board_myboard.h
|
||
```
|
||
|
||
2. Edit the new file and update all pin definitions for your hardware
|
||
|
||
3. Add your board to `board_config.h`:
|
||
```cpp
|
||
// ---- SELECT YOUR BOARD HERE ----
|
||
// #define BOARD_FEATHER_TFT
|
||
// #define BOARD_PICO2_TFT
|
||
// #define BOARD_PICO2_EINK
|
||
#define BOARD_MYBOARD // Your new board
|
||
// --------------------------------
|
||
```
|
||
|
||
4. Add the include section:
|
||
```cpp
|
||
#ifdef BOARD_FEATHER_TFT
|
||
#include "board_configs/board_feather_tft.h"
|
||
// ... other boards ...
|
||
#elif defined(BOARD_MYBOARD)
|
||
#include "board_configs/board_myboard.h"
|
||
#endif
|
||
```
|
||
|
||
5. (Optional) Add to `build_all_boards.sh` for automated builds
|
||
|
||
See `board_configs/README.md` for detailed configuration structure.
|
||
|
||
## Hardware Configuration Details
|
||
|
||
### Display Types
|
||
|
||
Each board configuration specifies a display type via `DISPLAY_TYPE_SELECTED`:
|
||
- `DISPLAY_TYPE_ST7796_VAL` (0) - ST7796 TFT (480x320)
|
||
- `DISPLAY_TYPE_ST7789_VAL` (1) - ST7789 TFT (ready for implementation)
|
||
- `DISPLAY_TYPE_EPAPER_VAL` (2) - E-Paper displays (various sizes)
|
||
|
||
### Touch Controller Types
|
||
|
||
Each board configuration specifies a touch type via `TOUCH_TYPE_SELECTED`:
|
||
- `TOUCH_TYPE_FT6336U_VAL` (0) - FT6336U capacitive touch with gesture support
|
||
- `TOUCH_TYPE_NONE_VAL` (1) - No touch controller (use hardware buttons)
|
||
|
||
### Touch Coordinate Transformation
|
||
|
||
Touch coordinates can be adjusted for different mounting orientations:
|
||
```c
|
||
#define TOUCH_SWAP_XY true // Swap X/Y coordinates (for 90° rotation)
|
||
#define TOUCH_INVERT_X true // Invert X axis (mirror horizontally)
|
||
#define TOUCH_INVERT_Y false // Invert Y axis (mirror vertically)
|
||
```
|
||
|
||
These settings are in each board's config file under `board_configs/`.
|
||
|
||
### Pin Assignments
|
||
|
||
Each board config file defines all hardware pin connections:
|
||
|
||
**Display Pins:**
|
||
- `DISPLAY_SPI_PORT` - SPI bus (spi0 or spi1)
|
||
- `DISPLAY_SCK_PIN`, `DISPLAY_MOSI_PIN`, `DISPLAY_MISO_PIN` - SPI data lines
|
||
- `DISPLAY_CS_PIN` - Chip select (active LOW)
|
||
- `DISPLAY_DC_PIN` - Data/Command select
|
||
- `DISPLAY_RST_PIN` - Hardware reset
|
||
- `DISPLAY_BL_PIN` - Backlight control (TFT only, -1 for e-ink)
|
||
- `DISPLAY_BUSY_PIN` - Busy signal (E-Paper only, -1 for TFT)
|
||
|
||
**Touch Pins:**
|
||
- `TOUCH_I2C_PORT` - I2C bus (i2c0 or i2c1)
|
||
- `TOUCH_SDA_PIN`, `TOUCH_SCL_PIN` - I2C data lines
|
||
- `TOUCH_INT_PIN` - Interrupt pin (active LOW when touch detected)
|
||
- `TOUCH_RST_PIN` - Hardware reset
|
||
|
||
**Button Pins (E-Ink boards):**
|
||
- `BUTTON_KEY0_PIN` - First hardware button (active LOW)
|
||
- `BUTTON_KEY1_PIN` - Second hardware button (active LOW)
|
||
|
||
**SD Card Pins (optional):**
|
||
- `SD_SPI_PORT`, `SD_CS_PIN`, `SD_MISO_PIN`, `SD_MOSI_PIN`, `SD_SCK_PIN`
|
||
|
||
### Communication Speeds
|
||
|
||
Configured per board based on display type:
|
||
- `SPI_BAUDRATE` - Display SPI speed (32MHz for TFT, 4MHz for e-ink)
|
||
- `I2C_BAUDRATE` - Touch controller I2C speed (typically 400kHz)
|
||
|
||
## Architecture
|
||
|
||
### Display Abstraction Layer
|
||
|
||
Provides a unified interface for different display types:
|
||
|
||
```cpp
|
||
class LowLevelDisplay {
|
||
public:
|
||
virtual bool init() = 0;
|
||
virtual void clear(bool white = true) = 0;
|
||
virtual void draw_buffer(const uint8_t* bit_buffer) = 0;
|
||
virtual void refresh() = 0;
|
||
// ... more methods
|
||
|
||
static LowLevelDisplay* create(DisplayType type, int width, int height);
|
||
};
|
||
```
|
||
|
||
Usage:
|
||
```cpp
|
||
LowLevelDisplay* display = LowLevelDisplay::create(
|
||
(DisplayType)DISPLAY_TYPE_SELECTED, V_WIDTH, V_HEIGHT);
|
||
display->init();
|
||
display->draw_buffer(buffer);
|
||
display->refresh();
|
||
```
|
||
|
||
### Touch Abstraction Layer
|
||
|
||
Unified interface for touch controllers:
|
||
|
||
```cpp
|
||
class LowLevelTouch {
|
||
public:
|
||
virtual bool init() = 0;
|
||
virtual bool read_touch(TouchData* data) = 0;
|
||
virtual bool is_touched() = 0;
|
||
// ... more methods
|
||
|
||
static LowLevelTouch* create(TouchType type, int width, int height,
|
||
bool swap_xy, bool invert_x, bool invert_y);
|
||
};
|
||
```
|
||
|
||
Usage:
|
||
```cpp
|
||
LowLevelTouch* touch = LowLevelTouch::create(
|
||
(TouchType)TOUCH_TYPE_SELECTED, V_WIDTH, V_HEIGHT,
|
||
TOUCH_SWAP_XY, TOUCH_INVERT_X, TOUCH_INVERT_Y);
|
||
|
||
TouchData touch_data;
|
||
if (touch->read_touch(&touch_data)) {
|
||
int x = touch_data.points[0].x;
|
||
int y = touch_data.points[0].y;
|
||
// Handle touch
|
||
}
|
||
```
|
||
|
||
### SD Card Abstraction
|
||
|
||
Board-aware initialization:
|
||
|
||
```cpp
|
||
// Initialize with board configuration
|
||
if (sd_card_init_with_board_config()) {
|
||
// Test FatFS functionality
|
||
sd_card_test_fatfs();
|
||
}
|
||
```
|
||
|
||
The test function:
|
||
- Mounts FatFS
|
||
- Lists directory contents
|
||
- Creates and reads test file
|
||
- Safely unmounts filesystem
|
||
|
||
## Pin Configurations Summary
|
||
|
||
Actual pin assignments are defined in `board_configs/*.h` files. Here's a quick reference:
|
||
|
||
### BOARD_FEATHER_TFT (Adafruit Feather RP2350)
|
||
- **Display (ST7796, SPI1):** SCK=18, MOSI=19, MISO=20, CS=17, DC=16, RST=15, BL=14
|
||
- **Touch (FT6336U, I2C0):** SDA=4, SCL=5, INT=6, RST=7
|
||
- **SD Card (SPI1):** CS=10 (shares SPI with display)
|
||
|
||
### BOARD_PICO2_TFT (Raspberry Pi Pico 2)
|
||
- **Display (ST7796, SPI0):** SCK=2, MOSI=3, MISO=4, CS=5, DC=6, RST=7, BL=8
|
||
- **Touch (FT6336U, I2C0):** SDA=12, SCL=13, INT=14, RST=15
|
||
- **SD Card (SPI1):** CS=17
|
||
|
||
### BOARD_PICO2_EINK (Raspberry Pi Pico 2 + E-Ink)
|
||
- **Display (E-Paper, SPI0):** SCK=10, MOSI=11, MISO=12, CS=9, DC=8, RST=12, BUSY=13
|
||
- **Touch:** None (uses hardware buttons instead)
|
||
- **Buttons:** KEY0=GP15 (active LOW), KEY1=GP17 (active LOW)
|
||
|
||
See individual board config files in `board_configs/` for complete details.
|
||
|
||
## Extending the System
|
||
|
||
### Adding a New Display Driver
|
||
|
||
1. Create implementation files:
|
||
```
|
||
display/low_level_display_mynewdisplay.h
|
||
display/low_level_display_mynewdisplay.cpp
|
||
```
|
||
|
||
2. Inherit from `LowLevelDisplay` base class and implement all virtual methods
|
||
|
||
3. Add a new constant in `board_config.h`:
|
||
```cpp
|
||
#define DISPLAY_TYPE_MYNEWDISPLAY_VAL 3
|
||
```
|
||
|
||
4. Update the factory in `display/low_level_display.cpp`:
|
||
```cpp
|
||
case 3: // DISPLAY_TYPE_MYNEWDISPLAY
|
||
display = new LowLevelDisplayMyNewDisplay(width, height);
|
||
break;
|
||
```
|
||
|
||
5. Update `CMakeLists.txt` to compile the new files
|
||
|
||
### Adding a New Touch Controller
|
||
|
||
1. Create implementation files:
|
||
```
|
||
display/low_level_touch_mynewtouch.h
|
||
display/low_level_touch_mynewtouch.cpp
|
||
```
|
||
|
||
2. Inherit from `LowLevelTouch` base class
|
||
|
||
3. Add constant and factory case similar to display drivers
|
||
|
||
4. Update CMakeLists.txt
|
||
|
||
### Workflow Summary
|
||
|
||
The typical development workflow:
|
||
|
||
1. **Select target board:** Edit `board_config.h`, uncomment your board
|
||
2. **Build:** Run `./build_and_flash.sh` (builds and flashes current board)
|
||
3. **Test:** Connect to USB, monitor via serial terminal
|
||
4. **Switch boards:** Edit `board_config.h`, rebuild
|
||
5. **Release:** Run `./build_all_boards.sh` to create UF2s for all boards
|
||
|
||
## Memory Usage
|
||
|
||
- **1-bit framebuffer:** Width×Height÷8 bytes
|
||
- 480×320: 19.2 KB
|
||
- 400×300: 15.0 KB
|
||
- **Display conversion:** Automatic 1-bit → RGB565 (TFT) or native (E-Paper)
|
||
- **Stack/heap:** Minimal, uses static buffers where possible
|
||
- **Code size:** ~100-150 KB depending on features enabled
|
||
|
||
## Troubleshooting
|
||
|
||
### Build Issues
|
||
|
||
**Error: "No board selected!"**
|
||
- You must uncomment exactly one `BOARD_xxx` define in `board_config.h`
|
||
|
||
**CMake configuration errors:**
|
||
- Delete `build/` directory and reconfigure: `rm -rf build && mkdir build`
|
||
|
||
### Display Issues
|
||
|
||
**Display stays blank:**
|
||
- Check SPI wiring (especially CS, DC, SCK, MOSI pins)
|
||
- Verify power supply (some displays need 5V logic level shifters)
|
||
- Check `DISPLAY_TYPE_SELECTED` matches your hardware
|
||
|
||
**Wrong colors or garbled display:**
|
||
- Verify display driver type (ST7796 vs ST7789)
|
||
- Check SPI baud rate (try reducing from 32MHz to 16MHz)
|
||
|
||
### Touch Issues
|
||
|
||
**Touch not responding:**
|
||
- Verify I2C wiring (SDA, SCL, INT, RST pins)
|
||
- Check for pull-up resistors on I2C lines (typically 4.7kΩ)
|
||
- Confirm touch controller type and I2C address
|
||
- Enable debug output to see if touch data is being read
|
||
|
||
**Touch coordinates inverted or swapped:**
|
||
- Adjust `TOUCH_SWAP_XY`, `TOUCH_INVERT_X`, `TOUCH_INVERT_Y` in board config
|
||
- These depend on physical mounting orientation
|
||
|
||
**Interrupt not triggering:**
|
||
- Verify `TOUCH_INT_PIN` is correctly defined
|
||
- Check INT pin is pulled high (internal pull-up or external resistor)
|
||
- Confirm touch controller is configured for interrupt mode
|
||
|
||
### SD Card Issues
|
||
|
||
**SD Card not detected:**
|
||
- Verify card is inserted and formatted (FAT32)
|
||
- Check SPI wiring and CS pin
|
||
- Ensure SD card shares SPI correctly with display (different CS pins)
|
||
- Try different SD card (some old/large cards have compatibility issues)
|
||
|
||
### E-Paper Display Issues
|
||
|
||
**Ghosting or partial images:**
|
||
- Use `full_refresh()` periodically to clear ghosting
|
||
- E-Paper retains previous image until fully refreshed
|
||
|
||
**Slow refresh:**
|
||
- Normal for e-paper (several seconds for full refresh)
|
||
- Use partial refresh for faster updates (may cause ghosting)
|
||
|
||
**BUSY pin timeout:**
|
||
- Verify `DISPLAY_BUSY_PIN` is correctly connected
|
||
- Increase timeout in e-paper driver if needed
|
||
|
||
## Development Tips
|
||
|
||
### Serial Debugging
|
||
|
||
Connect via USB and monitor serial output:
|
||
```bash
|
||
# macOS
|
||
screen /dev/tty.usbmodem* 115200
|
||
|
||
# Linux
|
||
screen /dev/ttyACM0 115200
|
||
|
||
# Exit screen: Ctrl+A, then K
|
||
```
|
||
|
||
The code includes `printf()` statements for debugging touch, display, and SD card operations.
|
||
|
||
### Power Optimization
|
||
|
||
For battery-powered projects:
|
||
- E-Paper displays use almost no power when idle
|
||
- Use `__wfi()` (Wait For Interrupt) to sleep between inputs
|
||
- Disable TFT backlight when idle
|
||
- Lower SPI/I2C baud rates to reduce power consumption
|
||
|
||
### Performance Tips
|
||
|
||
**TFT Displays:**
|
||
- Increase SPI baud rate up to 62.5MHz if display supports it
|
||
- Minimize full-screen refreshes (use partial updates if possible)
|
||
- 1-bit rendering is much faster than RGB565
|
||
|
||
**E-Paper Displays:**
|
||
- Use partial refresh for responsive UI (accepts some ghosting)
|
||
- Full refresh only when needed (menu changes, game over, etc.)
|
||
- Consider caching frequently used graphics
|
||
|
||
## Features by Component
|
||
|
||
### Display Features
|
||
- 1-bit monochrome rendering
|
||
- RGB565 color support (ST7796)
|
||
- Drawing primitives (lines, rectangles, circles)
|
||
- GUI widgets (windows, gauges, status bars)
|
||
- Multiple font support
|
||
|
||
### Touch Features
|
||
- Multi-touch support (up to 2 points)
|
||
- Coordinate transformation
|
||
- Touch debouncing
|
||
- Event types (press, lift, contact)
|
||
|
||
### SD Card Features
|
||
- SPI mode support
|
||
- FatFS integration
|
||
- Directory listing
|
||
- File read/write
|
||
- Automatic timestamps from compile time
|
||
|
||
## License
|
||
|
||
Copyright (c) 2021 Arm Limited and Contributors. All rights reserved.
|
||
SPDX-License-Identifier: Apache-2.0
|
||
|
||
## Dependencies
|
||
|
||
- Raspberry Pi Pico SDK 2.2.0+
|
||
- FatFS (included)
|
||
- TinyUSB (via SDK)
|
||
- Hardware drivers (included in `lib/`)
|
||
|
||
## Contributing
|
||
|
||
When adding new features:
|
||
1. Follow the abstraction layer pattern
|
||
2. Update `board_config.h` for hardware settings
|
||
3. Keep application code hardware-agnostic
|
||
4. Test on multiple boards if possible
|
||
5. Update this README
|