Jump to content

Just a little help with multiple displays..


david1982

Recommended Posts

Hello all,

Can some one please just help me with my multiple display set-up.

I understand the basics of using the multiple displays from the examples but how do I set-up my board file as the only difference between the two displays is the chip select (SPI).

Thanks.

Link to comment
Share on other sites

Where you are using the same controller chip with two displays you can use the board member of the gdisplay structure to work out which chip select pin to activate. This member is for your board files private use.

Your list of boards will then contain the same controller twice (or rather GDISP_TOTAL_DISPLAYS will be set to 2 if they use the same controller I think). It will then get initialised twice with a different display number each time. The init routine sets up the board member and thereafter that is used to distinguish the displays.

Link to comment
Share on other sites

I think that what I am doing ..

and sorry yes both displays use the same controller.

I have set the following in my ugfxconf..

#define GDISP_TOTAL_DISPLAYS 2

#define GDISP_TOTAL_CONTROLLERS 1

#define GDISP_PIXELFORMAT GDISP_PIXELFORMAT_RGB565

My board int looks like..

static inline void init_board(GDisplay *g) {
(void) g;
//Set up the pins..
palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL);//cs 2
palSetPadMode(SPI_PORT, CS_PAD, PAL_MODE_OUTPUT_PUSHPULL);//cs 1
palSetPadMode(SPI_PORT, SCK_PAD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
palSetPadMode(SPI_PORT, MISO_PAD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
palSetPadMode(SPI_PORT, MOSI_PAD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
palSetPadMode(RESET_PORT, RESET_PAD, PAL_MODE_OUTPUT_PUSHPULL );
palSetPadMode(DNC_PORT, DNC_PAD, PAL_MODE_OUTPUT_PUSHPULL);


switch(g->controllerdisplay)
{
case 0:
//Set pins.
palSetPad(CS_PORT, CS_PAD);
palSetPad(RESET_PORT, RESET_PAD);
palClearPad(DNC_PORT, DNC_PAD);
break;
//Start SPI1 with our config.
spiStart(SPI_DRIVER, &spi_cfg);
spiSelectI(SPI_DRIVER); /* Slave Select assertion. */

case 1:


//Set pins.
palSetPad(GPIOB, 0);
palSetPad(RESET_PORT, RESET_PAD);
palClearPad(DNC_PORT, DNC_PAD);

//Start SPI1 with our config.
spiStart(SPI_DRIVER, &spi_cfg2);
spiSelectI(SPI_DRIVER);
break;
}
}

But when I draw to each display only the second display works..

I am switching between displays like so..


coord_t displayA,displayB;
displayA = 0;
displayB = 1;
gdispSetDisplay(gdispGetDisplay(displayA));
///Do some drawing This does not show
gdispSetDisplay(gdispGetDisplay(displayB));
///Do some drawing This does show

Link to comment
Share on other sites

Your application code looks fine. Can you please post your entire board file. I suspect the problem is in the aquirebus/releasebus and the write calls.

To give you more detail...

You are configuring both boards (including their chip select lines) in the init call. Once you have init the spi for cs2 it will maintain that for all writes and thus only the 2nd display gets written to.

In practice the chibios experience of storing the chip select in the spi port means it is assuming a single slave device. There are two solutions, 1/ do your own chip select manipulation or 2/ re initialise the chibios spi port during each aquirebus operation.

Link to comment
Share on other sites

Yes you where right inmarket..

I have it working now, you don’t do anything with the spi in int board but you do all spi work in acquire bus.

Below is my board file for 2 ILI9341 displays running on a STM32F1 via spi.

It my help others as an example.

   #ifndef _GDISP_LLD_BOARD_H
#define _GDISP_LLD_BOARD_H
//**** ILI9341 on SPI1. TESTED on STM32L1, STM32F1 AND STM32F4.
// Pin & SPI setup

#define SPI_METHOD_IRQ 1
#define SPI_METHOD_POLLING 2
#define SPI_METHOD SPI_METHOD_POLLING
// SPI1
#define SPI_DRIVER (&SPID1)
#define SPI_PORT GPIOA
#define SCK_PAD 5 //PA5
#define MISO_PAD 6 //PA6
#define MOSI_PAD 7 //PA7

#define CS_PORT GPIOA
#define CS2_PORT GPIOB
#define RESET_PORT GPIOA
#define DNC_PORT GPIOA
#define CS_PAD 4 // PA4 -- 0 = chip selected
#define CS2_PAD 0 // PB0 -- 0 = chip selected
#define RESET_PAD 1 // PA1 -- 0 = reset
#define DNC_PAD 0 // PA0 -- control=0, data=1 -- DNC or D/C

// SPI setup ajust " SPI_BaudRatePrescaler_X" to set SPI speed.
// 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

static SPIConfig spi_cfg = {
NULL,
CS_PORT,
CS_PAD,
SPI_BaudRatePrescaler_2 //AJUST SPEED HERE..
};
static SPIConfig spi_cfg2 = {
NULL,
CS2_PORT,
CS2_PAD,
SPI_BaudRatePrescaler_2 //AJUST SPEED HERE..
};

static inline void init_board(GDisplay *g) {
(void) g;
//Set up the pins..
palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL);//cs 2
palSetPadMode(SPI_PORT, CS_PAD, PAL_MODE_OUTPUT_PUSHPULL);//cs 1
palSetPadMode(SPI_PORT, SCK_PAD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
palSetPadMode(SPI_PORT, MISO_PAD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
palSetPadMode(SPI_PORT, MOSI_PAD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
palSetPadMode(RESET_PORT, RESET_PAD, PAL_MODE_OUTPUT_PUSHPULL );
palSetPadMode(DNC_PORT, DNC_PAD, PAL_MODE_OUTPUT_PUSHPULL);
//Select both displays
palSetPad(CS_PORT, CS_PAD);
palSetPad(CS2_PORT, CS2_PAD);
//Reset both displays
palSetPad(RESET_PORT, RESET_PAD);
palClearPad(DNC_PORT, DNC_PAD);
//Unselect both displays
palClearPad(CS_PORT, CS_PAD);
palClearPad(CS2_PORT, CS2_PAD);




}

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

static inline void setpin_reset(GDisplay *g, bool_t state) {
(void) g;
palWritePad(RESET_PORT, RESET_PAD, !state);
}

static inline void set_backlight(GDisplay *g, uint8_t percent) {
(void) g;
(void) percent;
}
//This is where we select each display
static inline void acquire_bus(GDisplay *g) {
(void) g;
switch(g->controllerdisplay)
{
case 0:

spiStart(SPI_DRIVER, &spi_cfg);
spiSelectI(SPI_DRIVER);
break;
case 1:
spiStart(SPI_DRIVER, &spi_cfg2);
spiSelectI(SPI_DRIVER);
break;
}
}

static inline void release_bus(GDisplay *g) {
(void) g;
switch(g->controllerdisplay)
{
case 0:
spiUnselectI(SPI_DRIVER);
break;
case 1:
spiUnselectI(SPI_DRIVER);
break;

}
}

static inline void write_index(GDisplay *g, uint8_t index) {
(void) g;

palClearPad(DNC_PORT, DNC_PAD);
#if SPI_METHOD == SPI_METHOD_IRQ
spiSend(SPI_DRIVER, 1, &index);
#elif SPI_METHOD == SPI_METHOD_POLLING
spiPolledExchange(SPI_DRIVER, index);
#endif
palSetPad(DNC_PORT, DNC_PAD);


}

static inline void write_data(GDisplay *g, uint8_t data) {
(void) g;

#if SPI_METHOD == SPI_METHOD_IRQ
spiSend(SPI_DRIVER, 1, &data);
#elif SPI_METHOD == SPI_METHOD_POLLING
spiPolledExchange(SPI_DRIVER, data);
#endif
}

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

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

#endif /* _GDISP_LLD_BOARD_H */

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