Jump to content

Problem bringing up ESP32 ILI9488


0xF77E

Recommended Posts

Hey guys !

I'm stucking while bringing up my ILI9488-based LCD:
https://www.buydisplay.com/download/manual/ER-TFTM035-6_Datasheet.pdf

Here's my codes

 

/* board_ILI9488.h */
/*
 * This file is subject to the terms of the GFX License. If a copy of
 * the license was not distributed with this file, you can obtain one at:
 *
 *              http://ugfx.org/license.html
 */

#ifndef _GDISP_LLD_BOARD_H
#define _GDISP_LLD_BOARD_H

/*
*
* This code has been compiled mostly from the spi_master_example that is included
* in the espressif idf under examples/peripherals/spi_master.
*
* None of the code has been compiled/tested in this file so expect bugs!
*
*/

//#include <stdlib.h>
//#include <string.h>
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#include <string.h>

#define LCD_MOSI  23
#define LCD_MISO  25
#define LCD_SCK   19
#define LCD_CS    22
#define LCD_DC    21
#define LCD_RST   18
#define LCD_BCKL  5



//To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. More means more memory use,
//but less overhead for setting up / finishing transfers. Make sure 240 is dividable by this.
#define PARALLEL_LINES 16

static spi_device_handle_t spi;

//This function is called (in irq context!) just before a transmission starts. It will
//set the D/C line to the value indicated in the user field.
void lcd_spi_pre_transfer_callback(spi_transaction_t *t)
{
    int dc=(int)t->user;
    gpio_set_level(LCD_DC, dc);
}

static GFXINLINE void init_board(GDisplay *g) {
	(void) g;

	spi_bus_config_t buscfg={
			.miso_io_num=LCD_MISO,
			.mosi_io_num=LCD_MOSI,
			.sclk_io_num=LCD_SCK,
			.quadwp_io_num=-1,
			.quadhd_io_num=-1,
			.max_transfer_sz=PARALLEL_LINES*320*2+8
	};

	spi_device_interface_config_t devcfg={
//			.clock_speed_hz=26*1000*1000,           //Clock out at 26 MHz
			.clock_speed_hz=10*1000*1000,
			.mode=0,                                //SPI mode 0
			.spics_io_num=LCD_CS,                   //CS pin
			.queue_size=7,                          //We want to be able to queue 7 transactions at a time
			.pre_cb=lcd_spi_pre_transfer_callback,  //Specify pre-transfer callback to handle D/C line
	};

	//Initialize the SPI bus
	spi_bus_initialize(HSPI_HOST, &buscfg, 1);


	//Attach the LCD to the SPI bus
	spi_bus_add_device(HSPI_HOST, &devcfg, &spi);


	//Initialize non-SPI GPIOs
	gpio_set_direction(LCD_DC, GPIO_MODE_OUTPUT);
	gpio_set_direction(LCD_RST, GPIO_MODE_OUTPUT);
	gpio_set_direction(LCD_BCKL, GPIO_MODE_OUTPUT);

}

static GFXINLINE void post_init_board(GDisplay *g) {
	(void) g;
}

static GFXINLINE void setpin_reset(GDisplay *g, gBool state) {
	(void) g;

	if (state) {
		gpio_set_level(LCD_RST, 0);
	} else {
		gpio_set_level(LCD_RST, 1);
	}
}

static GFXINLINE void set_backlight(GDisplay *g, uint8_t percent) {
	(void) g;

	if (percent > 0) {
		  gpio_set_level(LCD_BCKL, 1);
		} else {
		  gpio_set_level(LCD_BCKL, 0);
	}
}

static GFXINLINE void acquire_bus(GDisplay *g) {
	(void) g;

	gpio_set_level(LCD_CS, 0);
}

static GFXINLINE void release_bus(GDisplay *g) {
	(void) g;

	gpio_set_level(LCD_CS, 1);
}

static GFXINLINE void write_index(GDisplay *g, uint16_t index) {
	(void) g;
	esp_err_t ret;
	spi_transaction_t t;
	memset(&t, 0, sizeof(t));       //Zero out the transaction
	t.length=16;                     //Command is 8 bits
	t.length=8;                     //Command is 8 bits
	t.tx_buffer=&index;               //The data is the cmd itself
	t.user=(void*)0;                //D/C needs to be set to 0
	ret=spi_device_transmit(spi, &t);  //Transmit!
	assert(ret==ESP_OK);            //Should have had no issues.
}

static GFXINLINE void write_data(GDisplay *g, uint16_t data) {
	(void) g;
	esp_err_t ret;
	spi_transaction_t t;
	memset(&t, 0, sizeof(t));       //Zero out the transaction
	t.length=16;                     //Command is 8 bits
	t.length=8;                     //Command is 8 bits
	t.tx_buffer=&data;               //The data is the cmd itself
	t.user=(void*)1;                //D/C needs to be set to 0
	ret=spi_device_transmit(spi, &t);  //Transmit!
	assert(ret==ESP_OK);            //Should have had no issues.
}

static GFXINLINE void setreadmode(GDisplay *g) {
	(void) g;
}

static GFXINLINE void setwritemode(GDisplay *g) {
	(void) g;
}

static GFXINLINE uint16_t read_data(GDisplay *g) {
	(void) g;
	return 0;
}

#endif /* _GDISP_LLD_BOARD_H */

This funcs is being called from gdisp_lld_ILI9488.c. I haven't changed it.
 

Wiring and SPI communication seems fine, however here's my pinout:
Pin name ESP32 pin LCD pin
MOSI 23 27
MISO 25 28
SCK 19 24
CS 22 23
DC 21 25
RST 18 21
BCKL 5 29
+5V +5V 2
GND GND 1
 

And here's the caller code:

/* Hello World Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_spi_flash.h"

#include "gfx.h"

#include "board_ILI9488_template.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#include <string.h>

portMUX_TYPE _hack_mux = portMUX_INITIALIZER_UNLOCKED;


static void taskInit(void* pvParameters)
{
	(void)pvParameters;
	gfxInit();
    gdispDrawLine(50, 50, 100,100,Red);
    vTaskDelete(NULL);
}

void app_main() {
  
	xTaskCreate(taskInit, "taskInit", 4096, NULL, 5, NULL);

}

All I see is a white screen (ok, backlight works :) ).

Thanks !

Edited by 0xF77E
Link to comment
Share on other sites

I'm standing between doors right now so I haven't checked your actual code yet, but let's work our way through the basics:

  • Did you use the debugger to check whether the system is halting somewhere?
  • Are you getting the µGFX logo to show up but you simply don't get your own stuff to show on the display (make sure that the startup logo option in the configuration file is enabled)?
  • Did  you check that the integration is actually working? You might want to run one of the GOS demos to confirm that stuff like software timers and threading is working correctly
Link to comment
Share on other sites

Hi Joel.

I'm using serial output. The system is running.

No uGFX logo. If I would saw that, that would be a big step further. Anyway, I saw that logo on a virtual LCD and then all that interface I have implemented, so the code is working.

Yes, integration is working as I have put the debugging messages into LCD SPI write calls and all of them are invoking properly.

 

Link to comment
Share on other sites

Okay, so at this point we're pretty sure that there's something "wrong" in the board file. Unfortunately, that's always the trickiest for us to help with as it's completely out of our scope.

The following things are helpful to track down the problem:

  • Tripple check your line logic: It's very common to accidentally invert the reset logic and similar,
  • Lower your SPI clock to something <= 1MHz to rule out electrical issues due to too high clock speeds.
  • Remove any DMA & general interrupt stuff and implement everything polling.
  • Use a logic analyzer to confirm that the data on the bus matches the values passed to the board file functions.
  • Most display controller provide some sort of chip ID-readout. You can query that in the drivers initialization function to figure out whether transmission is working correctly.
  • The ILIxxxx display controllers tend to be extremely difficult to work with when ordered from chinese sources. The main issue is that you often don't get the chip that you though you get. Eg. sometimes you get an ILI9325 instead of an ILI9320. To make matters worse, some of the ILI display controllers have (completely) different initialization sequences for different chip revisions. Usually you get some demo code with the display module that you're buying. Verify that the initialization sequence in the drivers initialization function matches with that provided by the manufacturer. If in doubt, always use the one you received with your display module.
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...