ST7735 Graphics Chip & read frame buffer memory over SPI

Go To Last Post
65 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can anyone help with this?

 

I am trying to read the colour of a pixel over SPI - i.e. implement a read_pixel() function

 

Having looked at the datasheet it states that COLMOD should be 0x66 for read operation, that's 18 bits per pixel

 

I assume it is going to return 3 bytes of data for pixel colour?

 

Datasheet states "Dummy" after command RAMRD - huh? what does that mean?

 

When I follow the COLMOD command & 0x66 data byte with a RAMRD command - do I then just SEND 4 bytes of data to clock in 4 bytes? and ignore the first byte back?

 

I just don't understand the datasheet for RAMRD command

 

Anyone used this before?

 

My display works fine but so far not attempted to read anything just write to it

 

Any help much appreciated

 

Regards

Steve

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Datasheet states "Dummy" after command RAMRD - huh? what does that mean?

SPI is a two way process. For the master to read back a byte it has to send a byte. Once it has sent the RAMRD command it will presumably have to send 3 more bytes to get the result. The actual value you send to clock out this result is irrelevant and as such these are often called "dummy" or "stuffing" bytes. So I imagine the sequence is going to be something like:

(void)spi_transfer(RAMRD);
byte1 = spi_transfer(0x00); // see a dummy 0
byte2 = spi_transfer(0x00); // see a dummy 0
byte3 = spi_transfer(0x00); // see a dummy 0

 

EDIT: so I googled this a bit and it seems that the command is 0x2E and it's documented in the data at 10.1.23 but in further googling I found this:

 

https://forums.adafruit.com/view...

 

If the skilled engineers at Adafruit couldn't get it to work I wouldn't set my sights too high if I were you!

 

(and if you can't read it then you may need to keep a complete display buffer image locally if you have the RAM available to do this).

Last Edited: Mon. Nov 30, 2015 - 01:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If my memory is correct,  the little Red or Blue ST7735 displays from Ebay do not have a MISO pin.  So you can't read the memory.

 

If you have a ST7735 with a parallel bus,  you probably can read the ID and memory.    But you use a lot of wires for a 128x160 display.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

displays from Ebay do not have a MISO pin.

which might explain that comment from Adafruit in fact ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I cannot remember. But the Data sheet will tell you if your SPI interface can be read.

It also depends on which IM# pins are made available from the module.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had a look at the datasheet, and it looks a bit odd, (not what I call SPI!)

 

 

So it looks like you always can read, but can't use a HW SPI

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How very odd the names "SDA" and "SCL" usually imply I2C not SPI (where the signals are usually names MOSI, MISO, SCK or sometimes just DO, DI, CLK)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

+1

 

But it only has SPI. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I noted that the datasheet states that the colour mode has to be switched to 18 bit mode BEFORE any read - at least that's my take on the note

 

Also I think CS has to go high at the end of the sequence, I have CS held permanently low if I recall correctly - will check later

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is very likely that you have a ST7735R with a regular 4-wire  SPI interface.

The data sheet is very obtuse.

 

Look at "9.4.4 4-line serial protocol"

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah-ha.   I had always just assumed that the Ebay modules were write-only.

 

Looking at "13.3.10 4-Line serial MCU Interface (IM2, IM1, IM0=”000”, SPI4W=1)"in theST7735R data sheet,   I see that SDA is bi-directional.   So you send a hardware 8-bit command,  disconnect SPI,  make MOSI input-pull-up and bit bash the read.

 

It had never crossed my mind to try it.   I will give it a go and see how I get on.

I tried reading SDA on a HX8347D a couple of days ago without success.

 

Woo-hoo,  I will dig out the Arduino sketch.  If it works on the ST7735R,  I will try a ILI9163.

 

David.

 

Edit.  I tried with both ST7735R with "almost" success.  

Last Edited: Mon. Nov 30, 2015 - 07:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see that SDA is bi-directional.

Yes look at my #6

Is that what you do ? (because on that drawing it looks like write one bit then read one bit ..... on next clk)

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have read my ST7735R and ILI9163C controllers:

// see if 4-line mode can read anything

#define TFT_DC  (9)     //DC=7 for HX8347
#define TFT_RESET (8)   //Backlight on HX8347
char *chip = "controller";

// use SPI mode #0
uint32_t readwrite8(uint8_t cmd, uint8_t bits, uint8_t dummy)
{
    uint32_t ret = 0;
    uint8_t val = cmd;
    int cnt = 8;
    digitalWrite(SS, LOW);
    digitalWrite(TFT_DC, LOW);
    pinMode(MOSI, OUTPUT);
    for (int i = 0; i < 8; i++) {   //send command
        digitalWrite(MOSI, (val & 0x80) != 0);
        digitalWrite(SCK, HIGH);
        digitalWrite(SCK, LOW);
        val <<= 1;
    }
    if (bits == 0) {
        digitalWrite(SS, HIGH);
        return 0;
    }
    pinMode(MOSI, INPUT_PULLUP);
    digitalWrite(TFT_DC, HIGH);
    for (int i = 0; i < dummy; i++) {  //any dummy clocks
        digitalWrite(SCK, HIGH);
        digitalWrite(SCK, LOW);
    }
    for (int i = 0; i < bits; i++) {  // read results
        ret <<= 1;
        if (digitalRead(MOSI)) ret |= 1;;
        digitalWrite(SCK, HIGH);
        digitalWrite(SCK, LOW);
    }
    digitalWrite(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(SS, HIGH);
    //    digitalWrite(SCK, HIGH);
    pinMode(SS, OUTPUT);
    pinMode(SCK, OUTPUT);
    pinMode(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 == 0x7C89F0uL) chip = "ST7735R";
    if (ID == 0x548066uL) chip = "ILI9163C";
    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);
}

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

}

The RDIDD and Status Registers require one dummy clock when you use 4-wire Serial.    No problem.   You have to bit bash it on an AVR because it has not got a SDIO capability.   So it does not matter if you have to do a few shenanegins.

 

You can see that I read the GRAM with register 0x2E.

 

Now that I can readGRAM(),  I will implement readPixel() for these two controllers.

 

David.

Last Edited: Mon. Nov 30, 2015 - 09:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So David,

 

You have suceeded where Adafruit failed - well done

 

the term "dummy" in the datasheet makes sense now and the timing diagrams indicates the dummy clocks

 

ref. read pixel

 

I could be talking crap here as I havnt looked into it in depth but

 

since there are 8 dummy clocks for read pixel, would it be possible to continue to use the hardware spi by turning the MOSI pin to input after the command has been issued and linking the MOSI and MISO pins on the AVR together, issue a standard 8 bit data out to generate the 8 dummy clocks then issue 3 more reading the bytes returned on MISO as normal?

 

Regards

Steve

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That sounds possible, but you need to think about the other devices on the SPI bus.
I will link MOSI, MISO with a 10k resistor. Send spi(cmd), make MOSI an input, and receive replies from spi(0xFF).

Yes, read 4 bytes for RDDID. Read 5 bytes for RDSTATUS. Shift by 1.
I will try this later. I can see that 8MHz reads might be iffy. It always amazes me just how fast these controllers can handle SPI. You do need to be careful with the Parallel bus. Reads are always slower than Writes.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi David,

 

Yes of course, however in my case I only have the ST7735 connected to the hardware SPI and I would like pixel reads to be fast as possible because I intend to read (up to) 160 pixels into a buffer at a time then write them back and repeat many times over for a software scroll feature of a text window. I dont think I need the 10k resistor - just need to be mindful of the attached programmer in my case, so will just fit a 2way jumper to select MISI on the AVR to connect either to MOSI on the ST7735R or the programmer MISO pin

 

Let me know how it goes, I probably wont get any time until this weekend to try

 

Steve

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Incidently my ST7735R based TFT display from Adafruit has a module pin labelled MISO (just to confuse folks) but as far as I can tell it is not connected to anything within the TFT module! (although thinking about it, it may be used by the sd card reader onboard - I dont use that) - MISO module pin is high impedance (floating) all the time.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well,  I have tried the 10k trick.   And captured it with a Logic Analyser.

MISO follows the MOSI line as you would expect.   However you get a glitch on each +ve edge of SCK.

This means that the SPI hardware reads this tiny glitch.   I suppose that I could put a small  capacitor on the MISO.

 

Yup,  tried 100pF i.e. TC=1us.    Works ok for slow SCK frequency but NBG @ 8MHz.   33pF is "ok" @ 1MHz.

I am reluctant to cripple my SD card.   And since the MOSI signal looks pretty good on my Logic Analyser,  it seems far simpler to do the bit-banging.   After all,   I should be able to bit-bang at 2MHz.   I will see.   

 

Anyway,  readGRAM should auto-increment.   So readPixel is a bad idea (tm).   readGRAM for a whole block is a lot more efficient.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi David

 

Yes I intend to implement 3 functions

 

read_pixel()          not that useful .... but proves method of reading from screen back to mcu

 

read_gop()            read a GroupOfPixels from screen to an array using auto-increment

write_gop()           write a GroupOfPixels from array to screen using auto-increment

 

array size = tft_xres

 

read_gop() & write_gop() will accept parameters specifying the start pixel coords and the number of pixels to read/write

 

Steve

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

David,

 

Out of interest ..... what is the difference between the ST7735R and the ILI9163C controllers - registers are obviously similar

 

Steve

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sitronix and Ilitech are two different companies.

All TFT controllers are similar in operation. It is the differences that you need to worry about.

If I was you, I would look at the API of current libraries. Life is a lot easier if you use the same method()s. e.g. look at Adafruit classes.

I have a single readGRAM() method. readPixel() is just the special case of a block with size of one.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi David,

 

I have tried to replicate your result by translating your code into something I can use but it does not appear to read anything back from the registers - what am I doing wrong?

 

I dont understand - what I am doing any different

 

I have an external pull-up on MOSI line & MISO is not connected (no point)

 

#include "globals.h"
#include "hd44780.h"
#include "hd44780_console.h"
#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>

#define CS_PIN  3
#define DC_PIN  4
#define MOSI_PIN 5
#define SCK_PIN  7

#define CS_INIT_OUTPUT() DDRB|=(1<<CS_PIN)
#define CS_HI    PORTB|=(1<<CS_PIN)
#define CS_LO    PORTB&=(~(1<<CS_PIN))
#define CS_TOGGLE   PORTB^=(1<<CS_PIN)

#define DC_INIT_OUTPUT() DDRB|=(1<<DC_PIN)
#define DC_HI    PORTB|=(1<<DC_PIN)
#define DC_LO    PORTB&=(~(1<<DC_PIN))
#define DC_TOGGLE   PORTB^=(1<<DC_PIN)

#define MOSI_INIT_OUTPUT() DDRB|=(1<<MOSI_PIN)
#define MOSI_INIT_INPUT() DDRB&=(~(1<<MOSI_PIN))
#define MOSI_HI    PORTB|=(1<<MOSI_PIN)
#define MOSI_LO    PORTB&=(~(1<<MOSI_PIN))
#define MOSI_TOGGLE   PORTB^=(1<<MOSI_PIN)

#define SCK_INIT_OUTPUT() DDRB|=(1<<SCK_PIN)
#define SCK_HI    PORTB|=(1<<SCK_PIN)
#define SCK_LO    PORTB&=(~(1<<SCK_PIN))
#define SCK_TOGGLE   PORTB^=(1<<SCK_PIN)

#define SLPOUT   0x11  //sleep out
#define DISPON   0x29  //display on
#define CASET   0x2a  //column address set
#define RASET   0x2b  //row address set
#define RAMWR   0x2c  //RAM write
#define MADCTL   0x36  //axis control
#define COLMOD   0x3a  //colour mode

char *chip = "Chip";

uint32_t readwrite8(uint8_t cmd, uint8_t bits, uint8_t dummy)
{
    uint32_t ret = 0;
    uint8_t val = cmd;
    
    uint8_t mosi_state;
    
// int cnt = 8;  //not used?

    CS_LO;           //digitalWrite(SS, LOW);
    DC_LO;           //digitalWrite(TFT_DC, LOW);
    MOSI_INIT_OUTPUT();        //pinMode(MOSI, OUTPUT);
    for (int i = 0; i < 8; i++) {                //send command
        if((val & 0x80) != 0)      //digitalWrite(MOSI, (val & 0x80) != 0);
            MOSI_HI;
        else
            MOSI_LO;
        SCK_HI;          //digitalWrite(SCK, HIGH);
        SCK_LO;          //digitalWrite(SCK, LOW);
        val <<= 1;
    }
    if (bits == 0) {
        CS_HI;          //digitalWrite(SS, HIGH);
        return 0;
    }
    MOSI_INIT_INPUT();        //pinMode(MOSI, INPUT_PULLUP);
    DC_HI;           //digitalWrite(TFT_DC, HIGH);
    for (int i = 0; i < dummy; i++) {               //any dummy clocks
        SCK_HI;          //digitalWrite(SCK, HIGH);
        SCK_LO;          //digitalWrite(SCK, LOW);
    }
    for (int i = 0; i < bits; i++) {               // read results
        ret <<= 1;
        mosi_state=PINB&=(1<<MOSI_PIN); //if (digitalRead(MOSI)) ret |= 1;;
        if(mosi_state>0)
            ret |= 1;
        SCK_HI;          //digitalWrite(SCK, HIGH);
        SCK_LO;          //digitalWrite(SCK, LOW);
    }
    CS_HI; //digitalWrite(SS, HIGH);
    return ret;
}

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

    console_write_string(chip);      //Serial.print(chip);
    console_write_string(" reg(0x");    //Serial.print(" reg(0x");
    if (reg < 0x10) console_write_string("0");  //if (reg < 0x10) Serial.print("0");
    console_write_byte_info_in_hexadecimal(reg); //Serial.print(reg , HEX);
    console_write_string(") = 0x");     //Serial.print(") = 0x");
    if (val < 0x10) console_write_string("0");  //if (val < 0x10) Serial.print("0");
    console_write_byte_info_in_hexadecimal(val); //Serial.println(val, HEX);

}

int main(void)
{
    lcd_init(NO_CURSOR);

    uint32_t ID = 0;
    console_init(NO_CURSOR);      //Serial.begin(9600);
    console_write_string("Registers");    //Serial.println("Bi-directional Read registers");
    CS_HI;           //digitalWrite(SS, HIGH);
    //    digitalWrite(SCK, HIGH);
    CS_INIT_OUTPUT();        //pinMode(SS, OUTPUT);
    SCK_INIT_OUTPUT();        //pinMode(SCK, OUTPUT);
    MOSI_INIT_OUTPUT();        //pinMode(MOSI, OUTPUT);
                                                    //pinMode(MISO, INPUT_PULLUP);
    DC_INIT_OUTPUT();        //(TFT_DC, OUTPUT);
                                                    //pinMode(TFT_RESET, OUTPUT);
                                                    //digitalWrite(TFT_RESET, HIGH);
                                                    //digitalWrite(TFT_RESET, LOW);    //Hardware Reset
                                                    //delay(50);
                                                    //digitalWrite(TFT_RESET, HIGH);
    _delay_ms(500);
    showreg(0x01, 0, 0);                  //Software Reset
    _delay_ms(500);
    showreg(SLPOUT, 0, 0);
    _delay_ms(150);
    showreg(DISPON, 0, 0);
    _delay_ms(100); //delay(100);

    ID = readwrite8(0x04, 24, 1);
    if (ID == 0x7C89F0uL) chip = "ST7735R";
    if (ID == 0x548066uL) chip = "ILI9163C";
    showreg(0x04, 24, 1);                  //RDDID
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0x09, 32, 1);                  //RDSTATUS
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0x0A, 8, 0);
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0x0B, 8, 0);
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0x0C, 8, 0);
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0x0D, 8, 0);
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0x0E, 8, 0);
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0x0F, 8, 0);
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0x2E, 24, 8);                  //readGRAM
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0xDA, 8, 0);
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0xDB, 8, 0);
    _delay_ms(1000);
    console_write_string("\r\n\r\n");
    showreg(0xDC, 8, 0);

    while(1)
    {
    }
}

I know my code is not good but it was only meant as a quick and dirty test to see if I could get the result you had with your code

 

Regards

Steve

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your code looks fine to me. Let's face it. The only Arduinoese is the pinMode and digitalRead and write.

I suggest that you put your delay and linefeeds into the showreg() function. Then you will have exactly the same structure as me.

You do realise that buying a 3.3V capable Arduino clone is the next best investment you can make (after buying some pencils)

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

but it does not work - it just reads 0xFF for every register

 

Any idea's? - Im all out of idea's now

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As I suggested.   Tidy up your "port".

 

I gave you an Arduino example because the whole world can use it.

 

If you have your own custom display functions,  it is up to you to debug them.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi David

 

Can you just confirm that you used the EXACT code you posted and definately with a ST7735R based TFT and you were able to read registers no problem

 

If that is so I will continue to try to make this work here, but I am thinking my issue maybe hardware related not software at this stage

 

Just acording to google noone else seems to have got this working except you, and I dont want to be on a wild goose chase here so would very much appreciate if you could confirm it definately does work with that SPECIFIC controller

 

I can "tidy up" when the fundamental issue of not readings registers is resolved

 

Steve

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, of course I ran it in real life.

While I was out with my dog, I realised that you had deliberately removed my hardware reset. Most modules do NOT have pull-ups on their pins. You need to have a pull-up on RST pin or else the controller will not know where it is.
You can avoid the active-low on RST by using software reset.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes I know - I have my ST7735R reset tied to the MCU reset pin and I have a reset jumper also - plus the display comes on and displays random pixels so dont think it is reset related and the fact that the exit sleep and display on commands work tells me all pins are connected correctly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What hardware are you using?
i
I have definitely got a C project for Codevision.
I would prefer to post an Arduino library solution.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just an ATmega324A on a breadboard externally clocked at 14.7456MHz with a 2x20 line HD44780 based lcd hung off the other ports nothing fancy - I am just using that for testing purposes at the minute

 

If you have it working and I beleive you do, then I am thinking it may be a timing problem at the point when I READ the MOSI line, your code may be introducing more delay before the line is actually sampled

 

I dont have the luxury of a scope or logic analyser so its difficult here

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I bit bashed it in C at an effective 1.5Mhz. I know that I can get faster with unrolled ASM.

If I am feeling keen, I will update a C++ library and incorporate the extra methods.

I strongly recommend that you get a 3.3V Arduino. You don't have to use it in a final project but it is excellent for broadcasting code that the whole world can use.
And a $10 Saleae clone does not break the bank.

David.

Last Edited: Wed. Dec 2, 2015 - 06:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have just hacked the code and introduced some significant delays around the MOSI read section and attached two logic probes to the SCK and MOSI lines

 

I can see the SCK clocking nicely during this period but the MOSI line does not budge - i.e. nuthin comes FROM of the display

 

Now something you have just said has set me thinking - this Adafruit module I am sure states that it can be used on 5V systems (hope so anyway because my system is 5V!!) but is the ST7735R a 3V part? and does the Adafruit module have level translation on its pins ?

 

because if it does I bet its only uni-directional !!

 

Need to look at this - what TFT module do you have David - not Adafruit and 3V only?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes MOSI pin drives into a 4050 on the underside of the PCA - guess MOSI pin is therefore unidirectional !!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So now I need a ST7735R 1.8" TFT module - 3.3V only - dont need or really want SD card slot - anyone know of one?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have the regular Ebay modules.   They are 3.3V operation (but Ebay vendors lie through their teeth about 5V)

 

I use them with ARM which is 3.3V or with a Seeeduino which is a "3.3V switchable" Duemilanove clone.

 

Life is far simpler with an MCU that runs at 3.3V.    Level shifting buffers that are unidirectional are just fine.    When you want individual pins to be bi-directional,  you have to think harder.

 

Why don't you buy a couple of Red modules from China?   128x160 is ST7735R and 128x128 is ILI9163C.

 

Why not hack your current module?    Just run a wire from the module's SDA pin to a GPIO pin on the AVR via a 1k series resistor.    You may get glitches but hey-ho,  it is worth  a try.

 

David.

Last Edited: Thu. Dec 3, 2015 - 08:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ordered some 3V ST7735S TFT displays off ebay

 

Not sure of the significance of the S part is but I am guessing it is a later variant

 

 

Will report back once I have them, will need a 3V MCU too

 

But for anyone attempting to read TFT pixel data or ST7735 registers from an Adafruit ST7735R 1.8" TFT module with SD Card - forget it its not going to happen !

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have software scrolling working on ST7735 and ILI9361. It is SLOW. It is also a bit iffy.
When you do an animated scroll, you are doing multiple readGRAM calls. This increases the chance of a single bit going wrong.

The ST7735 data sheet does not seem to show hardware vertical scrolling. It seems to work fine but I have not done extensive tests of subwindows.

So if you want horizontal scrolling, life would be a lot simpler if you just used Landscape.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi David,

 

When you read the pixel colour back is it 18bit encoded? - datasheet suggests it is

 

Since I am using 16bit colour that is a pig because thats means to write it back is going to take more SCK cycles for the extra byte or I have to reformat the colour info before writing 16bit colour back

 

I cant test for myself at the minute because still waiting for some TFT's to arrive without unidirectional level convertors in the way

 

Steve

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes,   you read 3 bytes :

int16_t ST7735_kbv::readGRAM(int16_t x, int16_t y, uint16_t * block, int16_t w, int16_t h)
{
	uint8_t r, g, b;
	int16_t n = w * h;    // we are NEVER going to read > 32k pixels at once
	setAddrWindow(x, y, x + w - 1, y + h - 1);
	CS_ACTIVE;
	WriteCmd(ST7735_RAMRD);
	CD_DATA;
	SDIO_INMODE();        // do this while CS is Active

	r = readbits(9);	  // needs 1 dummy read (8) for ILI9163
	while (n-- > 0) {
		r = readbits(8);
		g = readbits(8);
		b = readbits(8);
		*block++ = color565(r, g, b);
	}
	CS_IDLE;
	SDIO_OUTMODE();      //do this when CS is Idle
    setAddrWindow(0, 0, width() - 1, height() - 1);
    return 0;
}

The readbits():

#define SDIO_INMODE() uint8_t spcr = SPCR;SPCR = 0;MOSI_IN   //no braces
#define SDIO_OUTMODE() {MOSI_OUT;SPCR = spcr;}
static uint32_t readbits(uint8_t bits)
{
	uint32_t ret = 0;
	while (bits--) {
		ret <<= 1;
		if (PINB & (1<<MOSI_PIN)) ret++;
		SCK_HI;
		SCK_LO;
	}
	return ret;
}

I am sure that you can work out what the macros do.

Most "readable " registers are 8-bit.   Specials for RDDID and RDSTATUS:

static uint32_t readRegister(uint8_t reg)
{
    uint32_t ret;
	uint8_t bits = 8;
	if (reg == 4) bits = 25;
	if (reg == 9) bits = 33;
    CS_ACTIVE;
    WriteCmd(reg);
    CD_DATA;                    //
	SDIO_INMODE();
    ret = readbits(bits);
    CS_IDLE;
	SDIO_OUTMODE();
    return ret;	
}

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

idealpcsolutions wrote:

Ordered some 3V ST7735S TFT displays off ebay

 

Not sure of the significance of the S part is but I am guessing it is a later variant

 

 

Will report back once I have them, will need a 3V MCU too

 

But for anyone attempting to read TFT pixel data or ST7735 registers from an Adafruit ST7735R 1.8" TFT module with SD Card - forget it its not going to happen !

Hi David and Steve (and everybody else),

 

I am trying now for a long time to get the read register working with my XMC4800 and my ST7735R. I am using 3.3V logic my Display and my XMC.
Could you please explain to me again, whhy I cannot read registers with the ST7735R module?

 

Thank you very much!

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have ST7735R or ST7735S ?

 

The S can do Vertical Scroll.   The R can not.

Both variants can read certain registers via the bidirectional SDA line.

 

What is a XMC4800?   Does it have DDRB, PORTB, PINB registers?   or equivalents?

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for the incomplete information:

- I am using an infineon XMC4800 Controller with 3V3 (wirting display data works fine) and an ST7735R

 

What do you mean with "certain registers". I just want to read the RDDID but all I can see is 0xFF.

(see oscilloscope attached)

edit:
red: SCLK

green: MISO/MOSI
yellow: DC
Blue: CS (SS)

Thank you!

 

 

Last Edited: Tue. Oct 4, 2016 - 08:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Post your code.  Or at least study the code that I posted.

 

You must change the SDA data direction from write to read after you have written the command.

 

To be honest,   the risetime of the green trace does look as if you have changed SDA to "INPUT_PULLUP" at the time DC goes fom command to data.

 

David.

Last Edited: Tue. Oct 4, 2016 - 08:43 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have studied your code precisely.
I am setting the D/C to high right after i set my pin to INPUT_PULLUP (in my case to INPUT open drain, as I have an external pullup).

This seems correct to me, as only the last bit D0 seems for D/C. (By the way, the drawing (D/C = Dont care) is inconsistent with the description (D/C = 1) ... to be sure I set it to 1) .

 

I attached my code:


        USIC2_CH1->IN[4]=0x04; // SEND COMMAND RDDID (IN[] Triggers HPCDIR via TCI to be an Output (relevant for HW Controlled Ports e.g. P4_7)
	while ((((USIC2_CH1->PSR & USIC_CH_PSR_TSIF_Msk) >> USIC_CH_PSR_TSIF_Pos) == 0x00)); // Wait for SPI command to be sent
	//DUMMY BYTES FOR ANSWER
		for (disp_u8Cntr=0; disp_u8Cntr<disp_u8AnswerSize; disp_u8Cntr++)
		{
			USIC2_CH1->PSCR |= (0x01ul << USIC_CH_PSCR_CTSIF_Pos); // Set TSIF Flag
			USIC2_CH1->IN[8]=0x00; // Send Dummy bytes to generate clock  (IN[] Triggers HPCDIR via TCI to be an Input (relevant for HW Controlled Ports e.g. P4_7))
			HMI_TOOLS_Delay(1); // Delay for DC to make sure that its not before the end of the spi command
			P1_6_set(); // Set DC to high
			while ((((USIC2_CH1->PSR & USIC_CH_PSR_TSIF_Msk) >> USIC_CH_PSR_TSIF_Pos) == 0x00)); // wait for spi command to be sent
			disp_paReceivedBytes[disp_u8Cntr] = USIC2_CH1->OUTR; //Read answer from Register (irrelevant, as nothing appears on the scope)

		}
	}

Last Edited: Tue. Oct 4, 2016 - 09:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What value is your external pullup on SDA ?   I would use 10k - 47k.

 

I am not familiar with your MCU or the syntax in your code.   As you can see by the Timing Diagrams,   the DC state must be 0 when the last SCK pulse is sent (lsb of the command)

 

Your yellow trace shows that DC=0 when the green trace rises (entering hi-Z).   So the Timing looks correct to me.

 

I can post you an Arduino sketch that bit-bashes the ST7735.    Do you possess a 3V Arduino like Zero or Due ?

 

David.

 

Edit.   Silly question:  Have you got TFT_RST pin high?   Nothing will work when the controller is in reset.

Last Edited: Tue. Oct 4, 2016 - 10:33 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for you answer!

 

- I will try another pullup, but why would you use a 10k-47k Pullup? I have a 4.75k resistor, for which reason(s) is that not sufficient?

 

And yes my TFT_RST pin is high all the time after the initialization, but this is in regard to the datasheet correct (see below)? Furthermore my "write" procedure works fine with TFT_RST beeing HIGH.

 

- No I donnot possess an arduino, but I can try to understand the code.

 

regards

Peter

 

.

Last Edited: Tue. Oct 4, 2016 - 11:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

4k75 sounds rather an unusual value.   It does seem rather "strong".

 

When you have a bidirectional SDA pin,  the "output" drive tends to be a bit wimpy.

It may be a weak push-pull.   It is more likely to be a "common-drain" style.

 

The AVR internal pullup is about 30k.   I could try a strong external pullup to see what happens with ST7735S, ILI9163C, ...

I suggest that you try 22k first.

 

Yes,  you would use a hardware reset first.  e.g. 1ms active low pulse.   Then wait 120ms for the ST7735 to complete its internal reset before sending any commands.   

 

David.

Last Edited: Tue. Oct 4, 2016 - 11:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello David,

 

I built in a 22k pullup resistor, but unfortunately still no signal from the display.

All I can see is a low rising tri-state due to the high parasitic capacitance.

 

I attached my oscilloscope images, do you have any suggestions?
Thank you!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am a little horrified by the ringing on your signals.   I would try to clean this up first.

 

The XMC4800 seems to be a 144MHz Cortex-M4.    I see no reason for why it should not work ok with a ST7735.

I have run a ST7735S with 100Mhz M4 from ST and 96MHz M4 from Freescale.

 

Mind you,  this is supposed to be an "Atmel/Microchip" forum.

 

I would also suggest that an Arduino or MBED platform would be a wise investment.    It would mean that you could run example sketches from anyone, anywhere in the world.    Ok,   it might be on different target processors.

 

So my only advice is:

1.  buy a 3.3V Arduino / MBED

2.  run / study / investigate example code.

3.  reproduce the code / algorithms on your XMC4800.

 

In practice,   I read the ID from a ST7735 or ILI9163 to select the correct initialisation sequence.

I use the same graphics etc for any controller.    Occasionally I read blocks of GRAM memory.  e.g. to manipulate or save an area of screen.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi.

 

I've also been playing around with an eBay LCD and also trying to read the display memory. I'd like to point out one important thing I've found:

ILI9163 does not allow the reading of display memory through serial. Other read commands work as expected, but RAMRD does not.

 

In fact, the datasheet for ILI9163 even mentions this under the documentation for RAMRD: "Note: Memory Read is only possible via the Parallel Interface".

 

I hope this saves somebody from an infuriating debugging session :-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Rubbish.   I have read GRAM and the ID registers of the ILI9163C for always.

 

I have also published a diagnostic sketch for the Arduino.   And there is example code in #13.

 

David.

Pages