Jump to content

Unable to get ILI9320 display driver working on STM32F


uweng14

Recommended Posts

Hi Tectu,

I've posted on the old chibios forum, here is the link to that post.

http://forum.chibios.org/phpbb/viewtopi ... =11&t=1308

So I've tested all the suggestions you recommanded last time. But unfortunately I still can't get it to work.

I am using the ARMCM4-STM32F407-DISCOVERY board.

One question about PAL_STM32_OSPEED_HIGHEST,if I were to not use this macro. Do I replace it with something else or just leave it blank?

here is my current gdisp_lld_board.h

I've added an extra spi command that sends the 0x70 starting bit to start the spi communication before read and writes. The distributor example code had this line which I could not find it anywhere else in the driver code.



#ifndef GDISP_LLD_BOARD_H
#define GDISP_LLD_BOARD_H

#define SET_RST palSetPad(GPIOB, 8);
#define CLR_RST palClearPad(GPIOB, 8);

// Peripherial Clock 42MHz SPI2 SPI3
// Peripherial Clock 84MHz SPI1 SPI1 SPI2/3
//#define SPI_BaudRatePrescaler_2 ((uint16_t)0x0000) // 42 MHz 21 MHZ
//#define SPI_BaudRatePrescaler_4 ((uint16_t)0x0008) // 21 MHz 10.5 MHz
//#define SPI_BaudRatePrescaler_8 ((uint16_t)0x0010) // 10.5 MHz 5.25 MHz
//#define SPI_BaudRatePrescaler_16 ((uint16_t)0x0018) // 5.25 MHz 2.626 MHz
//#define SPI_BaudRatePrescaler_32 ((uint16_t)0x0020) // 2.626 MHz 1.3125 MHz
//#define SPI_BaudRatePrescaler_64 ((uint16_t)0x0028) // 1.3125 MHz 656.25 KHz
//#define SPI_BaudRatePrescaler_128 ((uint16_t)0x0030) // 656.25 KHz 328.125 KHz
//#define SPI_BaudRatePrescaler_256 ((uint16_t)0x0038) // 328.125 KHz 164.06 KHz

/*
*
* 10.5MHz, CPHA=1, CPOL=0, MSb first, 16 - bits
*
*/
static const SPIConfig spi2cfg1 = {
NULL,
/* HW dependent part.*/
GPIOB,
12,
SPI_CR1_DFF | SPI_CR1_CPHA | SPI_CR1_BR_0
};



static inline void gdisp_lld_init_board(void) {

palSetPadMode(GPIOB, 13, PAL_MODE_ALTERNATE(5) ); /* New SCK. */
palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(5) ); /* New MISO. */
palSetPadMode(GPIOB, 15, PAL_MODE_ALTERNATE(5) ); /* New MOSI. */
palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL); /* New CS. */
//palSetPad(GPIOB, 12);
palSetPad(GPIOB, 8);

spiStart(&SPID2, &spi2cfg1);


}

static inline void gdisp_lld_reset_pin(bool_t state) {
if (state) {
palSetPad(GPIOB, 8);

} else {

palClearPad(GPIOB, 8);
}
}

static inline void acquire_bus(void) {

spiAcquireBus(&SPID2);

}

static inline void release_bus(void) {

spiReleaseBus(&SPID2);
}

static inline void gdisp_lld_write_index(uint16_t data) {
//palClearPad(GPIOB, 12);
spiSelect(&SPID2);

static uint8_t txbuf[1] = {0};
txbuf[0] = 0x70 | 0x00 | 0x00;
while((SPI2->SR & SPI_SR_TXE) == 0);
spiSend(&SPID2, 1, txbuf);
while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));

txbuf[0] = data & 0xFF;
while((SPI2->SR & SPI_SR_TXE) == 0);
spiSend(&SPID2, 1, txbuf);
while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));
//txbuf[0] = data >> 8;
//txbuf[1] = data & 0xFF;

//palSetPad(GPIOB, 12);
spiUnselect(&SPID2);

}



static inline void gdisp_lld_write_data(uint16_t data) {

//palClearPad(GPIOB, 12);
spiSelect(&SPID2);
static uint8_t txbuf[2] = {0};
//txbuf[0] = data;
txbuf[0] = 0x70 | 0x00 | 0x02;
txbuf[1] = 0x70 | 0x00 | 0x02;

while((SPI2->SR & SPI_SR_TXE) == 0);
spiSend(&SPID2, 1, txbuf);
while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));

txbuf[0] = (data >> 8);
txbuf[1] = (data & 0xFF);

while((SPI2->SR & SPI_SR_TXE) == 0);
spiSend(&SPID2, 2, txbuf);
while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));
//palSetPad(GPIOB, 12);
spiUnselect(&SPID2);

}

static inline uint16_t gdisp_lld_read_data(void) {

//palClearPad(GPIOB, 12);
spiSelect(&SPID2);

static uint8_t txbuf[1] = {0};
txbuf[0] = 0x70 | 0x01 | 0x02;
while((SPI2->SR & SPI_SR_TXE) == 0);
spiSend(&SPID2, 1, txbuf);
while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));

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

while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));
//palSetPad(GPIOB, 12);
spiUnselect(&SPID2);

static uint16_t value = 0;
value = rxbuf[1] << 8 | rxbuf[2];
//test_println((char*)value);
return value;
}

/* if not available, just ignore the argument and return */
static inline uint16_t gdisp_lld_backlight(uint8_t percentage) {
//pwmEnableChannel(&PWMD4, 1, percentage);
}

#endif /* GDISP_LLD_BOARD_H */
/** @} */


gfxconf.h


/**
* This file has a different license to the rest of the GFX system.
* You can copy, modify and distribute this file as you see fit.
* You do not need to publish your source modifications to this file.
* The only thing you are not permitted to do is to relicense it
* under a different license.
*/

/**
* Copy this file into your project directory and rename it as gfxconf.h
* Edit your copy to turn on the GFX features you want to use.
*/

#ifndef _GFXCONF_H
#define _GFXCONF_H

#define GFX_USE_OS_CHIBIOS TRUE

/* GFX subsystems to turn on */
#define GFX_USE_GDISP TRUE
#define GFX_USE_TDISP FALSE
#define GFX_USE_GWIN FALSE
#define GFX_USE_GEVENT FALSE
#define GFX_USE_GTIMER FALSE
#define GFX_USE_GINPUT FALSE
#define GFX_USE_GADC FALSE
#define GFX_USE_GAUDIN FALSE
#define GFX_USE_GAUDOUT FALSE
#define GFX_USE_GMISC FALSE

/* Features for the GDISP subsystem */
#define GDISP_NEED_VALIDATION TRUE
#define GDISP_NEED_CLIP TRUE
#define GDISP_NEED_TEXT TRUE
#define GDISP_NEED_CIRCLE TRUE
#define GDISP_NEED_ELLIPSE TRUE
#define GDISP_NEED_ARC FALSE
#define GDISP_NEED_CONVEX_POLYGON FALSE
#define GDISP_NEED_SCROLL FALSE
#define GDISP_NEED_PIXELREAD FALSE
#define GDISP_NEED_CONTROL FALSE
#define GDISP_NEED_QUERY FALSE
#define GDISP_NEED_IMAGE FALSE
#define GDISP_NEED_MULTITHREAD FALSE
#define GDISP_NEED_ASYNC FALSE
#define GDISP_NEED_MSGAPI FALSE

/* GDISP - builtin fonts */
#define GDISP_INCLUDE_FONT_SMALL FALSE
#define GDISP_INCLUDE_FONT_LARGER FALSE
#define GDISP_INCLUDE_FONT_UI1 FALSE
#define GDISP_INCLUDE_FONT_UI2 TRUE
#define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE

/* GDISP image decoders */
#define GDISP_NEED_IMAGE_NATIVE FALSE
#define GDISP_NEED_IMAGE_GIF FALSE
#define GDISP_NEED_IMAGE_BMP FALSE
#define GDISP_NEED_IMAGE_JPG FALSE
#define GDISP_NEED_IMAGE_PNG FALSE
#define GDISP_NEED_IMAGE_ACCOUNTING FALSE

/* Optional image support that can be turned off */
/*
#define GDISP_NEED_IMAGE_BMP_1 TRUE
#define GDISP_NEED_IMAGE_BMP_4 TRUE
#define GDISP_NEED_IMAGE_BMP_4_RLE TRUE
#define GDISP_NEED_IMAGE_BMP_8 TRUE
#define GDISP_NEED_IMAGE_BMP_8_RLE TRUE
#define GDISP_NEED_IMAGE_BMP_16 TRUE
#define GDISP_NEED_IMAGE_BMP_24 TRUE
#define GDISP_NEED_IMAGE_BMP_32 TRUE
*/

/* Features for the TDISP subsystem. */
#define TDISP_NEED_MULTITHREAD FALSE

/* Features for the GWIN subsystem. */
#define GWIN_NEED_BUTTON FALSE
#define GWIN_NEED_CONSOLE FALSE
#define GWIN_NEED_GRAPH FALSE
#define GWIN_NEED_SLIDER FALSE

/* Features for the GEVENT subsystem. */
#define GEVENT_ASSERT_NO_RESOURCE FALSE

/* Features for the GTIMER subsystem. */
/* NONE */

/* Features for the GINPUT subsystem. */
#define GINPUT_NEED_MOUSE FALSE
#define GINPUT_NEED_KEYBOARD FALSE
#define GINPUT_NEED_TOGGLE FALSE
#define GINPUT_NEED_DIAL FALSE

/* Features for the GADC subsystem. */
/* NONE */

/* Features for the GAUDIN subsystem. */
/* NONE */

/* Features for the GAUDOUT subsystem. */
/* NONE */

/* Features for the GMISC subsystem. */
#define GMISC_NEED_ARRAYOPS FALSE

/* Optional Parameters for various subsystems */
/*
#define GDISP_MAX_FONT_HEIGHT 16
#define GEVENT_MAXIMUM_SIZE 32
#define GEVENT_MAX_SOURCE_LISTENERS 32
#define GTIMER_THREAD_WORKAREA_SIZE 512
#define GADC_MAX_LOWSPEED_DEVICES 4
#define GWIN_BUTTON_LAZY_RELEASE FALSE
*/

/* Optional Low Level Driver Definitions */

#define GDISP_USE__BOARD TRUE
#define GDISP_SCREEN_WIDTH 320
#define GDISP_SCREEN_HEIGHT 240
#define GDISP_USE_FSMC
#define GDISP_USE_GPIO
#define TDISP_COLUMNS 16
#define TDISP_ROWS 2
#define GDISP_THREAD_CHIBIOS TRUE


#endif /* _GFXCONF_H */

Thanks a lot,

David

Link to comment
Share on other sites

Hello David,

Just leave it blank so your line would look like this:

palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL

Why exactly are you modifying the SPI config registers in your SPI struct? I cannot remember the default values provided by ChibiOS/RT but experience says that it will work for 99% sure if you leave it as it is. Just set a higher prescaler to be sure that your LCD controller can handle it. I know that distributors often write «SPI Freq = 10MHz» in their example codes but those are very often just copied and copied and copied and copied so the comments are not up to date.


static const SPIConfig spi2cfg1 = {
NULL,
/* HW dependent part.*/
GPIOB,
12,
SPI_CR1_BR_2 | SPI_CR1_BR_1
};

Furthermore I can see that you seem to directly access your registers in the board file. Why do you do this? I advice you to do everything through the SPI driver provided by the ChibiOS/RT HAL because the spiSend() command already handles the busy flag and so on.

One more thing: How long are your wires?

~ Tectu

Link to comment
Share on other sites

  • 4 months later...
What was you final configuration and your wiring? I am facing the same problems and your experience could serve useful for fixing my own problem

Hello erwinkendo and welcome to the community!

What problems are you facing? Could you give some more information about your setup i.e. if you're using the STM32F407-Discovery board too and what interface you're using? The ILI9320 driver itself seems to work properly (just tried myself).

~ Tectu

Link to comment
Share on other sites

Hello Tectu, thank you for your welcome

I am facing the same problems David had, I can't display anything in the LCD. I have used the same code David had and followed the same advices but nothing works.

I am using ChibiOS/RT and stm32f4 Discovery Board

board_ILI9320.h


#ifndef GDISP_LLD_BOARD_H
#define GDISP_LLD_BOARD_H

#define SET_RST palSetPad(GPIOB, 10);
#define CLR_RST palClearPad(GPIOB, 10);

/*
*
* 10.5MHz, CPHA=1, CPOL=0, MSb first, 16 - bits
*
*/
static const SPIConfig SPI2cfg1 = {
NULL,
/* HW dependent part.*/
GPIOB,
12,
SPI_CR1_DFF | SPI_CR1_CPHA | SPI_CR1_BR_0
};

/**
* @brief Initialise the board for the display.
*
* @param[in] g The GDisplay structure
*
* @note Set the g->board member to whatever is appropriate. For multiple
* displays this might be a pointer to the appropriate register set.
*
* @notapi
*/
static inline void init_board(GDisplay *g) {
(void) g;
palSetPadMode(GPIOB, 13, PAL_MODE_ALTERNATE(5) ); /* New SCK. */
palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(5) ); /* New MISO. */
palSetPadMode(GPIOB, 15, PAL_MODE_ALTERNATE(5) ); /* New MOSI. */
palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL); /* New CS. */
//palSetPad(GPIOA, 4);

// Reset
palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL); /* New Reset. */
palSetPad(GPIOB, 10);

spiStart(&SPID2, &SPI2cfg1);

}

/**
* @brief After the initialisation.
*
* @param[in] g The GDisplay structure
*
* @notapi
*/
static inline void post_init_board(GDisplay *g) {
(void) g;
}

/**
* @brief Set or clear the lcd reset pin.
*
* @param[in] g The GDisplay structure
* @param[in] state TRUE = lcd in reset, FALSE = normal operation
*
* @notapi
*/
static inline void setpin_reset(GDisplay *g, bool_t state) {
(void) g;
if (state) {
palSetPad(GPIOB, 10);
} else {
palClearPad(GPIOB, 10);
}
}

/**
* @brief Set the lcd back-light level.
*
* @param[in] g The GDisplay structure
* @param[in] percent 0 to 100%
*
* @notapi
*/
static inline void set_backlight(GDisplay *g, uint8_t percent) {
(void) g;
(void) percent;
}

/**
* @brief Take exclusive control of the bus
*
* @param[in] g The GDisplay structure
*
* @notapi
*/
static inline void acquire_bus(GDisplay *g) {
(void) g;
spiAcquireBus(&SPID2);
}

/**
* @brief Release exclusive control of the bus
*
* @param[in] g The GDisplay structure
*
* @notapi
*/
static inline void release_bus(GDisplay *g) {
(void) g;
spiReleaseBus(&SPID2);
}

/**
* @brief Send data to the index register.
*
* @param[in] g The GDisplay structure
* @param[in] index The index register to set
*
* @notapi
*/
static inline void write_index(GDisplay *g, uint16_t index) {
(void) g;
spiSelect(&SPID2);

static uint8_t txbuf[1] = {0};
txbuf[0] = 0x70 | 0x00 | 0x00;
//while((SPI2->SR & SPI_SR_TXE) == 0);
spiSend(&SPID2, 1, txbuf);
//while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));

txbuf[0] = index & 0xFF;
//while((SPI2->SR & SPI_SR_TXE) == 0);
spiSend(&SPID2, 1, txbuf);
//while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));

spiUnselect(&SPID2);

}

/**
* @brief Send data to the lcd.
*
* @param[in] g The GDisplay structure
* @param[in] data The data to send
*
* @notapi
*/
static inline void write_data(GDisplay *g, uint16_t data) {
(void) g;
spiSelect(&SPID2);
static uint8_t txbuf[2] = {0};
txbuf[0] = 0x70 | 0x00 | 0x02;
txbuf[1] = 0x70 | 0x00 | 0x02;

//while((SPI2->SR & SPI_SR_TXE) == 0);
spiSend(&SPID2, 1, txbuf);
//while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));

txbuf[0] = (data >> 8);
txbuf[1] = (data & 0xFF);

//while((SPI2->SR & SPI_SR_TXE) == 0);
spiSend(&SPID2, 2, txbuf);
//while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));

spiUnselect(&SPID2);

}

/**
* @brief Set the bus in read mode
*
* @param[in] g The GDisplay structure
*
* @notapi
*/
static inline void setreadmode(GDisplay *g) {
(void) g;
}

/**
* @brief Set the bus back into write mode
*
* @param[in] g The GDisplay structure
*
* @notapi
*/
static inline void setwritemode(GDisplay *g) {
(void) g;
}

/**
* @brief Read data from the lcd.
* @return The data from the lcd
*
* @param[in] g The GDisplay structure
*
* @note The chip select may need to be asserted/de-asserted
* around the actual spi read
*
* @notapi
*/
static inline uint16_t read_data(GDisplay *g) {
(void) g;

spiSelect(&SPID2);

static uint8_t txbuf[1] = {0};
txbuf[0] = 0x70 | 0x01 | 0x02;
//while((SPI2->SR & SPI_SR_TXE) == 0);
spiSend(&SPID2, 1, txbuf);
//while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));

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

while(((SPI2->SR & SPI_SR_TXE) == 0) || ((SPI2->SR & SPI_SR_BSY) != 0));

spiUnselect(&SPID2);

static uint16_t value = 0;
value = rxbuf[1] << 8 | rxbuf[2];
return value;
}

#endif /* GDISP_LLD_BOARD_H */

gfxconf.h


#ifndef _GFXCONF_H
#define _GFXCONF_H

/* The operating system to use. One of these must be defined - preferably in your Makefile */
#define GFX_USE_OS_CHIBIOS TRUE
//#define GFX_USE_OS_WIN32 FALSE
//#define GFX_USE_OS_LINUX FALSE
//#define GFX_USE_OS_OSX FALSE

/* GFX subsystems to turn on */
#define GFX_USE_GDISP TRUE
#define GFX_USE_TDISP FALSE
#define GFX_USE_GWIN FALSE
#define GFX_USE_GEVENT FALSE
#define GFX_USE_GTIMER FALSE
#define GFX_USE_GQUEUE FALSE
#define GFX_USE_GINPUT FALSE
#define GFX_USE_GADC FALSE
#define GFX_USE_GAUDIN FALSE
#define GFX_USE_GAUDOUT FALSE
#define GFX_USE_GMISC FALSE

/* Features for the GDISP subsystem */
#define GDISP_NEED_AUTOFLUSH FALSE
#define GDISP_NEED_TIMERFLUSH FALSE
#define GDISP_NEED_VALIDATION TRUE
#define GDISP_NEED_CLIP TRUE
#define GDISP_NEED_TEXT TRUE
#define GDISP_NEED_CIRCLE TRUE
#define GDISP_NEED_ELLIPSE TRUE
#define GDISP_NEED_ARC FALSE
#define GDISP_NEED_CONVEX_POLYGON FALSE
#define GDISP_NEED_SCROLL FALSE
#define GDISP_NEED_PIXELREAD FALSE
#define GDISP_NEED_CONTROL FALSE
#define GDISP_NEED_QUERY FALSE
#define GDISP_NEED_IMAGE FALSE
#define GDISP_NEED_MULTITHREAD FALSE
#define GDISP_NEED_STREAMING FALSE

/* GDISP - text features */
#define GDISP_NEED_ANTIALIAS FALSE
#define GDISP_NEED_UTF8 FALSE
#define GDISP_NEED_TEXT_KERNING FALSE

/* GDISP - fonts to include */
#define GDISP_INCLUDE_FONT_UI1 TRUE
#define GDISP_INCLUDE_FONT_UI2 FALSE
#define GDISP_INCLUDE_FONT_LARGENUMBERS FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANS10 FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANS12 FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANS16 FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANS24 FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANS32 FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12 FALSE
#define GDISP_INCLUDE_FONT_FIXED_10x20 FALSE
#define GDISP_INCLUDE_FONT_FIXED_7x14 FALSE
#define GDISP_INCLUDE_FONT_FIXED_5x8 FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANS12_AA FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANS16_AA FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANS24_AA FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANS32_AA FALSE
#define GDISP_INCLUDE_FONT_DEJAVUSANSBOLD12_AA FALSE
#define GDISP_INCLUDE_USER_FONTS FALSE

/* GDISP image decoders */
#define GDISP_NEED_IMAGE_NATIVE FALSE
#define GDISP_NEED_IMAGE_GIF FALSE
#define GDISP_NEED_IMAGE_BMP FALSE
#define GDISP_NEED_IMAGE_JPG FALSE
#define GDISP_NEED_IMAGE_PNG FALSE
#define GDISP_NEED_IMAGE_ACCOUNTING FALSE

/* Optional image support that can be turned off */
/*
#define GDISP_NEED_IMAGE_BMP_1 TRUE
#define GDISP_NEED_IMAGE_BMP_4 TRUE
#define GDISP_NEED_IMAGE_BMP_4_RLE TRUE
#define GDISP_NEED_IMAGE_BMP_8 TRUE
#define GDISP_NEED_IMAGE_BMP_8_RLE TRUE
#define GDISP_NEED_IMAGE_BMP_16 TRUE
#define GDISP_NEED_IMAGE_BMP_24 TRUE
#define GDISP_NEED_IMAGE_BMP_32 TRUE
*/

/* Features for the TDISP subsystem. */
#define TDISP_NEED_MULTITHREAD FALSE

/* Features for the GWIN subsystem. */
#define GWIN_NEED_WINDOWMANAGER FALSE
#define GWIN_NEED_CONSOLE FALSE
#define GWIN_NEED_GRAPH FALSE
#define GWIN_NEED_WIDGET FALSE
#define GWIN_NEED_LABEL FALSE
#define GWIN_NEED_BUTTON FALSE
#define GWIN_NEED_SLIDER FALSE
#define GWIN_NEED_CHECKBOX FALSE
#define GWIN_NEED_IMAGE FALSE
#define GWIN_NEED_RADIO FALSE
#define GWIN_NEED_LIST FALSE

/* Features for the GEVENT subsystem. */
#define GEVENT_ASSERT_NO_RESOURCE FALSE

/* Features for the GTIMER subsystem. */
/* NONE */

/* Features for the GQUEUE subsystem. */
#define GQUEUE_NEED_ASYNC FALSE
#define GQUEUE_NEED_GSYNC FALSE
#define GQUEUE_NEED_FSYNC FALSE

/* Features for the GINPUT subsystem. */
#define GINPUT_NEED_MOUSE FALSE
#define GINPUT_NEED_KEYBOARD FALSE
#define GINPUT_NEED_TOGGLE FALSE
#define GINPUT_NEED_DIAL FALSE

/* Features for the GADC subsystem. */
/* NONE */

/* Features for the GAUDIN subsystem. */
/* NONE */

/* Features for the GAUDOUT subsystem. */
/* NONE */

/* Features for the GMISC subsystem. */
#define GMISC_NEED_ARRAYOPS FALSE
#define GMISC_NEED_FASTTRIG FALSE
#define GMISC_NEED_FIXEDTRIG FALSE
#define GMISC_NEED_INVSQRT FALSE

/* Optional Multiple Display support */
/*
#define GDISP_TOTAL_DISPLAYS 1
#define GDISP_TOTAL_CONTROLLERS 1

// Extra stuff required when GDISP_TOTAL_CONTROLLERS > 1
#define GDISP_CONTROLLER_LIST GDISPVMT_Win32, GDISPVMT_Win32
#define GDISP_CONTROLLER_DISPLAYS 1, 1
#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB888

// Optional extra stuff when GDISP_TOTAL_CONTROLLERS > 1
#define GDISP_HARDWARE_STREAM_WRITE FALSE
#define GDISP_HARDWARE_STREAM_READ FALSE
#define GDISP_HARDWARE_STREAM_POS FALSE
#define GDISP_HARDWARE_DRAWPIXEL FALSE
#define GDISP_HARDWARE_CLEARS FALSE
#define GDISP_HARDWARE_FILLS FALSE
#define GDISP_HARDWARE_BITFILLS FALSE
#define GDISP_HARDWARE_SCROLL FALSE
#define GDISP_HARDWARE_PIXELREAD FALSE
#define GDISP_HARDWARE_CONTROL FALSE
#define GDISP_HARDWARE_QUERY FALSE
#define GDISP_HARDWARE_CLIP FALSE
*/

/* Optional Parameters for various subsystems */
/*
#define GDISP_DEFAULT_ORIENTATION GDISP_ROTATE_LANDSCAPE
#define GDISP_LINEBUF_SIZE 128
#define GEVENT_MAXIMUM_SIZE 32
#define GEVENT_MAX_SOURCE_LISTENERS 32
#define GTIMER_THREAD_PRIORITY HIGH_PRIORITY
#define GTIMER_THREAD_WORKAREA_SIZE 1024
#define GADC_MAX_LOWSPEED_DEVICES 4
#define GWIN_BUTTON_LAZY_RELEASE FALSE
#define GWIN_CONSOLE_USE_BASESTREAM FALSE
#define GWIN_CONSOLE_USE_FLOAT FALSE
#define GWIN_NEED_IMAGE_ANIMATION FALSE
#define GMISC_INVSQRT_MIXED_ENDIAN FALSE
#define GMISC_INVSQRT_REAL_SLOW FALSE
*/

/* Optional Low Level Driver Definitions */
/*
#define GDISP_SCREEN_WIDTH 320
#define GDISP_SCREEN_HEIGHT 240
#define GDISP_GFXNET_PORT 13001
#define GDISP_GFXNET_CUSTOM_LWIP_STARTUP FALSE
#define GDISP_DONT_WAIT_FOR_NET_DISPLAY FALSE
#define GDISP_GFXNET_UNSAFE_SOCKETS FALSE
#define GDISP_USE_DMA FALSE
#define TDISP_COLUMNS 16
#define TDISP_ROWS 2
*/

#endif /* _GFXCONF_H */

main.c


#include "ch.h"
#include "hal.h"
#include "chprintf.h"
#include "gfx.h"


/*
* Application entry point.
*/
int main(void) {

/*
* System initializations.
* - HAL initialization, this also initializes the configured device drivers
* and performs the board-specific initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
halInit();
chSysInit();


palSetPadMode(GPIOD, GPIOD_LED3, PAL_MODE_OUTPUT_PUSHPULL);


coord_t width, height;
coord_t i, j;

// Initialize and clear the display
gfxInit();

// Get the screen size
width = gdispGetWidth();
height = gdispGetHeight();

// Code Here
gdispDrawBox(10, 10, width/2, height/2, Yellow);
gdispFillArea(width/2, height/2, width/2-10, height/2-10, Blue);
gdispDrawLine(5, 30, width-50, height-40, Red);

for(i = 5, j = 0; i < width && j < height; i += 7, j += i/20)
gdispDrawPixel(i, j, White);

while(TRUE) {
palTogglePad(GPIOD, GPIOD_LED3);
gfxSleepMilliseconds(500);
}
}

Any help is welcomed

Link to comment
Share on other sites

I cannot see anything obvious there as you are using the same board file. I PM'ed uweng14 so let's hope he looks by soon. Probably he has a newer version of those files.

What exactly do you see on your screen? Do you see random data (like colored snow?). That would mean that the controller has been initialised properly so far.

P.S.: Try to call a gdispClear(Black); right after the gfxInit();.

~ Tectu

Link to comment
Share on other sites

According to this picture there is an A and a B version of this board where the A only works with the parallen interface and B only with SPI. Are you 100% sure that you have the SPI version?

Two things to do: First, check out their example code and replace the initialisation routine of the µGFX driver by theirs (just the register values). Probably the initialisation code for the SPI mode is different. If that does still not work, you might want to try to use the parallel interface by connecting it to the FSMC peripheral of the STM32F4. There's a guide on the µGFX site that tells you what to do.

Do you have a scope accessible so you can check for proper SPI signals?

~ Tectu

Link to comment
Share on other sites

Hello

According to this picture there is an A and a B version of this board where the A only works with the parallen interface and B only with SPI. Are you 100% sure that you have the SPI version?

~ Tectu

Well, I bought from them the SPI version, but I am only testing this now, so I don't know if they made a mistake sending the LCD, although is unlikely.

Two things to do: First, check out their example code and replace the initialisation routine of the µGFX driver by theirs (just the register values). Probably the initialisation code for the SPI mode is different.

~ Tectu

I changed the code and still nothing.

If that does still not work, you might want to try to use the parallel interface by connecting it to the FSMC peripheral of the STM32F4. There's a guide on the µGFX site that tells you what to do.

~ Tectu

Will try after I keep doing some basic test (LCD responding to version request)

Do you have a scope accessible so you can check for proper SPI signals?

~ Tectu

I tested the SPI pins and they are emitting signals

I will keep working on this, thanks again for the advices

Link to comment
Share on other sites

Hi everybody

Good news, I got the screen working. The changes I had to do were:

- Put SPI interface in mode 3

. Use lower speed SPI for reading operations

- Change restart sequence a little

- Change initiation sequence

I am only having trouble changing orientation using the viewport option (result appears mirrored and rotated)

Bad news is, the manufacturing company is discontinuing this LCD for this new one http://www.hotmcu.com/28-touch-screen-tft-lcd-with-all-interface-p-63.html?cPath=6_16 (hope I can get my hands on one of this soon ;) )

This are my changes:

board_ILI9320.h

#ifndef GDISP_LLD_BOARD_H
#define GDISP_LLD_BOARD_H

#define SET_RST palSetPad(GPIOB, 11);
#define CLR_RST palClearPad(GPIOB, 11);

/*
* Maximum speed SPI configuration (21MHz, CPHA=1, CPOL=1, MSb first).
*/
static const SPIConfig hs_spicfg = {
NULL,
/* HW dependent part.*/
GPIOB,
12,
SPI_CR1_CPOL | SPI_CR1_CPHA
};

/*
* Low speed SPI configuration (328.125kHz, CPHA=1, CPOL=1, MSb first).
*/
static const SPIConfig ls_spicfg = {
NULL,
/* HW dependent part.*/
GPIOB,
12,
SPI_CR1_BR_1 | SPI_CR1_CPOL | SPI_CR1_CPHA
};

/**
* @brief Initialise the board for the display.
*
* @param[in] g The GDisplay structure
*
* @note Set the g->board member to whatever is appropriate. For multiple
* displays this might be a pointer to the appropriate register set.
*
* @notapi
*/
static inline void init_board(GDisplay *g) {
(void) g;
palSetPadMode(GPIOB, 13, PAL_MODE_ALTERNATE(5) ); /* New SCK. */
palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(5) ); /* New MISO. */
palSetPadMode(GPIOB, 15, PAL_MODE_ALTERNATE(5) ); /* New MOSI. */
palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL); /* New CS. */
//palSetPad(GPIOB, 12);

// Reset
palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL); /* New Reset. */
palSetPad(GPIOB, 11);

spiStart(&SPID2, &hs_spicfg);

}

/**
* @brief After the initialisation.
*
* @param[in] g The GDisplay structure
*
* @notapi
*/
static inline void post_init_board(GDisplay *g) {
(void) g;
}

/**
* @brief Set or clear the lcd reset pin.
*
* @param[in] g The GDisplay structure
* @param[in] state TRUE = lcd in reset, FALSE = normal operation
*
* @notapi
*/
static inline void setpin_reset(GDisplay *g, bool_t state) {
(void) g;
if (state) {
palSetPad(GPIOB, 11);
} else {
palClearPad(GPIOB, 11);
}
}

/**
* @brief Set the lcd back-light level.
*
* @param[in] g The GDisplay structure
* @param[in] percent 0 to 100%
*
* @notapi
*/
static inline void set_backlight(GDisplay *g, uint8_t percent) {
(void) g;
(void) percent;
}

/**
* @brief Take exclusive control of the bus
*
* @param[in] g The GDisplay structure
*
* @notapi
*/
static inline void acquire_bus(GDisplay *g) {
(void) g;
spiAcquireBus(&SPID2);
}

/**
* @brief Release exclusive control of the bus
*
* @param[in] g The GDisplay structure
*
* @notapi
*/
static inline void release_bus(GDisplay *g) {
(void) g;
spiReleaseBus(&SPID2);
}

/**
* @brief Send data to the index register.
*
* @param[in] g The GDisplay structure
* @param[in] index The index register to set
*
* @notapi
*/
static inline void write_index(GDisplay *g, uint16_t index) {
(void) g;
spiSelect(&SPID2);

static uint8_t txbuf[2] = {0};
txbuf[0] = 0x70 | 0x00 | 0x00;
spiSend(&SPID2, 1, txbuf);

//txbuf[0] = index & 0xFF;
txbuf[0] = (index >> 8);
txbuf[1] = (index & 0xFF);

spiSend(&SPID2, 2, txbuf);

spiUnselect(&SPID2);

}

/**
* @brief Send data to the lcd.
*
* @param[in] g The GDisplay structure
* @param[in] data The data to send
*
* @notapi
*/
static inline void write_data(GDisplay *g, uint16_t data) {
(void) g;
spiSelect(&SPID2);
static uint8_t txbuf[2] = {0};
txbuf[0] = 0x70 | 0x00 | 0x02;

spiSend(&SPID2, 1, txbuf);

txbuf[0] = (data >> 8);
txbuf[1] = (data & 0xFF);

spiSend(&SPID2, 2, txbuf);

spiUnselect(&SPID2);

}

/**
* @brief Set the bus in read mode
*
* @param[in] g The GDisplay structure
*
* @notapi
*/
static inline void setreadmode(GDisplay *g) {
(void) g;
}

/**
* @brief Set the bus back into write mode
*
* @param[in] g The GDisplay structure
*
* @notapi
*/
static inline void setwritemode(GDisplay *g) {
(void) g;
}

/**
* @brief Read data from the lcd.
* @return The data from the lcd
*
* @param[in] g The GDisplay structure
*
* @note The chip select may need to be asserted/de-asserted
* around the actual spi read
*
* @notapi
*/
static inline uint16_t read_data(GDisplay *g) {
(void) g;

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

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

spiUnselect(&SPID2);
spiStart(&SPID2, &hs_spicfg);
static uint16_t value = 0;
value = rxbuf[1] << 8 | rxbuf[2];
chprintf((BaseSequentialStream *)&SD2, "AA. %x-%x-%x-%x\r\n",
rxbuf[0], rxbuf[1], rxbuf[2], value);
return value;
}

#endif /* GDISP_LLD_BOARD_H */
/** @} */

gdisp_lld_ILI9320.c

LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
uint16_t cver;

// No private area for this controller
g->priv = 0;

// Initialise the board interface
init_board(g);

/* Hardware reset */
setpin_reset(g, TRUE);
gfxSleepMicroseconds(1000);
setpin_reset(g, FALSE);
gfxSleepMicroseconds(1000);
setpin_reset(g, TRUE);
gfxSleepMicroseconds(1000);

acquire_bus(g);
write_index(g, 0); // Get controller version
setreadmode(g);
dummy_read(g);
cver = read_data(g);
setwritemode(g);
//write_reg(g, 0x00, 0x0001); //start Int. osc
write_reg(g, 0x00, 0x0000);
//gfxSleepMicroseconds(500);
write_reg(g, 0x01, 0x0100); //Set SS bit (shift direction of outputs is from S720 to S1)
write_reg(g, 0x02, 0x0700); //select the line inversion
write_reg(g, 0x03, 0x1030); //Entry mode(Horizontal : increment,Vertical : increment, AM=1)
write_reg(g, 0x04, 0x0000); //Resize control(No resizing)
write_reg(g, 0x08, 0x0202); //front and back porch 2 lines
write_reg(g, 0x09, 0x0000); //select normal scan
write_reg(g, 0x0A, 0x0000); //display control 4
//write_reg(g, 0x0C, 0x0000); //system interface(2 transfer /pixel), internal sys clock,
write_reg(g, 0x0C, (1<<0)); /* Extern Display Interface Contral 1 */
write_reg(g, 0x0D, 0x0000); //Frame marker position
write_reg(g, 0x0F, 0x0000); //selects clk, enable and sync signal polarity,

gfxSleepMicroseconds(50);

write_reg(g, 0x07, 0x0101); /* Display Contral */

gfxSleepMicroseconds(50);

write_reg(g, 0x10,(1<<12)|(0<<8)|(1<<7)|(1<<6)|(0<<4)); /* Power Control 1 */
write_reg(g, 0x11,0x0007); /* Power Control 2 */
write_reg(g, 0x12,(1<<8)|(1<<4)|(0<<0)); /* Power Control 3 */
write_reg(g, 0x13,0x0b00); /* Power Control 4 */
write_reg(g, 0x29,0x0000); /* Power Control 7 */
write_reg(g, 0x2b,(1<<14)|(1<<4));

write_reg(g, 0x50,0); /* Set X Start */
write_reg(g, 0x51,239); /* Set X End */
write_reg(g, 0x52,0); /* Set Y Start */
write_reg(g, 0x53,319); /* Set Y End */
gfxSleepMicroseconds(50);

write_reg(g, 0x60,0x2700); /* Driver Output Control */
write_reg(g, 0x61,0x0001); /* Driver Output Control */
write_reg(g, 0x6a,0x0000); /* Vertical Srcoll Control */

write_reg(g, 0x80,0x0000); /* Display Position? Partial Display 1 */
write_reg(g, 0x81,0x0000); /* RAM Address Start? Partial Display 1 */
write_reg(g, 0x82,0x0000); /* RAM Address End-Partial Display 1 */
write_reg(g, 0x83,0x0000); /* Displsy Position? Partial Display 2 */
write_reg(g, 0x84,0x0000); /* RAM Address Start? Partial Display 2 */
write_reg(g, 0x85,0x0000); /* RAM Address End? Partial Display 2 */

write_reg(g, 0x90,(0<<7)|(16<<0)); /* Frame Cycle Contral */
write_reg(g, 0x92,0x0000); /* Panel Interface Contral 2 */
write_reg(g, 0x93,0x0001); /* Panel Interface Contral 3 */
write_reg(g, 0x95,0x0110); /* Frame Cycle Contral */
write_reg(g, 0x97,(0<<8));
write_reg(g, 0x98,0x0000); /* Frame Cycle Contral */
write_reg(g, 0x07,0x0133);

gfxSleepMicroseconds(100); /* delay 100 ms */

// write_reg(g, 0x10, 0x0000); //
// write_reg(g, 0x11, 0x0000); //power control 2 reference voltages = 1:1,
// write_reg(g, 0x12, 0x0000); //power control 3 VRH
// write_reg(g, 0x13, 0x0000); //power control 4 VCOM amplitude
// gfxSleepMicroseconds(500);
// write_reg(g, 0x10, 0x17B0); //power control 1 BT,AP
// write_reg(g, 0x11, 0x0137); //power control 2 DC,VC
// gfxSleepMicroseconds(500);
// write_reg(g, 0x12, 0x0139); //power control 3 VRH
// gfxSleepMicroseconds(500);
// write_reg(g, 0x13, 0x1d00); //power control 4 vcom amplitude
// write_reg(g, 0x29, 0x0011); //power control 7 VCOMH
// gfxSleepMicroseconds(500);
// write_reg(g, 0x30, 0x0007);
// write_reg(g, 0x31, 0x0403);
// write_reg(g, 0x32, 0x0404);
// write_reg(g, 0x35, 0x0002);
// write_reg(g, 0x36, 0x0707);
// write_reg(g, 0x37, 0x0606);
// write_reg(g, 0x38, 0x0106);
// write_reg(g, 0x39, 0x0007);
// write_reg(g, 0x3c, 0x0700);
// write_reg(g, 0x3d, 0x0707);
// write_reg(g, 0x20, 0x0000); //starting Horizontal GRAM Address
// write_reg(g, 0x21, 0x0000); //starting Vertical GRAM Address
// write_reg(g, 0x50, 0x0000); //Horizontal GRAM Start Position
// write_reg(g, 0x51, 0x00EF); //Horizontal GRAM end Position
// write_reg(g, 0x52, 0x0000); //Vertical GRAM Start Position
// write_reg(g, 0x53, 0x013F); //Vertical GRAM end Position
// switch (cver) {
// case 0x9320:
// write_reg(g, 0x60, 0x2700); //starts scanning from G1, and 320 drive lines
// break;
// case 0x9325:
// write_reg(g, 0x60, 0xA700); //starts scanning from G1, and 320 drive lines
// break;
// }

// write_reg(g, 0x61, 0x0001); //fixed base display
// write_reg(g, 0x6a, 0x0000); //no scroll
// write_reg(g, 0x90, 0x0010); //set Clocks/Line =16, Internal Operation Clock Frequency=fosc/1,
// write_reg(g, 0x92, 0x0000); //set gate output non-overlap period=0
// write_reg(g, 0x93, 0x0003); //set Source Output Position=3
// write_reg(g, 0x95, 0x0110); //RGB interface(Clocks per line period=16 clocks)
// write_reg(g, 0x97, 0x0110); //set Gate Non-overlap Period 0 locksc
// write_reg(g, 0x98, 0x0110); //
// write_reg(g, 0x07, 0x0173); //display On

// Finish Init
post_init_board(g);

// Release the bus
release_bus(g);

// Turn on the backlight
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 = GDISP_ROTATE_0;
g->g.Powermode = powerOn;
g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
g->g.Contrast = GDISP_INITIAL_CONTRAST;
return TRUE;
}

Link to comment
Share on other sites

Nice to heard that you got your display working!

We already had several times the issue with the initialization sequence of the ILI9320 driver. There were already plans to move the initialization to the board file, but as this only happened in a small amount of cases, it seemed to be like killing a fly with a bazooka.

Please let me know if you need a different initialization code for the new display again.

~ Tectu

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...