Need help with esp32 and 1.54" 3 wire 9 bit display

Dear Hardware/Arduino Gods,

I need help with my display to get it up and running.

I'm using ESP32 Dev module in Arduino with the display -

Link

The display is 3 wire SPI, with 9 bits, ST7789V.

There is no Command/Data signifying line. That data is added as MSB, i.e. the 9th bit before the command/Data byte.

I am using the Adafruit's library but I have modified it. I checked the display, it's working on some other processor, unfortunately, I don't have the code for it.

Here is the code that I have modified in Adafruit library -

Following is the code I'm using to initialize the display, ie its the driver supplied by the manufacturer.

void Adafruit_ST77xx::InitDisplay(){


spiWriteCMD9thBitFor3Wire (0x11);
delay(120); //Delay 120ms

//-------------------------------display and color format setting-----------------------------//
spiWriteCMD9thBitFor3Wire (0x36); 
spiWrite (0x00);

spiWriteCMD9thBitFor3Wire (0x3A);  
spiWrite (0x06);//  #06

//--------------------------------ST7789S Frame rate setting----------------------------------//
spiWriteCMD9thBitFor3Wire (0xB2);  
spiWrite (0x0C);  
spiWrite (0x0C);  
spiWrite (0x00);  
spiWrite (0x33);  
spiWrite (0x33);

//spiWriteCMD9thBitFor3Wire (0xB7);  
//spiWrite (0x75);//check this, other try 34, 35, 70

//---------------------------------ST7789S Power setting--------------------------------------//

spiWriteCMD9thBitFor3Wire (0xBB);  
spiWrite (0x1A);// other - 1c, 2B, 35

spiWriteCMD9thBitFor3Wire (0xC0);  
spiWrite (0x2C);

spiWriteCMD9thBitFor3Wire (0xC2);  
spiWrite (0x01);

//added by crystal-
spiWrite (0xFF);
//end

spiWriteCMD9thBitFor3Wire (0xC3); 
spiWrite (0x0F);//others

spiWriteCMD9thBitFor3Wire (0xC4);  
spiWrite (0x20);

spiWriteCMD9thBitFor3Wire (0xC6);  //frame rate
spiWrite (0x0F);

spiWriteCMD9thBitFor3Wire (0xD0);  
spiWrite (0xA4);  
spiWrite (0xA1);

//--------------------------------ST7789S gamma setting---------------------------------------//
spiWriteCMD9thBitFor3Wire (0xE0);  
spiWrite (0xD0);  
spiWrite (0x13);  
spiWrite (0x1A);  
spiWrite (0x0A);  
spiWrite (0x0A);  
spiWrite (0x26);  
spiWrite (0x3F);  
spiWrite (0x54);  
spiWrite (0x54);  
spiWrite (0x18);  
spiWrite (0x14);  
spiWrite (0x14);  
spiWrite (0x30);  
spiWrite (0x33);

spiWriteCMD9thBitFor3Wire (0xE1);  
spiWrite (0xD0);  
spiWrite (0x13);  
spiWrite (0x1A);  
spiWrite (0x0A);  
spiWrite (0x0A);  
spiWrite (0x26);  
spiWrite (0x3F);  
spiWrite (0x54);  
spiWrite (0x54);  
spiWrite (0x1A);  
spiWrite (0x16);  
spiWrite (0x16);  
spiWrite (0x32);  
spiWrite (0x35);


spiWriteCMD9thBitFor3Wire (0x29);

}

Following are the functions I'm using to write the 9 bits command or data -

  1. For command write -
void Adafruit_SPITFT::spiWriteCMD9thBitFor3Wire(uint8_t b) {

    if(_sclk < 0){
        HSPI_WRITE(b);
        return;
    }

 SSPI_MOSI_LOW(); // since its a command, so low
 SSPI_SCK_LOW(); // Clock it in
        SSPI_SCK_HIGH();

 // Now send the remaining 8 bits
    for(uint8_t bit = 0x80; bit; bit >>= 1){
        if((b) & bit){
            SSPI_MOSI_HIGH();
        } else {
            SSPI_MOSI_LOW();
        }
        SSPI_SCK_LOW();
        SSPI_SCK_HIGH();
    }
}

and the Data write -

void Adafruit_SPITFT::spiWrite(uint8_t b) {
    if(_sclk < 0){
        HSPI_WRITE(b);
        return;
    }

 SSPI_MOSI_HIGH(); // since its a Data, so HIGH
 SSPI_SCK_LOW(); // Clock it in
        SSPI_SCK_HIGH();

    for(uint8_t bit = 0x80; bit; bit >>= 1){
        if((b) & bit){
            SSPI_MOSI_HIGH();
        } else {
            SSPI_MOSI_LOW();
        }
        SSPI_SCK_LOW();
        SSPI_SCK_HIGH();
    }
}

I have made relevant changes in the library to call these functions, the code compiles properly, but the screen doesn't show anything. Its blank sort of. Please check image -

The wiring is correct as per the datasheet of the display, see attachment. I have externally attached 1K Ohm pull-up resistors to SDA and SCLK lines as well (Not shown in the attachment).

#define TFT_CS 5
#define TFT_RST 4
#define TFT_DC 2
#define TFT_MOSI 23
#define TFT_SCLK 18
#define LCD 13 // to power ON/Off the LCD

I'm not sure where is the fault, I feel may be the 9bit code that I'm sending out is the issue here, it doesn't look like it, but maybe?
Do I need 1K pull up resistors for SCL and SDA lines? I'm lost and any help is greatly appreciated.

PS - This is my first post here, so please be gentle with me if I have overlooked the forum posting codes.

From the Adafruit_SPITFT library:

/**************************************************************************/
/*!
    @brief   Write a command byte (must have a transaction in progress)
    @param   cmd  The 8-bit command to send
*/
/**************************************************************************/
void Adafruit_SPITFT::writeCommand(uint8_t cmd){
    SPI_DC_LOW();
    spiWrite(cmd);
    SPI_DC_HIGH();
}

Any subsequent "data" writes just use spiWrite(c) because the DC line has been left in "data" mode.

Alter any spiWrite() calls to writeData()
and create your own local writeCommand() and writeData() functions e.g. to write the 9th bit instead of a separate DC line.

Get it running in bit-bash mode.
Then you can implement the hardware version that uses the ESP32 hardware SPI.

You can swap between 4-wire and 3-wire with a conditional that uses SPITFT or local for the writeCommand() and writeData() primitives.

Untested.

David.

Hi David,

Thanks for the reply.

That's what I did in the two functions that I mentioned in my first post. Sorry if it wasn't clear. I commented out the Adafruit's WriteCommand function and directed all hits from that function to my spiWriteCMD9thBitFor3Wire() function. This function is shown in the first post. This function is used for the command writes.

The spiWrite() function is used for the data, also shown in the first post.

I realized that it should work, theoretically, but it's not working. By the way, the DC line is useless as defined initially in the code, it's there just for the sake of it. It is however connected to SDA1 pin on the display. I asked the manufacturer for the use of SDA1 and he said that SDA1 line can be left no connection. So I'm assuming it's useless. Not sure how it will help, but just telling you.

Sorry I didn't understand the bit-bash mode?

Edited- is this what you are referring to? I'll try it and tell you.

To reply to the last part- ( I hope I understood your point correctly)
I thought of adding a conditional sentence for my purpose, but I ended up cloning the entire adafruit library and changing it as per my need. I have been stuck here for few days, and I'll polish the solution, once I find it!

Really appreciate your help!

Sxk1185

@sxk1185

The ESP32 may be too fast for software SPI (bit-bash) with your display. Try add dummy instructions between setting CLK LOW and HIGH. Make sure the compiler does not eliminate (optimize) the dummy instructions. Adafruit_SPITFT software SPI may be slow enough on AVR Arduino only.

My apologies. Your method is much the same as my suggestion.

Who told you the interface setting?

IM# = 0b0101   9-bit / 2-data lane bidirectional
IM# = 0b0110   8-bit bidirectional
IM# = 0b1101   9-bit
IM# = 0b1110   8-bit

I suspect that it uses IM = 0b0110 i.e. 8-bit bidirectional.
SDA = SDA bidirectional data
SDA1 = DC
SCL = SCK
CS = CS

In other words, you can try the Adafruit library as-is.

If that does not work, try mode 0b0101

I only have mode = 0b0110 ST7789V display.

I can post a sketch that reads the ID via different interface styles.
Most ST7735 / ILI9163 displays use 4-wire bidirectional

I doubt if the ESP32 is too fast for bit-bash. I will try it. (normally I use ESP32 hardware SPI)

David.

The maximum ESP32 GPIO update rate is 20MHz due to the register access timing. This means the highest output clock frequency you can bit bash by toggling a GPIO pin is 10MHz. I found this out by using an oscilloscope during testing of the TFT_eSPI library with an 8 bit parallel TFT.

@ David,

I asked the manufacturer, he said its a 9-bit communication.

So, I checked the datasheet for the display and the driver IC. Please check the interface image. Two possible interfaces for 9-bit communication. I guess, its the highlighted one, with WRX pin, which is useless as mentioned in Image2 (attached) in ST7789H2 datasheet.

If I can read the interface mode, that will be a great start.

I tried the default Adafruit library for 240x240 display, it didn't work.
I tried switching SDA1 and SDA, didn't work.

Do you think the display's registers may be the problem? i.e. the drivers = the initial code that I'm sending to set up the display?

@ bodmer & ZinggJM:

Thanks for the reply. I haven't tried the bit-bash as of now. Its new to me and I'm not very sure of it.
One thing, I'm using OTA for everything, so I wanna avoid adding wires to the PCB, but will do as a last resort. See this link for the look of the product - YouTube

Edited - I do have access to the serial lines via USB though :slight_smile:

Regarding bit-bash speed from ESP32. My ST7789V display is running fine with software constructor in the Adafruit library.

Your Pinout diagram showed:
SDA
SDA1
SCL
CS

I would assume that SDA1 is either going to be DC or SDO pin. There is little point in a manufacturer doing anything different.
If it is DC the SDA pin is bidirectional.
If it is SDO then it must use 9-bit SPI.

Since you are in communication with the Manufacturer, ask her which IM# interface setting is used.

Of course there might be language problems. In which case you simply try each interface style. Read the ID.

David.

Here is a diagnostic sketch ST7789_readreg_diag.ino

/*
Serial.println("1. select correct defines for your board wiring");
Serial.println("2. select correct interface type");
Serial.println("3. select appropriate report function");
Serial.println("");
Serial.println("certain registers read first byte e.g. 0x00-0x0F, 0xDA-0xDC");
Serial.println("other multi-argument registers read first byte as dummy");
Serial.println("");
*/

#if defined(ESP32)
#define TFT_MOSI 23
#define TFT_MISO 19
#define TFT_SCK  18
#define TFT_SS   5
#define TFT_DC   13     //DC=7 for HX8347
#define TFT_RESET 12   //Backlight on HX8347
#elif defined(ESP8266)
#define TFT_MOSI D11
#define TFT_MISO D12
#define TFT_SCK  D13
#define TFT_SS   D10
#define TFT_DC   D9     //DC=7 for HX8347
#define TFT_RESET D8   //Backlight on HX8347
#else                   //suits Uno, Nucleo, ...
#define TFT_MOSI 11
#define TFT_MISO 12
#define TFT_SCK  13
#define TFT_SS   10
#define TFT_DC  (9)     //DC=7 for HX8347
#define TFT_RESET (8)   //Backlight on HX8347
#endif

#define NINEBITS  (1<<0)
#define SDA_BIDIR (1<<1)
#define HAS_MISO  (1<<2)
#define IS_9341   (1<<3)
#define IS_9481   (1<<4)
#define IS_9486   (1<<5)
const char *chip = "controller";
char interface = SDA_BIDIR;    //ST7789 bidirectional SDA + DC
//char interface = NINEBITS | SDA_BIDIR;  //3-wire SPI bidirectional SDA
//char interface = NINEBITS | HAS_MISO;  //4-wire SDA + SDO
//char interface = HAS_MISO | IS_9341;  //ILI9341 SPI
//char interface = HAS_MISO | IS_9481;  //ILI9481 SPI
//char interface = HAS_MISO | IS_9486;  //ILI9486 SPI
//char interface = HAS_MISO;  //regular SPI
//char interface = NINEBITS | SDA_BIDIR | IS_9481;  //ILI9481 3-wire SPI bidirectional pin

uint32_t ID = 0;

void setup() {
    // put your setup code here, to run once:
    Serial.begin(9600);

    Serial.println("");
    Serial.println("1. select correct defines for your board wiring");
    Serial.println("2. select correct interface type");
    Serial.println("3. select appropriate report function");
    Serial.println("");
    Serial.println("certain registers read first byte e.g. 0x00-0x0F, 0xDA-0xDC");
    Serial.println("other multi-argument registers read first byte as dummy");
    Serial.println("");

    if (interface & HAS_MISO)
        Serial.println("Read registers 8-bit SPI with MISO (+ DC)");
    else if (interface & NINEBITS)
        Serial.println("Bi-directional Read registers 9-bit SPI");
    else
        Serial.println("Bi-directional Read registers SDA (+ DC)");
    digitalWrite(TFT_SS, HIGH);
    //    digitalWrite(TFT_SCK, HIGH);
    pinMode(TFT_SS, OUTPUT);
    pinMode(TFT_SCK, OUTPUT);
    pinMode(TFT_MOSI, OUTPUT);
    pinMode(TFT_MISO, INPUT);
    pinMode(TFT_DC, OUTPUT);
    pinMode(TFT_RESET, OUTPUT);
    reset_pulse();
    soft_reset();
    ID = readwrite8(0x04, 24, 1);
    ID = readwrite8(0x04, 24, 1);  //ST7789 needs twice
    Serial.print("read reg(4):  ID = 0x");
    Serial.println(ID, HEX);
    if (ID == 0x858552uL) chip = "ST7789V";
    if (ID == 0x7C89F0uL) chip = "ST7735S";
    if (ID == 0x548066uL) chip = "ILI9163C";
    if ((ID & 0xFF0000) == 0x5C0000) chip = "ST7735";
    if (interface & SDA_BIDIR) {
        uint8_t sda_en = 0x80;
        if (interface & IS_9481) writeblock(0xc6, &sda_en, 1);
    }
    read_7735(chip);
    //    read_7735_9481(chip);
    //    read_regs("diagnose any controller");
    //    read_61509("R61509 / ILI9326");
    //    read_9327("ILI9327");
    //    read_9338("ILI9302 / ILI9329 / ILI9338 / ILI9341");
    //    if (interface & NINEBITS) find_sekret();
    //    read_9481("ILI9481 / HX8357 / R61581");
    //    read_9486("ILI9486 / 1LI9488");
}

void reset_pulse(void)
{
    digitalWrite(TFT_RESET, HIGH);
    digitalWrite(TFT_RESET, LOW);   //Hardware Reset
    delay(10);
    digitalWrite(TFT_RESET, HIGH);
    delay(10);
}

void soft_reset(void)
{
    writeblock(0x01, NULL, 0);   //software reset
    delay(10);
}

void read_7735(const char *title)
{
    Serial.println(title);
    Serial.println("data sheet specific calls");
    show7735(0x04, 3, 1);  //RDDID
    show7735(0x09, 4, 1);  //RDDSTATUS
    show7735(0x0A, 1, 0);
    show7735(0x0B, 1, 0);   //RDDMADCTL
    show7735(0x0C, 1, 0);   //RDDCOLMOD
    show7735(0x0D, 1, 0);
    show7735(0x0E, 1, 0);
    show7735(0x0F, 1, 0);
    show7735(0xDA, 1, 0);   //RDID1
    show7735(0xDB, 1, 0);   //RDID2
    show7735(0xDC, 1, 0);   //RDID3
}

void read_7735_9481(const char *title)
{
    Serial.println(title);
    Serial.println("data sheet specific calls");
    show7735(0x0A, 1, 0);
    show7735(0x0B, 1, 0);   //RDDMADCTL
    show7735(0x0C, 1, 0);   //RDDCOLMOD
    show7735(0x0D, 1, 0);
    show7735(0x0E, 1, 0);
    show7735(0x0F, 1, 0);
    show7735(0xA1, 4, 1);  //ILI9481 DDB_Start
    show7735(0xBF, 4, 1);  //ILI9481 ID
}

uint32_t readwrite8(uint8_t cmd, uint8_t bits, uint8_t dummy)
{
    digitalWrite(TFT_SS, LOW);
    write9(cmd, 0);
    uint32_t ret = read8(bits, dummy);
    digitalWrite(TFT_SS, HIGH);
    return ret;
}

void write9(uint8_t val, uint8_t dc)
{
    pinMode(TFT_MOSI, OUTPUT);
    digitalWrite(TFT_DC, dc);
    if (interface & NINEBITS) {
        digitalWrite(TFT_MOSI, dc);
        delay(1);
        digitalWrite(TFT_SCK, HIGH);
        delay(1);
        digitalWrite(TFT_SCK, LOW);
    }
    for (int i = 0; i < 8; i++) {   //send command
        digitalWrite(TFT_MOSI, (val & 0x80) != 0);
        delay(1);
        digitalWrite(TFT_SCK, HIGH);
        delay(1);
        digitalWrite(TFT_SCK, LOW);
        val <<= 1;
    }
}

void writeblock(uint8_t cmd, uint8_t *block, int8_t N)
{
    uint8_t val = cmd;
    digitalWrite(TFT_SS, LOW);
    write9(cmd, 0);
    while (N-- > 0) write9(*block++, 1);
    digitalWrite(TFT_SS, HIGH);
}

uint32_t read8(uint8_t bits, uint8_t dummy)
{
    uint32_t ret = 0;
    uint8_t SDAPIN = (interface & HAS_MISO) ? TFT_MISO : TFT_MOSI;
    pinMode(SDAPIN, INPUT_PULLUP);
    digitalWrite(TFT_DC, HIGH);
    for (int i = 0; i < dummy; i++) {  //any dummy clocks
        digitalWrite(TFT_SCK, HIGH);
        delay(1);
        digitalWrite(TFT_SCK, LOW);
        delay(1);
    }
    for (int i = 0; i < bits; i++) {  // read results
        ret <<= 1;
        delay(1);
        if (digitalRead(SDAPIN)) ret |= 1;;
        digitalWrite(TFT_SCK, HIGH);
        delay(1);
        digitalWrite(TFT_SCK, LOW);
    }
    return ret;
}

void show7735(uint8_t reg, uint8_t bytes, uint8_t dummy)
{
    uint32_t val, mask = 0x10000000;
    uint8_t bits = bytes * 8;
    for (uint8_t wid = 32; wid > bits; wid -= 4) mask >>= 4;
    //    reset_pulse();    //ST7789V not happy with this
    soft_reset();
    val = readwrite8(reg, bits, dummy);

    Serial.print(chip);
    Serial.print(" reg(0x");
    if (reg < 0x10) Serial.print("0");
    Serial.print(reg , HEX);
    Serial.print(") = 0x");
    while (val < mask) Serial.print("0"), mask >>= 4;
    if (val) Serial.println(val, HEX);
    else Serial.println();
}

void printhex(uint8_t val)
{
    if (val < 0x10) Serial.print("0");
    Serial.print(val, HEX);
}

void loop()
{
    // put your main code here, to run repeatedly:
    yield();
}

This is the result from my IM = 0b0110 display.

1. select correct defines for your board wiring
2. select correct interface type
3. select appropriate report function

certain registers read first byte e.g. 0x00-0x0F, 0xDA-0xDC
other multi-argument registers read first byte as dummy

Bi-directional Read registers SDA (+ DC)
read reg(4):  ID = 0x858552
ST7789V
data sheet specific calls
ST7789V reg(0x04) = 0x858552
ST7789V reg(0x09) = 0x00610000
ST7789V reg(0x0A) = 0x08
ST7789V reg(0x0B) = 0x00
ST7789V reg(0x0C) = 0x06
ST7789V reg(0x0D) = 0x00
ST7789V reg(0x0E) = 0x00
ST7789V reg(0x0F) = 0x00
ST7789V reg(0xDA) = 0x85
ST7789V reg(0xDB) = 0x85
ST7789V reg(0xDC) = 0x52

Try the different interface types. I presume you are using a proper 3.3V Arduino.
Paste your results to your message.

David.

Hi David,

Thanks for the code and effort put into it.

Well, I tried all the combinations, since there is only one line (SDA1) for either DC and MISO so I switched both for every combination of interface variable.
Unfortunately, I don't have good news for you. All I got was either 0x00 or 0xFF for all the tests. I can paste the output here if you would like to see.

Later, I noticed that you used the input pull-up resistors for SDA pins. I don't think they are required since I have added external pullup resistors for both SDA and SCL. (Should I remove them?). So I commented that line out and redid the test. Now, everything was 0x00. lol

I can't believe this. If you wanna see the circuit, I'll mail it to you.
The SPI bus also has a touch interface, with the reset of touch and display attached to the same pin. I did CS low for the touch just to be sure. You think I should unplug the touch panel to be extra sure?

I'm too tired today, I'll probably redo and recheck everything tomorrow. Its just a bit frustrating.

PS - attaching the datasheet of the display, if that helps.

1.54Inch 240X240 IPS SPI AML015410 V1-Shenzhen Amelin Electronic Technology Co. Ltd. .pdf (1.35 MB)

I suggest that you paste your TFT_MOSI, ... defines and interface assignment.
Together with a photo of your wiring.

You only need to do the wiring once.
The different combinations can be shown with each "paste" with the corresponding result e.g. "all 0xFF"

David.

Hi David,

So here is my define -

Note - pin# 27 i.e. DC pin is a dummy pin. TFT_MISO is connected to SDA1

#if defined(ESP32)
#define TFT_MOSI 23
#define TFT_MISO 2
#define TFT_SCK  18
#define TFT_SS   5
#define TFT_DC   27     //DC=7 for HX8347
#define TFT_RESET 4   //Backlight on HX8347

I was checking and unchecking one of the following -

//char interface = SDA_BIDIR;    //ST7789 bidirectional SDA + DC
//char interface = NINEBITS | SDA_BIDIR;  //3-wire SPI bidirectional SDA
//char interface = NINEBITS | HAS_MISO;  //4-wire SDA + SDO
//char interface = HAS_MISO | IS_9341;  //ILI9341 SPI
//char interface = HAS_MISO | IS_9481;  //ILI9481 SPI
//char interface = HAS_MISO | IS_9486;  //ILI9486 SPI
char interface = HAS_MISO;  //regular SPI
//char interface = NINEBITS | SDA_BIDIR | IS_9481;  //ILI9481 3-wire SPI bidirectional pin

for the regular SPI, here is the output. Since I'm using OTA -

Update: ST7789_readreg_diag.ino.esp32.bin
Update Success: 726656
Rebooting...
⸮R⸮⸮fgR
.....
Connected to deAdpool
IP address: 192.168.1.27
mDNS responder started

1. select correct defines for your board wiring
2. select correct interface type
3. select appropriate report function

certain registers read first byte e.g. 0x00-0x0F, 0xDA-0xDC
other multi-argument registers read first byte as dummy

Read registers 8-bit SPI with MISO (+ DC)
read reg(4):  ID = 0xFFFFFF
controller
data sheet specific calls
controller reg(0x04) = 0xFFFFFF
controller reg(0x09) = 0xFFFFFFFF
controller reg(0x0A) = 0xFF
controller reg(0x0B) = 0xFF
controller reg(0x0C) = 0xFF
controller reg(0x0D) = 0xFF
controller reg(0x0E) = 0xFF
controller reg(0x0F) = 0xFF
controller reg(0xDA) = 0xFF
controller reg(0xDB) = 0xFF
controller reg(0xDC) = 0xFF

The wiring diagram is attached. The PCB is a custom PCB that I got manufactured from China.

sxk1185

Okay so here is the detailed version -

For: char interface = SDA_BIDIR; //ST7789 bidirectional SDA + DC
Result: 0x0

For: char interface = NINEBITS | SDA_BIDIR; //3-wire SPI bidirectional SDA
Result: 0x0

For: char interface = NINEBITS | HAS_MISO; //4-wire SDA + SDO
Result: 0xFF

For: char interface = HAS_MISO | IS_9341; //ILI9341 SPI
Result: 0xFF

For: char interface = HAS_MISO | IS_9481; //ILI9481 SPI
Result: 0xFF

For: char interface = HAS_MISO | IS_9486; //ILI9486 SPI
Result: 0xFF

For: char interface = HAS_MISO; //regular SPI
Result: 0xFF

For: char interface = NINEBITS | SDA_BIDIR | IS_9481; //ILI9481 3-wire SPI bidirectional pin
0x00

I would try:

#define TFT_MOSI 23
#define TFT_MISO 2    //your SDA1 pin
#define TFT_SCK  18
#define TFT_SS   5
#define TFT_DC   27     //dummy
#define TFT_RESET 4   //
char interface = NINEBITS | HAS_MISO;    //assumes separate SDA/SDO

and

#define TFT_MOSI 23
#define TFT_MISO 27   //dummy
#define TFT_SCK  18
#define TFT_SS   5
#define TFT_DC   2     //your SDA1 pin
#define TFT_RESET 4   //
char interface = NINEBITS | SDA_BIDIR;    //assumes DC is on SDA1

RSEL, RSDA are unnecessary because I use pullups in software.

But the most important thing is to provide a sensible 2.8V power supply.

You can derive 2.8V from the 3.3V supply with a potential divider but you would need 100R and 560R.
In an ideal world you would use a LDO regulator to produce 2.8V

The 1.8V is a reference. So it is probably ok with 1k0 and 3k6

I presume that you have an Oscilloscope and/or Logic Analyser. And at least a DMM.
Or you could use an Analog pin to read the voltages when the chip is active i.e. CS low, RST high.

Incidentally, you can use this sketch to read from most MIPI controllers e.g. ST7735,
However many require you to "enable" bidirectional on the SDA pin e.g. via a hardware register.

David.

As David points out you are not powering the display properly, the datasheet says 6mA typical but that will be an average and that pin will need decoupling capacitors added. The digital logic inside the TFT display will be taking much higher peak currents for a short time, so that is what decoupling capacitors are for. The ESP32 digital output pin should not be used to power a device like this because the output voltage sags on load. Use an LDO and update your design. I suspect there will be other errors in the design so you ought to get someone experienced and local to you to review the schematic.

Since you appear to be producing a product you may need to pay for help.

Thanks, guys for pointing the power issue out. I'll make the changes. I'll add an LDO and resistor divider to power Display.

I guess I have to add an LDO controlled by ESP32 to power LCD, eventually to conserve power when ESP32 is sleeing.
Ugh, I'm so much constricted with the space on the PCB. I'll probably have to get an external antenna for ESP32 to make some space.

I'm producing a product, and as a student + startup, I barely have enough to pay anyone for the professional help. That's why this community here is so awesome, 'coz of the guys like you. I would love to give out a few samples to you guys to test/play or help me make it better, though.

Lemme make some changes in the circuit, do what David has said and I'll post the results here. Hang tight.

Cheers
sxk1185

Wow,

I can't really thank you guys enough, especially David for his awesomeness.

Here is the result I got -

read reg(4):  ID = 0x858552
ST7789V
data sheet specific calls
ST7789V reg(0x04) = 0x858552
ST7789V reg(0x09) = 0x00610000
ST7789V reg(0x0A) = 0x08
ST7789V reg(0x0B) = 0x00
ST7789V reg(0x0C) = 0x06
ST7789V reg(0x0D) = 0x00
ST7789V reg(0x0E) = 0x00
ST7789V reg(0x0F) = 0x00
ST7789V reg(0xDA) = 0x85
ST7789V reg(0xDB) = 0x85
ST7789V reg(0xDC) = 0x52

The code that worked was -

#define TFT_MOSI 23
#define TFT_MISO 27  // Dummy
#define TFT_SCK  18
#define TFT_SS   5
#define TFT_DC   2     //DC was SDA1
#define TFT_RESET 4   


#define NINEBITS  (1<<0)
#define SDA_BIDIR (1<<1)
#define HAS_MISO  (1<<2)
#define IS_9341   (1<<3)
#define IS_9481   (1<<4)
#define IS_9486   (1<<5)

const char *chip = "controller";

//char interface = SDA_BIDIR;    //ST7789 bidirectional SDA + DC

char interface = NINEBITS | SDA_BIDIR;  //3-wire SPI bidirectional SDA

//char interface = NINEBITS | HAS_MISO;  //4-wire SDA + SDO
//char interface = HAS_MISO | IS_9341;  //ILI9341 SPI
//char interface = HAS_MISO | IS_9481;  //ILI9481 SPI
//char interface = HAS_MISO | IS_9486;  //ILI9486 SPI
//char interface = HAS_MISO;  //regular SPI
//char interface = NINEBITS | SDA_BIDIR | IS_9481;  //ILI9481 3-wire SPI bidirectional pin

Next is touch, but tomorrow maybe, I have some paperwork to finish by Friday.

You guys are awesome! (seriously!)

Oh, Would you like to help me design the circuit better? Would love to chat, if you guys are free.

Shravan

char interface = NINEBITS | SDA_BIDIR;  //3-wire SPI bidirectional SDA

If this was the code that worked, SDA1 is never used. But it was certainly worth trying MISO and DC.

Regarding your voltage levels. The 2.8V LDO does not need to be very big package. The 1.8V LDO can be even smaller. The LDO package will take less pcb space than two resistors.
If you intend this to be a low-power device, you will send the ESP32 to sleep as much as possible. And you will need a transistor to switch the backlight off (or to PWM the brightness)

I suspect that you could use 2.8V for IOVCC if you wanted. Ask the display manufacturer.

David.

Dear David,

I am still struggling with the LCD display that we discussed in this thread. I can't seem to get it to show anything. I changed the circuit as per the suggestions here, and I am able to read registers with the code you have sent me.
But nothing on screen. I guess I need help with the basic code of say fillscreen(Red) or something.

With the MADCTL = 3Ah=”06h” (from the driver given by the manufacturer, and it has 16.7million colors, so...) and M[3] = 0101 it means its an RGB-6-6-6-bit input, with 262K-Colors. I figured this from Datasheet. (Hope this is correct)

Have you coded any LCD with this configuration? (if yes, I so would love to have a peek at the code).

The Adafruit code is for RGB565 and I was trying to fix it for the RGB666 and it's not working. I don't know where is it wrong.
Since this is a 9bit LCD, so after every byte, a DC bot needs to be sent. (see image attached)

Here is the code-

I'm calling fillscreen(MAGENTA);

#define MAGENTA 0xF600FF

void fillScreen(uint32_t color){
   chipEnable(); //_cs low
   setAddrWindow(0, 0, 240, 240);  
   writePixelColor(MAGENTA); //hard coded for now
   chipDisable(); // _cs high
}


//Im writing 24 bits only
writePixelColor(uint32_t color){
  uint8_t R = color >> 24;
  uint8_t G = color >> 16;
  uint8_t B = color >> 8;
  param(R);
  param(G);
  param(B);
  }


write32(uint32_t para){
  uint8_t R = para >> 24;
  uint8_t G = para >> 16;
  uint8_t B = para >> 8;
  uint8_t e = para; //& 0xFF;
  param(R);
  param(G);
  param(B);
  param(e);
  }

//x,y = start point of frame (16 bit each)
//w, h = width and lenght of frame (16 bit each)
void GFX::setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
  //x += _xstart;
  //y += _ystart;
  uint32_t xa = ((uint32_t)x << 16) | (x+w-1);
  uint32_t ya = ((uint32_t)y << 16) | (y+h-1); 

  command(CASET); // Column addr set
  write32(xa);

  command(RASET); // Row addr set
  write32(ya);

  command(RAMWR); // write to RAM
}


void  command(uint8_t val){
    pinMode(_mosi, OUTPUT);
        digitalWrite(_mosi, 0);
        digitalWrite(_sck, HIGH);
        digitalWrite(_sck, LOW);
    
    for (int i = 0; i < 8; i++) {   //send command
        digitalWrite(_mosi, (val & 0x80) != 0);
        digitalWrite(_sck, HIGH);
        digitalWrite(_sck, LOW);
        val <<= 1;
    }
}

void param(uint8_t val){
    pinMode(_mosi, OUTPUT);
        digitalWrite(_mosi, 1);
        digitalWrite(_sck, HIGH);
        digitalWrite(_sck, LOW);
    
    for (int i = 0; i < 8; i++) {   //send command
        digitalWrite(_mosi, (val & 0x80) != 0);
        digitalWrite(_sck, HIGH);
        digitalWrite(_sck, LOW);
        val <<= 1;
    }  
  }

9-bit comms means the DC bit is sent first not last.
The ST7789 can use 5-6-5 pixels i.e. PIXFMT=0x55.
MADCTL controls addressing not 565 or 666 format.

We discussed two styles of converting the Adafruit 8-bit+DC to 9-bit in messages #0-2.
This requires great care to ensure the 9-bits are always in sync.

Please post a ZIP or link to your actual code e.g. a GitHub fork.

I have only got an ILI9481 9-bit display. Also an ILI9488 with accessible IM# pins.

David.