lexus2k / ssd1306

Driver for SSD1306, SSD1331, SSD1351, IL9163, ILI9341, ST7735, PCD8544, Nokia 5110 displays running on Arduino/ESP32/Linux (Rasperry) platforms
MIT License
655 stars 125 forks source link

Configuration of ili9341 on TTGO T4 #101

Closed robinvanemden closed 4 years ago

robinvanemden commented 4 years ago

I am currently working on supporting both ssd1306 and ili9341 in an ESP32-IDF project. Using the lexus2k driver, ssd1306 devices work straight out of the box with:

ssd1306_128x64_i2c_init()

Next step: running the same application on a TTGO T4 v1.3. The T4 makes use of the ili9341 with the following pin-out:

#define TFT_MISO    12
#define TFT_MOSI    23
#define TFT_SCLK    18
#define TFT_CS      27  // Chip select control pin
#define TFT_DC      32  // Data Command control pin
#define TFT_RST     5  // Reset pin (could connect to RST pin)
#define TFT_BL      4  // Display back-light control pin

So I replaced the ssd1306 initialization line with:

ili9341_240x320_spi_init(5, 27, 32);

Yet including this line results in:

(InstrFetchProhibited). Exception was unhandled.

That remains the case when I remove most of the other code - which leaves this line as the clear culprit.

To cover all bases, I also adapted the MISO/MOSI/SCLK settings in the esp platform.c code:

// init your interface here
spi_bus_config_t buscfg=
{
    .miso_io_num= 12, //s_spi_bus_id ? 19 : 12,
    .mosi_io_num= 23, //s_spi_bus_id ? 23 : 13,
    .sclk_io_num= 18, //s_spi_bus_id ? 18 : 14,
    .quadwp_io_num=-1,
    .quadhd_io_num=-1,
    .max_transfer_sz=32
};

But this did not resolve the unhandled exception error.

Is there something obvious I am missing, or do I need to dig a little deeper to get to the bottom of this?

lexus2k commented 4 years ago

Hi,

So, as I understand, the issue happens during ili9341_240x320_spi_init(5, 27, 32);. Is my understanding correct? Could you please, provide code sample, that crashes?

robinvanemden commented 4 years ago

Hi!

So, as I understand, the issue happens during ili9341_240x320_spi_init(5, 27, 32);. Is my understanding correct?

Yes, that is correct.

Could you please, provide code sample, that crashes?

Of course! I created a repository with a minimal ESP-IDF 4.0 project for you:

https://github.com/robinvanemden/esp32-ili9341

It also contains a file with information on the TTGO T4:

https://github.com/robinvanemden/esp32-ili9341/blob/master/ESP32_TTGO_T4_V13.info

And, of course, the app_main file:

https://github.com/robinvanemden/esp32-ili9341/blob/master/main/app_main.cpp

lexus2k commented 4 years ago

@robinvanemden Is it private repo? I cannot access it:

image

robinvanemden commented 4 years ago

You are right! I forgot to set the repository to 'public'. You should have access now..

lexus2k commented 4 years ago

I compiled test example from the library via ./build_and_run.sh script using SPI settings, you pointed above, and it works. But when I tried your repo, it crashes. So, trying to understand what's wrong. I will come back to you with ideas.

lexus2k commented 4 years ago

The problem in your example is inside the changes:

  1. First of all, you removed original component.mk from the library and moved it to separate directory.
  2. Next, your version of ssd1306 library has not only source files modified, but also some files removed.

If to delete components/ssd1306 in your example, and to execute esp/esp32-ili9341/components$ git clone https://github.com/lexus2k/ssd1306 inside components of your sketch, then nothing crashes (even if to change pin numbers to the ones, specified by you).

robinvanemden commented 4 years ago

Thank you for investigating this issue! Much appreciated!

The removal of the component.mk did not prove to be the problem, as ESP-IDF 4.x moved away from component.mk to a CMakeLists.txt based approach to parsing components.

But it did point me in the right direction - when I converted the original component.mk by hand, I did not include *.cpp based source files. This is now resolved in my new CMakeLists.txt.

Now the test script works perfectly half the time.. The other half of the time, on resetting the ESP32, the text becomes garbled:

garbled

Any suggestions how I might resolve this last issue?

robinvanemden commented 4 years ago

Additionally, invoking ili9341_setRotation(2) and then running ssd1306_print() makes the screen initialize with a white top border (here partly overwritten by consecutive print statements):

IMG_20200122_181754

lexus2k commented 4 years ago

Hi

About resetting, maybe current delays are not enough to reset display controller completed on boot. As for ili9341_setRotation, do you observe white block issues on all rotation positions? I will double check addressing routines for this display

robinvanemden commented 4 years ago

Hi> About resetting, maybe current delays are not enough to reset display controller completed on boot. As for ili9341_setRotation, do you observe white block issues on all rotation positions? I will double check addressing routines for this display

Your suggestion that current delays might not be enough proved correct. Lengthening the existing delays did not make a difference, but adding an additional delay right after setting the reset pin high took care of the garbling.

I created a pull request that contains the added delay for the ili9341 here:

https://github.com/lexus2k/ssd1306/pull/102

The issue with the white top border first also seemed resolved, but that proved to be only the case in ili9341_setRotation(2).

When setting ili9341_setRotation(1) or ili9341_setRotation(3), I see the following:

IMG_20200125_110342

Of interest: this only happens in compat mode - with ssd1306_setMode(LCD_MODE_NORMAL) and using ssd1306_clearScreen8 etc the screen initializes just fine. So maybe I just need to use that?

lexus2k commented 4 years ago

Ok, I see the issue, So, what if you use ili9341_setRotation(1) and then ssd1306_clearScreen()? I'm trying to find the root cause. I will get back to you with solution.

lexus2k commented 4 years ago

I think that something is wrong with MADCTL register controlling RAM memory access inside of display controller. Can you check all modes and let me know, which modes do not work for you? From datasheet perspective, the code looks ok. To my opinion, this is the place.

    switch (s_rotation)
    {
    case 0:
        ram_mode = 0b10100000;
        break;
    case 1: // 90 degree CW
        ram_mode = 0b11010000;
        break;
    case 2: // 180 degree CW
        ram_mode = 0b01100000;
        break;
    case 3: // 270 degree CW
        ram_mode = 0b00000000;
        break;
    case 4:
        ram_mode = s_rotate_output ? 0b11100100: 0b10000100;
        break;
    case 5: // 90 degree CW
        ram_mode = 0b11100000;
        break;
    case 6: // 180 degree CW
        ram_mode = 0b01010100;
        break;
    default: // 270 degree CW
        ram_mode = 0b00100000;
        break;
    }
robinvanemden commented 4 years ago

Thanks again for investigating this!

So, what if you use ili9341_setRotation(1) and then ssd1306_clearScreen()?

That does not seeem to make a difference.

I think that something is wrong with MADCTL register controlling RAM memory access inside of display controller. Can you check all modes and let me know, which modes do not work for you?

Of course!

From datasheet perspective, the code looks ok. To my opinion, this is the place.

switch (s_rotation)
{
case 0:
    ram_mode = 0b10100000;
    break;

All is well.

case 1: // 90 degree CW
    ram_mode = 0b11010000;
    break;

Partly white background.

case 2: // 180 degree CW
    ram_mode = 0b01100000;
    break;

All is well.

case 3: // 270 degree CW
    ram_mode = 0b00000000;
    break;

Partly white background.

case 4:
    ram_mode = s_rotate_output ? 0b11100100: 0b10000100;
    break;

All is well.

case 5: // 90 degree CW
    ram_mode = 0b11100000;
    break;

Partly white background.

case 6: // 180 degree CW
    ram_mode = 0b01010100;
    break;

All is well

default: // 270 degree CW
    ram_mode = 0b00100000;
    break;
}

Partly white background.

So, all in all: portrait mode seems ok, landscape mode seems to fail.

lexus2k commented 4 years ago

Hello,

It looks like there is a bug in ssd1306_fillScreen() and ssd1306_clearScreen(). Uint8 types needs to be replaced with uint16. Can you check if my suggestion is correct?

PS. I'm failed for some reason to power up my ILI9341, something happened to my display.

robinvanemden commented 4 years ago

It looks like there is a bug in ssd1306_fillScreen() and ssd1306_clearScreen(). Uint8 types needs to be replaced with uint16. Can you check if my suggestion is correct?

Yes, you are absolutely right. The commit fully resolves the issue with the white background. Thanks!

lexus2k commented 4 years ago

ok, thank you. I integrated all code changes and released new version. Feel free to reopen issue, if you have more questions