Help in bringing up ILI9488 LCD

mkonnov
Posts: 1
Joined: Tue May 02, 2017 3:58 pm

Help in bringing up ILI9488 LCD

Postby mkonnov » Wed Aug 22, 2018 5:19 pm

Hello everyone.
We're going to use uGFX, so all the init commands are token from the uGFX library without of changes (they are called indirectly by calling gfxInit() ).

The help I need is that someone gives me a working code that outputs something to LCD so that I'll understand where I was wrong.
I'm not asking for uGFX codes. Any code that will work with ILI9488 would be applicable.

I'm always to walk step-by-step in resolving problems, so here's the LCD datasheet:
https://www.buydisplay.com/download/man ... asheet.pdf

here's my wiring:
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 my code:

this file lays in uGFX library

Code: Select all

 
 gdisp_lld_ILI9488.c
 /*
 * 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
 */

#include "gfx.h"

#if GFX_USE_GDISP

#if defined(GDISP_SCREEN_HEIGHT) || defined(GDISP_SCREEN_HEIGHT)
	#if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
		#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
	#elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
		COMPILER_WARNING("GDISP: This low level driver does not support setting a screen size. It is being ignored.")
	#endif
	#undef GDISP_SCREEN_WIDTH
	#undef GDISP_SCREEN_HEIGHT
#endif

#define GDISP_DRIVER_VMT			GDISPVMT_ILI9488
#include "gdisp_lld_config.h"
#include "../lib/ugfx/src/gdisp/gdisp_driver.h"

#include "board_ILI9488.h"

/*===========================================================================*/
/* Driver local definitions.                                                 */
/*===========================================================================*/

#ifndef GDISP_SCREEN_HEIGHT
	#define GDISP_SCREEN_HEIGHT		480
#endif
#ifndef GDISP_SCREEN_WIDTH
	#define GDISP_SCREEN_WIDTH		320
#endif
#ifndef GDISP_INITIAL_CONTRAST
	#define GDISP_INITIAL_CONTRAST	50
#endif
#ifndef GDISP_INITIAL_BACKLIGHT
	#define GDISP_INITIAL_BACKLIGHT	100
#endif

/*===========================================================================*/
/* Driver local functions.                                                   */
/*===========================================================================*/
static void dummy_read(GDisplay* g) {
  volatile uint16_t dummy;
  dummy = read_data(g);
  (void)dummy;
}

static void set_viewport(GDisplay* g) {


  write_index(g, 0x2A);
  write_data(g, ((g->p.x >> 8) & 0x00FF));
  write_data(g, ((g->p.x >> 0) & 0x00FF));
  write_data(g, ((g->p.x + g->p.cx - 1) >> 8) & 0x00FF);
  write_data(g, ((g->p.x + g->p.cx - 1) >> 0) & 0x00FF);

  write_index(g, 0x2B);
  write_data(g, ((g->p.y >> 8) & 0x00FF));
  write_data(g, ((g->p.y >> 0) & 0x00FF));
  write_data(g, ((g->p.y + g->p.cy - 1) >> 8) & 0x00FF);
  write_data(g, ((g->p.y + g->p.cy - 1) >> 0) & 0x00FF);

	write_index(g, 0x2C);
}

/*===========================================================================*/
/* Driver interrupt handlers.                                                */
/*===========================================================================*/

/*===========================================================================*/
/* Driver exported functions.                                                */
/*===========================================================================*/

LLDSPEC gBool gdisp_lld_init(GDisplay *g) {
	// No private area for this controller
	g->priv = 0;

	// Initialise the board interface
	init_board(g);

	/* Hardware reset */
	setpin_reset(g, gTrue);
	gfxSleepMilliseconds(2);
  setpin_reset(g, gFalse);
  gfxSleepMilliseconds(10);
  setpin_reset(g, gTrue);
  gfxSleepMilliseconds(120);

	/* Get the bus for the following initialisation commands */
	acquire_bus(g);

	write_index(g, 0xF7);
	write_data(g, 0xA9);
	write_data(g, 0x51);
	write_data(g, 0x2C);
	write_data(g, 0x82);

	write_index(g, 0xC0);
	write_data(g, 0x11);
	write_data(g, 0x09);

	write_index(g, 0xC1);
	write_data(g, 0x41);

	write_index(g, 0xC5);
	write_data(g, 0x00);
	write_data(g, 0x2A);
	write_data(g, 0x80);

	write_index(g, 0xB1);
	write_data(g, 0xB0);
	write_data(g, 0x11);

	write_index(g, 0xB4);
	write_data(g, 0x02);

	write_index(g, 0xB6);
	write_data(g, 0x02);
	write_data(g, 0x22);
	write_data(g, 0x3B);

	write_index(g, 0xB7);
	write_data(g, 0xC6);

	write_index(g, 0xBE);
	write_data(g, 0x00);
	write_data(g, 0x04);

	write_index(g, 0xE9);
	write_data(g, 0x00);

	write_index(g, 0x36);
	write_data(g, 0x08);

	write_index(g, 0x3A);
	write_data(g, 0x55);

	write_index(g, 0xE0);
	write_data(g, 0x00);
	write_data(g, 0x07);
	write_data(g, 0x12);
	write_data(g, 0x0B);
	write_data(g, 0x18);
	write_data(g, 0x0B);
	write_data(g, 0x3F);
	write_data(g, 0x9B);
	write_data(g, 0x4B);
	write_data(g, 0x0B);
	write_data(g, 0x0F);
	write_data(g, 0x0B);
	write_data(g, 0x15);
	write_data(g, 0x17);
	write_data(g, 0x0F);

	write_index(g, 0xE1);
	write_data(g, 0x00);
	write_data(g, 0x16);
	write_data(g, 0x1B);
	write_data(g, 0x02);
	write_data(g, 0x0F);
	write_data(g, 0x06);
	write_data(g, 0x34);
	write_data(g, 0x46);
	write_data(g, 0x48);
	write_data(g, 0x04);
	write_data(g, 0x0D);
	write_data(g, 0x0D);
	write_data(g, 0x35);
	write_data(g, 0x36);
	write_data(g, 0x0F);

	write_index(g, 0x11);
	gfxSleepMilliseconds(120);
	write_index(g, 0x29);

  // Finish Init
  post_init_board(g);

 	// Release the bus
	release_bus(g);

	// Turn on the back-light
	set_backlight(g, GDISP_INITIAL_BACKLIGHT);

	// Initialise the GDISP structure
	g->g.Width = GDISP_SCREEN_WIDTH;
	g->g.Height = GDISP_SCREEN_HEIGHT;
	g->g.Orientation = gOrientation0;
	g->g.Powermode = gPowerOn;
	g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
	g->g.Contrast = GDISP_INITIAL_CONTRAST;

	return gTrue;
}

#if GDISP_HARDWARE_STREAM_WRITE
	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
		acquire_bus(g);
		set_viewport(g);
	}

	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
		write_data(g, gdispColor2Native(g->p.color));
	}

	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
		release_bus(g);
	}
#endif

#if GDISP_HARDWARE_STREAM_READ
	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
		acquire_bus(g);
		set_viewport(g);
		setreadmode(g);
		dummy_read(g);
	}

	LLDSPEC	gColor gdisp_lld_read_color(GDisplay *g) {
		uint16_t	data;

		data = read_data(g);
		return gdispNative2Color(data);
	}

	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
		setwritemode(g);
		release_bus(g);
	}
#endif

#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
	LLDSPEC void gdisp_lld_control(GDisplay *g) {
		switch(g->p.x) {
		case GDISP_CONTROL_POWER:
			if (g->g.Powermode == (gPowermode)g->p.ptr)
				return;

			switch((gPowermode)g->p.ptr) {
			case gPowerOff:
				acquire_bus(g);
				write_index(g, 0x28);
				gfxSleepMilliseconds(10);
				write_index(g, 0x10);
				release_bus(g);
				break;

			case gPowerOn:
				acquire_bus(g);
				write_index(g, 0x11);
				gfxSleepMilliseconds(120);
				write_index(g, 0x29);
				release_bus(g);
				if (g->g.Powermode != gPowerSleep)
					gdisp_lld_init(g);
				break;

			case gPowerSleep:
				acquire_bus(g);
        write_index(g, 0x28);
        gfxSleepMilliseconds(10);
        write_index(g, 0x10);
				release_bus(g);
				break;

			default:
				return;
			}

			g->g.Powermode = (gPowermode)g->p.ptr;
			return;

		case GDISP_CONTROL_ORIENTATION:
			if (g->g.Orientation == (gOrientation)g->p.ptr)
				return;

			switch((gOrientation)g->p.ptr) {
			case gOrientation0:
				acquire_bus(g);

			  write_index(g, 0x36);
			  write_data(g, 0x08);

				release_bus(g);
				g->g.Height = GDISP_SCREEN_HEIGHT;
				g->g.Width = GDISP_SCREEN_WIDTH;
				break;

			case gOrientation90:
				acquire_bus(g);

        write_index(g, 0x36);
        write_data(g, 0x68);

				release_bus(g);
				g->g.Height = GDISP_SCREEN_WIDTH;
				g->g.Width = GDISP_SCREEN_HEIGHT;
				break;

			case gOrientation180:
				acquire_bus(g);

			  write_index(g, 0x36);
			  write_data(g, 0xC8);

				release_bus(g);
				g->g.Height = GDISP_SCREEN_HEIGHT;
				g->g.Width = GDISP_SCREEN_WIDTH;
				break;

			case gOrientation270:
				acquire_bus(g);

        write_index(g, 0x36);
        write_data(g, 0xA8);

				release_bus(g);
				g->g.Height = GDISP_SCREEN_WIDTH;
				g->g.Width = GDISP_SCREEN_HEIGHT;
				break;

			default:
				return;
			}

			g->g.Orientation = (gOrientation)g->p.ptr;
			return;

      default:
        return;
		}
	}
#endif

#endif /* GFX_USE_GDISP */
 
this file should be provided in the caller project

Code: Select all

/*
 * 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 */
I think that the SPI data flow is clear.

However I've tried to draw smth on screen using uGFX calls, there's no result.

Again, I need some codes that will output SPI commands to LCD so that I'll have some point to start the integration.
Thanks.

Who is online

Users browsing this forum: Majestic-12 [Bot] and 149 guests