# 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