Reading Pixels from GRAM memory in ILI9341 and ILI9325

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I composed this reply to a question from "lekter" that was deleted while I was typing:

So I thought that I will post it myself.

uint16_t readPixel(int16_t x, int16_t y)
{
    uint8_t block[4];
    write_cmd_rpt(ILI9341_CMD_COLUMN_ADDRESS_SET, x, 1);
    write_cmd_rpt(ILI9341_CMD_PAGE_ADDRESS_SET, y, 1);
    write_cmd(ILI9341_CMD_MEMORY_READ);
    read_byte_block(block, 4);
    return ((block[1] & 0xF8) << 8u) | ((block[2] & 0xFC) << 3u) | (block[3] >> 3u);
}

It depends a bit on your interface and setup. I use SPI, and you need to read 4 bytes. i.e. 1 dummy, then R, G, B. Then I convert the 3 RGB bytes to a 5-6-5 uint16_t.

If you want to read a whole block of pixels, you can read continuously.
It should be possible to read the 5-6-5 in 2 SPI bytes. However, I would need to check on this.

With most TFT controllers, you just set an address window and then read or write continuously. i.e. 16-bits per pixel. As opposed to setting up the X, Y address, and writing one pixel. (which is 6 words or 12 bytes per pixel)

As always in life, post a link to your TFT module. It makes it far easier to give an answer.
It also helps to say dev board, AVR, Compiler, IDE, ...

Incidentally, with an ILI9320 and ILI9325, reading GRAM does not increment the GRAM address even though it says that it should in the data sheet.
Or does anyone know how to do this? (without dummy writes)

David.

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

This is a very old topic but maybe someone have a working full example for reading pixel from GRAM for Arduino? I cannot get this to work. 

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

Surely you should ask your question on the Displays Topic of the Arduino.cc forum.
.
Quote the library you are using and post a link to the actual display that you have e.g. Ebay sale.
You can find the library version from the Library Manager.
.
David.

Last Edited: Thu. Aug 3, 2017 - 01:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm using this: https://github.com/adafruit/Adaf... and this is my screen: http://www.ebay.pl/itm/2-2-inch-...

I couldn't find working lib with reading pixel from GRAM routine.

I have also asked a question on arduino forum but I don't think that anyone will be able to help me with that :/

 

Last Edited: Thu. Aug 3, 2017 - 01:14 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The display requires 3.3V logic. Either use level shifter chip(s) or series resistors.
Personally, I run these displays on 3.3V Xmega, STM32, SAM, LPC ... as well as a 3.3V Seeeduino.
I will update my copy of this Adafruit library and check for myself later today.
.
David.

Last Edited: Thu. Aug 3, 2017 - 01:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Super! I have this display already running with level shifter and only readpixel is what I need. The best solution would be to get full lib with support for pixel read. I also have stm32f103 so If You have running lib with get pixel for this ARM then it will be enough for me. 

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

I updated the Adafruit library to v1.0.10 from my previous 1.0.1.

I note that neither version supported readPixel()

 

I had given protected status to the v1.0.1 writecommand(), writedata(), readdata() methods.

Which let me implement readPixel(), readGRAM(), vertcroll() with a GLUE class.

 

v1.0.10 has altered the primitive private methods.   So the names are different.  But this is what it was:

        uint16_t readPixel(int16_t x, int16_t y) {
            uint8_t r, g, b;
            setAddrWindow(x, y, x, y);
            r = readcommand8(0x2E);
            r = readdata();              //dummy
            r = readdata();
            g = readdata();
            b = readdata();
            return color565(r, g, b);    //.kbv
        }

        int16_t  readGRAM(int16_t x, int16_t y, uint16_t *block, int16_t w, int16_t h)
        {
            uint16_t *p;
            for (int row = 0; row < h; row++) {
                p = block + row * w;
                for (int col = 0; col < w; col++) {
                    *p++ = readPixel(x + col, y + row);
                }
            }
        }

        void vertScroll(int16_t top, int16_t scrollines, int16_t offset)
        {
            // .kbv add this line to Adafruit_ILI9341: friend class GLUEAdafruit_ILI9341;
            int16_t vsp = top + offset;      // vertical start position
            if (offset < 0)
                vsp += scrollines;          //keep in unsigned range
            int16_t bfa = HEIGHT - top - scrollines;
            writecommand(0x0033);
            writedata(top >> 8);           //TOP
            writedata(top);             //TOP
            writedata(scrollines >> 8);
            writedata(scrollines);
            writedata(bfa >> 8);
            writedata(bfa);
            writecommand(0x0037);
            writedata(vsp >> 8);     //VL#
            writedata(vsp);       //VL#
        }

If you are familiar with the MCUFRIEND_kbv library examples,   you will see that the SPI version of ILI9341 can do everything that that all the other MCUFRIEND_kbv controllers can.

 

David.

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

I have checked Adafruit ILI9341 library and it seems that ver 1.0.2 -> https://github.com/adafruit/Adaf... is the latest which has writecommand(), writedata(), readdata() methods so I will downgrade my version to 1.0.2 at first.  Can You also point me what changes have You done to the header file? You have mentioned about protected class ... Or maybe simply You could zip Yours lib an post it here?

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

David, I also trying to read from ILI9341 using the blue pill, and have no success.

This is my board: http://www.ebay.de/itm/2-4-SPI-T...

 

I tried your code readPixel() posted above, using the Adafruit code, and it always reads 0.

Tried to insert delays between consecutive reads, tried to lower SPI clock - nothing helps.

 

Is it possible that the  ILI9341 chip is set somehow to disable reading?

Last Edited: Fri. Aug 4, 2017 - 08:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The AVR processors ar pretty much under powered for controlling TFT LCD's. Main limits are RAM size and pixel pushing speed), and I assume not many people use them on AVR's for that reason.

https://www.mbed.com/en/ might be a much beter place for asking questions on TFT displays, even if you insist on sticking to using them with AVR's.

Code is all written in C / C++ nowaday's so the underlying uC architecture does not matter much except for some details about the embeddded peripherals.

 

If you can write to the display at least almost all connections are done right.

But sometimes it is assumed that reading is not needed and the Read signal is just directly connected to GND.

Have you tried looking at the datasheet to find out what's needed to read from the chip? It's only 233 pages...

 

Page 15 through 22 are also fun. It lists the pinout of that little monster. 1278 pins with a pitch of 28um, but don't worry, about 30 of them are "dummy's".

Total chip size is 15560um * 650 um (Yep, less than a mm wide)

octave:3> 1/0.028
ans =  35.714           // Pins per mm.
octave:4> ans *25.4
ans =  907.14           // Pins per inch.

And then any hobbyist can buy these on a breakout board and a piece of glass for < USD 10 from Ali.

Electronics is moving into the realm of total madness.

What will we have in 20 years time ???

Attachment(s): 

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

Paul, I studied carefully and in details the datasheet.

 

Writing works fine.

Running the graphicstest I get following readings at the beginning:

Display Power Mode: 0x0
MADCTL Mode: 0x0
Pixel Format: 0xFF
Image Format: 0x0
Self Diagnostic: 0x0

 

Still, the GRAM reading causes a lot of headache, and because I don't have direct access to the controller chip pins, I can only control the signals brought out to the board pins.

And these seem not to be enough, as I have tried many variants to get the GRAM reading work, without success.

I am using SPI to interface the chip, where the WR and RD signals should not have any function, but I may be wrong.

Anyway, I don't have any of these signals available on board pins.

 

Before posting here I also tried to get help from Internet, Arduino forum could also not help, as @pawkon also experienced.

 

So I am here and use my last chance to get this work with the help of David (I had already several contact with David in other forums/threads, especially on www.stm32duino.com).

 

Any idea/suggestion/support is welcome.

Last Edited: Fri. Aug 4, 2017 - 03:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

stevestrong wrote:
I don't have direct access to the controller chip pins, I can only control

Yeah, I know. No messin' around with a 0.028mm pitch or even trying to see the traces without a microscope...

About the best you can do is measure the leakage current into the Read / write pin. It should be about the same as from other pins...

Oops, missed you don't need that pin (But it may need to be at some fixed level).

 

First I have to confess I have some of these displays too, but my experience with them is very limited.

Not much more than running a demo program to confirm they work.

 

After a (mostly random) search:

https://duckduckgo.com/html?q=%2...

 

I bumped into:

https://community.ugfx.io/topic/...

Wich suggests this code for reading through SPI.:

static inline uint16_t read_data(GDisplay *g) {
   (void) g;

   spiStart(SPI_DRIVER, &spi_cfg);
   spiSelect(SPI_DRIVER);
   static uint8_t txbuf[1] = {0};
   txbuf[0] = 0x70 | 0x01 | 0x02;
   spiSend(SPI_DRIVER, 1, txbuf);

   static uint8_t rxbuf[3] = {0};
   spiReceive(SPI_DRIVER, 3, rxbuf);

   spiUnselect(SPI_DRIVER);
   spiStart(SPI_DRIVER, &spi_cfg);
   static uint16_t value = 0;
   value = rxbuf[1] << 8 | rxbuf[2];
   return value;
}

Have you been able to read any data from the display?

Is that "Self diagnostics" reading anything from the display?

If there is any (working) reading (even a single byte) you can clone that piece of code and work from there.

 

Datasheet of ILI also makes a difference between 3-line or 4-line SPI.

Timing diagrams are on page 230 and 231.

Have you verified your timing with a logic analyser?

(And also with a scope (Rise / Fall times <15ns)).

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

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

Just for the record, if anyone else having problem with reading...

 

There are two important things you have to pay attention:

1. CS must be kept low all the time

2. SPI frequency must be <= 24MHz.

 

With these conditions, reading is possible.

I attach here my working code.

uint16_t Adafruit_ILI9341_STM::readPixel(int16_t x, int16_t y)
{
  // CS is set to GND within writecommand
  writecommand(ILI9341_CASET); // Column addr set
  spiwrite16(x);
  spiwrite16(x);
  writecommand(ILI9341_PASET); // Row addr set
  spiwrite16(y);
  spiwrite16(y);
  writecommand(ILI9341_RAMRD); // read GRAM
  (void)spiread();             //dummy read
  uint8_t r = spiread();
  uint8_t g = spiread();
  uint8_t b = spiread();
  cs_set();

  return color565(r, g, b);
}

uint16_t Adafruit_ILI9341_STM::readPixels(int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t *buf)
{
  // CS is set to GND within writecommand
  writecommand(ILI9341_CASET); // Column addr set
  spiwrite16(x1);
  spiwrite16(x2);
  writecommand(ILI9341_PASET); // Row addr set
  spiwrite16(y1);
  spiwrite16(y2);
  writecommand(ILI9341_RAMRD); // read GRAM
  (void)spiread();             //dummy read
  uint8_t r, g, b;
  uint16_t len = (x2-x1+1)*(y2-y1+1);
  uint16_t ret = len;
  while (len--) {
    r = spiread();
    g = spiread();
    b = spiread();
    *buf++ = color565(r, g, b);
  }
  cs_set();

  return ret;
}

https://github.com/stevstrong/Ar...

 

Last Edited: Mon. Aug 7, 2017 - 08:08 AM