Go Down

Topic: 1.44 inch TFT 128x128 GLCD ILI9163 (Read 32094 times) previous topic - next topic

gimpo

#30
Jan 16, 2016, 10:02 pm Last Edit: Jan 16, 2016, 10:04 pm by gimpo
Updates about Arduino Pro Mini 3.3V/8Mhz


Seems that there is no way to speed up drawing performances further. Sumotoy libs are using SPI settings at their best.

Since arduino is an AVR device and new libs provide SPI transactions then the line 309 of the TFT_ILI9163.cpp is executed and used around the program:
.
.
.
ILI9163C_SPI = SPISettings(8000000, MSBFIRST, SPI_MODE0);
.
.
.

In fact, 8,000,000 is really the max speed that you can use on an 8Mhz processor (even if that value is just the max that can be used by SPI communications, not the actual).

I tried to substitute different values while running a stupid graphical test (the one drawing lines from the four corners of the screen). Here below the results:

parameter      execution time (ms)
500,00012042
1,000,0008639
2,000,0006940
3,000,0006940
4,000,0006089
5,000,0006089
6,000,0006089
7,000,0006089
8,000,0006089

(Quite strange that third and fourth values give the same result...)

So seems that there is not so much to do to increase drawing speed.
On the Pro mini performance are not so poor, are simply honest performance. But when I see test videos with Tensy I get envy...  :smiley-eek:

Any other idea is welcome.

(sumotoy is preparing version 1.0 of his libs, maybe there will be some further optimization, I don't know...)
Arduino, what else?

david_prentice

Go on.   The 128x128 screen is so small that you never notice the speed.

I am fascinated by your red/black discoveries.

Since you are running at 3.3V without any level-shifting,   the display should work 100%.

Please could you run this sketch and copy-paste the result from the Serial Terminal.
Code: [Select]

// see if 4-line mode can read anything

#define TFT_MOSI 11
#define TFT_SCK  13
#define TFT_SS   10
#define TFT_DC  (9)     //DC=7 for HX8347
#define TFT_RESET (8)   //Backlight on HX8347
char *chip = "controller";

#if defined(SPDR)
// use SPI mode #0
uint8_t spi(uint8_t c)
{
    SPDR = c;
    while ((SPSR & 0x80) == 0) ;
    return SPDR;
}
#endif

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_SS, LOW);
#if 0
    SPSR = (0 << SPI2X);
    SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); //1MHz
    digitalWrite(TFT_DC, LOW);
    pinMode(TFT_MOSI, OUTPUT);
    spi(cmd);
    if (bits) {
        digitalWrite(TFT_DC, HIGH);
        pinMode(TFT_MOSI, INPUT);
        while (bits) {
            ret <<= 8;
            ret |= spi(0x00);
            bits -= 8;
        }
        ret >>= dummy;
    }
#elif 0
    digitalWrite(TFT_DC, LOW);
    pinMode(TFT_MOSI, OUTPUT);
    for (uint8_t i = 0; i < 8; i++) {   //send command
        if (val & 0x80) PORTB |= (1 << 3);
        else PORTB &= ~(1 << 3);
        PORTB |= (1 << 5);
        PORTB &= ~(1 << 5);
        val <<= 1;
    }
    if (bits == 0) {
        digitalWrite(TFT_SS, HIGH);
        return 0;
    }
    pinMode(TFT_MOSI, INPUT_PULLUP);
    digitalWrite(TFT_DC, HIGH);
    for (uint8_t i = 0; i < dummy; i++) {  //any dummy clocks
        PORTB |= (1 << 5);
        PORTB &= ~(1 << 5);
    }
    while (bits) {
        for (uint8_t i = 8; i-- > 0; ) {  // read results
            val <<= 1;
            if (PINB & (1 << 3)) val |= 1;;
            PORTB |= (1 << 5);
            PORTB &= ~(1 << 5);
        }
        bits -= 8;
        ret <<= 8;
        ret |= val;
    }
#else
    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_SS, 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);
    }
#endif
    digitalWrite(TFT_SS, HIGH);
    return ret;
}

void showreg(uint8_t reg, uint8_t bits, uint8_t dummy)
{
    uint32_t val;
    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");
    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("Bi-directional Read registers");
    digitalWrite(TFT_SS, HIGH);
    //    digitalWrite(TFT_SCK, HIGH);
    pinMode(TFT_SS, OUTPUT);
    pinMode(TFT_SCK, OUTPUT);
    pinMode(TFT_MOSI, OUTPUT);
    pinMode(MISO, INPUT);
    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 == 0x7C89F0uL) chip = "ST7735R";
    if (ID == 0x548066uL) chip = "ILI9163C";
    ID &= 0xFF0000;
    if (ID == 0x5C0000) chip = "ST7735";
    showreg(0x04, 24, 1);  //RDDID
    showreg(0x09, 32, 1);  //RDDSTATUS
    showreg(0x0A, 8, 0);
    showreg(0x0B, 8, 0);   //RDDMADCTL
    showreg(0x0C, 8, 0);   //RDDCOLMOD
    showreg(0x0D, 8, 0);
    showreg(0x0E, 8, 0);
    showreg(0x0F, 8, 0);
    showreg(0x2E, 24, 8);  //readGRAM
    showreg(0xDA, 8, 0);   //RDID1
    showreg(0xDB, 8, 0);   //RDID2
    showreg(0xDC, 8, 0);   //RDID3
}

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

}


My red display shows an ID of 0x548066
Code: [Select]

Bi-directional Read registers
controller reg(0x01) = 0x00
ILI9163C reg(0x04) = 0x548066
ILI9163C reg(0x09) = 0x610000
ILI9163C reg(0x0A) = 0x08
ILI9163C reg(0x0B) = 0x00
ILI9163C reg(0x0C) = 0x06
ILI9163C reg(0x0D) = 0x00
ILI9163C reg(0x0E) = 0x00
ILI9163C reg(0x0F) = 0x00
ILI9163C reg(0x2E) = 0x00
ILI9163C reg(0xDA) = 0x54
ILI9163C reg(0xDB) = 0x80
ILI9163C reg(0xDC) = 0x66


Your controller might have a different ID.   Otherwise there is no way to tell whether the display has been configured for 128x132 or 128x128.

David.

CrossRoads

I believe SPI clock of 4 MHz is the fastest you can get with 8 MHz system clock.
See Table 19-5. Relationship Between SCK and the Oscillator Frequency of the '328P datasheet for example.
The 7 SCK clock rates are Fosc (system clock) divided by 2,4,8,16,32,64 and 128.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

david_prentice

Yes,  4MHz is maximum.    With care you can run the SPI with "minimal" gaps.

All the same,   even at 4MHz,   128x128 is not going to take very long to draw.

David.

gimpo

Please could you run this sketch and copy-paste the result from the Serial Terminal.
Here the result:
Code: [Select]

controller reg(0x01) = 0x00
controller reg(0x04) = 0x9101
controller reg(0x09) = 0x610000
controller reg(0x0A) = 0x08
controller reg(0x0B) = 0x00
controller reg(0x0C) = 0x06
controller reg(0x0D) = 0x00
controller reg(0x0E) = 0x00
controller reg(0x0F) = 0x00
controller reg(0x2E) = 0xFFFFFF
controller reg(0xDA) = 0x00
controller reg(0xDB) = 0x91
controller reg(0xDC) = 0x01


What is your conclusion?
Arduino, what else?

david_prentice

My conclusion is that you have a different ID.   So my library can run "native" when it finds your ID.

If it finds my ID,   it makes the appropriate 32 pixel shift.

Where did you get your "good" red display?     I thought that it was only the black pcb that behaved properly.
They are very sweet little displays.    Admittedly,   the 128x160 ST7735 red displays are just a bit more useful.   They have an SD socket and a screen that can provide readable text.

David.

gimpo

All the same,   even at 4MHz,   128x128 is not going to take very long to draw.
Yes, performances are honest.
I'm building a little gauge for motorcycle, it gets the input from various sensors. Now I observe just a little flickering when redrawing some "big" numbers on the display, but results are acceptable anyway (I have yet optimized my drawing routine).

Sumotoy claims that for his version 1.0 of TFT_ILI9163C libs he will abandon Adrafruit_GFX libs. He is writing his own graphical libs (there are yet some pre-releases on GitHub).
I think/hope that there will be some little improvement about performance 'cause of this. I will see...
Arduino, what else?

gimpo

#37
Jan 16, 2016, 11:26 pm Last Edit: Jan 16, 2016, 11:26 pm by gimpo
My conclusion is that you have a different ID.   So my library can run "native" when it finds your ID.
So my red tab is not simply a black tab painted with another color. It's a new animal in the zoo! :)

If it finds my ID,   it makes the appropriate 32 pixel shift.
Since you have a "genuine" black tab (if I remember right) the __OFFSET variable in that xyzwhatever.h file is set to 0. Do you apply the shift on your own? Maybe are you using an old version of sumotoy's libs (less than 0.9)?

Where did you get your "good" red display?     I thought that it was only the black pcb that behaved properly.
I saw many red tabs at cheap prices offered on ebay. But I was impatient so I've ordered one from this german vendor (yes, the price is too high).
No idea from where the vendor is getting that TFTs.
Arduino, what else?

gimpo

I believe SPI clock of 4 MHz is the fastest you can get with 8 MHz system clock.
See Table 19-5. Relationship Between SCK and the Oscillator Frequency of the '328P datasheet for example.
The 7 SCK clock rates are Fosc (system clock) divided by 2,4,8,16,32,64 and 128.
Just a question/curiosity: increasing the SPI speed has some kind of impact on the processor performances? I mean... it slows down the processor somehow?
Arduino, what else?

david_prentice

What style of gauge do you want?

A bar graph is easy.     A clockface gauge is a lot harder.

For a motorcycle,   you want a steady display.     You just need to display a running average.    Whether for RPM or for KPH.

I have no intention of abandoning the Adafruit graphics.    I might draw the text in hardware for bigger displays.   As I said,   128x128 is very quick to update.

David.

gimpo

What style of gauge do you want?
My gauge is mixed up with textual and graphical information both. A tree-menu (displayed on the screen) allows the user to choose between different display configurations. Preferences are then saved on the EEPROM. I've developed my own (optimized) routines to draw and update numbers of any size on the screen. So I'm not linked to prefixed font sizes at all, in this way I have no constrains about the general layout on the screen.

You just need to display a running average.    Whether for RPM or for KPH
Yesss.
Arduino, what else?

david_prentice

Your link shows a ST7735 display.    My ST7735 has an ID of
0x7C89F0
Code: [Select]

Bi-directional Read registers
controller reg(0x01) = 0x00
ST7735R reg(0x04) = 0x7C89F0
ST7735R reg(0x09) = 0x610000
ST7735R reg(0x0A) = 0x08
ST7735R reg(0x0B) = 0x00
ST7735R reg(0x0C) = 0x06
ST7735R reg(0x0D) = 0x00
ST7735R reg(0x0E) = 0x00
ST7735R reg(0x0F) = 0x00
ST7735R reg(0x2E) = 0x3E003C
ST7735R reg(0xDA) = 0x7C
ST7735R reg(0xDB) = 0x89
ST7735R reg(0xDC) = 0xF0

From the data sheet,  the "RDDID (04h): Read Display ID"
Quote
-The 2nd parameter (ID17 to ID10): LCD module's manufacturer ID.
-The 3rd parameter (ID26 to ID20): LCD module/driver version ID
-The 4th parameter (ID37 to UD30): LCD module/driver ID.
Since it is up to the manufacturer to program the ID,   the 2nd and 4th parameter may vary.
It looks like Sitronix uses values like 0x80, 0x81, ..., 0x89, ..., 0x91, ... for the 3rd parameter.

The ST7789V has 0x82.

Pure speculation.  Perhaps there are other owners of similar displays.

Incidentally,   these modern controllers are pretty good at powering up by themselves.
I had an ILI9163C on my Seeeduino running a "graphictest_kbv.ino" sketch.
I plugged in the ST7735 display and switched on (with the same sketch).
It ran everything perfectly apart from the RGB setting.

I think you have a Sitronix controller.

David.    

gimpo

Here a simple preview/demo of the program running on the red (?) tab:



In this configuration there is:

- the gear number on the left
- a speed meter on the top
- a digit speed meter on the right/middle
- a rpm bar on the right/low
Arduino, what else?

gimpo

I think you have a Sitronix controller.

David.   
This information is really precious for me. I would buy the same kind of display in future, without your help it would be almost impossible for me.
Thanks!
Arduino, what else?

david_prentice

Your numbers are very blocky.    Yes,   they will be quicker to draw,   but they are not very attractive.
I do not see any speed issues at all.    0-100 KPH in 10 seconds would have plenty of time to update gear, revs, speed, ...

I would suggest that you just have one main display value e.g. KPH.
With coloured bars or smaller digits for the RPM and gear selection.

I am not a motorcyclist.    I know which gear I am in on my push bike by how hard it is to pedal.
Surely on a motorbike,   you change gear by the sound of the engine.

David.

Go Up