Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

st7796s

ST7796S TFT Display Driver — ESP32-S3 / ESP-IDF v6.0 C library · MSP4020 480×320 px · RGB565 · SPI · DMA

ESP-IDF v6.0 ESP32-S3 ST7796S C MIT

🇫🇷 Lire en français


Table of Contents

  1. What is st7796s?
  2. Feature List
  3. Hardware Wiring
  4. Installation as an ESP-IDF Component
  5. Quick Start — Hello World
  6. Migration: UART Hello World → TFT Hello World
  7. Complete API Reference
  8. Using with esp32-tft-designer
  9. Adding a New Pattern
  10. Examples
  11. Project Structure
  12. Troubleshooting

1. What is st7796s?

st7796s is a pure C driver for the ST7796S TFT controller, designed for the ESP32-S3 with ESP-IDF v6.0.

It targets the MSP4020 panel (480×320 px, RGB565, SPI) and provides:

  • A full graphics primitive API (fill, pixel, lines, rectangles, circles)
  • An 8×16 bitmap text system with scale support
  • Reusable pattern functions (WiFi icon — extendable)
  • DMA-accelerated pixel transfer via SPI2
  • Backlight PWM control via LEDC
  • 4 hardware rotation modes validated on MSP4020

The library is standalone and independent of any design tool. It can be used directly or alongside esp32-tft-designer to display visually designed screens.


2. Feature List

Feature Description
DMA pixel fill tft_fill_rect / tft_fill_screen using DMA buffer (15 360 bytes)
Pixel-level drawing tft_draw_pixel with out-of-bounds clipping
Optimized lines tft_draw_hline / tft_draw_vline via fill_rect
Rectangle tft_draw_rect (outline)
Circles tft_draw_circle / tft_fill_circle (Bresenham midpoint algorithm)
Bitmap text 8×16 px font, ASCII 32–126, scale ×1 to ×4, auto line-wrap
Hello World tft_show_hello_world() — centered, decorative, yellow text
WiFi icon tft_draw_wifi_icon() — 3 concentric half-arcs + center dot
Bitmap push tft_draw_bitmap() — raw RGB565 pixel buffer
Test patterns 9 built-in patterns (color bars, gradient, checkerboard, circles…)
4 rotations TFT_ROT_0/90/180/270, MADCTL validated on MSP4020
Backlight PWM tft_set_backlight() — 0–255, LEDC timer 0 / channel 0
PSRAM support DMA buffer allocated in PSRAM if available
Error handling All functions return esp_err_t, ESP_ERROR_CHECK compatible

3. Hardware Wiring

ESP32-S3 DevKit ↔ MSP4020 (ST7796S)

MSP4020 Pin Signal ESP32-S3 GPIO Notes
VCC Power 3V3 3.3V only — never 5V
GND Ground GND Common ground
CS SPI Chip Select GPIO 10 Active LOW
RESET Hardware reset GPIO 9 Active LOW pulse on init
DC / RS Data / Command GPIO 8 HIGH = data, LOW = command
SDI / MOSI SPI data out GPIO 11 SPI2_HOST MOSI
SCK / CLK SPI clock GPIO 12 SPI2_HOST CLK
LED / BL Backlight GPIO 46 PWM via LEDC timer 0
SDO / MISO SPI data in GPIO 13 Optional — read-back only

SPI: mode 0, 40 MHz write, 10 MHz read.

To change pin numbers, modify the #define TFT_PIN_* constants in include/st7796s.h.


4. Installation as an ESP-IDF Component

Option A — Copy into your project (recommended)

# In your ESP-IDF project root
mkdir -p components
cp -r /path/to/st7796s-lib components/st7796s

Your main/CMakeLists.txt:

idf_component_register(
    SRCS "main.c"
    INCLUDE_DIRS "."
    REQUIRES st7796s
)

Option B — Relative path (for the provided examples)

# main/idf_component.yml
dependencies:
  st7796s:
    path: "../../../"    # Points to the library root
  idf:
    version: ">=6.0.0"

5. Quick Start — Hello World

#include "st7796s.h"

void app_main(void)
{
    tft_handle_t tft;

    // Initialize display (SPI, GPIO, backlight, reset sequence)
    ESP_ERROR_CHECK(tft_init(&tft));

    // Display centered Hello World with decorative frame
    ESP_ERROR_CHECK(tft_show_hello_world(&tft));

    // Or draw manually:
    tft_fill_screen(&tft, TFT_BLUE);
    tft_draw_string(&tft, 10, 10, "Hello ESP32!", TFT_WHITE, TFT_BLUE, 2);
    tft_draw_wifi_icon(&tft, 240, 160, 40, TFT_CYAN, 2, TFT_BLUE);

    while (1) { vTaskDelay(pdMS_TO_TICKS(1000)); }
}

6. Migration: UART Hello World → TFT Hello World

This section shows the exact changes to migrate from a standard UART Hello World to TFT display output.

Before: UART Hello World (hello_world_uart)

#include "esp_log.h"
static const char *TAG = "HELLO";

void app_main(void) {
    ESP_LOGI(TAG, "Hello World from ESP32-S3!");
    for (int i = 10; i >= 0; i--) {
        ESP_LOGI(TAG, "Restarting in %d...", i);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
    esp_restart();
}

After: TFT Hello World (hello_world_tft)

#include "esp_log.h"
#include "st7796s.h"          // ← ADD THIS / AJOUTER CECI
static const char *TAG = "HELLO";

void app_main(void) {
    tft_handle_t tft;                          // ← ADD: declare handle
    ESP_ERROR_CHECK(tft_init(&tft));           // ← ADD: initialize display

    // ← REPLACE ESP_LOGI with TFT output:
    tft_show_hello_world(&tft);
    tft_draw_string(&tft, 8, tft.height - 20,
                    "Hello World from ESP32-S3!",
                    TFT_LIGHTGRAY, TFT_BLACK, 1);

    // UART log still works alongside TFT:
    ESP_LOGI(TAG, "Hello World on TFT: %u×%u px", tft.width, tft.height);

    while (1) { vTaskDelay(pdMS_TO_TICKS(10000)); }
    // No more esp_restart() needed
}

Diff summary

UART version TFT version
Output Serial monitor TFT display
New include — #include "st7796s.h"
New variable — tft_handle_t tft;
New init call — tft_init(&tft)
Output call ESP_LOGI(...) tft_draw_string(...)
CMakeLists REQUIRES — st7796s

7. Complete API Reference

Initialization

Function Description Returns
tft_init(handle) Initialize SPI, GPIO, backlight, ST7796S sequence ESP_OK | error
tft_deinit(handle) Release SPI and free DMA buffer ESP_OK

Configuration

Function Description Returns
tft_set_rotation(handle, rotation) Change rotation (TFT_ROT_0–270) ESP_OK | INVALID_ARG
tft_set_backlight(handle, brightness) PWM backlight 0–255 void

Basic Drawing

Function Parameters Description
tft_fill_screen(h, color) RGB565 Fill entire screen via DMA
tft_fill_rect(h, x, y, w, h, color) top-left + size + RGB565 Fill rectangle via DMA
tft_draw_pixel(h, x, y, color) position + RGB565 Single pixel
tft_draw_hline(h, x, y, len, color) start + length Horizontal line
tft_draw_vline(h, x, y, len, color) start + length Vertical line
tft_draw_rect(h, x, y, w, h, color) top-left + size Rectangle outline
tft_draw_circle(h, x0, y0, r, color) center + radius Circle outline (Bresenham)
tft_fill_circle(h, x0, y0, r, color) center + radius Filled circle

Text (8×16 bitmap font, ASCII 32–126)

Function Parameters Description
tft_draw_char(h, x, y, c, fg, bg, scale) pos + char + colors + scale Single character
tft_draw_string(h, x, y, str, fg, bg, scale) pos + string + colors + scale String with auto-wrap
tft_show_hello_world(h) — Centered Hello World + frame

Scale: 1 = 8×16 px, 2 = 16×32 px, 3 = 24×48 px, 4 = 32×64 px.

Patterns

Function Parameters Description
tft_draw_wifi_icon(h, cx, cy, r, color, thickness, bg_color) center + radius + color + thickness + bg WiFi signal icon

Bitmap and Test Patterns

Function Parameters Description
tft_draw_bitmap(h, x, y, w, h, data) area + pixel array Raw RGB565 pixel buffer
tft_draw_test_pattern(h, pattern) tft_test_pattern_t One of 9 built-in patterns

Color constants

TFT_BLACK, TFT_WHITE, TFT_RED, TFT_GREEN, TFT_BLUE, TFT_CYAN, TFT_MAGENTA, TFT_YELLOW, TFT_ORANGE, TFT_PURPLE, TFT_GRAY, TFT_DARKGREEN, TFT_DARKBLUE, TFT_DARKRED, TFT_LIGHTGRAY.

Custom color: RGB565(r, g, b) — converts RGB888 to RGB565 at compile time.


8. Using with esp32-tft-designer

esp32-tft-designer is a web-based visual editor that generates C/C++ code using the functions of this library.

Workflow

1. Start esp32-tft-designer:
   cd esp32-tft-designer
   ./esp32-tft-container.sh start
   → http://localhost:5100

2. Design your screen visually in the browser

3. Click "Generate C" → select "st7796s (ESP-IDF)"
   → Preview the generated code

4. Click "Export ZIP"
   → Download tft_screen_TIMESTAMP.zip

5. Extract tft_screen_st7796s_TIMESTAMP.c into main/

6. In your main.c:
   #include "tft_screen_st7796s.h"
   tft_handle_t tft;
   ESP_ERROR_CHECK(tft_init(&tft));
   tft_draw_screen(&tft);          // Generated function

7. idf.py build && idf.py flash

The designer generates calls to:

  • tft_fill_screen() — for the background
  • tft_draw_pixel(), tft_draw_hline(), tft_draw_vline() — for pixels and lines
  • tft_fill_rect(), tft_draw_rect() — for rectangles
  • tft_draw_circle(), tft_fill_circle() — for circles
  • tft_draw_string() — for text
  • tft_draw_wifi_icon() — for the WiFi pattern

9. Adding a New Pattern

The library is designed to be extended with new patterns. The WiFi icon (tft_draw_wifi_icon) serves as the complete reference model.

Quick overview of the 4 steps

Step File Action
1 include/st7796s.h Declare the function (copy WiFi Doxygen block as template)
2 st7796s.c Implement in section 7. Patterns
3 esp32-tft-designer/codegen.py Add elif t == "your_type": in generate_st7796s() and generate_lovyangfx()
4 esp32-tft-designer/app.js Add cases in buildElement(), drawElement(), getBBox(), getHandles(), layerLabel(), buildPropsHTML()

Full step-by-step guide with code examples: docs/adding_new_pattern.md


10. Examples

Example Location Description
hello_world_uart examples/hello_world_uart/ Classic UART Hello World — starting point
hello_world_tft examples/hello_world_tft/ TFT Hello World — shows the UART→TFT migration
designer_integration examples/designer_integration/ Full designer + st7796s integration

Building an example

cd examples/hello_world_tft
idf.py set-target esp32s3
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor

11. Project Structure

st7796s-lib/
├── include/
│   ├── st7796s.h        ← Public API — all declarations + Doxygen docs
│   └── font8x16.h       ← Bitmap font array declaration
├── st7796s.c            ← Implementation (897 lines, bilingual comments)
├── font8x16.c           ← 8×16 bitmap font data (ASCII 32–126)
├── CMakeLists.txt       ← IDF component registration
├── idf_component.yml    ← IDF Component Manager manifest
├── README.md            ← This file (English)
├── README.fr.md         ← French documentation
├── docs/
│   └── adding_new_pattern.md  ← Step-by-step guide to extend the library
└── examples/
    ├── hello_world_uart/      ← Classic UART Hello World
    ├── hello_world_tft/       ← TFT Hello World (UART→TFT migration)
    └── designer_integration/  ← esp32-tft-designer + st7796s integration

12. Troubleshooting

Symptom Possible cause Solution
White or blank screen RST pulse too short Check RST wiring and 120 ms delay
Wrong colors (R/B swapped) Wrong BGR flag Change MADCTL_BGR in tft_set_rotation()
Garbage pixels SPI noise at 40 MHz Reduce to 20 MHz: TFT_SPI_FREQ_HZ (20*1000*1000)
ESP_ERR_NO_MEM No DMA RAM Ensure CONFIG_ESP32S3_DATA_CACHE_SIZE is large enough
Compilation error: tft_draw_wifi_icon undefined Old header Rebuild after updating st7796s.h
Text is ? characters Non-ASCII input Use only ASCII 32–126

st7796s — MIT License — ESP32-S3 / MSP4020 / ST7796S

About

A custom library to drive TFT Display.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages