358 lines
8.9 KiB
Markdown
358 lines
8.9 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.
|
||
|
||
## Features
|
||
|
||
- **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** - Automatic pin configuration for different RP2350 boards
|
||
- **1-bit Rendering** - Memory-efficient monochrome graphics with GUI widgets
|
||
- **Board Configuration** - Single configuration file for all hardware settings
|
||
|
||
## Supported Hardware
|
||
|
||
### Boards
|
||
1. **Adafruit Feather RP2350** (default)
|
||
2. **Raspberry Pi Pico 2**
|
||
3. **Raspberry Pi Pico 2 W**
|
||
|
||
### Displays
|
||
- ST7796 (480x320 TFT LCD) - Fully implemented
|
||
- ST7789 - Ready for driver implementation
|
||
- E-Paper - Ready for driver implementation
|
||
|
||
### Touch Controllers
|
||
- FT6336U (I2C capacitive touch) - Fully implemented
|
||
- Extensible for additional controllers
|
||
|
||
### Storage
|
||
- SD Card via SPI with FatFS file system
|
||
|
||
## Quick Start
|
||
|
||
### Building for Default Board (Feather RP2350)
|
||
|
||
```bash
|
||
mkdir -p build
|
||
cd build
|
||
cmake -G Ninja ..
|
||
ninja
|
||
```
|
||
|
||
### Building for Specific Board
|
||
|
||
```bash
|
||
cmake -G Ninja -DPICO_BOARD=pico2 ..
|
||
ninja
|
||
```
|
||
|
||
Available boards: `adafruit_feather_rp2350`, `pico2`, `pico2_w`
|
||
|
||
### Building for All Boards
|
||
|
||
```bash
|
||
./build_all_boards.sh
|
||
```
|
||
|
||
Generates:
|
||
- `basic1_adafruit_feather_rp2350.uf2`
|
||
- `basic1_pico2.uf2`
|
||
- `basic1_pico2_w.uf2`
|
||
|
||
### Flashing
|
||
|
||
1. Hold BOOTSEL button while connecting USB
|
||
2. Copy the `.uf2` file to the mounted drive
|
||
3. Device will automatically reboot and run
|
||
|
||
Or use the flash script:
|
||
```bash
|
||
./build_and_flash.sh
|
||
```
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
basic1/
|
||
├── basic1.cpp # Main application
|
||
├── board_config.h # Board-specific pin configuration
|
||
├── CMakeLists.txt # Build configuration
|
||
├── build_all_boards.sh # Multi-board build script
|
||
├── build_and_flash.sh # Build and flash helper
|
||
│
|
||
├── display/ # Display and GUI abstraction
|
||
│ ├── low_level_display.h # Display interface
|
||
│ ├── low_level_display_*.cpp # Display implementations
|
||
│ ├── low_level_touch.h # Touch interface
|
||
│ ├── low_level_touch_*.cpp # Touch implementations
|
||
│ ├── low_level_render.h/cpp # 1-bit rendering engine
|
||
│ └── low_level_gui.h/cpp # GUI widgets
|
||
│
|
||
├── lib/ # Hardware drivers
|
||
│ ├── ft6336u/ # FT6336U touch driver
|
||
│ ├── st7796/ # ST7796 display driver
|
||
│ ├── sd_card/ # SD card driver with FatFS test
|
||
│ └── fatfs/ # FatFS filesystem
|
||
│
|
||
├── fonts/ # Bitmap font definitions
|
||
└── fatfs_time.c # FatFS timestamp (uses compile time)
|
||
```
|
||
|
||
## Configuration
|
||
|
||
### Board Configuration (`board_config.h`)
|
||
|
||
All hardware settings are defined per board:
|
||
|
||
```c
|
||
// Display configuration
|
||
#define DISPLAY_WIDTH 480
|
||
#define DISPLAY_HEIGHT 320
|
||
#define DISPLAY_TYPE_SELECTED 0 // DISPLAY_TYPE_ST7796
|
||
|
||
// Touch configuration
|
||
#define TOUCH_TYPE_SELECTED 0 // TOUCH_TYPE_FT6336U
|
||
#define TOUCH_SWAP_XY true
|
||
#define TOUCH_INVERT_X true
|
||
#define TOUCH_INVERT_Y false
|
||
|
||
// SPI pins for display
|
||
#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
|
||
|
||
Modify `DISPLAY_TYPE_SELECTED` in `board_config.h`:
|
||
- `0` = ST7796 (480x320 TFT)
|
||
- `1` = ST7789
|
||
- `2` = E-Paper
|
||
|
||
### Changing Touch Type
|
||
|
||
Modify `TOUCH_TYPE_SELECTED` in `board_config.h`:
|
||
- `0` = FT6336U
|
||
- `1` = None (disable touch)
|
||
|
||
### Touch Coordinate Transformation
|
||
|
||
Adjust orientation in `board_config.h`:
|
||
```c
|
||
#define TOUCH_SWAP_XY true // Swap X/Y coordinates
|
||
#define TOUCH_INVERT_X true // Invert X axis
|
||
#define TOUCH_INVERT_Y false // Invert Y axis
|
||
```
|
||
|
||
## 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
|
||
|
||
### Adafruit Feather RP2350
|
||
- **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
|
||
- **SD Card (SPI1):** CS=10 (shares SPI with display)
|
||
|
||
### Raspberry Pi Pico 2 / Pico 2 W
|
||
- **Display (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
|
||
- **SD Card (SPI1):** CS=17
|
||
|
||
## Adding New Hardware
|
||
|
||
### Adding a New Display Driver
|
||
|
||
1. Create implementation files:
|
||
```cpp
|
||
display/low_level_display_mydriver.h
|
||
display/low_level_display_mydriver.cpp
|
||
```
|
||
|
||
2. Implement the `LowLevelDisplay` interface
|
||
|
||
3. Add to factory in `low_level_display_factory.cpp`:
|
||
```cpp
|
||
case DISPLAY_TYPE_MYDRIVER:
|
||
display = new LowLevelDisplayMyDriver(width, height);
|
||
break;
|
||
```
|
||
|
||
4. Update `CMakeLists.txt` to include new files
|
||
|
||
### Adding a New Touch Controller
|
||
|
||
1. Create implementation files:
|
||
```cpp
|
||
display/low_level_touch_mydriver.h
|
||
display/low_level_touch_mydriver.cpp
|
||
```
|
||
|
||
2. Implement the `LowLevelTouch` interface
|
||
|
||
3. Add to factory in `low_level_touch_factory.cpp`
|
||
|
||
4. Update `CMakeLists.txt`
|
||
|
||
### Adding a New Board
|
||
|
||
Edit `board_config.h`:
|
||
|
||
```c
|
||
#elif defined(PICO_BOARD_MY_CUSTOM_BOARD)
|
||
#define BOARD_NAME "My Custom Board"
|
||
|
||
// Display configuration
|
||
#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
|
||
|
||
- **1-bit framebuffer:** 480×320÷8 = 19.2 KB
|
||
- **Display conversion:** Automatic 1-bit → RGB565/monochrome
|
||
- **Stack/heap:** Minimal, uses static buffers where possible
|
||
|
||
## Known Issues & Troubleshooting
|
||
|
||
### Touch Not Working
|
||
- **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
|
||
- **CMD0 Returns 0x00:** Check card insertion, CS pin, SPI wiring
|
||
- **Mount Fails:** Ensure card is formatted as FAT/FAT32
|
||
|
||
### Display Shows Nothing
|
||
- Check SPI wiring and CS/DC/RST pins
|
||
- Verify backlight is connected and enabled
|
||
- Check voltage levels (3.3V logic)
|
||
|
||
## 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
|