Raspberry Pi Pico 2 drive 4.0" 320x480 TFT SPI ST7796 with FT6336U Capacitive Touch + SD, in Arduino framework
Exercise of
Raspberry Pi Pico 2
(in Arduino framework) to drive 4.0" 320x480 TFT SPI ST7796 with FT6336U Capacitive Touch + SD. The Raspberry Pi Pico 2 are programmed in Arduino framework using board
of Raspberry Pi Pico/RP2040/RP2350 by Earle F. Philhower, III
(arduino-pico), load bmp images from SD card, display on ST7796 using TFT_eSPI, and touch screen to switching among images.
Connection:
This ST7796 display module have on board level conversion circuit, compatible with 5V and 3.3V MCU. According LCDWiKi 4.0inch Capacitive SPI Module ST7796, VCC is recommended to connect to 5V. When connected to 3.3V, the backlight brightness will be slightly dim. In my test on Raspberry Pi Pico 2 on breadboard, VCC connected to VBUS is much more stable than connect to 3V3(OUT).
In my connection, both SPI (shared by ST7796 and SD) and I2C (FT6336U) are default GPIO in the board Raspberry Pi Pico/RP2040/RP2350.
Board of Raspberry Pi Pico/RP2040/RP2350
Board of Raspberry Pi Pico/RP2040/RP2350 by Earle F. Philhower, III is a Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards. To install it on Arduino IDE, read the post Install Earle Philhower Raspberry Pi Pico Arduino core.
Prepare TFT_eSPI Library and setup
It's easy to install TFT_eSPI in Arduino IDE in its Library Manager, but take a notice on user setup file.
Read TFT_eSPI page, scroll down to Tips section. It's suggest to create a new folder in your Arduino library folder called "TFT_eSPI_Setups". You then place your custom setup.h files in there.
Setup_ST7796_pico2.h, my setup.h file.
Test bmp images:
All test images were generated using X Grok, resized and converted to 426*320, RGB888, .bmp using Python, read Resize jpg and convert to bmp in RGB888 and RGB565 mode, using Python/GIMP,
Exercise Code:
pico2_st7796_sd.ino
pico2_st7796_slideshow.ino
pico2_st7796_slideshow_touch.ino
Next:
~ LVGL on Raspberry Pi Pico 2 (Arduino framework/arduino-pico) with 320x480 TFT SPI ST7796 + FT6336U Capacitive Touch
Connection:
ST7796 Module Raspberry Pi Pico 2
---------------------------------------
SD_CS GP15
CTP_INT not used
CTP_SDA GP4
CTP_RST GP14 (optional, or 3V3)
CTP_SCL GP5
SDO(MISO) GP16
LED GP22
SCK GP18
SDI(MOSI) GP19
LCD_RS GP21
LCD_RST GP20
LCD_CS GP17
GND GND
VCC VBUS (5V)
This ST7796 display module have on board level conversion circuit, compatible with 5V and 3.3V MCU. According LCDWiKi 4.0inch Capacitive SPI Module ST7796, VCC is recommended to connect to 5V. When connected to 3.3V, the backlight brightness will be slightly dim. In my test on Raspberry Pi Pico 2 on breadboard, VCC connected to VBUS is much more stable than connect to 3V3(OUT).
In my connection, both SPI (shared by ST7796 and SD) and I2C (FT6336U) are default GPIO in the board Raspberry Pi Pico/RP2040/RP2350.
Board of Raspberry Pi Pico/RP2040/RP2350
Board of Raspberry Pi Pico/RP2040/RP2350 by Earle F. Philhower, III is a Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards. To install it on Arduino IDE, read the post Install Earle Philhower Raspberry Pi Pico Arduino core.
Prepare TFT_eSPI Library and setup
It's easy to install TFT_eSPI in Arduino IDE in its Library Manager, but take a notice on user setup file.
Read TFT_eSPI page, scroll down to Tips section. It's suggest to create a new folder in your Arduino library folder called "TFT_eSPI_Setups". You then place your custom setup.h files in there.
Setup_ST7796_pico2.h, my setup.h file.
// Setup_ST7796_pico2.h in
// ..\Arduino\libraries\TFT_eSPI_Setups\
//
// Modify
// ..\Arduino\libraries\TFT_eSPI\User_Setup_Select.h to load it.
// #include <../TFT_eSPI_Setups/Setup_ST7796_pico2.h>
#define ST7796_DRIVER
#define TFT_WIDTH 320
#define TFT_HEIGHT 480
// TFT_MOSI/TFT_SCLK for default SPI pin assignment
#define TFT_MISO -1
#define TFT_MOSI 19
#define TFT_SCLK 18
#define TFT_CS 17
#define TFT_DC 21
#define TFT_RST 20
#define TFT_BL 22 // LED back-light control pin
#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW)
// if use SPI0, undefine TFT_SPI_PORT, or define as 0
// if use SPI1, define TFT_SPI_PORT as 1
//#define TFT_SPI_PORT 0
#define SPI_FREQUENCY 27000000
////////////////////////////////////////////////////////////////////////////////////////////
// Fonts to be available
////////////////////////////////////////////////////////////////////////////////////////////
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
#define SMOOTH_FONT
Edit \TFT_eSPI\User_Setup_Select.h to include it.#include <../TFT_eSPI_Setups/Setup_ST7796_pico2.h>
Once you finished the setup files, you can run the TFT_eSPI examples in Arduino
IDE.Test bmp images:
All test images were generated using X Grok, resized and converted to 426*320, RGB888, .bmp using Python, read Resize jpg and convert to bmp in RGB888 and RGB565 mode, using Python/GIMP,
Exercise Code:
pico2_st7796_sd.ino
/*
A simple exercise on Raspberry Pi Pico 2,
run in Arduino framework using board of arduino-pico by earlephilhower
(named Raspberry Pi Pico/RP2040/RP2350 in Arduino IDE Boards Manager).
List files in SD,
load a fixed bmp file from SD and display on 4.0inch Capacitive SPI Module ST7796 using TFT_eSPI library.
The ST7796 and SD share the same SPI with separated CS.
The testing images are 426*320, RGB888, .bmp.
Converted using Python in:
https://coxxect.blogspot.com/2024/11/resize-jpg-and-convert-to-bmp-in-rgb888.html
*/
#include <SPI.h>
#include <SD.h>
#include <TFT_eSPI.h>
#define SD_CS 15
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
void setup() {
delay(500);
Serial.begin(115200);
delay(1000);
Serial.println("--- Start ---");
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
SPI.begin();
// Hardware Reset ST7796 at power up
// try to fix sometimes screen blank.
Serial.println("Hardware Reset on TFT_RST: " + String(TFT_RST));
pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, HIGH);
delay(100);
pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, LOW);
delay(100);
pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, HIGH);
delay(100);
tft.init();
//tft.setRotation(1);
Serial.println("TFT_WIDTH x TFT_HEIGHT = " + String(TFT_WIDTH) + " x " + String(TFT_HEIGHT));
Serial.println("tft.width() x tft.height() = " + String(tft.width()) + " x " + String(tft.height()));
tft.fillScreen(TFT_BLACK);
tft.drawRect(0, 0, tft.width(), tft.height(), TFT_GREEN);
// Set "cursor" at top left corner of display (0,0) and select font 1
tft.setCursor(0, 0, 1);
//init SD
Serial.println("Initialize SD");
tft.println("Initialize SD");
while (!SD.begin(SD_CS)){
Serial.println("Fail!");
tft.println("Fail!");
delay(1000);
}
Serial.println("Success");
tft.println("Success");
listSDCard();
}
void loop() {
tft.fillScreen(TFT_BLACK);
drawBmp("/images/img_001_320x426_rgb888.bmp", 0, 0);
delay(5000);
}
void listDir(File dir, int numTabs) {
while (true) {
File entry = dir.openNextFile();
if (!entry) {
break; // no more file
}
for (int i = 0; i < numTabs; i++) {
Serial.print("\t");
}
Serial.print(entry.name());
tft.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
tft.println("/");
listDir(entry, numTabs + 1);
} else {
Serial.println(entry.size());
tft.println(entry.size());
}
entry.close();
}
}
void listSDCard() {
File root = SD.open("/");
listDir(root, 0);
}
void drawBmp(const char *filename, int16_t x, int16_t y) {
File bmpFile;
uint8_t bmpHeader[54];
uint32_t dataOffset, imageWidth, imageHeight;
uint16_t rowPadding;
uint16_t pixel;
// Open the BMP file
bmpFile = SD.open(filename);
if (!bmpFile) {
Serial.println("Failed to open BMP file");
return;
}
// Read the BMP file header
bmpFile.read(bmpHeader, 54);
// Check for BMP signature ("BM")
if (bmpHeader[0] != 'B' || bmpHeader[1] != 'M') {
Serial.println("Not a valid BMP file");
bmpFile.close();
return;
}
// Get image dimensions
dataOffset = *(uint32_t *)&bmpHeader[10];
imageWidth = *(uint32_t *)&bmpHeader[18];
imageHeight = *(uint32_t *)&bmpHeader[22];
rowPadding = (4 - (imageWidth * 3) % 4) % 4;
// Move to image data start
bmpFile.seek(dataOffset);
// Draw the BMP pixel-by-pixel
for (int16_t row = imageHeight - 1; row >= 0; row--) { // BMPs are stored bottom-up
for (int16_t col = 0; col < imageWidth; col++) {
uint8_t b = bmpFile.read();
uint8_t g = bmpFile.read();
uint8_t r = bmpFile.read();
pixel = tft.color565(r, g, b);
tft.drawPixel(x + col, y + row, pixel);
}
// Skip row padding
bmpFile.seek(bmpFile.position() + rowPadding);
}
bmpFile.close();
}
pico2_st7796_slideshow.ino
/*
Exercise on Raspberry Pi Pico 2,
run in Arduino framework using board of arduino-pico by earlephilhower
(named Raspberry Pi Pico/RP2040/RP2350 in Arduino IDE Boards Manager).
Display bmp on 4.0inch Capacitive SPI Module ST7796 using TFT_eSPI library, in slideahow form.
In-between drawing bmp, you can touch screen to check the touch detection.
This exercise ensure all three parts (ST7796, SD and FT6336U cap. touch) work.
The testing images are 426*320, RGB888, .bmp.
Converted using Python in:
https://coxxect.blogspot.com/2024/11/resize-jpg-and-convert-to-bmp-in-rgb888.html
The bmp draw in pixel-by-pixel using drawPixel(), more than 5 seconds to read and display a 426*320 bmp.
FT6336U is accessed using Wire (I2C) directly, without using library.
*/
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <TFT_eSPI.h> // Hardware-specific library
#include <LinkedList.h> // Have to install "LinkedList" in Library Manager
#define SD_CS 15
#define CTP_RST 14 // option, can connect to 3V3.
#define FT6336U_ADDR 0x38
#define TFT_WIDTH 320
#define TFT_HEIGHT 480
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
unsigned long nextTime;
const unsigned long duration = 5000;
LinkedList<String> bmpFiles;
String images_folder = "/images"; // target images directory in SD
int image_index = 0;
void setup() {
delay(500);
Serial.begin(115200);
delay(1000);
Serial.println("--- Start ---");
// default SDA = 4
// default SCL = 5
Serial.println("SDA " + String(SDA));
Serial.println("SCL " + String(SCL));
Wire.begin(); // I2C
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
SPI.begin();
// Hardware Reset ST7796 at power up
// try to fix sometimes screen blank.
Serial.println("Hardware Reset on TFT_RST: " + String(TFT_RST));
pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, HIGH);
delay(100);
digitalWrite(TFT_RST, LOW);
delay(100);
digitalWrite(TFT_RST, HIGH);
delay(100);
// Optional CTS_RST
// In my test, CTS_RST can be connect to 3V3.
Serial.println("Hardware Reset on CTP_RST: ");
pinMode(CTP_RST, OUTPUT);
digitalWrite(CTP_RST, HIGH);
delay(100);
digitalWrite(CTP_RST, LOW);
delay(100);
digitalWrite(CTP_RST, HIGH);
delay(100);
tft.init();
tft.setRotation(1);
tft.init();
tft.setRotation(1);
Serial.println("TFT_WIDTH x TFT_HEIGHT = " + String(TFT_WIDTH) + " x " + String(TFT_HEIGHT));
Serial.println("tft.width() x tft.height() = " + String(tft.width()) + " x " + String(tft.height()));
tft.fillScreen(TFT_BLACK);
tft.drawRect(0, 0, tft.width(), tft.height(), TFT_GREEN);
// Set "cursor" at top left corner of display (0,0) and select font 2
tft.setCursor(0, 0, 2);
//init SD
Serial.println("Initialize SD");
tft.println("Initialize SD");
while (!SD.begin(SD_CS)) {
Serial.println("Fail!");
tft.println("Fail!");
delay(1000);
}
Serial.println("Success");
tft.println("Success");
listBmpFiles();
sortBmpFiles();
for (int i=0; i<bmpFiles.size(); i++){
Serial.println(" " + String(i) + " : " + bmpFiles.get(i));
tft.println(" " + String(i) + " : " + bmpFiles.get(i));
}
nextTime = millis() + 1000; // list bmp files on screen for 1 second
}
void loop() {
if (millis() > nextTime) {
tft.fillScreen(TFT_BLACK);
String a = images_folder + "/" + bmpFiles.get(image_index);
unsigned long begin_drawBmp = millis();
drawBmp(a, 0, 0);
unsigned long end_drawBmp = millis();
Serial.println("in " + String(end_drawBmp-begin_drawBmp) + " ms");
image_index++;
if (image_index==bmpFiles.size()){
image_index = 0;
}
nextTime = millis() + duration;
} else {
if (get_touch_count() > 0) {
int x, y;
get_touch_point(&x, &y);
Serial.print(x);
Serial.print(" : ");
Serial.println(y);
tft.fillCircle(x, y, 3, TFT_WHITE);
}
}
}
void listBmpFiles(){
File dir = SD.open(images_folder);
if(!dir){
Serial.println("Cannot open " + images_folder);
return;
}
while (true){
File file = dir.openNextFile();
if (!file) break; // no more file
String filename = String(file.name());
if (filename.endsWith(".bmp")){
bmpFiles.add(filename);
}
file.close();
}
Serial.println(String(bmpFiles.size()) + " bmp files:");
tft.println(String(bmpFiles.size()) + " bmp files:");
}
void sortBmpFiles() {
int n = bmpFiles.size();
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (bmpFiles.get(j) > bmpFiles.get(j + 1)) {
// Swap elements
String temp = bmpFiles.get(j);
bmpFiles.set(j, bmpFiles.get(j + 1));
bmpFiles.set(j + 1, temp);
}
}
}
}
void drawBmp(String filename, int16_t x, int16_t y) {
Serial.println("drawBmp(): " + filename);
File bmpFile;
uint8_t bmpHeader[54];
uint32_t dataOffset, imageWidth, imageHeight;
uint16_t rowPadding;
uint16_t pixel;
// Open the BMP file
bmpFile = SD.open(filename);
if (!bmpFile) {
Serial.println("Failed to open BMP file");
return;
}
// Read the BMP file header
bmpFile.read(bmpHeader, 54);
// Check for BMP signature ("BM")
if (bmpHeader[0] != 'B' || bmpHeader[1] != 'M') {
Serial.println("Not a valid BMP file");
bmpFile.close();
return;
}
// Get image dimensions
dataOffset = *(uint32_t *)&bmpHeader[10];
imageWidth = *(uint32_t *)&bmpHeader[18];
imageHeight = *(uint32_t *)&bmpHeader[22];
rowPadding = (4 - (imageWidth * 3) % 4) % 4;
// Move to image data start
bmpFile.seek(dataOffset);
// Draw the BMP
for (int16_t row = imageHeight - 1; row >= 0; row--) { // BMPs are stored bottom-up
for (int16_t col = 0; col < imageWidth; col++) {
uint8_t b = bmpFile.read();
uint8_t g = bmpFile.read();
uint8_t r = bmpFile.read();
pixel = tft.color565(r, g, b);
tft.drawPixel(x + col, y + row, pixel);
}
// Skip row padding
bmpFile.seek(bmpFile.position() + rowPadding);
}
bmpFile.close();
}
int get_touch_count() {
// Register 0x02
// Touch count, max 2.
Wire.beginTransmission(FT6336U_ADDR);
Wire.write(0x02);
Wire.endTransmission();
Wire.requestFrom(FT6336U_ADDR, 1);
return (Wire.read());
}
// Read x, y
// May be have to exchange/adjust x, y according to screen rotation.
void get_touch_point(int *x, int *y) {
// Read X:
// Register 0x03
// bit7-bit6 Touch event of the 1st touch point
// bit3-bit0 Hight 4 bit of the 1st touch point
// Register 0x04
// Low 8 bit of the 1st touch point
Wire.beginTransmission(FT6336U_ADDR);
Wire.write(0x03);
Wire.endTransmission();
Wire.requestFrom(FT6336U_ADDR, 2);
*y = (Wire.read() & 0x0f) << 8 | Wire.read();
*y = TFT_WIDTH - *y; // adjust depends on screen rotation
// Read Y:
// Register 0x05
// bit7-bit6 ID of the 1st touch point
// bit3-bit0 Hight 4 bit of the 1st touch point
// Register 0x06
// Low 8 bit of the 1st touch point
Wire.beginTransmission(FT6336U_ADDR);
Wire.write(0x05);
Wire.endTransmission();
Wire.requestFrom(FT6336U_ADDR, 2);
*x = (Wire.read() & 0x0f) << 8 | Wire.read();
}
pico2_st7796_slideshow_touch.ino
/*
Exercise on Raspberry Pi Pico 2,
run in Arduino framework using board of arduino-pico by earlephilhower
(named Raspberry Pi Pico/RP2040/RP2350 in Arduino IDE Boards Manager).
Display bmp on 4.0inch Capacitive SPI Module ST7796 using TFT_eSPI library.
After bmp drawn, touch left 1/3 of the screen to switch to previous bmp, or right 1/3 to switch to next bmp.
This exercise ensure all three parts (ST7796, SD and FT6336U cap. touch) work.
The testing images are 426*320, RGB888, .bmp.
Converted using Python in:
https://coxxect.blogspot.com/2024/11/resize-jpg-and-convert-to-bmp-in-rgb888.html
The bmp are read in 3 bytes (one pixel) together, and display in row-by-row using pushImage().
About 2.x seconds to read and display a 426*320 bmp.
FT6336U is accessed using Wire (I2C) directly, without using library.
*/
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <TFT_eSPI.h> // Hardware-specific library
#include <LinkedList.h> // Have to install "LinkedList" in Library Manager
#define SD_CS 15
#define CTP_RST 14 // option, can connect to 3V3.
#define FT6336U_ADDR 0x38
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
LinkedList<String> bmpFiles;
String images_folder = "/images"; // target images directory in SD
int image_index = 0;
bool request_to_draw;
void setup() {
delay(500);
Serial.begin(115200);
delay(1000);
Serial.println("--- Start ---");
// default SDA = 4
// default SCL = 5
Serial.println("SDA " + String(SDA));
Serial.println("SCL " + String(SCL));
Wire.begin(); // I2C
pinMode(SD_CS, OUTPUT);
digitalWrite(SD_CS, HIGH);
SPI.begin();
// Hardware Reset ST7796 at power up
// try to fix sometimes screen blank.
Serial.println("Hardware Reset on TFT_RST: " + String(TFT_RST));
pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, HIGH);
delay(100);
digitalWrite(TFT_RST, LOW);
delay(100);
digitalWrite(TFT_RST, HIGH);
delay(100);
// Optional CTS_RST
// In my test, CTS_RST can be connect to 3V3.
Serial.println("Hardware Reset on CTP_RST: ");
pinMode(CTP_RST, OUTPUT);
digitalWrite(CTP_RST, HIGH);
delay(100);
digitalWrite(CTP_RST, LOW);
delay(100);
digitalWrite(CTP_RST, HIGH);
delay(100);
tft.init();
tft.setRotation(1);
Serial.println("TFT_WIDTH x TFT_HEIGHT = " + String(TFT_WIDTH) + " x " + String(TFT_HEIGHT));
Serial.println("tft.width() x tft.height() = " + String(tft.width()) + " x " + String(tft.height()));
tft.fillScreen(TFT_BLACK);
tft.drawRect(0, 0, tft.width(), tft.height(), TFT_GREEN);
// Set "cursor" at top left corner of display (0,0) and select font 4
tft.setCursor(0, 0, 2);
//init SD
Serial.println("Initialize SD");
tft.println("Initialize SD");
while (!SD.begin(SD_CS)) {
Serial.println("Fail!");
tft.println("Fail!");
delay(1000);
}
Serial.println("Success");
tft.println("Success");
listBmpFiles();
sortBmpFiles();
for (int i=0; i<bmpFiles.size(); i++){
Serial.println(" " + String(i) + " : " + bmpFiles.get(i));
tft.println(" " + String(i) + " : " + bmpFiles.get(i));
}
delay(1000);
request_to_draw = true;
}
void loop() {
if (request_to_draw){
tft.fillScreen(TFT_BLACK);
String a = images_folder + "/" + bmpFiles.get(image_index);
unsigned long begin_drawBmp = millis();
drawBmp(a, 0, 0);
unsigned long end_drawBmp = millis();
Serial.println("in " + String(end_drawBmp-begin_drawBmp) + " ms");
request_to_draw = false;
}
if (get_touch_count() > 0) {
int x, y;
get_touch_point(&x, &y);
if (x<=tft.width()/3){
Serial.println("<< Previous");
image_index--;
if (image_index==-1){
image_index = bmpFiles.size()-1;
}
request_to_draw = true;
}else if (x>=tft.width()*2/3){
Serial.println(">> Next");
image_index++;
if (image_index==bmpFiles.size()){
image_index = 0;
}
request_to_draw = true;
}else{
delay(100);
}
}else{
delay(100);
}
}
void listBmpFiles(){
File dir = SD.open(images_folder);
if(!dir){
Serial.println("Cannot open " + images_folder);
return;
}
while (true){
File file = dir.openNextFile();
if (!file) break; // no more file
String filename = String(file.name());
if (filename.endsWith(".bmp")){
bmpFiles.add(filename);
}
file.close();
}
Serial.println(String(bmpFiles.size()) + " bmp files:");
tft.println(String(bmpFiles.size()) + " bmp files:");
}
void sortBmpFiles() {
int n = bmpFiles.size();
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (bmpFiles.get(j) > bmpFiles.get(j + 1)) {
// Swap elements
String temp = bmpFiles.get(j);
bmpFiles.set(j, bmpFiles.get(j + 1));
bmpFiles.set(j + 1, temp);
}
}
}
}
//Draw bmp, row-by-row
void drawBmp(String filename, int16_t x, int16_t y) {
Serial.println("drawBmp() row-by-row: " + filename);
File bmpFile;
uint8_t bmpHeader[54];
uint32_t dataOffset, imageWidth, imageHeight;
uint16_t rowPadding;
// Open the BMP file
bmpFile = SD.open(filename);
if (!bmpFile) {
Serial.println("Failed to open BMP file");
return;
}
// Read the BMP file header
bmpFile.read(bmpHeader, 54);
// Check for BMP signature ("BM")
if (bmpHeader[0] != 'B' || bmpHeader[1] != 'M') {
Serial.println("Not a valid BMP file");
bmpFile.close();
return;
}
// Get image dimensions
dataOffset = *(uint32_t *)&bmpHeader[10];
imageWidth = *(uint32_t *)&bmpHeader[18];
imageHeight = *(uint32_t *)&bmpHeader[22];
rowPadding = (4 - (imageWidth * 3) % 4) % 4;
// Move to image data start
bmpFile.seek(dataOffset);
uint16_t pixelBuffer[imageWidth];
// draw row-by-row
for (int16_t row = imageHeight - 1; row >= 0; row--) { // in reverse order
for (int16_t col = 0; col < imageWidth; col++) {
uint8_t pixelData[3];
bmpFile.read(pixelData, 3); // Read 3 bytes at a time
uint16_t value = tft.color565(pixelData[2], pixelData[1], pixelData[0]);
pixelBuffer[col] = (value>>8) | (value<<8);
}
// Skip row padding
bmpFile.seek(bmpFile.position() + rowPadding);
// draw a whole row using pushImage()
tft.pushImage(x, y + row, imageWidth, 1, pixelBuffer);
}
bmpFile.close();
}
/*
//Draw bmp, pixel-by-pixel
void drawBmp(String filename, int16_t x, int16_t y) {
Serial.println("drawBmp() pixel-by-pixel: " + filename);
File bmpFile;
uint8_t bmpHeader[54];
uint32_t dataOffset, imageWidth, imageHeight;
uint16_t rowPadding;
uint16_t pixel;
// Open the BMP file
bmpFile = SD.open(filename);
if (!bmpFile) {
Serial.println("Failed to open BMP file");
return;
}
// Read the BMP file header
bmpFile.read(bmpHeader, 54);
// Check for BMP signature ("BM")
if (bmpHeader[0] != 'B' || bmpHeader[1] != 'M') {
Serial.println("Not a valid BMP file");
bmpFile.close();
return;
}
// Get image dimensions
dataOffset = *(uint32_t *)&bmpHeader[10];
imageWidth = *(uint32_t *)&bmpHeader[18];
imageHeight = *(uint32_t *)&bmpHeader[22];
rowPadding = (4 - (imageWidth * 3) % 4) % 4;
// Move to image data start
bmpFile.seek(dataOffset);
// Draw the BMP
for (int16_t row = imageHeight - 1; row >= 0; row--) { // BMPs are stored bottom-up
for (int16_t col = 0; col < imageWidth; col++) {
uint8_t b = bmpFile.read();
uint8_t g = bmpFile.read();
uint8_t r = bmpFile.read();
pixel = tft.color565(r, g, b);
tft.drawPixel(x + col, y + row, pixel);
}
// Skip row padding
bmpFile.seek(bmpFile.position() + rowPadding);
}
bmpFile.close();
}
*/
int get_touch_count() {
// Register 0x02
// Touch count, max 2.
Wire.beginTransmission(FT6336U_ADDR);
Wire.write(0x02);
Wire.endTransmission();
Wire.requestFrom(FT6336U_ADDR, 1);
return (Wire.read());
}
// Read x, y
// May be have to exchange/adjust x, y according to screen rotation.
void get_touch_point(int *x, int *y) {
// Read X:
// Register 0x03
// bit7-bit6 Touch event of the 1st touch point
// bit3-bit0 Hight 4 bit of the 1st touch point
// Register 0x04
// Low 8 bit of the 1st touch point
Wire.beginTransmission(FT6336U_ADDR);
Wire.write(0x03);
Wire.endTransmission();
Wire.requestFrom(FT6336U_ADDR, 2);
*y = (Wire.read() & 0x0f) << 8 | Wire.read();
*y = TFT_HEIGHT - *y; // adjust depends on screen rotation
// Read Y:
// Register 0x05
// bit7-bit6 ID of the 1st touch point
// bit3-bit0 Hight 4 bit of the 1st touch point
// Register 0x06
// Low 8 bit of the 1st touch point
Wire.beginTransmission(FT6336U_ADDR);
Wire.write(0x05);
Wire.endTransmission();
Wire.requestFrom(FT6336U_ADDR, 2);
*x = (Wire.read() & 0x0f) << 8 | Wire.read();
}
Next:
~ LVGL on Raspberry Pi Pico 2 (Arduino framework/arduino-pico) with 320x480 TFT SPI ST7796 + FT6336U Capacitive Touch
Comments
Post a Comment