Esp32, ST7735 working, SD card not

Just when I was starting to understand to understand SPI, enter the esp32 to set me back to beginner. I upgraded to an esp32-s3 r8n16 for the memory capabilities. Prior hardware, Mega 2560 and Nano both had hardware SPI and the pins were dedicated. Wire device to SPI pins, init SPI on code and it works. With the esp32 it doesn't seem to have dedicated SPI pins but re-mappable pins. I have 2 problems:

  1. Working with both an ST7735 display and the attached SD Card reader, I can get the screen to work and the SD Card initializes, but won't read a file. I just don't understand the pin assignments. I initialize the LCD screen first. The bb_spi_lcd library takes all the pins assignments and initializes. That "seems" to set up/map the SPI pins and I just use those pins for the SD Card with a separate chip select? Is it using hardware SPI or software SPI? How can I tell? Where do I set the MISO pin for the SD Card?

  2. Without the SD Card initialization code, I can get the screen to refresh at 11ms or about 90fps. With the SD Card initialized (albeit not working), the screen only refreshes at 85ms or 12fps. Why the slow down?

I'm confused on the mapping pins for SPI and what has priority over the SPI setup? Does the SD.begin() change the SPI freqency slower than what the LCD library sets because I call it after?

// #########################  Includes  ##############################
#include <bb_spi_lcd.h>          // Library for the ST7735 LCD display
#include <SPI.h>                 // Library for SPI functions
#include <SD.h>                  // Library for SD Card

// ########################  Defines  ################################
#define TFT_CS_PIN    14         // LCD Display control signals using SPI
#define TFT_DC_PIN    12
#define TFT_RESET_PIN 13
#define TFT_LED_PIN   -1
#define MISO_PIN      9
#define MOSI_PIN      11
#define CLK_PIN       10
#define SDC_CS_PIN    3         // SD Card Chip Select

// ########################  Function Prototypes  #####################

// ########################  Global Variables #########################
BB_SPI_LCD tft;                 // Create LCD instance
int color[10];

// ########################  Setup  ###################################
void setup() {
  
  int time;

  #ifdef ESP32                 // Verify esp32 is detected
    int esp=1;
  #else
    int esp=0;
  #endif

  color[0] = TFT_BLACK;       // put colors in an array
  color[1] = TFT_GREEN;
  color[2] = TFT_RED;
  color[3] = TFT_BLUE;
  color[4] = TFT_CYAN;
  color[5] = TFT_YELLOW;
  color[6] = TFT_MAGENTA;
  color[7] = TFT_WHITE;
  color[8] = TFT_GREY;
  color[9] = TFT_ORANGE;

  
  Serial.begin(115200);
  Serial.println();
  Serial.print("1 = esp32 found, 0 = esp32 NOT found: ");
  Serial.println(esp);
  Serial.print("Initalizing LCD... ");

  // begin(int iType, int iFlags, int iFreq, int iCSPin, int iDCPin, int iResetPin, int iLEDPin, int iMISOPin, int iMOSIPin, int iCLKPin)
  // For unused pins, pass -1  
  tft.begin(LCD_ST7735R, FLAGS_NONE, 40000000, TFT_CS_PIN, TFT_DC_PIN, TFT_RESET_PIN, TFT_LED_PIN, MISO_PIN, MOSI_PIN, CLK_PIN);
  Serial.println("done");

  // The default orientation is portrait. To set landscape mode use setRotation(270)
  tft.setRotation(270);

  Serial.print("Time in ms to refresh screen... ");
  time = millis();  
  tft.fillScreen(TFT_BLACK); 
  time = millis() - time;
  Serial.println(time);

  tft.setTextColor(TFT_GREEN); 
  tft.setFont(FONT_6x8);
  tft.println("Generic SPI display");
  tft.println("Using bb_spi_lcd");

  if (!SD.begin(SDC_CS_PIN)) {         // Initialize the SD Card
    Serial.println("initialization failed. Things to check:");
    Serial.println("1. is a card inserted?");
    Serial.println("2. is your wiring correct?");
    Serial.println("3. did you change the chipSelect pin to match your shield or module?");
    Serial.println("Note: press reset button on the board and reopen this Serial Monitor after fixing your issue!");

    delay(2000);
  } 
  else 
    Serial.println("SD Card Initialized");  

  delay(1000);

}

// #############################  Main  ############################
void loop() {

  File image_file;
  int i;
  int time;
  char sprite_file[13];

  strcpy(sprite_file, "Test.txt");
  if(SD.exists(sprite_file)) 
    Serial.println("File exists on SD Card");
  else
    Serial.println("File does NOT exist on SD Card");

  if (!(image_file = SD.open(sprite_file, FILE_READ))) { // Check if file exists
    Serial.println(F("-> File not found"));              // If not, Error message    
  }
  image_file.close();
    
  while(1) {
    for(i=0; i<10; i++) {
      Serial.print("Time in ms to refresh screen... ");
      time = millis();  
      tft.fillScreen(color[i]); 
      time = millis() - time;
      Serial.println(time);

      if(i == 0)  tft.setTextColor(TFT_WHITE); 
      else tft.setTextColor(TFT_BLACK, color[i]);
      tft.setFont(FONT_6x8);
      tft.print("Refresh time in ms... ");
      tft.println(time);

      delay(1000);

    }
  } 
}

can you give a link to the specific display you are using?
I have used the 1.8" version of SPI TFT LCD Module Display Shield ST7735S with a ESP32-S3-DevKitC-1 using the TFT and on board SD card
using the adafruit-st7735-and-st7789-library

horace,
Thank you for your reply. I am using a 1.8" 160x128 ST7735 w/ SD card reader attached.
1.8" SPI LCD
I had a lot of difficulty just getting the Adafruit or the TFT_eSPI libraries to work on the esp32. They didn't have a setup that included the 160x128 resolution and trying to adapt one of the other setups, I just couldn't get them to work. I had no problems on either the mega 2560 or Nano. The bb_spi_lcd library was much simpler.
The heart of the problem is still the original 2. I can't seem to grasp the how the SPI pins are mapped. I set the pins using the TFT library. Does that set them for all SPI devices? The SD library just uses the SD.begin(CSPin). There is no further pin settings for SD.begin. So does it just use the pins allocated by the LCD setup? Or, should I use some SPI.xxx to init the pins and then init the LCD/SD?

Some progress...
So I changed the "strcpy(sprite_file, "Test.txt");" to "strcpy(sprite_file, "/Test.txt");"
and now the files are recognized, I can open and read a file but only once.
In my new test I use strcpy(sprite_file, "/wizsm.raw"); which is a small RGB565 file of a wizard.
I can open the file, read the file, close the file and that's it. Any subsequent tries to open and read the file, or any other files, results in a file not found condition.

Despite the progress the screen refresh is still extremely slow.

ESP32-S3-DevKitC-1 using the adafruit-st7735-and-st7789-library extended File>Examples>/Adafruit-ST7735-and-ST7789/graphicstest to also test a SD card reader

TFT 1.8 SPI 128*160 display

graphicstest.ino file

// ESP32-S3-DevKitC-1 1.8 inch_ST7735_TFT and SD card reader test

// adapted from File>Examples>/Adafruit-ST7735-and-ST7789/graphicstest
//    https://www.arduinolibraries.info/libraries/adafruit-st7735-and-st7789-library

//  ESP32-S3-DevKitC-1 to use 5V output "bridge the little pads just above pin 11 and 12." otherwise reads 2V

/**************************************************************************
  This is a library for several Adafruit displays based on ST77* drivers.

  Works with the Adafruit 1.8" TFT Breakout w/SD card
    ----> http://www.adafruit.com/products/358
  The 1.8" TFT shield
    ----> https://www.adafruit.com/product/802
  The 1.44" TFT breakout
    ----> https://www.adafruit.com/product/2088
  The 1.14" TFT breakout
  ----> https://www.adafruit.com/product/4383
  The 1.3" TFT breakout
  ----> https://www.adafruit.com/product/4313
  The 1.54" TFT breakout
    ----> https://www.adafruit.com/product/3787
  The 1.69" TFT breakout
    ----> https://www.adafruit.com/product/5206
  The 2.0" TFT breakout
    ----> https://www.adafruit.com/product/4311
  as well as Adafruit raw 1.8" TFT display
    ----> http://www.adafruit.com/products/618

  Check out the links above for our tutorials and wiring diagrams.
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional).

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 **************************************************************************/

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
//#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>

  // ESP32-C3-MINI-1 supermini  These pins will also work for the 1.8" TFT shield.
  // TFT VCC to 5V - regulator on board J1 open
  // BL to 3.3V
  // ESP32-C3-MINI-1 supermini  These pins will also work for the 1.8" TFT shield.
  // TFT VCC to 5V - regulator on board J1 open
  // BL to 3.3V
  #define TFT_CS         10
  #define TFT_RST        5 // Or set to -1 and connect to Arduino RESET pin
  #define TFT_DC         9  // labled RS on other connector
  // NOTE: TFT DIN or SDA to MOSI

// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique
// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and
// SCLK = pin 13. This is the fastest mode of operation and is required if
// using the breakout board's microSD card.

// For 1.44" and 1.8" TFT with ST7735 use:
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// For 1.14", 1.3", 1.54", 1.69", and 2.0" TFT with ST7789:
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);


// OPTION 2 lets you interface the display using ANY TWO or THREE PINS,
// tradeoff being that performance is not as fast as hardware SPI above.
//#define TFT_MOSI 11  // Data out
//#define TFT_SCLK 13  // Clock out

// For ST7735-based displays, we will use this call
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

// OR for the ST7789-based displays, we will use this call
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);


float p = 3.1415926;

void setupSD();

void setup(void) {
  Serial.begin(115200);
  delay(2000);
  setupSD();
  Serial.print(F("Hello! ESP32-S3-DevKitC-1 ST77xx TFT Test"));

  // Use this initializer if using a 1.8" TFT screen:
  //tft.initR(INITR_BLACKTAB);      // Init ST7735S chip, black tab

  // OR use this initializer if using a 1.8" TFT screen with offset such as WaveShare:
  tft.initR(INITR_GREENTAB);      // Init ST7735S chip, green tab

  // OR use this initializer (uncomment) if using a 1.44" TFT:
  //tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab

  // OR use this initializer (uncomment) if using a 0.96" 160x80 TFT:
  //tft.initR(INITR_MINI160x80);  // Init ST7735S mini display
  // OR use this initializer (uncomment) if using a 0.96" 160x80 TFT with 
  // plug-in FPC (if you see the display is inverted!)
  //tft.initR(INITR_MINI160x80_PLUGIN);  // Init ST7735S mini display

  // OR use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT:
  //tft.init(240, 240);           // Init ST7789 240x240

  // OR use this initializer (uncomment) if using a 1.69" 280x240 TFT:
  //tft.init(240, 280);           // Init ST7789 280x240

  // OR use this initializer (uncomment) if using a 2.0" 320x240 TFT:
  //tft.init(240, 320);           // Init ST7789 320x240

  // OR use this initializer (uncomment) if using a 1.14" 240x135 TFT:
  //tft.init(135, 240);           // Init ST7789 240x135
  //tft.init(128, 160);           // Init ST7789 240x135
  // OR use this initializer (uncomment) if using a 1.47" 172x320 TFT:
  //tft.init(172, 320);           // Init ST7789 172x320

  // SPI speed defaults to SPI_DEFAULT_FREQ defined in the library, you can override it here
  // Note that speed allowable depends on chip and quality of wiring, if you go too fast, you
  // may end up with a black screen some times, or all the time.
  tft.setSPISpeed(10000000);

  Serial.println(F("Initialized"));

  uint16_t time = millis();
  tft.fillScreen(ST77XX_BLACK);
  time = millis() - time;

  Serial.println(time, DEC);
  delay(500);

  // large block of text
  tft.fillScreen(ST77XX_BLACK);
  testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST77XX_WHITE);
  delay(1000);

  // tft print function!
  tftPrintTest();
  delay(4000);

  // a single pixel
  tft.drawPixel(tft.width()/2, tft.height()/2, ST77XX_GREEN);
  delay(500);

  // line draw test
  testlines(ST77XX_YELLOW);
  delay(500);

  // optimized lines
  testfastlines(ST77XX_RED, ST77XX_BLUE);
  delay(500);

  testdrawrects(ST77XX_GREEN);
  delay(500);

  testfillrects(ST77XX_YELLOW, ST77XX_MAGENTA);
  delay(500);

  tft.fillScreen(ST77XX_BLACK);
  testfillcircles(10, ST77XX_BLUE);
  testdrawcircles(10, ST77XX_WHITE);
  delay(500);

  testroundrects();
  delay(500);

  testtriangles();
  delay(500);

  mediabuttons();
  delay(500);

  Serial.println("done");
  delay(1000);
}

void loopSD();
void loop() {
  tft.invertDisplay(true);
  delay(500);
  tft.invertDisplay(false);
  delay(500);
  loopSD();
}

void testlines(uint16_t color) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, 0, x, tft.height()-1, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, 0, tft.width()-1, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, 0, 0, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, tft.height()-1, x, 0, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, tft.height()-1, tft.width()-1, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color);
    delay(0);
  }
}

void testdrawtext(char *text, uint16_t color) {
  tft.setCursor(0, 0);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
}

void testfastlines(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t y=0; y < tft.height(); y+=5) {
    tft.drawFastHLine(0, y, tft.width(), color1);
  }
  for (int16_t x=0; x < tft.width(); x+=5) {
    tft.drawFastVLine(x, 0, tft.height(), color2);
  }
}

void testdrawrects(uint16_t color) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color);
  }
}

void testfillrects(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=tft.width()-1; x > 6; x-=6) {
    tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
  }
}

void testfillcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=radius; x < tft.width(); x+=radius*2) {
    for (int16_t y=radius; y < tft.height(); y+=radius*2) {
      tft.fillCircle(x, y, radius, color);
    }
  }
}

void testdrawcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
    for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
      tft.drawCircle(x, y, radius, color);
    }
  }
}

void testtriangles() {
  tft.fillScreen(ST77XX_BLACK);
  uint16_t color = 0xF800;
  int t;
  int w = tft.width()/2;
  int x = tft.height()-1;
  int y = 0;
  int z = tft.width();
  for(t = 0 ; t <= 15; t++) {
    tft.drawTriangle(w, y, y, x, z, x, color);
    x-=4;
    y+=4;
    z-=4;
    color+=100;
  }
}

void testroundrects() {
  tft.fillScreen(ST77XX_BLACK);
  uint16_t color = 100;
  int i;
  int t;
  for(t = 0 ; t <= 4; t+=1) {
    int x = 0;
    int y = 0;
    int w = tft.width()-2;
    int h = tft.height()-2;
    for(i = 0 ; i <= 16; i+=1) {
      tft.drawRoundRect(x, y, w, h, 5, color);
      x+=2;
      y+=3;
      w-=4;
      h-=6;
      color+=1100;
    }
    color+=100;
  }
}

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_BLUE);
  tft.setTextSize(4);
  tft.print(1234.567);
  delay(1500);
  tft.setCursor(0, 0);
  tft.fillScreen(ST77XX_BLACK);
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(0);
  tft.println("Hello World!");
  tft.setTextSize(1);
  tft.setTextColor(ST77XX_GREEN);
  tft.print(p, 6);
  tft.println(" Want pi?");
  tft.println(" ");
  tft.print(8675309, HEX); // print 8,675,309 out in HEX!
  tft.println(" Print HEX!");
  tft.println(" ");
  tft.setTextColor(ST77XX_WHITE);
  tft.println("Sketch has been");
  tft.println("running for: ");
  tft.setTextColor(ST77XX_MAGENTA);
  tft.print(millis() / 1000);
  tft.setTextColor(ST77XX_WHITE);
  tft.print(" seconds.");
}

void mediabuttons() {
  // play
  tft.fillScreen(ST77XX_BLACK);
  tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE);
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED);
  delay(500);
  // pause
  tft.fillRoundRect(25, 90, 78, 60, 8, ST77XX_WHITE);
  tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_GREEN);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_GREEN);
  delay(500);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE);
  delay(50);
  // pause color
  tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_RED);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_RED);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN);
}

SD_test.cpp (place in same directory as the above graphicstest.ino file

// ESP32-S3-DevKitC-1 SD card test
// File>Examples/SD/SD_test

// may require https://github.com/espressif/arduino-esp32/tree/master

// ESP32-S3-DevKitC-1 connections
// ESP32_S3 SS  pin GPIO 4   to SD card SS
 
#include "FS.h"
#include "SD.h"
#include "SPI.h"

void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if(!root){
        Serial.println("Failed to open directory");
        return;
    }
    if(!root.isDirectory()){
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.path(), levels -1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

void createDir(fs::FS &fs, const char * path){
    Serial.printf("Creating Dir: %s\n", path);
    if(fs.mkdir(path)){
        Serial.println("Dir created");
    } else {
        Serial.println("mkdir failed");
    }
}

void removeDir(fs::FS &fs, const char * path){
    Serial.printf("Removing Dir: %s\n", path);
    if(fs.rmdir(path)){
        Serial.println("Dir removed");
    } else {
        Serial.println("rmdir failed");
    }
}

void readFile(fs::FS &fs, const char * path){
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if(!file){
        Serial.println("Failed to open file for reading");
        return;
    }

    Serial.print("Read from file: ");
    while(file.available()){
        Serial.write(file.read());
    }
    file.close();
}

void writeFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("Failed to open file for writing");
        return;
    }
    if(file.print(message)){
        Serial.println("File written");
    } else {
        Serial.println("Write failed");
    }
    file.close();
}

void appendFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if(!file){
        Serial.println("Failed to open file for appending");
        return;
    }
    if(file.print(message)){
        Serial.println("Message appended");
    } else {
        Serial.println("Append failed");
    }
    file.close();
}

void renameFile(fs::FS &fs, const char * path1, const char * path2){
    Serial.printf("Renaming file %s to %s\n", path1, path2);
    if (fs.rename(path1, path2)) {
        Serial.println("File renamed");
    } else {
        Serial.println("Rename failed");
    }
}

void deleteFile(fs::FS &fs, const char * path){
    Serial.printf("Deleting file: %s\n", path);
    if(fs.remove(path)){
        Serial.println("File deleted");
    } else {
        Serial.println("Delete failed");
    }
}

void testFileIO(fs::FS &fs, const char * path){
    File file = fs.open(path);
    static uint8_t buf[512];
    size_t len = 0;
    uint32_t start = millis();
    uint32_t end = start;
    if(file){
        len = file.size();
        size_t flen = len;
        start = millis();
        while(len){
            size_t toRead = len;
            if(toRead > 512){
                toRead = 512;
            }
            file.read(buf, toRead);
            len -= toRead;
        }
        end = millis() - start;
        Serial.printf("%u bytes read for %u ms\n", flen, end);
        file.close();
    } else {
        Serial.println("Failed to open file for reading");
    }


    file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("Failed to open file for writing");
        return;
    }

    size_t i;
    start = millis();
    for(i=0; i<2048; i++){
        file.write(buf, 512);
    }
    end = millis() - start;
    Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
    file.close();
}

void setupSD(){
   // Serial.begin(115200);
    delay(2000);
    if(!SD.begin(4)){
        Serial.println("Card Mount Failed");
        return;
    }
    uint8_t cardType = SD.cardType();

    if(cardType == CARD_NONE){
        Serial.println("No SD card attached");
        return;
    }

    Serial.print("SD Card Type: ");
    if(cardType == CARD_MMC){
        Serial.println("MMC");
    } else if(cardType == CARD_SD){
        Serial.println("SDSC");
    } else if(cardType == CARD_SDHC){
        Serial.println("SDHC");
    } else {
        Serial.println("UNKNOWN");
    }

    uint64_t cardSize = SD.cardSize() / (1024 * 1024);
    Serial.printf("SD Card Size: %lluMB\n", cardSize);

    listDir(SD, "/", 0);
    createDir(SD, "/mydir");
    listDir(SD, "/", 0);
    removeDir(SD, "/mydir");
    listDir(SD, "/", 2);
    writeFile(SD, "/hello.txt", "Hello ");
    appendFile(SD, "/hello.txt", "World!\n");
    readFile(SD, "/hello.txt");
    deleteFile(SD, "/foo.txt");
    renameFile(SD, "/hello.txt", "/foo.txt");
    readFile(SD, "/foo.txt");
    testFileIO(SD, "/test.txt");
    Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
    Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
}

void loopSD(){
  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
    Serial.printf("SD Card Size: %lluMB\n", cardSize);
}

serial monitor displays

ImSD Card Type: SDHC
SD Card Size: 29664MB
Listing directory: /
  DIR : System Volume Information
  FILE: UsefulLinks.doc  SIZE: 110592
  FILE: DELETE.BAT  SIZE: 179
  FILE: del.bat  SIZE: 72
  DIR : test
  FILE: test.txt  SIZE: 1048576
  FILE: foo.txt  SIZE: 13
Creating Dir: /mydir
Dir created
Listing directory: /
  DIR : System Volume Information
  FILE: UsefulLinks.doc  SIZE: 110592
  FILE: DELETE.BAT  SIZE: 179
  FILE: del.bat  SIZE: 72
  DIR : test
  FILE: test.txt  SIZE: 1048576
  FILE: foo.txt  SIZE: 13
  DIR : mydir
Removing Dir: /mydir
Dir removed
Listing directory: /
  DIR : System Volume Information
Listing directory: /System Volume Information
  FILE: WPSettings.dat  SIZE: 12
  FILE: IndexerVolumeGuid  SIZE: 76
  FILE: UsefulLinks.doc  SIZE: 110592
  FILE: DELETE.BAT  SIZE: 179
  FILE: del.bat  SIZE: 72
  DIR : test
Listing directory: /test
  FILE: DELETE.BAT  SIZE: 179
  FILE: UsefulLinks.doc  SIZE: 110592
  FILE: del.bat  SIZE: 72
  FILE: LinuxHelp.odt  SIZE: 8149
  FILE: shhXwindow.odt  SIZE: 7721
  FILE: test.txt  SIZE: 1048576
  FILE: foo.txt  SIZE: 13
Writing file: /hello.txt
File written
Appending to file: /hello.txt
Message appended
Reading file: /hello.txt
Read from file: Hello World!
Deleting file: /foo.txt
File deleted
Renaming file /hello.txt to /foo.txt
File renamed
Reading file: /foo.txt
Read from file: Hello World!
1048576 bytes read for 2477 ms
1048576 bytes written for 2697 ms
Total space: 29646MB
Used space: 2MB
Hello! ST77xx TFT TestInitialized
36
done
SD Card Size: 29664MB
SD Card Size: 29664MB
SD Card Size: 29664MB

horace,
Thank you for the attempt. I can get the screen to work and I can get the SD card to work. I really didn't know if I should post this under the screen section or the SD card section or some other section.
The problem is 2 fold.

  1. When both are working at the same time, the SD card will only read 1 file and any subsequent requests result in a "file not found" condition.
  2. Before the SD card in initialized, I can get the screen to refresh at 90fps. While after the SD card is initialized, the SPI bus slows down and the screen only refreshes at about 12fps.

Is it because of the shared bus and the SD card overrides and only allows a certain frequency, much slower than the screen?
I'm having difficulty figuring out the SPI hardware pins, where the esp32 doesn't seem to have "dedicated" hardware pins like older arduino boards, despite there being "default" pins. And, why the SD card will only read 1 file.
As a note, I don't care for the Adafruit TFT library because it doesn't have some of the advanced functions that the bb_spi_lcd or the tft_espi libraries have. For my project, which I've done a similiar one on a TTGo w/ built in screen, I'm able to set a unsigned int variable array the size of the screen as a double buffer. I've written my own functions to write pixel data to this buffer and use the pushImage function to quickly write the data to the screen. This gives me flicker free animation. The Adafruit library doesn't have the pushImage function that I'm aware of.
The esp32 has 2 SPI busses and I might have enough pins to try to get the screen to work on 1 of the SPI busses and the SD Card on the other. For my full project, I was hoping to get 2 screens, the SD card reader, a 4x3 keypad, a 2nd arduino to send data too via the SPI bus and a MAX98357 amp. I'll have to try the 2 screens on 1 SPI bus and the SD card on the other. This is why I'm testing the ability to have multiple devices on 1 SPI bus. As of yet, I'm having trouble just getting 2 of them.

I have finally got this to work. Not exactly the way I wanted. I did find in the SD.h file that when the SD Card is initialized, it sets the SPI bus to 4Mhz. A far cry from the 40Mhz the screen initializes at. Result, slow screen refresh. So the slow down is because both were on the same SPI bus. That would also explain the when the SD card was initialized first, and the screen would boost the bus to 40Mhz, the SD card couldn't handle the speed. Now the SD Card is working and the screen is back to about 11ms or 90fps.
I still can't figure out and configure the HSPI and VSPI. Although, it seems my screen is using the hardware HSPI bus. I ended up using soft SPI (I think?) and put the SD Card on a separate bus. Both are working right now.
I'm still confused on the whole mapping of SPI2&3 but, I guess if it's working, I don't care right now.
Thank you horace for trying to help. Sometimes it just takes a suggestion from another person to spark an idea.