Update: Like I said, I was messing around with Grok. I was able to clean out a bunch of unnecessary code. See below:
// Filename: 'Setup1b_ILI9341V.h'
#define TFT_MISO -1
#define TFT_MOSI 51
#define TFT_SCLK 52
#define TFT_CS 9
#define TFT_DC 8
#define TFT_RST 7
#define TFT_BL 6 // LED back-light
#define TFT_BACKLIGHT_ON LOW
#define ILI9341_DRIVER
#define TFT_WIDTH 240
#define TFT_HEIGHT 320
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 20000000
#define SPI_TOUCH_FREQUENCY 2500000
#define TFT_RGB_ORDER TFT_BGR // BGR panel
#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
In, short- You might want to observe the initialization sequence shown in the code below, but otherwise just set “tft.invertDisplay(true)” in your sketch and use “#define TFT_RGB_ORDER TFT_BGR” in your User Setup file, that way you can use TFT_eSPI’s native colors, but also makes images print in color-correct fashion.
// Filename: ILI9341_Display_Test.ino
#include <TFT_eSPI.h>
#include <SPI.h>
#include <SdFat_Adafruit_Fork.h>
TFT_eSPI tft = TFT_eSPI();
SdFat SD;
File rawFile;
#define SD_CS 4
#define TFT_BL 6
#define RAW_NAME "logo565.raw"
#define RAW_SIZE 115200
#define IMG_W 240
#define IMG_H 240
#define ROW_PIXELS 240
#define ROW_BYTES (ROW_PIXELS * 2)
#define BATCH_ROWS 12
#define BATCH_PIXELS (ROW_PIXELS * BATCH_ROWS)
#define BATCH_BYTES (BATCH_PIXELS * 2)
SPISettings tftSPI(40000000, MSBFIRST, SPI_MODE0);
SPISettings sdSPI(25000000, MSBFIRST, SPI_MODE0);
void writeCommand(uint8_t cmd) {
digitalWrite(TFT_DC, LOW);
digitalWrite(TFT_CS, LOW);
SPI.transfer(cmd);
digitalWrite(TFT_CS, HIGH);
}
void writeData(uint8_t data) {
digitalWrite(TFT_DC, HIGH);
digitalWrite(TFT_CS, LOW);
SPI.transfer(data);
digitalWrite(TFT_CS, HIGH);
}
void setAddrWindow(int16_t x, int16_t y, int16_t w, int16_t h) {
uint16_t x1 = x + w - 1;
uint16_t y1 = y + h - 1;
writeCommand(0x2A);
writeData(x >> 8); writeData(x & 0xFF);
writeData(x1 >> 8); writeData(x1 & 0xFF);
writeCommand(0x2B);
writeData(y >> 8); writeData(y & 0xFF);
writeData(y1 >> 8); writeData(y1 & 0xFF);
writeCommand(0x2C);
}
void pushColors(uint16_t *data, int len) {
digitalWrite(TFT_DC, HIGH);
digitalWrite(TFT_CS, LOW);
for (int i = 0; i < len; i++) {
SPI.transfer(data[i] >> 8);
SPI.transfer(data[i] & 0xFF);
}
digitalWrite(TFT_CS, HIGH);
}
bool displayLogoCentered() {
Serial.print(F("Opening "));
Serial.println(RAW_NAME);
rawFile = SD.open(RAW_NAME);
if (!rawFile || rawFile.size() != RAW_SIZE) {
Serial.println(F("ERROR: File not found or wrong size"));
return false;
}
Serial.print(F("File OK. Buffering "));
Serial.print(BATCH_ROWS);
Serial.println(F(" rows per batch..."));
uint32_t startTime = millis();
uint16_t batchBuffer[BATCH_PIXELS];
uint32_t fileOffset = 0;
for (int startY = 0; startY < IMG_H; startY += BATCH_ROWS) {
int rowsThisBatch = min(BATCH_ROWS, IMG_H - startY);
int pixelsThisBatch = rowsThisBatch * ROW_PIXELS;
int bytesThisBatch = pixelsThisBatch * 2;
SPI.beginTransaction(sdSPI);
digitalWrite(SD_CS, LOW);
rawFile.seek(fileOffset);
int read = rawFile.read(batchBuffer, bytesThisBatch);
digitalWrite(SD_CS, HIGH);
SPI.endTransaction();
if (read != bytesThisBatch) {
Serial.print(F("ERROR: Read failed at offset "));
Serial.println(fileOffset);
rawFile.close();
return false;
}
int drawY = startY;
setAddrWindow(40, drawY, IMG_W, rowsThisBatch); // ← (40, 0) = centered
pushColors(batchBuffer, pixelsThisBatch);
fileOffset += bytesThisBatch;
}
rawFile.close();
uint32_t elapsed = millis() - startTime;
Serial.print(F("Logo displayed in "));
Serial.print(elapsed);
Serial.println(F(" ms"));
return true;
}
#ifdef __arm__
extern "C" char* sbrk(int incr);
#else
extern char *__brkval;
#endif
int freeMemory() {
char top;
#ifdef __arm__
return &top - reinterpret_cast<char*>(sbrk(0));
#else
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif
}
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("=== v40.7.1 — FINAL VICTORY ===");
pinMode(TFT_BL, OUTPUT);
pinMode(TFT_RST, OUTPUT);
digitalWrite(TFT_RST, LOW);
delay(100);
digitalWrite(TFT_RST, HIGH);
delay(100);
pinMode(TFT_CS, OUTPUT);
pinMode(TFT_DC, OUTPUT);
digitalWrite(TFT_CS, HIGH);
digitalWrite(TFT_DC, HIGH);
SPI.begin();
tft.init();
tft.invertDisplay(true);
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
Serial.print(F("Free RAM: "));
Serial.println(freeMemory());
Serial.println(F("SD init..."));
SPI.beginTransaction(sdSPI);
if (!SD.begin(SD_CS, SD_SCK_MHZ(25))) {
Serial.println(F("SD FAILED"));
analogWrite(TFT_BL, 255);
return;
}
SPI.endTransaction();
Serial.println(F("SD OK"));
if (!displayLogoCentered()) {
tft.fillRect(20, 100, 200, 40, TFT_RED);
}
for (int i = 0; i <= 255; i += 5) {
analogWrite(TFT_BL, i);
delay(50);
}
Serial.println(F("DISPLAY READY — LOGO CENTERED IN LANDSCAPE"));
delay(1000);
for (int i = 255; i >= 0; i -= 5) {
analogWrite(TFT_BL, i);
delay(10);
}
tft.fillScreen(TFT_BLACK);
}
void loop() {}