Bodmer / TFT_eSPI

Arduino and PlatformIO IDE compatible TFT library optimised for the Raspberry Pi Pico (RP2040), STM32, ESP8266 and ESP32 that supports different driver chips
Other
3.84k stars 1.1k forks source link

ST7796S compatibility. #499

Closed peppeve closed 4 years ago

peppeve commented 4 years ago

Is possible to have compatibility on esp32 with this it use the ST7796S i think very similar to ili9488. I have ordered 2 pieces and i think i get next week. Thank's.

Bodmer commented 4 years ago

The screen appears to have a special serial to parallel IC fitted to the PCB, thus is likely to have a bespoke interface protocol.

Do you have information on the protocol used to communicate and setup the screen?

peppeve commented 4 years ago

sorry but i have no idea. When i get it i try to tell you more.

Bodmer commented 4 years ago

It looks interesting as it can be clocked fast if the spec is to be beleived, but it may be necessary to reverse engineer the protocol...

peppeve commented 4 years ago

btw st7796s support this Interface:

peppeve commented 4 years ago

Here there is the configuration file used on the raspberry if it can help you.

peppeve commented 4 years ago

@Bodmer, some news? My dispaly is underway, i hope to receive soon.

Bodmer commented 4 years ago

The good news is that I have one of these displays now as I think it will be impossible to get it running otherwise.

The bad news (for you) is that paid work and family are taking up my time, but I may be able to look at it again towards the end of January.

Bodmer commented 4 years ago

I have had a go at getting this display to work, but no success. This maybe because of an incorrect assumption about the way the interface chip on the back of the board works, I suspect it is just a serial to parallel converter. To eliminate the ST7789S driver as the cause I have bought one of these, but it will take a few weeks to arrive.

peppeve commented 4 years ago

My displays are under delivery today, tell me how i can help you.

peppeve commented 4 years ago

I get the displays but the big square chip is without any sign. :(

Bodmer commented 4 years ago

Good news. I have a working version on the ESP32. Performance is very good for a SPI display as it is working fine at 80MHz SPI clock rate (which is the maximum SPI clock rate for an ESP32).

Benchmark,                Time (microseconds)
Screen fill,              180522
Text,                     13573
Lines,                    165921
Horiz/Vert Lines,         16287
Rectangles (outline),     9354
Rectangles (filled),      440321
Circles (filled),         102082
Circles (outline),        101753
Triangles (outline),      34522
Triangles (filled),       164049
Rounded rects (outline),  43086
Rounded rects (filled),   490614
Total = 1762084us
Total = 1.7621s

I anticipate I will be able to push the changes to Github hopefully within 24hrs after testing with the ESP8266.

peppeve commented 4 years ago

:) very happy.

Hans007a commented 4 years ago

I'm very happy too! :)

Bodmer commented 4 years ago

Display support now added to the Master branch.

ESP32 SPI can clock the display at 80MHz.

ESP8266 can clock the display at 40MHz maximum.

Please raise any problems as a NEW issue.

simonchen007 commented 4 years ago

it seems not works in st7796s currently. just a white screen.

Bodmer commented 4 years ago

The setups and testing has been performed on a RPi MHS 4.0 display.

If I guess that you are using an ESP32 and an SPI base display that is not for a RPi then try this setup and wiring:

#define ST7796_DRIVER

#define TFT_MISO 19
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS   15
#define TFT_DC    2
#define TFT_RST   4

#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

#define SPI_FREQUENCY  20000000

I am not able to advise further without knowing more about your hardware and software setup.

simonchen007 commented 4 years ago

I tried your configuration,still a white blank screen. here is the main code I using:

/*
 * Blink
 * Turns on an LED on for one second,
 * then off for one second, repeatedly.
 */

#include <Arduino.h>
/*

  This program provides cartesian type graph function

  Revisions
  rev     date        author      description
  1       12-24-2015  kasprzak    initial creation

  Updated by Bodmer to be an example for the library here:
  https://github.com/Bodmer/TFT_eSPI

*/

#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>

TFT_eSPI tft = TFT_eSPI();                   // Invoke custom library with default width and height

#define LTBLUE    0xB6DF
#define LTTEAL    0xBF5F
#define LTGREEN   0xBFF7
#define LTCYAN    0xC7FF
#define LTRED     0xFD34
#define LTMAGENTA 0xFD5F
#define LTYELLOW  0xFFF8
#define LTORANGE  0xFE73
#define LTPINK    0xFDDF
#define LTPURPLE  0xCCFF
#define LTGREY    0xE71C

#define BLUE      0x001F
#define TEAL      0x0438
#define GREEN     0x07E0
#define CYAN      0x07FF
#define RED       0xF800
#define MAGENTA   0xF81F
#define YELLOW    0xFFE0
#define ORANGE    0xFC00
#define PINK      0xF81F
#define PURPLE    0x8010
#define GREY      0xC618
#define WHITE     0xFFFF
#define BLACK     0x0000

#define DKBLUE    0x000D
#define DKTEAL    0x020C
#define DKGREEN   0x03E0
#define DKCYAN    0x03EF
#define DKRED     0x6000
#define DKMAGENTA 0x8008
#define DKYELLOW  0x8400
#define DKORANGE  0x8200
#define DKPINK    0x9009
#define DKPURPLE  0x4010
#define DKGREY    0x4A49

// these are the only external variables used by the graph function
// it's a flag to draw the coordinate system only on the first call to the Graph() function
// and will mimize flicker
// also create some variables to store the old x and y, if you draw 2 graphs on the same display
// you will need to store ox and oy per each display
boolean display1 = true;
boolean update1 = true;

double ox = -999, oy = -999; // Force them to be off screen

/*

  function to draw a cartesian coordinate system and plot whatever data you want
  just pass x and y and the graph will be drawn

  huge arguement list
  &d name of your display object
  x = x data point
  y = y datapont
  gx = x graph location (lower left)
  gy = y graph location (lower left)
  w = width of graph
  h = height of graph
  xlo = lower bound of x axis
  xhi = upper bound of x asis
  xinc = division of x axis (distance not count)
  ylo = lower bound of y axis
  yhi = upper bound of y asis
  yinc = division of y axis (distance not count)
  title = title of graph
  xlabel = x asis label
  ylabel = y asis label
  &redraw = flag to redraw graph on first call only
  color = plotted trace colour
*/

void Graph(TFT_eSPI &tft, double x, double y, byte dp,
                           double gx, double gy, double w, double h,
                           double xlo, double xhi, double xinc,
                           double ylo, double yhi, double yinc,
                           char *title, char *xlabel, char *ylabel,
                           boolean &redraw, unsigned int color) {

  double ydiv, xdiv;
  double i;
  double temp;
  int rot, newrot;

  // gcolor = graph grid colors
  // acolor = axes line colors
  // pcolor = color of your plotted data
  // tcolor = text color
  // bcolor = background color
  unsigned int gcolor = DKBLUE;
  unsigned int acolor = RED;
  unsigned int pcolor = color;
  unsigned int tcolor = WHITE;
  unsigned int bcolor = BLACK;

  if (redraw == true) {

    redraw = false;
    // initialize old x and old y in order to draw the first point of the graph
    // but save the transformed value
    // note my transform funcition is the same as the map function, except the map uses long and we need doubles
    //ox = (x - xlo) * ( w) / (xhi - xlo) + gx;
    //oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;

    tft.setTextDatum(MR_DATUM);

    // draw y scale
    for ( i = ylo; i <= yhi; i += yinc) {
      // compute the transform
      temp =  (i - ylo) * (gy - h - gy) / (yhi - ylo) + gy;

      if (i == 0) {
        tft.drawLine(gx, temp, gx + w, temp, acolor);
        tft.setTextColor(acolor, bcolor);
        tft.drawString(xlabel, (int)(gx + w) , (int)temp, 2);
      }
      else {
        tft.drawLine(gx, temp, gx + w, temp, gcolor);
      }
      // draw the axis labels
      tft.setTextColor(tcolor, bcolor);
      // precision is default Arduino--this could really use some format control
      tft.drawFloat(i, dp, gx - 4, temp, 1);
    }

    // draw x scale
    for (i = xlo; i <= xhi; i += xinc) {

      // compute the transform
      temp =  (i - xlo) * ( w) / (xhi - xlo) + gx;
      if (i == 0) {
        tft.drawLine(temp, gy, temp, gy - h, acolor);
        tft.setTextColor(acolor, bcolor);
        tft.setTextDatum(BC_DATUM);
        tft.drawString(ylabel, (int)temp, (int)(gy - h - 8) , 2);
      }
      else {
        tft.drawLine(temp, gy, temp, gy - h, gcolor);
      }
      // draw the axis labels
      tft.setTextColor(tcolor, bcolor);
      tft.setTextDatum(TC_DATUM);
      // precision is default Arduino--this could really use some format control
      tft.drawFloat(i, dp, temp, gy + 7, 1);
    }

    //now draw the graph labels
    tft.setTextColor(tcolor, bcolor);
    tft.drawString(title, (int)(gx + w / 2) , (int)(gy - h - 30), 4);
  }

  // the coordinates are now drawn, plot the data
  // the entire plotting code are these few lines...
  // recall that ox and oy are initialized above
  //x =  (x - xlo) * ( w) / (xhi - xlo) + gx;
  //y =  (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
  //tft.drawLine(ox, oy, x, y, pcolor);
  // it's up to you but drawing 2 more lines to give the graph some thickness
  //tft.drawLine(ox, oy + 1, x, y + 1, pcolor);
  //tft.drawLine(ox, oy - 1, x, y - 1, pcolor);
  //ox = x;
  //oy = y;

}

void Trace(TFT_eSPI &tft, double x,  double y,  byte dp,
           double gx, double gy,
           double w, double h,
           double xlo, double xhi, double xinc,
           double ylo, double yhi, double yinc,
           char *title, char *xlabel, char *ylabel,
           boolean &update1, unsigned int color)
{
  double ydiv, xdiv;
  double i;
  double temp;
  int rot, newrot;

  //unsigned int gcolor = DKBLUE;   // gcolor = graph grid color
  unsigned int acolor = RED;        // acolor = main axes and label color
  unsigned int pcolor = color;      // pcolor = color of your plotted data
  unsigned int tcolor = WHITE;      // tcolor = text color
  unsigned int bcolor = BLACK;      // bcolor = background color

  // initialize old x and old y in order to draw the first point of the graph
  // but save the transformed value
  // note my transform funcition is the same as the map function, except the map uses long and we need doubles
  if (update1) {
    update1 = false;

    ox = (x - xlo) * ( w) / (xhi - xlo) + gx;
    oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;

    if ((ox < gx) || (ox > gx+w)) {update1 = true; return;}
    if ((oy < gy-h) || (oy > gy)) {update1 = true; return;}

    tft.setTextDatum(MR_DATUM);

    // draw y scale
    for ( i = ylo; i <= yhi; i += yinc) {
      // compute the transform
      temp =  (i - ylo) * (gy - h - gy) / (yhi - ylo) + gy;

      if (i == 0) {
        tft.setTextColor(acolor, bcolor);
        tft.drawString(xlabel, (int)(gx + w) , (int)temp, 2);
      }
      // draw the axis labels
      tft.setTextColor(tcolor, bcolor);
      // precision is default Arduino--this could really use some format control
      tft.drawFloat(i, dp, gx - 4, temp, 1);
    }

    // draw x scale
    for (i = xlo; i <= xhi; i += xinc) {

      // compute the transform
      temp =  (i - xlo) * ( w) / (xhi - xlo) + gx;
      if (i == 0) {
        tft.setTextColor(acolor, bcolor);
        tft.setTextDatum(BC_DATUM);
        tft.drawString(ylabel, (int)temp, (int)(gy - h - 8) , 2);
      }

      // draw the axis labels
      tft.setTextColor(tcolor, bcolor);
      tft.setTextDatum(TC_DATUM);
      // precision is default Arduino--this could really use some format control
      tft.drawFloat(i, dp, temp, gy + 7, 1);
    }

    //now draw the graph labels
    tft.setTextColor(tcolor, bcolor);
    tft.drawString(title, (int)(gx + w / 2) , (int)(gy - h - 30), 4);
  }

  // the coordinates are now drawn, plot the data
  // the entire plotting code are these few lines...
  // recall that ox and oy are initialized above
  x =  (x - xlo) * ( w) / (xhi - xlo) + gx;
  y =  (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;

  if ((x < gx) || (x > gx+w)) {update1 = true; return;}
  if ((y < gy-h) || (y > gy)) {update1 = true; return;}

  tft.drawLine(ox, oy, x, y, pcolor);
  // it's up to you but drawing 2 more lines to give the graph some thickness
  //tft.drawLine(ox, oy + 1, x, y + 1, pcolor);
  //tft.drawLine(ox, oy - 1, x, y - 1, pcolor);
  ox = x;
  oy = y;

}

/*

  End of graphing function

*/

void setup() {
  double x, y;

  tft.begin();
  tft.fillScreen(BLACK);
  tft.setRotation(1);

  Graph(tft, x, y, 1, 60, 290, 390, 260, 0, 6.5, 1, -1, 1, .25, "", "", "", display1, YELLOW);

  //delay(1000);

  update1 = true;
  for (x = 0; x <= 6.3; x += .1) {
    y = sin(x);
    Trace(tft, x, y, 1, 60, 290, 390, 260, 0, 6.5, 1, -1, 1, .25, "Sin(x)", "x", "fn(x)", update1, YELLOW);
  }

  delay(2000);

  update1 = true;
  for (x = 0; x <= 6.3; x += .1) {
    y = cos(x);
    Trace(tft, x, y, 1, 60, 290, 390, 260, 0, 6.5, 1, -1, 1, .25, "Sin(x) + Cos(x)", " x", "fn(x)", update1, TFT_PINK);
  }

  delay(2000);

  update1 = true;
  for (x = 0; x <= 6.3; x += .02) {
    y = tan(x);
    Trace(tft, x, y, 1, 60, 290, 390, 260, 0, 6.5, 1, -1, 1, .25, "Sin(x) + Cos(x) + Tan(x)", " x", "fn(x)", update1, CYAN);
  }
}
void loop(void) {
}

And here is the platformio.ini

[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
platform_packages =
  ; use a special branch
  framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#idf-release/v4.0
; change microcontroller
board_build.mcu = esp32

; change MCU frequency
; 240000000L/ 160000000L / 80000000L
; set frequency to 240MHz
board_build.f_cpu = 240000000L
;20000000L
;26000000L
;40000000L (default)
;80000000L
board_build.f_flash = 80000000L
;qio
;qout
;dio
;dout
board_build.flash_mode = dio

;partitions
; check it here: https://github.com/espressif/arduino-esp32/tree/master/tools/partitions
; default = 1.5M
;
;Switch between built-in tables
; https://github.com/espressif/arduino-esp32/tree/master/tools/partitions
; https://github.com/espressif/esp-idf/tree/master/components/partition_table
board_build.partitions = partitions/custome_partitions.csv

upload_protocol = esptool
upload_speed = 460800
monitor_speed = 115200

how ever, I can make this display works in esp8266 without spi.h only from manufacturer:

// IMPORTANT: LCDWIKI_SPI LIBRARY MUST BE SPECIFICALLY
// CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD.

//This program is a demo of clearing screen to display black,white,red,green,blue.

//when using the BREAKOUT BOARD only and using these hardware spi lines to the LCD,
//the SDA pin and SCK pin is defined by the system and can't be modified.
//if you don't need to control the LED pin,you can set it to 3.3V and set the pin definition to -1.
//other pins can be defined by youself,for example
//pin usage as follow:
//                 CS  DC/RS  RESET  SDI  SCK  LED    VCC     GND    
//ESP8266 D1 nimi  D1   D3     D2    D7   D5   D4   5V/3.3V   GND

//Remember to set the pins to suit your display module!
/********************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, QD electronic SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
**********************************************************************************/
#include <SPI.h>

#define X_MAX_PIXEL 320
#define Y_MAX_PIXEL 480

#define LCD_CS  D1
#define LCD_RST D2
#define LCD_RS  D3
#define LED D0

#define LCD_CS_SET (digitalWrite(LCD_CS,HIGH))
#define LCD_RST_SET (digitalWrite(LCD_RST,HIGH))
#define LCD_RS_SET (digitalWrite(LCD_RS,HIGH))
#define LED_SET (digitalWrite(LED,HIGH))

#define LCD_CS_CLR (digitalWrite(LCD_CS,LOW))
#define LCD_RST_CLR (digitalWrite(LCD_RST,LOW))
#define LCD_RS_CLR (digitalWrite(LCD_RS,LOW))

#define BLACK 0x0000
#define WHITE 0xFFFF
#define RED 0xF800
#define GREEN 0x07E0
#define BLUE  0x001F

void spi_init(void)
{
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV2); // 4 MHz (half speed)
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0); 
}

// void spi_write(unsigned char data)
// {  
//   SPI.transfer(data);
// }

// void Lcd_WriteIndex(unsigned char index)
// {
//    LCD_CS_CLR; //low
//    LCD_RS_CLR; //low
//    spi_write(index);
//    LCD_CS_SET; //high
// }

// void Lcd_WriteData(unsigned char data)
// {
//    LCD_CS_CLR;  //low
//    LCD_RS_SET;  //high
//    spi_write(data);
//    LCD_CS_SET;  //high
// }

void Lcd_writeregs(unsigned char data,boolean type=false)
{
  LCD_CS_CLR; //low
  (type==true)?LCD_RS_CLR:LCD_RS_SET;
  SPI.transfer(data);
   LCD_CS_SET;  //low
}

void Lcd_SetRegion(unsigned int x_start,unsigned int y_start,unsigned int x_end,unsigned int y_end)
{    
  Lcd_writeregs(0x2a,true);
  Lcd_writeregs(x_start>>8);
  Lcd_writeregs(x_start);
  Lcd_writeregs(x_end>>8);
  Lcd_writeregs(x_end);

  Lcd_writeregs(0x2b,true);
  Lcd_writeregs(y_start>>8);
  Lcd_writeregs(y_start);
  Lcd_writeregs(y_end>>8);
  Lcd_writeregs(y_end);

  Lcd_writeregs(0x2c,true);
}

void Lcd_Reset(void)
{
  LCD_RST_CLR;
  delay(20);
  LCD_RST_SET;
  delay(10);
}

void LCD_WriteData_16Bit(unsigned int data)
{
  Lcd_writeregs((data>>8)&0xF8);//RED
  Lcd_writeregs((data>>3)&0xFC);//GREEN
  Lcd_writeregs(data<<3);//BLUE
}

void Lcd_Clear(unsigned int color)               
{  
   unsigned int i,m;
   Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);
   for(i=0;i<Y_MAX_PIXEL;i++)
   {
    delay(0); //must be set
    for(m=0;m<X_MAX_PIXEL;m++)
    { 
      LCD_WriteData_16Bit(color);      
    }   
   }
}

void Lcd_Init(void)
{  
  Lcd_Reset(); //Reset before LCD Init.

  Lcd_writeregs(0xA7,true);
  Lcd_writeregs(0xB0,true);
  Lcd_writeregs(0x80);

  Lcd_writeregs(0xB1,true);
  Lcd_writeregs(0x80);  
  Lcd_writeregs(0x10);

  Lcd_writeregs(0xB4,true);
  Lcd_writeregs(0x00);

  Lcd_writeregs(0xB5,true);
  Lcd_writeregs(0x02);
  Lcd_writeregs(0x03);
  Lcd_writeregs(0x00);
  Lcd_writeregs(0x04);

  Lcd_writeregs(0xB6,true);
  Lcd_writeregs(0x00);
  Lcd_writeregs(0x02);

  Lcd_writeregs(0xB7,true);
  Lcd_writeregs(0xc6);

  Lcd_writeregs(0xC2,true);

  Lcd_writeregs(0xC5,true);
  Lcd_writeregs(0x24);

  Lcd_writeregs(0xE0,true);
  Lcd_writeregs(0xF0);
  Lcd_writeregs(0x09);
  Lcd_writeregs(0x13);
  Lcd_writeregs(0x12);
  Lcd_writeregs(0x12);
  Lcd_writeregs(0x2B);
  Lcd_writeregs(0x3C);
  Lcd_writeregs(0x44);
  Lcd_writeregs(0x4B);
  Lcd_writeregs(0x1B);
  Lcd_writeregs(0x18);
  Lcd_writeregs(0x17);
  Lcd_writeregs(0x1D);
  Lcd_writeregs(0x21);

  Lcd_writeregs(0XE1,true);
  Lcd_writeregs(0xF0);
  Lcd_writeregs(0x09);
  Lcd_writeregs(0x13);
  Lcd_writeregs(0x0C);
  Lcd_writeregs(0x0D);
  Lcd_writeregs(0x27);
  Lcd_writeregs(0x3B);
  Lcd_writeregs(0x44);
  Lcd_writeregs(0x4D);
  Lcd_writeregs(0x0B);
  Lcd_writeregs(0x17);
  Lcd_writeregs(0x17);
  Lcd_writeregs(0x1D);
  Lcd_writeregs(0x21);

  Lcd_writeregs(0xE4,true);
  Lcd_writeregs(0x31);

  Lcd_writeregs(0xE8,true);
  Lcd_writeregs(0x40);
  Lcd_writeregs(0x8A);
  Lcd_writeregs(0x00);
  Lcd_writeregs(0x00);
  Lcd_writeregs(0x29);
  Lcd_writeregs(0x19);
  Lcd_writeregs(0xA5);
  Lcd_writeregs(0x33);

  Lcd_writeregs(0xF0,true);
  Lcd_writeregs(0xC3);

  Lcd_writeregs(0xF0,true);
  Lcd_writeregs(0x69);

  Lcd_writeregs(0x3A,true);
  Lcd_writeregs(0x66);

  Lcd_writeregs(0x36,true);
  Lcd_writeregs(0x48);

  Lcd_writeregs(0X13,true);

  Lcd_writeregs(0X11,true);
  delay(10);
  Lcd_writeregs(0X29,true);
}

void pin_init(void)
{
    pinMode(LCD_CS, OUTPUT);
    pinMode(LCD_RST, OUTPUT);
    pinMode(LCD_RS, OUTPUT); 
    pinMode(LED,OUTPUT);
    LED_SET;
    LCD_CS_SET;
    LCD_RST_SET;
    LCD_RS_SET;
}

void setup() 
{
    spi_init();
    pin_init();
    Lcd_Init();
}

void loop() 
{   
   Lcd_Clear(RED); 
 // delay(0); 
  Lcd_Clear(GREEN);
 // delay(0);  
   Lcd_Clear(BLUE); 
 // delay(100); 
  // }
}
Bodmer commented 4 years ago

Hi, I do not have an SPI ST7796S display so I cannot test. My ST7796 board is 8 bit parallel.

I suspect that in SPI mode the ST7796 may be like the ILI9488 and only accept 18 bit color configuration. You can test this for me by finding this line, and changing it to:

writedata(0x66);    //Control interface color format set to 18

Recompile and upload your sketch. The display should look different, it will have missing pixels but at the moment this is a test and we can correct the missing pixels later when we know this color mode is the problem.

simonchen007 commented 4 years ago

no, it still not works with your way. but however, I make it works just now. I change with that way, change:

    writecommand(0xB6); //Display Function Control
    writedata(0x20);    //RGB interface for RAM access, RGB transfer in DE mode  
                                  //display data path in memory
                                  //Gate outputs in non-display area in Normal scan 
                                  //Source output in non-display area =V63

    writedata(0x02);    //Source Output Scan from S1 to S960, Gate Output scan from G1 to G480, scan cycle=2
        writedata(0x3B);    //LCD Drive Line=8*(59+1)

with:

    writecommand(0xB6); //Display Function Control
    // writedata(0x20);    //RGB interface for RAM access, RGB transfer in DE mode  
                                  //display data path in memory
                                  //Gate outputs in non-display area in Normal scan 
                                  //Source output in non-display area =V63

    writedata(0x02);    //Source Output Scan from S1 to S960, Gate Output scan from G1 to G480, scan cycle=2
    // writedata(0x3B);    //LCD Drive Line=8*(59+1)

it works now. but another problem here, I can not change SPI_FREQUENCY as 80000000, once it changed as 80000000, it will also white display.

And I also have the parallel version of ST7796s, can you please show me the way about connection between esp32 to display ? I will test it tomorrow.

prenticedavid commented 4 years ago

I have the Red SPI ST7796S display. It "works" with the TFT_eSPI init code if you change the first parameter for the 0xB6 register e.g. from 0xB6, 3, 0x20, 0x02, 0x3B, // Display Function Control [80 02 3B] to 0xB6, 3, 0x80, 0x02, 0x3B, // Display Function Control [80 02 3B] i.e. the power up default.

The ST7796S can read GRAM in 565 mode (16-bit) as well as write GRAM in 565 mode. Obviously read and write use 24-bit in 666 mode. So this is a great relief compared to the ILI9488 which can only use 666 mode with the SPI interface.

Most commands work fine.

However, there are some very weird behaviours e.g. when you write to MADCTRL (0x36) readPixel() seems to require monster delays. I get intermitient weird behaviour with an SD card.

I was hoping that you (Bodmer) possessed a native SPI display. And we could resolve these weirdos.

David.

Bodmer commented 4 years ago

Thanks.

I have updated the init code for the ST7796 to that specified by David.

I do not have an SPI ST7796 to test. I will have a look to see if I can find one for sale. I see no obvious reason for the slow reads.

A SPI clock rate of 27MHz or 40MHz maximum is suggested. The 80MHz rate is only for the MHS 4.0 RPi display which has a dedicated high speed serial to parallel chip.

simonchen007 commented 4 years ago

I got the data sheet just now. B6 = BYPASS | RCM | RM | 0 | PTG[1:0] | PT[1:0] RM Interface for RAM access 0 System Interface 1 RGB interface

0x20 = 0010 0000 so, I do not works in the SPI mode. In spi version, we need ??0? ???? so, 0x80 or 0x00 also okay.

@Bodmer , Could you please show me the way about connection between esp32 to display of the ST7796s parallel version ?

simonchen007 commented 4 years ago

Thanks.

I have updated the init code for the ST7796 to that specified by David.

I do not have an SPI ST7796 to test. I will have a look to see if I can find one for sale. I see no obvious reason for the slow reads.

A SPI clock rate of 27MHz or 40MHz maximum is suggested. The 80MHz rate is only for the MHS 4.0 RPi display which has a dedicated high speed serial to parallel chip.

LCDWIKI is our partner. can you please drop me a email ? simon@yeacreate.com I can sponsor a SPI version of 4.0 inch st7796s display module.

prenticedavid commented 4 years ago

@simonchen007, I have never seen a ST7796S with 8080-8 interface. Bodmer supports the "8080-16 driven by shift register" e.g. RaspberryPi Hat

I would expect the ST7796S to work exactly the same with 8080-8, 8080-16, SPI, ... Obviously some Manufacturer Registers only apply to the RGB interface.

If you have some connection with LCDWIKI, it would be useful to have a GitHub link. The current lcdwiki GitHub does not respond to any Pull Requests or contain the ST7796S support.

@Bodmer , 40MHz is the practical limit for native SPI.

David.

simonchen007 commented 4 years ago

@simonchen007, I have never seen a ST7796S with 8080-8 interface. Bodmer supports the "8080-16 driven by shift register" e.g. RaspberryPi Hat

I would expect the ST7796S to work exactly the same with 8080-8, 8080-16, SPI, ... Obviously some Manufacturer Registers only apply to the RGB interface.

If you have some connection with LCDWIKI, it would be useful to have a GitHub link. The current lcdwiki GitHub does not respond to any Pull Requests or contain the ST7796S support.

@Bodmer , 40MHz is the practical limit for native SPI.

David.

They just use github as a net disk. so, few respond. if you need some documents, please let me know.

Bodmer commented 4 years ago

This is the 8 bit parallel ST7796S board that I have.

It fits on the ESP32 UNO format board as shown in the TFT_eSPI Github ReadMe. Extra links have to be added to the board as shown. The pin connections are then in the setup file here, to use that setup change the driver from ILI9431 to ST7796.

@ simonchen007 : If you wish you can contact me.

prenticedavid commented 4 years ago

Having any central Repository is wise. LCDWIKI don't have to use GitHub (but GitHub would be fine)

Correction. I see that LCDWIKI have a 8/16 bit parallel board with 34-pin header. Arduino 16-bit shields are for Mega2560 / Due. Or there are 40-pin boards that use 40-pin Arduino Adapter Shields. The ESP32 has not got enough GPIO for 8080-16 but it can drive 8080-8.

Documents. Some Mcufriend Uno Shields have appeared with ID = 0x3229. I would dearly like to find a datasheet. The Manufacturer or part number might help me to find a datasheet.

David.

Bodmer commented 4 years ago

I think this is solved now so closing, but feel free to carry on conversations.

Triangulix commented 1 year ago

I can confirm that my recently bought red no-name display board with ST7796 only works if the ST7796_Init.h is changed as described by prenticedavid.

Triangulix commented 1 year ago

@Bodmer Do you still have no display with ST7796? I would donate one if you like.