Graphics library for cheap KMR-1.8 SPI (S6D02A1 and ILI9163) TFT displays

Hello Bodmer,

Thanks for your reply. Here is a photo of front and back in attachment.

Yes, I have noticed the instruction in the example and I modified the User_Setup.h according to my IO configuration.

Thanks again! Simon

20160915.jpg|2704x1165

slessard: I have wired this way - RESET to 49 - A0 to 47 - SDA to 51 - SCK to 52 - CS to 45

All these with 1K in series. I also tried a voltage divider with a 1.5K that gave me 3V at the pin (should be enough for the logic 1 CMOS level).

Thanks for your help!

It may be a typo error but you should use SCL not SCK (which is the clock line for the SD Card slot).

The white plastic frame and ribbon cable off the display is different to mine. I will check if that corresponds to one of my displays later today and post a display ID reader. You may have a ST7735 driver or a Hynix driver.

What Hynix controllers are there? I googled and found that Hynix sold (or were trying to sell) their TFT business in 2001. Did 128x160 singlechip controllers exist in 2001?

There seem to be several 128x160 controllers from different manufacturers e.g. ILI9163C Ilitek ST7735S Sitronix S6D02A1 Samsung

I presume that Renesas, Himax, SolomonSystech, ... have parts too.

David.

Hello Bodmer,

Yes it was a typo. I use the SCL pin on the TFT side, wired to the SCK on the Mega side. Thanks for pointing out.

David, I tried with library for ST7735S and S6D02A1. A got at least some basic responding with the ST7735S (I looped over the function InvertDisplay every second and I saw the screen flashing at same frequency. I'm not sure it was actually inverting but it did something). The call to fill with a solid color didn't filled the entire screen but about 2/3 with some large areas in the middle being unaffected by the command (tried on two different parts). I got no result with the driver from Samsung so unless drivers have similar command register or I got lucky and the InvertDisplay function was recognized by my display even if I was using the wrong library, I guess that mine is ST7735S. I can still try with the libs for ILI9163C just in case!

Thanks, Simon

My comments / questions were directed to Bodmer. He knows a lot about this class of controller.

If you can diagnose which make of controller is present, you can use the correct library. Or configure a universal library to suit your display.

These controllers are readable if you use 3.3V logic. And readable with 5V logic if you use series resistors. I have published a sketch before now. I can't remember which thread(s) that I posted in.

David.

@david_prentice: I meant Himax, well spotted! I remember seeing a 1.8" display with a HX---- driver advertised, but I am not sure where I saw it. Yes you are right, ILI9163/S6D02A1/ST7735 are all options often advertised for 1.8" displays.

@slessard: Your PCB has different track routing to mine.

Below is a sketch that might help identify the driver. I have used the ID's from the data sheets for the ILI9163/S6D02A1/ST7735S drivers.

// Read the ID from the TFT controller
// The sketch only supports displays with a bi-directional SPI data line (often labelled SDA)

// Bit bashes SPI so it does NOT assume hardware SPI wired up
// No other libraries are needed

// Original author unknown
// Adapted by Bodmer 22/5/16, updated 16/9/16

// Change the pin settings to suit your hardware

// UNO etc
//#define TFT_MOSI  11
//#define TFT_SCK 13
//#define TFT_CS 9
//#define TFT_DC  8
//#define TFT_RESET 7

//Mega
#define TFT_MOSI  51
#define TFT_SCK 52
#define TFT_CS 47
#define TFT_DC  48
#define TFT_RESET 44

/* Example Serial Monitor output:

TFT driver register values:
===========================
Register 0x01: 0x00
Register 0x04: 0x548066
Register 0x09: 0x610000
Register 0x0A: 0x08
Register 0x0B: 0x00
Register 0x0C: 0x06
Register 0x0D: 0x00
Register 0x0E: 0x00
Register 0x0F: 0x00
Register 0x2E: 0x1834B4
Register 0xDA: 0x54
Register 0xDB: 0x80
Register 0xDC: 0x66
===========================

Looks like driver chip is: ILI9163 (based on datasheet ID)

*/

char *chip = "Unknown                                                                                           ";


uint32_t readwrite8(uint8_t cmd, uint8_t bits, uint8_t dummy)
{
    uint32_t ret = 0;
    uint8_t val = cmd;
    int cnt = 8;
    digitalWrite(TFT_CS, LOW);
    digitalWrite(TFT_DC, LOW);
    pinMode(TFT_MOSI, OUTPUT);
    for (int i = 0; i < 8; i++) {   //send command
        digitalWrite(TFT_MOSI, (val & 0x80) != 0);
        digitalWrite(TFT_SCK, HIGH);
        digitalWrite(TFT_SCK, LOW);
        val <<= 1;
    }
    if (bits == 0) {
        digitalWrite(TFT_CS, HIGH);
        return 0;
    }
    pinMode(TFT_MOSI, INPUT_PULLUP);
    digitalWrite(TFT_DC, HIGH);
    for (int i = 0; i < dummy; i++) {  //any dummy clocks
        digitalWrite(TFT_SCK, HIGH);
        digitalWrite(TFT_SCK, LOW);
    }
    for (int i = 0; i < bits; i++) {  // read results
        ret <<= 1;
        if (digitalRead(TFT_MOSI)) ret |= 1;;
        digitalWrite(TFT_SCK, HIGH);
        digitalWrite(TFT_SCK, LOW);
    }
    digitalWrite(TFT_CS, HIGH);
    return ret;
}

void showreg(uint8_t reg, uint8_t bits, uint8_t dummy)
{
    uint32_t val;
    val = readwrite8(reg, bits, dummy);

    Serial.print("Register 0x");
    if (reg < 0x10) Serial.print("0");
    Serial.print(reg , HEX);
    Serial.print(": 0x");
    if (val < 0x10) Serial.print("0");
    Serial.println(val, HEX);
}

void setup() {
    // put your setup code here, to run once:
    uint32_t ID = 0;
    Serial.begin(9600);
    Serial.println("TFT driver register values:");
    Serial.println("===========================");
    digitalWrite(TFT_CS, HIGH);
    //    digitalWrite(TFT_SCK, HIGH);
    pinMode(TFT_CS, OUTPUT);
    pinMode(TFT_SCK, OUTPUT);
    pinMode(TFT_MOSI, OUTPUT);
    pinMode(MISO, INPUT_PULLUP);
    pinMode(TFT_DC, OUTPUT);
    pinMode(TFT_RESET, OUTPUT);
    digitalWrite(TFT_RESET, HIGH);
    digitalWrite(TFT_RESET, LOW);   //Hardware Reset
    delay(50);
    digitalWrite(TFT_RESET, HIGH);
    showreg(0x01, 0, 0);            //Software Reset
    delay(100);
    ID = readwrite8(0x04, 24, 1);

    if ((ID & 0xFF8000) == 0x5C8000uL) chip = "ST7735 (based on datasheet ID)";
    if (ID == 0x7C89F0uL) chip = "ST7735 (empirical value)";
    if (ID == 0x548066uL) chip = "ILI9163 (based on datasheet ID)";
    if (ID == 0x5C0000uL) chip = "S6D02A1 (based on datasheet ID)";

    showreg(0x04, 24, 1);   //RDDID
    showreg(0x09, 32, 1);   //RDSTATUS
    showreg(0x0A, 8, 0);
    showreg(0x0B, 8, 0);
    showreg(0x0C, 8, 0);
    showreg(0x0D, 8, 0);
    showreg(0x0E, 8, 0);
    showreg(0x0F, 8, 0);
    showreg(0x2E, 24, 8);   //readGRAM
    showreg(0xDA, 8, 0);
    showreg(0xDB, 8, 0);
    showreg(0xDC, 8, 0);

    Serial.println("===========================");
    Serial.println();
    Serial.print("Looks like driver chip is: " );Serial.println(chip);
}

void loop() {

}

Interestingly it reports my display as having an ILI9163 but I am using initialisation code from this library for a S6D02A1 and it works OK but that may just be by luck and a degree of initialisation address compatibility.

Can you tell me where you got your display and what the ID reading sketch reports in the Serial Monitor window (9600 baud)?

The ID reader code in post #13 above indicates I have a ILI9163 driver on my display but this just happens to work OK with the S6D02A1 library!

So I have created a specific library for the ILI9163 and it is working fine. It retains the high plotting performance and is suited to AVR processors only (UNO, Mega, Leonardo etc) because of the way the performance enhancements have been done.

Report any bugs here.

Hello Bodmer,

Yes it was a typo. I use the SCL pin on the TFT side, wired to the SCK on the Mega side. Thanks for pointing out.

David, I tried with library for ST7735S and S6D02A1. A got at least some basic responding with the ST7735S (I looped over the function InvertDisplay every second and I saw the screen flashing at same frequency. I'm not sure it was actually inverting but it did something). The call to fill with a solid color didn't filled the entire screen but about 2/3 with some large areas in the middle being unaffected by the command (tried on two different parts). I got no result with the driver from Samsung so unless drivers have similar command register or I got lucky and the InvertDisplay function was recognized by my display even if I was using the wrong library, I guess that mine is ST7735S. I can still try with the libs for ILI9163C just in case!

Thanks, Simon

Hello bodmer,

Thanks for the script! Pretty effective... I just ran it and here is the output :

TFT driver register values:
===========================
Register 0x01: 0x00
Register 0x04: 0x548066
Register 0x09: 0x610000
Register 0x0A: 0x08
Register 0x0B: 0x00
Register 0x0C: 0x06
Register 0x0D: 0x00
Register 0x0E: 0x00
Register 0x0F: 0x00
Register 0x2E: 0x482020
Register 0xDA: 0x54
Register 0xDB: 0x80
Register 0xDC: 0x66
===========================

Looks like driver chip is: ILI9163 (based on datasheet ID)

The one I haven't tried yet, so there is hope! I also went back to the description of the TFT part I bought and it says ST7735... we always have surprises with these products from China! I will try your lib and give you some news.

Thanks again!

@slessard

OK, it looks like you have an ILI9163 based display then. The results indicate you have got the connections right.

You will need a resistor divider on the logic lines with that driver to avoid brightness modulation (happens when the display is being updated), I use 1k2 and 2k2 as I have lots of those values. Power the display from 5V, I notice that my display is fitted with a 3.0V regulator.

I intend to make a minor tweak to the library later today to add a "belt and braces" software reset at the start of initialisation.

I tested another display that I thought had a S6D02A1 and this does indeed seem to be the case as it only works with the TFT_S6D02A1 library and no others. Whereas the ILI9163 based display works fine with either the TFT_ILI9163 or the S6D02A1 library!

PS The TFT_ILI9163 library has been updated to add a software reset at the start of initialisation. This will help in cases where a display does not have a hardware reset pin.

It's starting to give some results! Apparently my TFT that was identified to be built with driver ST7735 by the vendor was finally made from ILI9163... Although it is not perfect, I have a good start see attached. The background is weird and the two bright stripes we can see is like those I got when I was using the library for the ST7735 but at this time it was two solid color areas, not pixelized like that and obviously without the text.

20160919.jpg|1255x1141

@slessard

That looks like the random startup state of the graphics RAM that is inside the display chip.

In setup() or somewhere else in your sketch, after tft.init(), you must clear the screen to the desired background colour, say with:

tft.fillScreen(TFT_BLACK);

bodmer: @slessard

OK, it looks like you have an ILI9163 based display then. The results indicate you have got the connections right.

You will need a resistor divider on the logic lines with that driver to avoid brightness modulation (happens when the display is being updated), I use 1k2 and 2k2 as I have lots of those values. Power the display from 5V, I notice that my display is fitted with a 3.0V regulator.

I intend to make a minor tweak to the library later today to add a "belt and braces" software reset at the start of initialisation.

Bodmer GOOD PLACE IS NECESSARY FOR THE DRIVER ST7735 RESISTENCIAS?

For 5V Arduino's a 1K2 series resistor can be used to interface with a ST7735 driver.

Example connections at the end of step 1 here.

bodmer;

My ST7735 TFT is working like a champ. You sir are a genius among geniuses.

@dad5019

Thanks for the feedback. Good luck with your project!

What's the reason this does not work on ESP8266-based MCUs? Regardless the speed, should I use the Adafruit ST7735 lib? Does it support I2C?

It is optimised for the AVR processors and uses machine coded sections to improve rendering speeds. This makes it 3 to 12 times faster depending on the graphics functions used.

If you wish to usse the display with an ESP8266 then you could try this library. It is optimised for the ESP8266.

This is the information dump

Looks like driver chip is: Unknown                                                                                           
`Hú5BþÿTFT driver register values:
===========================
Register 0x01: 0x00
Register 0x04: 0xE38835
Register 0x09: 0x610000
Register 0x0A: 0x08
Register 0x0B: 0x00
Register 0x0C: 0x06
Register 0x0D: 0x00
Register 0x0E: 0x00
Register 0x0F: 0x00
Register 0x2E: 0xFFFFFF
Register 0xDA: 0xE3
Register 0xDB: 0x88
Register 0xDC: 0x35
===========================

Looks like driver chip is: Unknown

|500x457

|500x441

Can help me identify