Multiple displays

From uGFX Wiki
Jump to: navigation, search

It's possible to drive more than just one display out of the GDISP module. Each display is completely independent. The displays can have different display controllers and therefore different interfaces and also different resolutions. Note: "multiple displays" means that you can also use more than just two displays. A common purpose of this feature would be to have one main control screen and a smaller status screen. Furthermore, this can be very interesting in combination with the remote display support.


Configuration

When dealing with multiple displays, GFX distinguishes between the displays and the controller types. This is useful for when using the same type of display controller more than once so you don't have to include the code multiple times.

The first thing to do is to specify the amount of displays and the number of different controller types in your gfxconf.h:

#define GDISP_TOTAL_DISPLAYS		3
#define GDISP_TOTAL_CONTROLLERS		2

Where GDISP_TOTAL_DISPLAYS is the total amount of displays, regardless of the number of controller types, and GDISP_TOTAL_CONTROLLERS is the total amount of different display controller types. We're going to use the SSD2119 and the ILI9320 in the following example.

If you are using the same controller type for every display (GDISP_TOTAL_CONTROLLERS = 1) that is all you need to do.

If not, you have to provide the list of drivers that are used through the GDISP_CONTROLLER_LIST macro and map the displays to them:

#define GDISP_CONTROLLER_LIST		GDISPVMT_SSD2119, GDISPVMT_ILI9320
#define GDISP_CONTROLLER_DISPLAYS	2, 1

The GDISP_CONTROLLER_DISPLAYS macro tells how many displays that have to be mapped to the corresponding displays driver from the GDISP_CONTROLLER_LIST macro. The sum of GDISP_CONTROLLER_DISPLAYS must be equal to the amount of displays specified through GDISP_TOTAL_DISPLAYS.

And the last thing left to do in your gfxconf.h for multiple controller types is to specify the color format you want your application to run in. Each display controller will automatically translate it for his specifications:

#define GDISP_PIXELFORMAT		GDISP_PIXELFORMAT_RGB888

As the changes to the gfxconf.h are now complete, the next thing to modify is your Makefile. Simply include all the drivers that are used in your system instead of only one. The following example uses an SSD1963 and an ILI9320 again:

include $(GFXLIB)/drivers/gdisp/SSD2119/gdisp_lld.mk
include $(GFXLIB)/drivers/gdisp/ILI9320/gdisp_lld.mk

From now on, you can access all your displays independently.

Example - Different controllers

The following config example shows how two displays can be used, where one uses the SSD2119 and the other the ILI9320 display controller.

#define GDISP_TOTAL_DISPLAYS			2
#define GDISP_TOTAL_CONTROLLERS			2
#define GDISP_CONTROLLER_LIST			GDISPVMT_SSD2119, GDISPVMT_ILI9320
#define GDISP_CONTROLLER_DISPLAYS		1, 1
#define GDISP_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565

Example - Same controller

If you're using more than one display, but each display uses the same controller, you only have to specify the number of displays as the driver is automatically recognized by the Makefile.

#define GDISP_TOTAL_DISPLAYS			2

Board files

Your board files for your controllers will need to be updated to indicate how each controller talks to each display. There is a special member g->board in the GDisplay structure that gets passed to each function. This member variable can be used by the board file to (for example) point to hardware register sets. This member is purely for the board file's use and is not touched by any other code.

Access the displays

Your displays are now set up and you can access them. There are two different ways to do so. One way is to select the current active display through the gdispSetDisplay() call and use the gdispXxx() routines as you would with just one display. The other way is to use the gdispGXxx() call instead where the first parameter is always the display that shall be accessed.

This example shows how to use the first method:

#include "gfx.h"
 
int main(void) {
    coord_t    width, height;
    coord_t    display, i, j;
 
    /* Initialize and clear the display */
    gfxInit();
 
 
    /* Cycle through each display */
    for(display = 0; display < GDISP_TOTAL_DISPLAYS; display++) {
 
        /* Set the default display to the specified display */
        gdispSetDisplay(gdispGetDisplay(display));
 
        /* Get the screen size */
        width = gdispGetWidth();
        height = gdispGetHeight();
 
        /* Draw draw draw */
        gdispDrawBox(10, 10, width/2, height/2, Yellow);
        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) {
        gfxSleepMilliseconds(500);
    }
}

And this example shows how to use the second method:

#include "gfx.h"
 
int main(void) {
    coord_t    width, height;
    coord_t    display, i, j;
    GDisplay   *g;
 
    /* Initialize and clear the display */
    gfxInit();
 
    /* Cycle through each display */
    for(display = 0; display < GDISP_TOTAL_DISPLAYS; display++) {
 
        /* Get the specified display */
        g = gdispGetDisplay(display);
 
        /* Get the screen size */
        width = gdispGGetWidth(g);
        height = gdispGGetHeight(g);
 
        /* Draw draw draw */
        gdispGDrawBox(g, 10, 10, width/2, height/2, Yellow);
        sprintf(buf, "Display %u", display);
        gdispGFillStringBox(g, width/2, height/2, width/2-10, height/2-10, buf, f, White, Blue, justifyCenter);
        gdispGDrawLine(g, 5, 30, width-50, height-40, Red);
 
        for(i = 5, j = 0; i < width && j < height; i += 7, j += i/20)
            gdispGDrawPixel(g, i, j, White);
    }
 
    while(TRUE) {
        gfxSleepMilliseconds(500);
    }
}