Viewing images from SD card on 3.2inch tft display connected to arduino uno

Im using on-shield display (see picture in att., only difference is my has IC HX8352A instead of B) connected to UNO and trying to view images stored on the SD card. After downloading dozen libraries and trying to upload any code so that I dont have to look at the white screen anymore I found out that example codes from MCUFRIEND_kbv library works. Still haven't figured out the code for viewing the images from the SD card after trying some examples from projects that work on similar lcds.
Any idea whats the deal with this lcd?

tft-3-2-b.jpg

It should work just fine. The microSD is connected to the 3x2 SPI header. So it should work with regular SD.h on Uno, Mega, Leonardo, ...

The regular Mcufriend Shields map the microSD to 10-13. This is fine for a Uno because the hardware SPI is on 10-13.
If you use Mega you have to do Software SPI on 10-13 with a third party SdFat.h library.

David.

It works fine of some example codes such as button_simple and other, but I cant find any valid code for viewing image from SD card on the screen.

Shirley showBMP_Uno_kbv will work because it uses 3x2 SPI header. You just have to change SD_CS to 5 instead of 10.

I have a HX8352-B Open-Smart. So I can try it on Uno, Mega, Due.

David.

Here is the code I found in example you mentioned. I commented lines with SD_CS 10 and just left 5. Now the screen turns from white to blue and still no images are shown on the screen, but on serial monitor it lists the images that are on the SD card but it doesent show them on the screen.

P.S. I tried to paste the code in the post but it was too long so Ill send .ino file in the attachment.

showBMP_kbv_Uno_p1.ino (9.51 KB)

No, I have not looked at your INO.

I have attached an example sketch. I have added a line to change rotation to match the .BMP
But the important change is to insert a RESTORE_SPI_GPIO() macro after an SD/File operation and before a tft operation.

// OPEN-SMART boards share the TFT data bus with SPI on 10, 11, 13
// SD.h always configures SPI for each call.
// SD.h does not turn SPI off when it has finished the call.
// Chan's fatFS (on which SD.h is based) did turn SPI on and off as required.
// You can disable this macro on a Mega because SPI is not shared
#define RESTORE_SPI_GPIO() SPCR = 0
...
#define SD_CS     5 //10         //Use 5 for OPEN-SMART Shields 
...
        tft.setRotation(w > h ? 1 : 0);   //PORTRAIT or LANDSCAPE
...
    bmpFile.close();
    RESTORE_SPI_GPIO();
...

David.

showBMP_OpenSmart.ino (9.84 KB)

It worked this time. Thanks for the help. Karma going 2up :slight_smile:

One more question:
Since the lcd shield takes all of the pins from UNO board my question is does it really need all of the pins to work and if not can I use those pins that it doesent need to put up a sensor that will change the images on the screen depending on the state? Do I have to remove the pins that I use for the sensor from the lcd shield so that they don't go in the UNO if it influences the work of the display or can I just use those pins with display injected in them if it wont interfere with its work? For example I see that on lcd shield pins D2 and D3 from Arduino UNO aren't mentioned so I presume that lcd shield doesent need them to work?

It is a fact of life. The Uno does not have many GPIO pins.

Mcufriend Shields use 2-9, A0-A4 for TFT. 10-13 for SD. 0-1 for Serial. A5 is available e.g. CS for a second SPI.

Open-Smart Shields use 4,6,7,8,9,10,11,13, A0-A3 for TFT. 5,11-13 for SD. 0-1 for Serial. 2,3, A4,A5 are available e.g. 4 CS or 2 CS + multiple I2C or 2 INT + multiple I2C

You can use A5 (and A4) for ADC if you don't use I2C
If you have a SMD clone, you have A6, A7 as additional ADC pins.

Open-Smart comes with an LM75 chip with pullups. So A4, A5 are not really available for ADC.
Quite honestly. What is the point of an LM75? You could read the internal Temperature Sensor on the ATmega328P. Not accurate.

David.

So there are no pins available on my UNO board? I need 2 digital pins. Don't want to read from on-board temp sensor, but rather external sensor that is not even for temperature, has 2 outputs that give logical 0 or 1 so it has 4 different states : 0 0, 0 1, 1 0, 1 1. I want to change pictures based on what state sensor gives to the board.

You are only using the TFT and the SD. You could use 2, 3, A4, A5 for digital GPIO.

You could remove the LM75 if you want. But it is pretty unlikely that your external device sends valid I2C signals on A4, A5 that wake up the LM75. 2,3 have no conflicts.

The Touch Panel on the TFT does not use any extra GPIO pins.

David.

Yeah thanks Ive deleted some parts of the code for lcd cause it kept cruising through all of the pictures on the SD card so Ive removed parts that I thought were doing that and the part that kept loading image all the time cause I don't need it to be loaded every second I just need it to be loaded while the state from the sensor is the same.
My problem now is that sensor just reads the state one time and picture is just loaded 1 time depending ont he state of the sensor. It doesent iterate in void loop for some reason.

#define RESTORE_SPI_GPIO() SPCR = 0

#include <SPI.h>            

#include <SD.h>             

#include <Adafruit_GFX.h>   
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#if defined(ESP32) 
#define SD_CS     5
#else
#define SD_CS     5 //10          
#endif
#define NAMEMATCH1 "green.bmp"        
#define NAMEMATCH2 "yellow.bmp"
#define NAMEMATCH3 "red.bmp"

#define PALETTEDEPTH   0     


char namebuf[32] = "/";   
//char namebuf[32] = "/bitmaps/";  

File root;
int pathlen;
int A = 2;
int B = 3;

void setup()
{
    uint16_t ID;
    Serial.begin(9600);
    Serial.print("Show BMP files on TFT with ID:0x");
    ID = tft.readID();
    Serial.println(ID, HEX);
    if (ID == 0x0D3D3) ID = 0x9481;
    tft.begin(ID);
    tft.fillScreen(0x001F);
    tft.setTextColor(0xFFFF, 0x0000);
    bool good = SD.begin(SD_CS);
    if (!good) {
        Serial.print(F("cannot start SD"));
        while (1);
    }
    root = SD.open(namebuf);
    pathlen = strlen(namebuf);
    pinMode (A, INPUT);
    pinMode (B, INPUT);
}

void loop()
{
    char *nm = namebuf + pathlen;
    File f = root.openNextFile();
    uint8_t ret;
    uint32_t start;
    if (f != NULL) {
#ifdef USE_SDFAT
        f.getName(nm, 32 - pathlen);
#else
        strcpy(nm, (char *)f.name());
#endif
        f.close();
        RESTORE_SPI_GPIO();
        strlwr(nm);

        int a = digitalRead(A);
        int b = digitalRead(B);
        Serial.println("Vrijednost A:");
        Serial.println(a);
        Serial.println("Vrijednost B:");
        Serial.println(b);
        
        
        if(a==LOW && b==LOW){
        if (strstr(nm, ".bmp") != NULL && strstr(nm, NAMEMATCH1) != NULL) {
            Serial.print(namebuf);
            //Serial.print(F(" - "));
            tft.fillScreen(0);
            //start = millis();
            ret = showBMP(namebuf, 5, 5);
           
        }}
        
        if(a==LOW && b==HIGH) {
        if (strstr(nm, ".bmp") != NULL && strstr(nm, NAMEMATCH2) != NULL) {
            Serial.print(namebuf);
            //Serial.print(F(" - "));
            tft.fillScreen(0);
            //start = millis();
            ret = showBMP(namebuf, 5, 5);
           
        }}

        if(a==HIGH && b==LOW) {
        if (strstr(nm, ".bmp") != NULL && strstr(nm, NAMEMATCH2) != NULL) {
            Serial.print(namebuf);
            //Serial.print(F(" - "));
            tft.fillScreen(0);
            //start = millis();
            ret = showBMP(namebuf, 5, 5);
           
        }}
        
        if(a==HIGH && b==HIGH){
        if (strstr(nm, ".bmp") != NULL && strstr(nm, NAMEMATCH3) != NULL) {
            Serial.print(namebuf);
            //Serial.print(F(" - "));
            tft.fillScreen(0);
            //start = millis();
            ret = showBMP(namebuf, 5, 5);
           
        }}
    }
    
}

#define BMPIMAGEOFFSET 54

#define BUFFPIXEL      20

uint16_t read16(File& f) {
    uint16_t result;         
    f.read((uint8_t*)&result, sizeof(result));
    return result;
}

uint32_t read32(File& f) {
    uint32_t result;
    f.read((uint8_t*)&result, sizeof(result));
    return result;
}

uint8_t showBMP(char *nm, int x, int y)
{
    File bmpFile;
    int bmpWidth, bmpHeight;    
    uint8_t bmpDepth;           
    uint32_t bmpImageoffset;    
    uint32_t rowSize;           
    uint8_t sdbuffer[3 * BUFFPIXEL];    
    uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
    uint8_t bitmask, bitshift;
    boolean flip = true;        
    int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
    uint32_t pos;               
    boolean is565 = false;      

    uint16_t bmpID;
    uint16_t n;                 
    uint8_t ret;

    if ((x >= tft.width()) || (y >= tft.height()))
        return 1;               // off screen

    bmpFile = SD.open(nm);      
    bmpID = read16(bmpFile);    
    (void) read32(bmpFile);     
    (void) read32(bmpFile);     
    bmpImageoffset = read32(bmpFile);      
    (void) read32(bmpFile);     
    bmpWidth = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    n = read16(bmpFile);        
    bmpDepth = read16(bmpFile); 
    pos = read32(bmpFile);     
    if (bmpID != 0x4D42) ret = 2; 
    else if (n != 1) ret = 3;  
    else if (pos != 0 && pos != 3) ret = 4; 
    else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5;
    else {
        bool first = true;
        is565 = (pos == 3);             
        
        rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
        if (bmpHeight < 0) {             
            bmpHeight = -bmpHeight;
            flip = false;
        }

        w = bmpWidth;
        h = bmpHeight;
        RESTORE_SPI_GPIO();
        tft.setRotation(w > h ? 1 : 0);   
        if ((x + w) >= tft.width())      
            w = tft.width() - x;
        if ((y + h) >= tft.height())     
            h = tft.height() - y;

        if (bmpDepth <= PALETTEDEPTH) {  
            bmpFile.seek(BMPIMAGEOFFSET); 
            bitmask = 0xFF;
            if (bmpDepth < 8)
                bitmask >>= bmpDepth;
            bitshift = 8 - bmpDepth;
            n = 1 << bmpDepth;
            lcdbufsiz -= n;
            palette = lcdbuffer + lcdbufsiz;
            for (col = 0; col < n; col++) {
                pos = read32(bmpFile);    
                palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);
            }
        }

        RESTORE_SPI_GPIO();
        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
        for (row = 0; row < h; row++) {
            
            uint8_t r, g, b, *sdptr;
            int lcdidx, lcdleft;
            if (flip)   
                pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
            else      
                pos = bmpImageoffset + row * rowSize;
            if (bmpFile.position() != pos) { 
                bmpFile.seek(pos);
                buffidx = sizeof(sdbuffer); 
            }

            for (col = 0; col < w; ) {  
                lcdleft = w - col;
                if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
                for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { 
                    uint16_t color;
                    
                    if (buffidx >= sizeof(sdbuffer)) { 
                        bmpFile.read(sdbuffer, sizeof(sdbuffer));
                        buffidx = 0; 
                        r = 0;
                    }
                    switch (bmpDepth) {       
                        case 24:
                            b = sdbuffer[buffidx++];
                            g = sdbuffer[buffidx++];
                            r = sdbuffer[buffidx++];
                            color = tft.color565(r, g, b);
                            break;
                        case 16:
                            b = sdbuffer[buffidx++];
                            r = sdbuffer[buffidx++];
                            if (is565)
                                color = (r << 8) | (b);
                            else
                                color = (r << 9) | ((b & 0xE0) << 1) | (b & 0x1F);
                            break;
                        case 1:
                        case 4:
                        case 8:
                            if (r == 0)
                                b = sdbuffer[buffidx++], r = 8;
                            color = palette[(b >> bitshift) & bitmask];
                            r -= bmpDepth;
                            b <<= bmpDepth;
                            break;
                    }
                    lcdbuffer[lcdidx] = color;

                }
                RESTORE_SPI_GPIO();
                tft.pushColors(lcdbuffer, lcdidx, first);
                first = false;
                col += lcdidx;
            }           
        }               
        tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1);
        ret = 0;        
    }
    bmpFile.close();
    RESTORE_SPI_GPIO();
  return (ret);
}

There are several ways to do your sketch e.g.

File root;
int pathlen;
int A = 2;
int B = 3;

void setup()
{
    uint16_t ID;
    Serial.begin(9600);
    Serial.print("Show BMP files on TFT with ID:0x");
    ID = tft.readID();
    Serial.println(ID, HEX);
    if (ID == 0x0D3D3) ID = 0x9481;
    tft.begin(ID);
    tft.fillScreen(0x001F);
    tft.setTextColor(0xFFFF, 0x0000);
    bool good = SD.begin(SD_CS);
    if (!good) {
        Serial.print(F("cannot start SD"));
        while (1);
    }
    root = SD.open(namebuf);
    pathlen = strlen(namebuf);
    pinMode (A, INPUT_PULLUP);
    pinMode (B, INPUT_PULLUP);
}

void loop()
{
    uint8_t ret;
    static int oldstate = -1;
    int state = digitalRead(A) + digitalRead(B) * 2;
    if (state == oldstate) return;   //state has not changed.
    switch (state) {
        case 1: ret = showBMP("green.bmp", 0, 0); break;
        case 2: ret = showBMP("yellow.bmp", 0, 0); break;
        case 3: ret = showBMP("red.bmp", 0, 0); break;
    }
    oldstate = state;
}

Obviously it is wise to report the return value.
You could just select the name in the switch block.

If you mix TFT and SD calls you should insert the RESTORE_SPI_GPIO() macro.

David.

#define RESTORE_SPI_GPIO() SPCR = 0
#include <SPI.h>            
#include <SD.h>             
#include <Adafruit_GFX.h>   
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#if defined(ESP32) 
#define SD_CS     5
#else
#define SD_CS     5 //10          
#endif


#define PALETTEDEPTH   0     


char namebuf[32] = "/";   
File root;
int pathlen;
int A = 2;
int B = 3;

void setup()
{
    uint16_t ID;
    Serial.begin(9600);
    Serial.print("Show BMP files on TFT with ID:0x");
    ID = tft.readID();
    Serial.println(ID, HEX);
    if (ID == 0x0D3D3) ID = 0x9481;
    tft.begin(ID);
    ft.fillScreen(0x001F);
    tft.setTextColor(0xFFFF, 0x0000);
    bool good = SD.begin(SD_CS);
    if (!good) {
        Serial.print(F("cannot start SD"));
        while (1);
    }
    root = SD.open(namebuf);
    pathlen = strlen(namebuf);
    Serial.println(namebuf);
    pinMode (A, INPUT);
    pinMode (B, INPUT);
}

void loop()
{
    uint8_t ret;
    static int oldstate = -1;
    int state = digitalRead(A) + digitalRead(B) * 2;
    if (state == oldstate) return;   //state has not changed.
    
    switch (state) {
        case 0: ret = showBMP("green.bmp", 5, 5); Serial.println("case0"); break;
        case 1: ret = showBMP("yellow.bmp", 5, 5); Serial.println("case1"); break;
        case 2: ret = showBMP("yellow.bmp", 5, 5); Serial.println("case2"); break;
        case 3: ret = showBMP("red.bmp", 5, 5); Serial.println("case3"); break;
    }
    oldstate = state;
}

#define BMPIMAGEOFFSET 54

#define BUFFPIXEL      20

uint16_t read16(File& f) {
    uint16_t result;         
    f.read((uint8_t*)&result, sizeof(result));
    return result;
}

uint32_t read32(File& f) {
    uint32_t result;
    f.read((uint8_t*)&result, sizeof(result));
    return result;
}

uint8_t showBMP(char *nm, int x, int y)
{
    File bmpFile;
    int bmpWidth, bmpHeight;    
    uint8_t bmpDepth;           
    uint32_t bmpImageoffset;    
    uint32_t rowSize;           
    uint8_t sdbuffer[3 * BUFFPIXEL];    
    uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
    uint8_t bitmask, bitshift;
    boolean flip = true;        
    int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
    uint32_t pos;               
    boolean is565 = false;      

    uint16_t bmpID;
    uint16_t n;                 
    uint8_t ret;

    if ((x >= tft.width()) || (y >= tft.height()))
        return 1;               // off screen

    bmpFile = SD.open(nm);      
    bmpID = read16(bmpFile);    
    (void) read32(bmpFile);     
    (void) read32(bmpFile);     
    bmpImageoffset = read32(bmpFile);      
    (void) read32(bmpFile);     
    bmpWidth = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    n = read16(bmpFile);        
    bmpDepth = read16(bmpFile); 
    pos = read32(bmpFile);     
    if (bmpID != 0x4D42) ret = 2; 
    else if (n != 1) ret = 3;  
    else if (pos != 0 && pos != 3) ret = 4; 
    else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5;
    else {
        bool first = true;
        is565 = (pos == 3);             
        
        rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
        if (bmpHeight < 0) {             
            bmpHeight = -bmpHeight;
            flip = false;
        }

        w = bmpWidth;
        h = bmpHeight;
        RESTORE_SPI_GPIO();
        tft.setRotation(w > h ? 1 : 0);   
        if ((x + w) >= tft.width())      
            w = tft.width() - x;
        if ((y + h) >= tft.height())     
            h = tft.height() - y;

        if (bmpDepth <= PALETTEDEPTH) {  
            bmpFile.seek(BMPIMAGEOFFSET); 
            bitmask = 0xFF;
            if (bmpDepth < 8)
                bitmask >>= bmpDepth;
            bitshift = 8 - bmpDepth;
            n = 1 << bmpDepth;
            lcdbufsiz -= n;
            palette = lcdbuffer + lcdbufsiz;
            for (col = 0; col < n; col++) {
                pos = read32(bmpFile);    
                palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);
            }
        }

        RESTORE_SPI_GPIO();
        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
        for (row = 0; row < h; row++) {
            
            uint8_t r, g, b, *sdptr;
            int lcdidx, lcdleft;
            if (flip)   
                pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
            else      
                pos = bmpImageoffset + row * rowSize;
            if (bmpFile.position() != pos) { 
                bmpFile.seek(pos);
                buffidx = sizeof(sdbuffer); 
            }

            for (col = 0; col < w; ) {  
                lcdleft = w - col;
                if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
                for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { 
                    uint16_t color;
                    
                    if (buffidx >= sizeof(sdbuffer)) { 
                        bmpFile.read(sdbuffer, sizeof(sdbuffer));
                        buffidx = 0; 
                        r = 0;
                    }
                    switch (bmpDepth) {       
                        case 24:
                            b = sdbuffer[buffidx++];
                            g = sdbuffer[buffidx++];
                            r = sdbuffer[buffidx++];
                            color = tft.color565(r, g, b);
                            break;
                        case 16:
                            b = sdbuffer[buffidx++];
                            r = sdbuffer[buffidx++];
                            if (is565)
                                color = (r << 8) | (b);
                            else
                                color = (r << 9) | ((b & 0xE0) << 1) | (b & 0x1F);
                            break;
                        case 1:
                        case 4:
                        case 8:
                            if (r == 0)
                                b = sdbuffer[buffidx++], r = 8;
                            color = palette[(b >> bitshift) & bitmask];
                            r -= bmpDepth;
                            b <<= bmpDepth;
                            break;
                    }
                    lcdbuffer[lcdidx] = color;

                }
                RESTORE_SPI_GPIO();
                tft.pushColors(lcdbuffer, lcdidx, first);
                first = false;
                col += lcdidx;
            }           
        }               
        tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1);
        ret = 0;        
    }
    bmpFile.close();
    RESTORE_SPI_GPIO();
  return (ret);
}

Tried that but with few minor changes cause there was no case 0 when A=0 and B = 0 then the picture is green.bmp. Anyway now it shows blue screen again for some reason.

What does ret say?

Where are the files stored? e.g. "/red.bmp" or "/bitmaps/red.bmp" or "/folder/red.bmp"

It would be neater to say:

    char *nm;   
    switch (state) {
        case 0: nm = "/green.bmp"; break;
        case 1: nm = "/yellow.bmp"; break;
        case 2: nm = "/yellow.bmp"; break;
        case 3: nm = "/red.bmp"; break;
    }
    ret = showBMP(nm, 5, 5);
    Serial.print(nm);
    Serial.print(" returns ");
    Serial.println(ret);
    oldstate = state;

The images are in the root of the SD card. Now its a constant black screen on the lcd and Serial print output is:

Show BMP files on TFT with ID:0x5252
/
green.bmp returns 2
yellow.bmp returns 2
green.bmp returns 2
yellow.bmp returns 2
green.bmp returns 2
yellow.bmp returns 2
green.bmp returns 2
yellow.bmp returns 2
green.bmp returns 2
yellow.bmp returns 2
green.bmp returns 2
yellow.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2
yellow.bmp returns 2
red.bmp returns 2

From showBMP_kbv_Uno.ino

                case 2:
                    Serial.println(F("bad BMP ID"));
                    break;

I tested the code with an Open-Smart HX8352-B shield on a Uno.
It displayed my example .BMP pictures just fine.

Please can you attach your red.bmp yellow.bmp and green.bmp

Please put the microSD into your PC. Do red.bmp yellow.bmp and green.bmp show the correct images on your PC ?

Note that the .BMP file format from your PC is not the same as the drawBitmap() method from Adafruit_GFX

David.

Ive uploaded the early .ino code that runs without the sensor and it scrolled through this 3 pictures that are on the SD card and showed them on the lcd normally. Three pictures are in the attachment.

P.S.
Ive figured it out, the picture names that I thought were on SD card were green,yellow and red but instead it was 1green,2yellow and 3red for some reason. Ill test the code by adding a sensor now and will let you know if it changes images correctly.
P.P.S.
Guess the forum doesent support uploading bmp format.

UPDATE:

I was wondering if its possible for the images to be loaded on the display faster, usually it takes cca. 3 seconds for the picture to be loaded on the screen and you can see the screen being filled little by little. Is it a Uno problem, lcd module problem or can it be solved somehow or do I need to look for better lcd display?

You have an Open-Smart display with a Uno. The HX8352-A controller is a little slower than regular 240x400 e.g. ILI9327.

If you are diplaying graphics, it is quicker to draw them from scratch.
Photos must come from a SD card.

Yes, a faster Arduino can read the SD card faster.
If the data bus is mapped to a single port, the TFT would be faster.
A smaller screen would be faster.

David.