I'm working on a project which uses a Elegoo 2.8" 240x320 TFT LCD display hardwired (breakout) to a Mega2560 Pro (mini) board. Everything works as expected, but the bmp image display draws extremely slowly on the screen, taking about 21 seconds to reveal, every time. My project displays several lines of text over top of the image, and also drives a 24 LED NeoPixel ring, which all work perfectly. I load the BMP upon power up as a background image one time, which takes 21 seconds, then everything works with very good speed thereafter. I've stripped my code down to only include the necessary lines to load and display the BMP. It's pretty much the example code which came with the screen. Are there any obvious errors or changes I can make to improve the drawing speed of the image? Here is my code:
//External Libraries to Include
#include <Elegoo_TFTLCD.h> // Hardware-specific library
#include <SD.h> // SD Card library
//LCD Screen Settings
#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0
#define PIN_SD_CS 53 // Elegoo SD shields and modules: pin 53
#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
// ************ LCD Screen Setup ************************
Elegoo_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
// If using the shield, all control and data lines are fixed, and
// a simpler declaration can optionally be used:
// Elegoo_TFTLCD tft;
#define MAX_BMP 10 // bmp file num
#define FILENAME_LEN 20 // max file name length
const int __Gnbmp_height = 320; // bmp hight
const int __Gnbmp_width = 240; // bmp width
unsigned char __Gnbmp_image_offset = 0; // offset
int __Gnfile_num = 1; // num of file
char __Gsbmp_files[1][FILENAME_LEN] = // add file name here
{
"Freddie3.bmp"
};
File bmpFile;
#define BUFFPIXEL 60 // must be a divisor of 240
#define BUFFPIXEL_X3 180 // BUFFPIXELx3
// Assign human-readable names to some common 16-bit color values:
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
bool imgDisp = true; //Flag to display (true) or hide (false) background image
void setup() {
Serial.begin(9600);
//Load Image
tft.reset();
uint16_t identifier = 0x9341;
tft.begin(identifier);
tft.fillScreen(BLACK); //Blackout screen
//Init SD_Card
pinMode(53, OUTPUT);
if (!SD.begin(53)) {
Serial.println("SD Initialization Failed!");
tft.setCursor(120, 10);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.println("SD Card Init fail.");
}else
Serial.println("SD Initialization Success");
for(unsigned char i=0; i<__Gnfile_num; i++) {
bmpFile = SD.open(__Gsbmp_files[i]);
if (! bmpFile) {
Serial.println("Didn't Find BMP Image");
tft.setTextColor(WHITE); tft.setTextSize(1);
tft.println("Didn't Find BMP Image");
while (1);
}
if(! bmpReadHeader(bmpFile)) {
Serial.println("Bad BMP Image");
tft.setTextColor(WHITE); tft.setTextSize(1);
tft.println("Bad BMP Image");
return;
}
if(imgDisp == true){
tft.setRotation(0); //Set screen orientation for BMP
bmpdraw(bmpFile, 0, 0);
bmpFile.close();
}
}
}
void loop() {
}
void bmpdraw(File f, int x, int y)
{
bmpFile.seek(__Gnbmp_image_offset);
uint32_t time = millis();
uint8_t sdbuffer[BUFFPIXEL_X3]; // 3 * pixels to buffer
for (int i=0; i< __Gnbmp_height; i++) {
for(int j=0; j<(240/BUFFPIXEL); j++) {
bmpFile.read(sdbuffer, BUFFPIXEL_X3);
uint8_t buffidx = 0;
int offset_x = j*BUFFPIXEL;
unsigned int __color[BUFFPIXEL];
for(int k=0; k<BUFFPIXEL; k++) {
__color[k] = sdbuffer[buffidx+2]>>3; // read
__color[k] = __color[k]<<6 | (sdbuffer[buffidx+1]>>2); // green
__color[k] = __color[k]<<5 | (sdbuffer[buffidx+0]>>3); // blue
buffidx += 3;
}
for (int m = 0; m < BUFFPIXEL; m ++) {
tft.drawPixel(m+offset_x, i,__color[m]);
}
}
}
// Serial.print(millis() - time, DEC);
// Serial.println(" ms");
}
boolean bmpReadHeader(File f)
{
// read header
uint32_t tmp;
uint8_t bmpDepth;
if (read16(f) != 0x4D42) {
// magic bytes missing
return false;
}
// read file size
tmp = read32(f);
// Serial.print("size 0x");
// Serial.println(tmp, HEX);
// read and ignore creator bytes
read32(f);
__Gnbmp_image_offset = read32(f);
// Serial.print("offset ");
// Serial.println(__Gnbmp_image_offset, DEC);
// read DIB header
tmp = read32(f);
// Serial.print("header size ");
// Serial.println(tmp, DEC);
int bmp_width = read32(f);
int bmp_height = read32(f);
if(bmp_width != __Gnbmp_width || bmp_height != __Gnbmp_height) { // if image is not 320x240, return false
return false;
}
if (read16(f) != 1)
return false;
bmpDepth = read16(f);
// Serial.print("bitdepth ");
// Serial.println(bmpDepth, DEC);
if (read32(f) != 0) {
// compression not supported!
return false;
}
// Serial.print("compression ");
// Serial.println(tmp, DEC);
return true;
}
/*********************************************/
// These read data from the SD card file and convert them to big endian
// (the data is stored in little endian format!)
// LITTLE ENDIAN!
uint16_t read16(File f)
{
uint16_t d;
uint8_t b;
b = f.read();
d = f.read();
d <<= 8;
d |= b;
return d;
}
// LITTLE ENDIAN!
uint32_t read32(File f)
{
uint32_t d;
uint16_t b;
b = read16(f);
d = read16(f);
d <<= 16;
d |= b;
return d;
}