update readme

This commit is contained in:
Adolfo Reyna
2026-01-29 15:37:44 -05:00
parent 95e3f3f32d
commit 26e67d13d3

482
README.md
View File

@@ -7,33 +7,90 @@ A modular embedded application for RP2350 microcontrollers featuring display, to
- **Display Abstraction Layer** - Support for multiple display types (ST7796, ST7789, E-Paper) - **Display Abstraction Layer** - Support for multiple display types (ST7796, ST7789, E-Paper)
- **Touch Abstraction Layer** - Extensible touch controller support (FT6336U) - **Touch Abstraction Layer** - Extensible touch controller support (FT6336U)
- **SD Card with FatFS** - File system support with board-aware initialization - **SD Card with FatFS** - File system support with board-aware initialization
- **Multi-Board Support** - Automatic pin configuration for different RP2350 boards - **Multi-Board Support** - Single-file board configuration system for easy board switching
- **1-bit Rendering** - Memory-efficient monochrome graphics with GUI widgets - **1-bit Rendering** - Memory-efficient monochrome graphics with GUI widgets
- **Board Configuration** - Single configuration file for all hardware settings - **Automated Build Scripts** - Build for one board or all boards with single commands
- **Hardware Abstraction** - Factory pattern for displays and touch controllers
## Supported Hardware ## Supported Hardware Configurations
### Boards ### Available Board Configurations
1. **Adafruit Feather RP2350** (default)
2. **Raspberry Pi Pico 2**
3. **Raspberry Pi Pico 2 W**
### Displays 1. **BOARD_FEATHER_TFT** - Adafruit Feather RP2350 with 4.0" TFT ST7796
- ST7796 (480x320 TFT LCD) - Fully implemented - Display: ST7796 (480x320 RGB TFT)
- ST7789 - Ready for driver implementation - Touch: FT6336U capacitive touch
- E-Paper - Ready for driver implementation - Features: High-speed refresh, backlight control, SD card support
### Touch Controllers 2. **BOARD_PICO2_TFT** - Raspberry Pi Pico 2 with 4.0" TFT ST7796
- FT6336U (I2C capacitive touch) - Fully implemented - Display: ST7796 (480x320 RGB TFT)
- Extensible for additional controllers - Touch: FT6336U capacitive touch
- Features: High-speed refresh, backlight control, SD card support
### Storage 3. **BOARD_PICO2_EINK** - Raspberry Pi Pico 2 with E-Ink Display
- SD Card via SPI with FatFS file system - Display: E-Paper (400x300 monochrome)
- Touch: None (uses hardware buttons KEY0/KEY1)
- Features: Ultra-low power, partial/full refresh modes
## Quick Start ### Supported Displays
- **ST7796** - 480x320 RGB TFT LCD (Fully implemented)
- **E-Paper** - Various sizes, monochrome (Fully implemented)
- **ST7789** - Ready for driver implementation
### Building for Default Board (Feather RP2350) ### 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 ```bash
mkdir -p build mkdir -p build
cd build cd build
@@ -41,35 +98,50 @@ cmake -G Ninja ..
ninja ninja
``` ```
### Building for Specific Board The output file will be `build/basic1.uf2`.
```bash ### Method 2: Build for All Boards
cmake -G Ninja -DPICO_BOARD=pico2 ..
ninja
```
Available boards: `adafruit_feather_rp2350`, `pico2`, `pico2_w` To create UF2 files for all supported boards in one command:
### Building for All Boards
```bash ```bash
./build_all_boards.sh ./build_all_boards.sh
``` ```
Generates: This script will:
- `basic1_adafruit_feather_rp2350.uf2` 1. Backup your current `board_config.h`
- `basic1_pico2.uf2` 2. Build each board configuration automatically
- `basic1_pico2_w.uf2` 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`
### Flashing This is useful for:
- Creating releases for multiple hardware variants
- Testing code on all board configurations
- Batch building without manual configuration changes
1. Hold BOOTSEL button while connecting USB ### Manual Flashing
2. Copy the `.uf2` file to the mounted drive
3. Device will automatically reboot and run 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/`:
Or use the flash script:
```bash ```bash
./build_and_flash.sh # Load and auto-reboot
picotool load build/basic1.uf2 -fx
# Or load without auto-reboot
picotool load build/basic1.uf2
``` ```
## Project Structure ## Project Structure
@@ -77,78 +149,128 @@ Or use the flash script:
``` ```
basic1/ basic1/
├── basic1.cpp # Main application ├── basic1.cpp # Main application
├── board_config.h # Board-specific pin configuration ├── board_config.h # Board selector (edit this to switch boards!)
├── CMakeLists.txt # Build configuration ├── board_configs/ # Board-specific configurations
├── build_all_boards.sh # Multi-board build script │ ├── board_feather_tft.h # Feather RP2350 + TFT pin config
├── build_and_flash.sh # Build and flash helper │ ├── board_pico2_tft.h # Pico 2 + TFT pin config
│ ├── board_pico2_eink.h # Pico 2 + E-Ink pin config
│ └── README.md # Board config documentation
├── display/ # Display and GUI abstraction ├── CMakeLists.txt # Build configuration
│ ├── low_level_display.h # Display interface ├── build_all_boards.sh # Build all boards automatically
│ ├── low_level_display_*.cpp # Display implementations ├── build_and_flash.sh # Build and flash current board
├── low_level_touch.h # Touch interface
│ ├── low_level_touch_*.cpp # Touch implementations ├── 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_render.h/cpp # 1-bit rendering engine
│ └── low_level_gui.h/cpp # GUI widgets │ └── low_level_gui.h/cpp # GUI widgets (buttons, gauges, etc.)
├── lib/ # Hardware drivers ├── lib/ # Hardware drivers
│ ├── ft6336u/ # FT6336U touch driver │ ├── ft6336u/ # FT6336U capacitive touch driver
│ ├── st7796/ # ST7796 display driver │ ├── st7796/ # ST7796 TFT display driver
│ ├── epaper/ # E-Paper display driver
│ ├── sd_card/ # SD card driver with FatFS test │ ├── sd_card/ # SD card driver with FatFS test
│ └── fatfs/ # FatFS filesystem │ └── fatfs/ # FatFS filesystem
├── fonts/ # Bitmap font definitions ├── fonts/ # 25+ bitmap font definitions (5x5 to 8x8)
└── fatfs_time.c # FatFS timestamp (uses compile time) └── fatfs_time.c # FatFS timestamp support
``` ```
## Configuration ## Adding a New Board Configuration
### Board Configuration (`board_config.h`) 1. Create a new config file in `board_configs/`:
```bash
cp board_configs/board_pico2_tft.h board_configs/board_myboard.h
```
All hardware settings are defined per board: 2. Edit the new file and update all pin definitions for your hardware
```c 3. Add your board to `board_config.h`:
// Display configuration ```cpp
#define DISPLAY_WIDTH 480 // ---- SELECT YOUR BOARD HERE ----
#define DISPLAY_HEIGHT 320 // #define BOARD_FEATHER_TFT
#define DISPLAY_TYPE_SELECTED 0 // DISPLAY_TYPE_ST7796 // #define BOARD_PICO2_TFT
// #define BOARD_PICO2_EINK
#define BOARD_MYBOARD // Your new board
// --------------------------------
```
// Touch configuration 4. Add the include section:
#define TOUCH_TYPE_SELECTED 0 // TOUCH_TYPE_FT6336U ```cpp
#define TOUCH_SWAP_XY true #ifdef BOARD_FEATHER_TFT
#define TOUCH_INVERT_X true #include "board_configs/board_feather_tft.h"
#define TOUCH_INVERT_Y false // ... other boards ...
#elif defined(BOARD_MYBOARD)
#include "board_configs/board_myboard.h"
#endif
```
// SPI pins for display 5. (Optional) Add to `build_all_boards.sh` for automated builds
#define DISPLAY_SPI_PORT spi1
#define DISPLAY_SCK_PIN 18
#define DISPLAY_MOSI_PIN 19
#define DISPLAY_MISO_PIN 20
#define DISPLAY_CS_PIN 17
// ... more pins
```
### Changing Display Type See `board_configs/README.md` for detailed configuration structure.
Modify `DISPLAY_TYPE_SELECTED` in `board_config.h`: ## Hardware Configuration Details
- `0` = ST7796 (480x320 TFT)
- `1` = ST7789
- `2` = E-Paper
### Changing Touch Type ### Display Types
Modify `TOUCH_TYPE_SELECTED` in `board_config.h`: Each board configuration specifies a display type via `DISPLAY_TYPE_SELECTED`:
- `0` = FT6336U - `DISPLAY_TYPE_ST7796_VAL` (0) - ST7796 TFT (480x320)
- `1` = None (disable touch) - `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 Coordinate Transformation
Adjust orientation in `board_config.h`: Touch coordinates can be adjusted for different mounting orientations:
```c ```c
#define TOUCH_SWAP_XY true // Swap X/Y coordinates #define TOUCH_SWAP_XY true // Swap X/Y coordinates (for 90° rotation)
#define TOUCH_INVERT_X true // Invert X axis #define TOUCH_INVERT_X true // Invert X axis (mirror horizontally)
#define TOUCH_INVERT_Y false // Invert Y axis #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 ## Architecture
### Display Abstraction Layer ### Display Abstraction Layer
@@ -226,92 +348,182 @@ The test function:
- Creates and reads test file - Creates and reads test file
- Safely unmounts filesystem - Safely unmounts filesystem
## Pin Configurations ## Pin Configurations Summary
### Adafruit Feather RP2350 Actual pin assignments are defined in `board_configs/*.h` files. Here's a quick reference:
- **Display (SPI1):** SCK=18, MOSI=19, MISO=20, CS=17, DC=16, RST=15, BL=14
- **Touch (I2C0):** SDA=4, SCL=5, INT=6, RST=7 ### 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) - **SD Card (SPI1):** CS=10 (shares SPI with display)
### Raspberry Pi Pico 2 / Pico 2 W ### BOARD_PICO2_TFT (Raspberry Pi Pico 2)
- **Display (SPI0):** SCK=2, MOSI=3, MISO=4, CS=5, DC=6, RST=7, BL=8 - **Display (ST7796, SPI0):** SCK=2, MOSI=3, MISO=4, CS=5, DC=6, RST=7, BL=8
- **Touch (I2C0):** SDA=12, SCL=13, INT=14, RST=15 - **Touch (FT6336U, I2C0):** SDA=12, SCL=13, INT=14, RST=15
- **SD Card (SPI1):** CS=17 - **SD Card (SPI1):** CS=17
## Adding New Hardware ### 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 ### Adding a New Display Driver
1. Create implementation files: 1. Create implementation files:
```cpp ```
display/low_level_display_mydriver.h display/low_level_display_mynewdisplay.h
display/low_level_display_mydriver.cpp display/low_level_display_mynewdisplay.cpp
``` ```
2. Implement the `LowLevelDisplay` interface 2. Inherit from `LowLevelDisplay` base class and implement all virtual methods
3. Add to factory in `low_level_display_factory.cpp`: 3. Add a new constant in `board_config.h`:
```cpp ```cpp
case DISPLAY_TYPE_MYDRIVER: #define DISPLAY_TYPE_MYNEWDISPLAY_VAL 3
display = new LowLevelDisplayMyDriver(width, height); ```
4. Update the factory in `display/low_level_display.cpp`:
```cpp
case 3: // DISPLAY_TYPE_MYNEWDISPLAY
display = new LowLevelDisplayMyNewDisplay(width, height);
break; break;
``` ```
4. Update `CMakeLists.txt` to include new files 5. Update `CMakeLists.txt` to compile the new files
### Adding a New Touch Controller ### Adding a New Touch Controller
1. Create implementation files: 1. Create implementation files:
```cpp ```
display/low_level_touch_mydriver.h display/low_level_touch_mynewtouch.h
display/low_level_touch_mydriver.cpp display/low_level_touch_mynewtouch.cpp
``` ```
2. Implement the `LowLevelTouch` interface 2. Inherit from `LowLevelTouch` base class
3. Add to factory in `low_level_touch_factory.cpp` 3. Add constant and factory case similar to display drivers
4. Update `CMakeLists.txt` 4. Update CMakeLists.txt
### Adding a New Board ### Workflow Summary
Edit `board_config.h`: The typical development workflow:
```c 1. **Select target board:** Edit `board_config.h`, uncomment your board
#elif defined(PICO_BOARD_MY_CUSTOM_BOARD) 2. **Build:** Run `./build_and_flash.sh` (builds and flashes current board)
#define BOARD_NAME "My Custom Board" 3. **Test:** Connect to USB, monitor via serial terminal
4. **Switch boards:** Edit `board_config.h`, rebuild
// Display configuration 5. **Release:** Run `./build_all_boards.sh` to create UF2s for all boards
#define DISPLAY_WIDTH 480
#define DISPLAY_HEIGHT 320
#define DISPLAY_TYPE_SELECTED 0
// Touch configuration
#define TOUCH_TYPE_SELECTED 0
// ... define all pins
#endif
```
## Memory Usage ## Memory Usage
- **1-bit framebuffer:** 480×320÷8 = 19.2 KB - **1-bit framebuffer:** Width×Height÷8 bytes
- **Display conversion:** Automatic 1-bit → RGB565/monochrome - 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 - **Stack/heap:** Minimal, uses static buffers where possible
- **Code size:** ~100-150 KB depending on features enabled
## Known Issues & Troubleshooting ## Troubleshooting
### Touch Not Working ### Build Issues
- **I2C Communication Failure:** Check wiring, pull-up resistors, I2C address
- **Wrong Coordinates:** Adjust `TOUCH_SWAP_XY`, `TOUCH_INVERT_X/Y` settings
### SD Card Not Detected **Error: "No board selected!"**
- **CMD0 Returns 0x00:** Check card insertion, CS pin, SPI wiring - You must uncomment exactly one `BOARD_xxx` define in `board_config.h`
- **Mount Fails:** Ensure card is formatted as FAT/FAT32
### Display Shows Nothing **CMake configuration errors:**
- Check SPI wiring and CS/DC/RST pins - Delete `build/` directory and reconfigure: `rm -rf build && mkdir build`
- Verify backlight is connected and enabled
- Check voltage levels (3.3V logic) ### 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 ## Features by Component