About Driving TFT with 3-wire SPI (no D/C pin, 9 bit data)

ngjones
Posts: 2
Joined: Tue Mar 19, 2019 3:22 am

About Driving TFT with 3-wire SPI (no D/C pin, 9 bit data)

Postby ngjones » Fri Apr 12, 2019 2:12 am

Hi,

I am able to drive a TFT display using SPI with 4 wires which are CS, CLK, MOSI, D/C. But recently, I am working on driving another TFT display using SPI with only CS, CLK, MOSI (without D/C pin). The trick is that I need to add once more bit in front of the 8 bits data/command I want to send. And that bit indicates whether the following 8 bits is command or not. Is it possible for esp32 to send 9 bit signal a time. What is the best way to implement it? Is there any limitation to that (i.e. cannot use dma)?

Please comment, thank you.

Thanks,
Jones

Sprite
Espressif staff
Espressif staff
Posts: 10593
Joined: Thu Nov 26, 2015 4:08 am

Re: About Driving TFT with 3-wire SPI (no D/C pin, 9 bit data)

Postby Sprite » Sun Apr 14, 2019 10:59 am

It's no different from other ways to control a SPI device, but you have to keep in mind that you need to pack the 9 bits of the data into the 8 bits you feed into the SPI peripheral. So for instance, a 3x9-bit transaction would have this data: dc 7 6 5 4 3 2 1 | 0 dc 7 6 5 4 3 2 | 1 0 dc 7 6 5 4 3 | 2 1 x x x x (Note that I'm not sure about the word or bit ordering, but you get the idea I hope.)

zambonim
Posts: 1
Joined: Mon Aug 24, 2020 10:37 am

Re: About Driving TFT with 3-wire SPI (no D/C pin, 9 bit data)

Postby zambonim » Mon Aug 24, 2020 10:41 am

Hi ngjones,

have you found a good way to perform this succesfully?
I am running into the same issue while trying to control an OLED display with 3-wire SPI.

Thanks a lot in advance,

- MZ

nochkin
Posts: 9
Joined: Tue Jun 20, 2023 5:04 am

Re: About Driving TFT with 3-wire SPI (no D/C pin, 9 bit data)

Postby nochkin » Tue Jun 20, 2023 5:14 am

Just in case someone else comes here:
I tried to follow @ESP_Sprite's suggestion and it worked great. I was afraid I had to toggle CS line after every 9 bits, but it appears it's not required as long as I keep CS low all the time.
Thank you @ESP_Sprite!

The way I've done it is by creating a buffer to write data into SPI. Using uint16_t is enough.
I append 9 bits on every write attempt and when my buffer length is over 8 bits, then I push those 8-bits into SPI.
I also had to add some dummy write of 0x00 at the end in case when I have less than 8 bits of data when everything is completed.

electronicsguy
Posts: 29
Joined: Tue Jan 12, 2016 4:12 pm
Location: Taipei, Taiwan
Contact:

Re: About Driving TFT with 3-wire SPI (no D/C pin, 9 bit data)

Postby electronicsguy » Wed Mar 26, 2025 4:05 pm

Just in case someone else comes here:
I tried to follow @ESP_Sprite's suggestion and it worked great. I was afraid I had to toggle CS line after every 9 bits, but it appears it's not required as long as I keep CS low all the time.
Thank you @ESP_Sprite!

The way I've done it is by creating a buffer to write data into SPI. Using uint16_t is enough.
I append 9 bits on every write attempt and when my buffer length is over 8 bits, then I push those 8-bits into SPI.
I also had to add some dummy write of 0x00 at the end in case when I have less than 8 bits of data when everything is completed.
@nochkin Could you share your code?

There is an example I found which works with the Lilygo displays:
https://github.com/crosser/lvgl_esp_lcd

nochkin
Posts: 9
Joined: Tue Jun 20, 2023 5:04 am

Re: About Driving TFT with 3-wire SPI (no D/C pin, 9 bit data)

Postby nochkin » Fri Mar 28, 2025 12:39 am

@electronicsguy
Sorry for delay man. I'm doing things differently now and could not find the code right away.
Anyway, I used ESP32-S3 connected using 3-wire SPI to SD2828 controller. I use LovyanGFX lib.
I have my own custom init code, but the config looks the following (adjust the references from SD2828 to whatever you need):

Code: Select all

class LGFX_SSD2828_SPI : public lgfx::LGFX_Device
{

  Panel_SSD2828       _panel_instance;
  lgfx::Bus_SPI       _bus_instance;

public:
  LGFX_SSD2828_SPI(void)
  {
    {
      auto cfg = _bus_instance.config();
      cfg.freq_write = 10 * 1000000;
      cfg.pin_dc = -1; // not needed
      cfg.pin_miso = -1; // not needed
      cfg.pin_mosi = MY_SSD2828_SDI;
      cfg.pin_sclk = MY_SSD2828_SCLK;
      cfg.spi_3wire = true;
      cfg.spi_host = SPI3_HOST;

      _bus_instance.config(cfg);
      _panel_instance.setBus(&_bus_instance);
    }

    { 
      auto cfg = _panel_instance.config();    

      cfg.pin_cs           =    MY_SSD2828_CS;
      cfg.pin_rst          =    MY_SSD2828_RST;
      cfg.pin_busy         =    -1;

      cfg.panel_width      =     1;
      cfg.panel_height     =     1;
      cfg.offset_x         =     0;
      cfg.offset_y         =     0;
      cfg.offset_rotation  =     0;
      cfg.dummy_read_pixel =     8;
      cfg.dummy_read_bits  =     1;
      cfg.readable         =  false;
      cfg.invert           =  false;
      cfg.rgb_order        =  false;
      cfg.dlen_16bit       =  false;
      cfg.bus_shared       =  false;

      _panel_instance.config(cfg);
    }

    setPanel(&_panel_instance); 
  }
};
I _think_ this is the code I used to achieve that.

Who is online

Users browsing this forum: Applebot, Perplexity-User and 4 guests