Arduino Forum

Products => Arduino Due => Topic started by: step1 on Jul 25, 2020, 07:52 pm

Title: don't get my display to display anything
Post by: step1 on Jul 25, 2020, 07:52 pm
Hi,

I recently bought a bunch of these:
https://www.aliexpress.com/item/4000838284629.html (https://www.aliexpress.com/item/4000838284629.html)

since the seller did not provide any specifics (like Model type etc.) and also no code I had to find something on the net. The closest display I could find was here:

https://www.youtube.com/watch?v=Zq5HjnNUWcE (https://www.youtube.com/watch?v=Zq5HjnNUWcE)

I downloaded their UTFT library and their example sketch (which is linked to in the video description where it says "where to buy") which was lacking the memorysaver.h file. I found that file in another UTFT library so now the compiler does not complain anymore.

However, all the LCD drawings and texts in the sample won't show on the display. I checked if there is any communication with the display at all and found out that

getDisplayXSize() and getDisplayYSize()

return the correct size (240, 240). Also the backlight can be turned on/off via pin 10 on my Due.

I suspect that the display type is wrong, the code uses the following:

UTFT myGLCD(ST7789_TFTM013_1,11,12,7,8,9);

where the parameters are the pins SDA,SCK (called SCL in the code, does it matter?), 7 is not used, Reset, DC in that order.

there are two files in the library called initlcd.h and setxy.h where I assume that changes are necessary but I have no idea how to do it. If needed I can post the code of those files, jlmk.

I hope someone can help :)

Title: Re: don't get my display to display anything
Post by: david_prentice on Jul 26, 2020, 12:53 am
Identify any printing on the U2 component.   It is either a transistor for switching the backlight or a voltage regulator.

The SSD7789 definitely expects 3.3V logic levels.
It should work fine on 3.3V Zero, Due, STM32, ESP8266, ESP32, ...

The official UTFT v2.8.3 does not have any model called ST7789_TFTM013_1

I suggest that you use Adafruit_ST7789 library that can be installed via the IDE Library Manager.
But there are several respectable ST7789 SPI libraries.

David.
Title: Re: don't get my display to display anything
Post by: step1 on Jul 26, 2020, 02:34 am
Hi David,

there ist a black component next to the text U2. If I read it correctly it says J3Y on it. Above it is a resistor (?) R1.

Yes, the original UTFT library does not contain a st7789 driver folder. The UTFT library they (buydisplay.com) provide contains it though. That folder contains the files initlcd.h and setxy.h,

initlcd.h:

Code: [Select]
case ST7789_TFTM013_1:
 LCD_Write_COM(0x11);//Sleep exit
 delay(120);
 
 
 //************* Start Initial Sequence **********//
 LCD_Write_COM(0x36);
 LCD_Write_DATA(0x00);
 //LCD_Write_DATA(0x70);
 
 LCD_Write_COM(0x3A);
 LCD_Write_DATA(0x05);
 
 LCD_Write_COM(0xB2);
 LCD_Write_DATA(0x0C);
 LCD_Write_DATA(0x0C);
 LCD_Write_DATA(0x00);
 LCD_Write_DATA(0x33);
 LCD_Write_DATA(0x33);
 
 LCD_Write_COM(0xB7);
 LCD_Write_DATA(0x35);  
 
 LCD_Write_COM(0xBB);
 LCD_Write_DATA(0x19);
 
 LCD_Write_COM(0xC0);
 LCD_Write_DATA(0x2C);
 
 LCD_Write_COM(0xC2);
 LCD_Write_DATA(0x01);
 
 LCD_Write_COM(0xC3);
 LCD_Write_DATA(0x12);  
 
 LCD_Write_COM(0xC4);
 LCD_Write_DATA(0x20);  
 
 LCD_Write_COM(0xC6);
 LCD_Write_DATA(0x0F);    
 
 LCD_Write_COM(0xD0);
 LCD_Write_DATA(0xA4);
 LCD_Write_DATA(0xA1);
 
 LCD_Write_COM(0xE0);
 LCD_Write_DATA(0xD0);
 LCD_Write_DATA(0x04);
 LCD_Write_DATA(0x0D);
 LCD_Write_DATA(0x11);
 LCD_Write_DATA(0x13);
 LCD_Write_DATA(0x2B);
 LCD_Write_DATA(0x3F);
 LCD_Write_DATA(0x54);
 LCD_Write_DATA(0x4C);
 LCD_Write_DATA(0x18);
 LCD_Write_DATA(0x0D);
 LCD_Write_DATA(0x0B);
 LCD_Write_DATA(0x1F);
 LCD_Write_DATA(0x23);
 
 LCD_Write_COM(0xE1);
 LCD_Write_DATA(0xD0);
 LCD_Write_DATA(0x04);
 LCD_Write_DATA(0x0C);
 LCD_Write_DATA(0x11);
 LCD_Write_DATA(0x13);
 LCD_Write_DATA(0x2C);
 LCD_Write_DATA(0x3F);
 LCD_Write_DATA(0x44);
 LCD_Write_DATA(0x51);
 LCD_Write_DATA(0x2F);
 LCD_Write_DATA(0x1F);
 LCD_Write_DATA(0x1F);
 LCD_Write_DATA(0x20);
 LCD_Write_DATA(0x23);
 
 LCD_Write_COM(0x21);
 

 
 LCD_Write_COM(0x29);//Display on
 break;


setxy.h:

Code: [Select]
case ST7789_TFTM013_1:
 
 LCD_Write_COM(0x2a);
   LCD_Write_DATA(x1>>8);
   LCD_Write_DATA(x1);
   LCD_Write_DATA(x2>>8);
   LCD_Write_DATA(x2);
 LCD_Write_COM(0x2b);
   LCD_Write_DATA(y1>>8);
   LCD_Write_DATA(y1);
   LCD_Write_DATA(y2>>8);
   LCD_Write_DATA(y2);
 LCD_Write_COM(0x2c);
 break;


I had tried the Adafruit_7789 library before and had tried some code (from this site: https://simple-circuit.com/arduino-st7789-ips-tft-display-example/ (https://simple-circuit.com/arduino-st7789-ips-tft-display-example/) )

unfortunately the code is for the UNO and I couldn't figure out the correct pins to use on the DUE. I have tried the SPI pins but I guess there would need to be some additional code to make it work.

So I have tried this code (from the example given by buydisplay.com):

Code: [Select]
/***************************************************
// web: http://www.buydisplay.com
EastRising Technology Co.,LTD
Examples for ER-TFTM013-1
Software SPI 4-Wire SPI Interface 3.3V Power Supply
Library only supports software SPI at this time
NOTE: support  DUE , MEGA , UNO   If you use MEGA and UNO boar, you need to connection level conversion.
       Otherwise the display may not work.
****************************************************/
/*
  == Hardware connection ==
    OLED   =>    Arduino
  *1. GND    ->    GND
  *2. VCC    ->    3.3
  *3. SCL    ->    12
  *4. SDA    ->    11
  *5. RES    ->    8
  *6. DC     ->    9
  *7. BL     ->    10
*/

#include <UTFT.h>

// Declare which fonts we will be using
extern uint8_t SmallFont[];

// Initialize display
// Library only supports software SPI at this time
UTFT myGLCD(ST7789_TFTM013_1,11,12,7,8,9);    //LCD:  4Line  serial interface      SDI  SCL  /CS  /RST  D/C    NOTE:Only support  DUE   MEGA  UNO

// Declare which fonts we will be using
extern uint8_t BigFont[];

int color = 0;
word colorlist[] = {VGA_WHITE, VGA_BLACK, VGA_RED, VGA_BLUE, VGA_GREEN, VGA_FUCHSIA, VGA_YELLOW, VGA_AQUA};
int  bsize = 4;

void drawColorMarkerAndBrushSize(int col)
{
  myGLCD.setColor(VGA_BLACK);
  myGLCD.fillRect(25, 0, 31, 239);
  myGLCD.fillRect(myGLCD.getDisplayXSize()-31, 161, myGLCD.getDisplayXSize()-1, 191);
  myGLCD.setColor(VGA_WHITE);
  myGLCD.drawPixel(25, (col*30)+15);
  for (int i=1; i<7; i++)
    myGLCD.drawLine(25+i, ((col*30)+15)-i, 25+i, ((col*30)+15)+i);
  
  if (color==1)
    myGLCD.setColor(VGA_WHITE);
  else
    myGLCD.setColor(colorlist[col]);
  if (bsize==1)
    myGLCD.drawPixel(myGLCD.getDisplayXSize()-15, 177);
  else
    myGLCD.fillCircle(myGLCD.getDisplayXSize()-15, 177, bsize);
    
  myGLCD.setColor(colorlist[col]);
}

void setup()
{ //backlihgt on/off
// -------------------------------------------------------------
    pinMode(10, OUTPUT);  
    digitalWrite(10, HIGH);//Backlight on
// -------------------------------------------------------------

// Just get some random numbers
  randomSeed(analogRead(0));
  
// Setup the LCD
  myGLCD.InitLCD(PORTRAIT);
  myGLCD.setFont(SmallFont);
  Serial.begin(9600);
int Xsize = myGLCD.getDisplayXSize();int Ysize = myGLCD.getDisplayYSize();
Serial.print(Xsize);Serial.print("x");Serial.print(Ysize);
}

void loop()
{
  int buf[318];
  int x, x2;
  int y, y2;
  int r;
  myGLCD.setFont(SmallFont);
// Clear the screen and draw the frame
  myGLCD.clrScr();

  myGLCD.setColor(255, 0, 0);
  myGLCD.fillRect(0, 0, 239, 13);
  myGLCD.setColor(64, 64, 64);
  myGLCD.fillRect(0, 226, 239, 239);
  myGLCD.setColor(255, 255, 255);
  myGLCD.setBackColor(255, 0, 0);
  myGLCD.print("* EastRising Technology  *", CENTER, 1);
  myGLCD.setBackColor(64, 64, 64);
  myGLCD.setColor(255,255,0);
  myGLCD.print("<http://buydisplay.com>", CENTER, 227);

  myGLCD.setColor(0, 0, 255);
  myGLCD.drawRect(0, 14, 239, 225);

// Draw crosshairs
  myGLCD.setColor(0, 0, 255);
  myGLCD.setBackColor(0, 0, 0);
  myGLCD.drawLine(119, 15, 119, 224);
  myGLCD.drawLine(1, 119, 238, 119);
  for (int i=9; i<230; i+=10)
    myGLCD.drawLine(i, 117, i, 121);
  for (int i=19; i<220; i+=10)
    myGLCD.drawLine(117, i, 121, i);

// Draw sin-, cos- and tan-lines  
  myGLCD.setColor(0,255,255);
  myGLCD.print("Sin", 5, 15);
  for (int i=1; i<238; i++)
  {
    myGLCD.drawPixel(i,119+(sin(((i*1.13)*3.14)/180)*95));
  }
  
  myGLCD.setColor(255,0,0);
  myGLCD.print("Cos", 5, 27);
  for (int i=1; i<238; i++)
  {
    myGLCD.drawPixel(i,119+(cos(((i*1.13)*3.14)/180)*95));
  }

  myGLCD.setColor(255,255,0);
  myGLCD.print("Tan", 5, 39);
  for (int i=1; i<238; i++)
  {
    myGLCD.drawPixel(i,119+(tan(((i*1.13)*3.14)/180)));
  }

  delay(2000);

  myGLCD.setColor(0,0,0);
  myGLCD.fillRect(1,15,238,224);
  myGLCD.setColor(0, 0, 255);
  myGLCD.setBackColor(0, 0, 0);
  myGLCD.drawLine(119, 15, 119, 224);
  myGLCD.drawLine(1, 119, 238, 119);

// Draw a moving sinewave
  x=1;
  for (int i=1; i<(238*20); i++)
  {
    x++;
    if (x==239)
      x=1;
    if (i>239)
    {
      if ((x==119)||(buf[x-1]==119))
        myGLCD.setColor(0,0,255);
      else
        myGLCD.setColor(0,0,0);
      myGLCD.drawPixel(x,buf[x-1]);
    }
    myGLCD.setColor(0,255,255);
    y=119+(sin(((i*1.1)*3.14)/180)*(90-(i / 100)));
    myGLCD.drawPixel(x,y);
    buf[x-1]=y;
  }

  delay(2000);
  
  myGLCD.setColor(0,0,0);
  myGLCD.fillRect(1,15,238,224);


... code goes on, too long to post  :smiley-confuse:
  
  
}


but as I said, except for the fact that the size info and the backlight function work the display simply won't display anything.

step1
Title: Re: don't get my display to display anything
Post by: ard_newbie on Jul 26, 2020, 06:13 am
Maybe this document might help you:

http://www.rinkydinkelectronics.com/resource/UTFT/UTFT.pdf (http://www.rinkydinkelectronics.com/resource/UTFT/UTFT.pdf)

and this topic (reply #13), eventhough it's for 5'' or 7'' displays:

https://forum.arduino.cc/index.php?topic=286567.0 (https://forum.arduino.cc/index.php?topic=286567.0)
Title: Re: don't get my display to display anything
Post by: david_prentice on Jul 26, 2020, 10:34 am
Quote
there ist a black component next to the text U2. If I read it correctly it says J3Y on it. Above it is a resistor (?) R1.
J3Y is an NPN transistor that switches the backlight LED.
There is no 3.3V regulator on the pcb.   Connect VCC to 3.3V pin in your Due.

Note that the AliExpress advert is criminal when it says: "VCC: DC 3.3-5V".    This is deliberately attempting to lie to 5V Uno, Mega2560 owners.

The Due has good 3.3V pin and has regular 3.3V logic levels.   So should be fine.

The display has no CS pin which is crazy.   It prevents reading GRAM memory.  It prevents using other SPI devices on the SPI bus.

However several libraries cope with this "no CS" display.
Quote
I had tried the Adafruit_7789 library before and had tried some code (from this site: https://simple-circuit.com/arduino-st7789-ips-tft-display-example/ )
This site looks fine.   Note that the Due has hardware SPI is on the 3x2 header.   So you use Digital #75, digital #76 instead of #11, #13.

Always install libraries via the IDE Library Manager.   
I suggest that you connect to the hardware SPI pins.    But test with  the software constructor first.

When the display is working 100% with software constructor,   try the hardware constructor.   It will be a lot faster.

I would not bother with UTFT unless you enjoy SLOW displays.

Build library examples.
Quote example by name.   Paste only your constructor statement.   (no point in pasting the whole public example sketch)
 
Wire carefully.    Post a photo.    So readers can compare your wires with your constructor.

David.
Title: Re: don't get my display to display anything
Post by: step1 on Jul 26, 2020, 04:06 pm
Hi David,

it is working now. Yesterday before I asked I almost had it right except for that I had changed the value in tft.init(240, 240, SPI_MODE2) to mode 0 and afterwards (when I had wired it correctly) did not set it back to mode 2. I am currently using it with an ultrasonic device to measure distance. Here's the main code for the display:

Code: [Select]
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>             // Arduino SPI library

#define TFT_CS    10  // define chip select pin
#define TFT_DC    9  // define data/command pin
#define TFT_RST   8  // define reset pin, or set to -1 and connect to Arduino RESET pin
 
// Initialize Adafruit ST7789 TFT library
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

int distance;

[...]


void setup() {
[...]
tft.init(240, 240, SPI_MODE2);tft.setRotation(2);
tft.fillScreen(ST77XX_BLUE);
}

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

[...]

void loop() {

[...]

  tft.fillScreen(ST77XX_BLUE);
  testdrawtext(distance, ST77XX_WHITE,6,"cm");}

[...]
}

and the wiring as you said (instead of #11 and #13 use D75, D76 i.e. MOSI (SDA), SCK), rest as in the simple-circuit.com link above.

Thanks for you help, David!

also thanks to ard_newbie for the links

step1
Title: Re: don't get my display to display anything
Post by: step1 on Jul 27, 2020, 03:21 am
Quote
However several libraries cope with this "no CS" display.
I am now at the point where I guess I need those libraries! Although the display works fine with the standard commands (writing text etc.) I would like to make use of a micro SD reader to load an image to the display. I have already connected the reader and it even reports a "Success" when loading the image. Unfortunately there only appear a few lines of gibberish on the display instead of the actual image. Depending on the image I use the code sometimes hangs.

So here's the micro SD reader I use:
https://www.aliexpress.com/item/32728051288.html (https://www.aliexpress.com/item/32728051288.html)

and here the code:
Code: [Select]

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SdFat.h>                // SD card & FAT filesystem library
#include <Adafruit_ImageReader.h>
#include <SPI.h>             // Arduino SPI library

#define TFT_CS    10  // define chip select pin
#define TFT_DC    9  // define data/command pin
#define TFT_RST   8  // define reset pin, or set to -1 and connect to Arduino RESET pin
#define SD_CS   52 // SD card select pin
 
// Initialize Adafruit ST7789 TFT library
Adafruit_ST7789 tft = Adafruit_ST7789(-1, TFT_DC, TFT_RST);
SdFat SD;         // SD card filesystem
Adafruit_ImageReader reader(SD); // Image-reader object, pass in SD filesys

[...]

int distance;

[...]

void setup() {
  tft.init(240, 240, SPI_MODE2);tft.setRotation(2);
  tft.fillScreen(ST77XX_BLUE);
  Serial.begin(9600);
  if(!SD.begin(SD_CS, SD_SCK_MHZ(25))) { // ESP32 requires 25 MHz limit
  Serial.println(F("SD begin() failed"));
  for(;;); // Fatal error, do not continue
  }

ImageReturnCode stat;
stat = reader.drawBMP("1.bmp", tft, 0, 0);
reader.printStatus(stat);  // <-- THIS SHOWS "SUCCESS" ON THE SERIAL MONITOR
delay(5000);
[...]

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

void loop() {
[...]

  tft.fillScreen(ST77XX_BLUE);
  testdrawtext(distance, ST77XX_WHITE,6,"cm");}

[...]

}



I have wired the reader to the 5V pin and GND. SCK & MOSI are on the same pins (SPI Bus) as the display - I guess that's called 'in series'. In addition the MISO pin of the reader goes to the MISO pin on the SPI Bus.

So how can I get the display to show the image (correctly)? I guess the problem is with the lack of the CS pin on the display as you said, David. Two devices trying to share the SPI but only one has a CS pin.

I hope you are still following this thread :)

step1

ps. btw, what is GRAM?
Title: Re: don't get my display to display anything
Post by: david_prentice on Jul 27, 2020, 09:05 am
GRAM is Graphics Random Access Memory.

The controller stores every pixel in its on-chip RAM.
Most if not all TFT controllers have RAM and you can read the RAM (unless the external electronics prevents it)

I have never managed to use a "no CS" display to its full extent.

Your Due has only got one hardware SPI peripheral.
Which means you have to choose whether you use HW SPI for display or SD card.    And bit-bang SPI in software for the less important device.

It is a mystery why they chose to add Backlight control but omit CS.

David.
Title: Re: don't get my display to display anything
Post by: ard_newbie on Jul 27, 2020, 09:37 am

FYI the USART peripheral (USART0, USART1, USART2, USART3) can work in SPI mode too (Master or Slave).

See chapter 35.2.
Title: Re: don't get my display to display anything
Post by: david_prentice on Jul 27, 2020, 11:08 am
Ah-ha.   I am not familiar with the SAM3XE.

It looks as if PA11, PA10, PA17 can operate as MOSI0, MISO0, SCK0
Or PA13, PA12, PA16 as MOSI1, MISO1, SCK1

PA17 is available on the SDA1 header,   PA16 is A0 on the Analog header.

It should be relatively easy to drive the ST7789 via USART_MSPI.

SCK2, SCK3 are not available on any Due headers.    But at least the Due has SCK0, SCK1.
The MEGA2560 was deliberately designed with no access to SCK0, SCK1, SCK2, SCK3 at all.
Since the AVR SPI peripheral is crap it seems crazy that the Arduino designers prevent AVR USART_MSPI

I still reckon that the ST7789 board should have a CS pin in the first place.

David.

Title: Re: don't get my display to display anything
Post by: step1 on Jul 27, 2020, 07:14 pm
David,

thanks for the information. What you are saying concerning RAM makes me think: would it be possible to load the image file to the internal memory of the DUE and then from there to the display? Probably that's the way it works anyway. Or maybe the image data is directly fed to the TFT memory/ RAM? I am really not that well informed and a little slow on the uptake :D. Also, as for bit-banging, I see that's actually a method to "emulate" the SPI via software. Too complicated for me at the moment. I was looking for a ready-to-use sketch (with some minor adjustments necessary) or just a few templates to work with, could not come up with something though. And if I understand you correctly you are saying that you did not have any luck with those NO-CS displays displaying images either or have you only been dissatisfied with performance? Anyways, I guess I'll have to buy a CS display then, right?

step1
Title: Re: don't get my display to display anything
Post by: david_prentice on Jul 27, 2020, 07:35 pm
In an ideal world you would have a CS pin.

Perhaps you could "trick" the ST7789 to ignore any SPI traffic.    Write to other SPI devices.   Then "trick" the ST7789 to listen to SPI traffic intended for the TFT.
My attempts have never succeeded.

I suggest that you use the regular SD.h library for the SD card connected to HW SPI pins.
And use the software constructor to bit-bang the TFT on (different) random GPIO pins.

Then you don't need any "library writing skills".

But seriously,   TFT displays are cheap.   Buy one that is already on a Shield that will plug directly into your Due.

David.
Title: Re: don't get my display to display anything
Post by: step1 on Jul 27, 2020, 08:15 pm
meanwhile I have seen many threads on this forum that have been posted over the years and dealing with the topic. You have been pretty active in those threads trying to help and even contributed to the libraries. So if you won't get those "NO CS" displays to work properly with other SPI devices I most certainly won't either :D And thus I guess it's really better trying to find a different display :)

The thing is, as far as I can see there are no other 240 x 240 displays with a CS pin. I would not buy one with less resolution. I think this one looks promising:

https://www.aliexpress.com/item/33039755727.html (https://www.aliexpress.com/item/33039755727.html)

it has a CS pin, high resoltion and comes with an on-board SD reader. But this time I'll first check for available sketches before I buy it :D

If you like feel free to recommend a display. It should be at least 240x240 resolution and suitable for the DUE (without the need for LLCs)... and not cost more than 10 bucks :smiley-money:


step1
Title: Re: don't get my display to display anything
Post by: step1 on Jul 29, 2020, 02:16 am
Perhaps you could "trick" the ST7789 to ignore any SPI traffic.    Write to other SPI devices.   Then "trick" the ST7789 to listen to SPI traffic intended for the TFT.
My attempts have never succeeded.
David, I just managed (after a whole day of trying  :smiley-fat: ) to display an image on the TFT. Making the ST7789 ignore the SPI traffic is part of the solution. The other part is loading the BMP data into an array. I ran into memory issues at first because the resolution is 240 x 240 (this means 3x 57600 Bytes while the DUE only has 96kB of SRAM) which means only about half of the memory needed is available on the DUE for use. So I run the for loop (for reading the pixels into the array) twice, making the TFT ignore the SPI each time. As soon as the array is full the TFT can listen to the SPI again and retrieve the pixel data from the array. Can post the code tomorrow (need some sleep right now  :smiley-sleep: )

step1
Title: Re: don't get my display to display anything
Post by: david_prentice on Jul 29, 2020, 10:32 am
I might have another go at this.

My theory was to send a writeCmd(NOP) and then set DC to Data.
The NOP should terminate any multi-pixel write.
The ST7789 should ignore anything on the bus unless it has DC set to Command.

I am sure that I had tried this some years ago.   Without success.

But the real problem is "how to stop a multi-pixel read".
Just altering DC to Command will not reverse the bidirectional data pin.   (but CS going false does work)

David.
Title: Re: don't get my display to display anything
Post by: step1 on Jul 29, 2020, 11:17 am
I had a similar idea. In one of the older threads you mentioned that the ST7735 could be sent to sleep mode. In a data sheet of a similar device I found out that in this mode the memory of the display stays preserved. But I couldn't find out how to put the ST7789 into sleep mode. So I tried something else. It came to me by accident more or less. Remember when I said that I forgot to change the SPI_MODE back from 0 to 2? Mode 0 prevents the display from receiving data. How - that I don't know. But that was the crucial idea: I set SPI_MODE0 for ignoring the SPI bus and then back to SPI_MODE3 to listen to it again. It seems that while in MODE0 the display is "fighting back" the data as it flickers just a tiny bit. But that may also be due to bad connections on the breadboard.

here is the code:

Code: [Select]
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SD.h>                // SD card & FAT filesystem library
#include <SPI.h>             // Arduino SPI library

#define TFT_CS    10  // define chip select pin
#define TFT_DC    9  // define data/command pin
#define TFT_RST   8  // define reset pin, or set to -1 and connect to Arduino RESET pin
#define SD_CS   4 // SD card select pin
 
// Initialize Adafruit ST7789 TFT library
Adafruit_ST7789 tft = Adafruit_ST7789(-1, TFT_DC, TFT_RST);

// defines variables

bool c=false;

int32_t width;
int32_t height;

int32_t readNbytesInt(File *p_file, int position, byte nBytes)
{
    if (nBytes > 4)
        return 0;

    p_file->seek(position);

    int32_t weight = 1;
    int32_t result = 0;
    for (; nBytes; nBytes--)
    {
        result += weight * p_file->read();
        weight <<= 8;
    }
    return result;
}

void setup() {
  
Serial.begin(9600);
    while (!Serial);

    Serial.print("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("initialization failed!");
        while (1); // <- this is how you should block execution, not with returns
    }
    Serial.println("initialization done.");

}

void drawBMP(){
  // Open
    File bmpImage = SD.open("/1.bmp", FILE_READ);

    int32_t dataStartingOffset = readNbytesInt(&bmpImage, 0x0A, 4);

    // Change their types to int32_t (4byte)
    width = readNbytesInt(&bmpImage, 0x12, 4);
    height = readNbytesInt(&bmpImage, 0x16, 4);
    Serial.println(width);
    Serial.println(height);

    int16_t pixelsize = readNbytesInt(&bmpImage, 0x1C, 2);

    if (pixelsize != 24)
    {
        Serial.println("Image is not 24 bpp");
        while (1);
    }

    bmpImage.seek(dataStartingOffset);//skip bitmap header

    // 24bpp means you have three bytes per pixel, usually B G R
int s;
for(s=0;s<2;s++){
    byte R[28800], G[28800], B[28800];
    int i,j;
    for(i = 0; i < 28800; i++) {
            B[i] = bmpImage.read();
            G[i] = bmpImage.read();
            R[i] = bmpImage.read();
        }
Serial.println("done read.");

    tft.init(240, 240, SPI_MODE3); // <-- important to put this here. AFTER filling the array.
    if(s==0)tft.setRotation(0);
        tft.startWrite();
        tft.setAddrWindow(0, 120*s, width, height); // first load lower half of the image, then in second run of the loop load upper half
        
          for (i=0; i<120; i++) {
            for(j=1;j<241;j++){
              tft.pushColor(tft.color565(R[(i+1)*240-j],G[(i+1)*240-j],B[(i+1)*240-j])); // image is mirrored left to right, hence the transformation
          }}

        tft.endWrite();if(s==0)tft.init(240, 240, SPI_MODE0);} // crucial step: SPI_MODE0 prevents the display from receiving data via the SPI that is meant for the SD card reader.

bmpImage.close();
delay(10000); // showing the image for 10 seconds
}

void loop() {
  
if(c==false){drawBMP();c=true;} // shows image only once

// [...] any other code you want

}


for reading the BMP I used this source:
https://arduino.stackexchange.com/questions/38332/serial-write-pixels-of-a-bmp-image

of course reading takes a couple of seconds this way but the goal was achieved :)

step1

ps. maybe I'm going to make a video about this. Takes some work though.

edit: for wiring see attachment

edit II: video added: https://youtu.be/xU1gWKsm9oY (https://youtu.be/xU1gWKsm9oY)