diff options
author | inmarket <andrewh@inmarket.com.au> | 2014-11-05 19:32:47 +1000 |
---|---|---|
committer | inmarket <andrewh@inmarket.com.au> | 2014-11-05 19:32:47 +1000 |
commit | b6d183832e2301ae5bef577f27f97ae5d8e7ee7f (patch) | |
tree | 5b9625acebcfc1ff3185d1e7840b04a95a977b60 /drivers/gdisp/STM32F429iDiscovery/gdisp_lld_STM32F429iDiscovery.c | |
parent | 804fcc7c6ab8f2e0932c65a0fc7a967337f431d6 (diff) | |
download | uGFX-b6d183832e2301ae5bef577f27f97ae5d8e7ee7f.tar.gz uGFX-b6d183832e2301ae5bef577f27f97ae5d8e7ee7f.tar.bz2 uGFX-b6d183832e2301ae5bef577f27f97ae5d8e7ee7f.zip |
STM32F429i-Discovery board is now a supported board with an example project.
New gdisp driver (currently non-accelerated)
Mouse and other drivers still to come.
The board file is currently ChibiOS specific however the gdisp driver is suitable for any OS.
Diffstat (limited to 'drivers/gdisp/STM32F429iDiscovery/gdisp_lld_STM32F429iDiscovery.c')
-rw-r--r-- | drivers/gdisp/STM32F429iDiscovery/gdisp_lld_STM32F429iDiscovery.c | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_STM32F429iDiscovery.c b/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_STM32F429iDiscovery.c new file mode 100644 index 00000000..aae21a8e --- /dev/null +++ b/drivers/gdisp/STM32F429iDiscovery/gdisp_lld_STM32F429iDiscovery.c @@ -0,0 +1,410 @@ +/* + * 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) + #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored." + #undef GISP_SCREEN_HEIGHT +#endif +#if defined(GDISP_SCREEN_WIDTH) + #warning "GDISP: This low level driver does not support setting a screen size. It is being ignored." + #undef GDISP_SCREEN_WIDTH +#endif + +#define GDISP_DRIVER_VMT GDISPVMT_STM32F429iDiscovery +#include "drivers/gdisp/STM32F429iDiscovery/gdisp_lld_config.h" +#include "src/gdisp/driver.h" + +#include "stm32_ltdc.h" + +typedef struct ltdcLayerConfig { + // frame + LLDCOLOR_TYPE *frame; // Frame buffer address + coord_t width, height; // Frame size in pixels + coord_t pitch; // Line pitch, in bytes + ltdc_pixfmt_t fmt; // Pixel format in LTDC format + + // window + coord_t x, y; // Start pixel position of the virtual layer + coord_t cx, cy; // Size of the virtual layer + + uint32_t defcolor; // Default color, ARGB8888 + uint32_t keycolor; // Color key, RGB888 + uint32_t blending; // Blending factors + const uint32_t *palette; // The palette, RGB888 (can be NULL) + uint16_t palettelen; // Palette length + uint8_t alpha; // Constant alpha factor + uint8_t layerflags; // Layer configuration +} ltdcLayerConfig; + +#define LTDC_UNUSED_LAYER_CONFIG { 0, 1, 1, 1, LTDC_FMT_L8, 0, 0, 1, 1, 0x000000, 0x000000, LTDC_BLEND_FIX1_FIX2, 0, 0, 0, 0 } + +typedef struct ltdcConfig { + coord_t width, height; // Screen size + coord_t hsync, vsync; // Horizontal and Vertical sync pixels + coord_t hbackporch, vbackporch; // Horizontal and Vertical back porch pixels + coord_t hfrontporch, vfrontporch; // Horizontal and Vertical front porch pixels + uint8_t syncflags; // Sync flags + uint32_t bgcolor; // Clear screen color RGB888 + + ltdcLayerConfig bglayer; // Background layer config + ltdcLayerConfig fglayer; // Foreground layer config +} ltdcConfig; + +#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565 + #define LTDC_PIXELFORMAT LTDC_FMT_RGB565 + #define LTDC_PIXELBYTES 2 + #define LTDC_PIXELBITS 16 +#elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB888 + #define LTDC_PIXELFORMAT LTDC_FMT_RGB888 + #define LTDC_PIXELBYTES 3 + #define LTDC_PIXELBITS 24 +#else + #error "GDISP: STM32F4iDiscovery - unsupported pixel format" +#endif + +#include "board_STM32F429iDiscovery.h" + +#include "ili9341.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#ifndef GDISP_INITIAL_CONTRAST + #define GDISP_INITIAL_CONTRAST 50 +#endif +#ifndef GDISP_INITIAL_BACKLIGHT + #define GDISP_INITIAL_BACKLIGHT 100 +#endif + +/*===========================================================================*/ +/* Driver local routines . */ +/*===========================================================================*/ + +#define PIXIL_POS(g, x, y) ((y) * driverCfg.bglayer.pitch + (x) * LTDC_PIXELBYTES) +#define PIXEL_ADDR(g, pos) ((LLDCOLOR_TYPE *)((uint8_t *)driverCfg.bglayer.frame+pos)) + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +static void InitController(GDisplay *g) { + #define REG_TYPEMASK 0xFF00 + #define REG_DATAMASK 0x00FF + + #define REG_DATA 0x0000 + #define REG_COMMAND 0x0100 + #define REG_DELAY 0x0200 + + static const uint16_t initdata[] = { + REG_COMMAND | ILI9341_CMD_RESET, + REG_DELAY | 5, + REG_COMMAND | ILI9341_CMD_DISPLAY_OFF, + REG_COMMAND | ILI9341_SET_FRAME_CTL_NORMAL, 0x00, 0x1B, + REG_COMMAND | ILI9341_SET_FUNCTION_CTL, 0x0A, 0xA2, + REG_COMMAND | ILI9341_SET_POWER_CTL_1, 0x10, + REG_COMMAND | ILI9341_SET_POWER_CTL_2, 0x10, + REG_COMMAND | ILI9341_SET_VCOM_CTL_1, 0x45, 0x15, + REG_COMMAND | ILI9341_SET_VCOM_CTL_2, 0x90, + REG_COMMAND | ILI9341_SET_MEM_ACS_CTL, 0xC8, + REG_COMMAND | ILI9341_SET_RGB_IF_SIG_CTL, 0xC2, + REG_COMMAND | ILI9341_SET_FUNCTION_CTL, 0x0A, 0xA7, 0x27, 0x04, + REG_COMMAND | ILI9341_SET_COL_ADDR, 0x00, 0x00, 0x00, 0xEF, + REG_COMMAND | ILI9341_SET_PAGE_ADDR, 0x00, 0x00, 0x01, 0x3F, + REG_COMMAND | ILI9341_SET_IF_CTL, 0x01, 0x00, 0x06, + REG_COMMAND | ILI9341_SET_GAMMA, 0x01, + REG_COMMAND | ILI9341_SET_PGAMMA, + 0x0F, 0x29, 0x24, 0x0C, 0x0E, 0x09, 0x4E, 0x78, + 0x3C, 0x09, 0x13, 0x05, 0x17, 0x11, 0x00, + REG_COMMAND | ILI9341_SET_NGAMMA, + 0x00, 0x16, 0x1B, 0x04, 0x11, 0x07, 0x31, 0x33, + 0x42, 0x05, 0x0C, 0x0A, 0x28, 0x2F, 0x0F, + REG_COMMAND | ILI9341_CMD_SLEEP_OFF, + REG_DELAY | 10, + REG_COMMAND | ILI9341_CMD_DISPLAY_ON, + REG_COMMAND | ILI9341_SET_MEM + }; + + const uint16_t *p; + + acquire_bus(g); + for(p = initdata; p < &initdata[sizeof(initdata)/sizeof(initdata[0])]; p++) { + switch(*p & REG_TYPEMASK) { + case REG_DATA: write_data(g, *p); break; + case REG_COMMAND: write_index(g, *p); break; + case REG_DELAY: gfxSleepMilliseconds(*p & 0xFF); break; + } + } + release_bus(g); +} + +static void LTDC_Reload(void) { + LTDC->SRCR |= LTDC_SRCR_IMR; + while (LTDC->SRCR & (LTDC_SRCR_IMR | LTDC_SRCR_VBR)) + gfxYield(); +} + +static void LTDC_LayerInit(LTDC_Layer_TypeDef *pLayReg, const ltdcLayerConfig * pCfg) { + static const uint8_t fmt2Bpp[] = { + 4, /* LTDC_FMT_ARGB8888 */ + 3, /* LTDC_FMT_RGB888 */ + 2, /* LTDC_FMT_RGB565 */ + 2, /* LTDC_FMT_ARGB1555 */ + 2, /* LTDC_FMT_ARGB4444 */ + 1, /* LTDC_FMT_L8 */ + 1, /* LTDC_FMT_AL44 */ + 2 /* LTDC_FMT_AL88 */ + }; + uint32_t start, stop; + + // Set the framebuffer dimensions and format + pLayReg->PFCR = (pLayReg->PFCR & ~LTDC_LxPFCR_PF) | ((uint32_t)pCfg->fmt & LTDC_LxPFCR_PF); + pLayReg->CFBAR = (uint32_t)pCfg->frame & LTDC_LxCFBAR_CFBADD; + pLayReg->CFBLR = ((((uint32_t)pCfg->pitch << 16) & LTDC_LxCFBLR_CFBP) | (((uint32_t)fmt2Bpp[pCfg->fmt] * pCfg->width + 3) & LTDC_LxCFBLR_CFBLL)); + pLayReg->CFBLNR = (uint32_t)pCfg->height & LTDC_LxCFBLNR_CFBLNBR; + + // Set the display window boundaries + start = (uint32_t)pCfg->x + driverCfg.hsync + driverCfg.hbackporch; + stop = start + pCfg->cx - 1; + pLayReg->WHPCR = ((start << 0) & LTDC_LxWHPCR_WHSTPOS) | ((stop << 16) & LTDC_LxWHPCR_WHSPPOS); + start = (uint32_t)pCfg->y + driverCfg.vsync + driverCfg.vbackporch; + stop = start + pCfg->cy - 1; + pLayReg->WVPCR = ((start << 0) & LTDC_LxWVPCR_WVSTPOS) | ((stop << 16) & LTDC_LxWVPCR_WVSPPOS); + + // Set colors + pLayReg->DCCR = pCfg->defcolor; + pLayReg->CKCR = (pLayReg->CKCR & ~0x00FFFFFF) | (pCfg->keycolor & 0x00FFFFFF); + pLayReg->CACR = (pLayReg->CACR & ~LTDC_LxCACR_CONSTA) | ((uint32_t)pCfg->alpha & LTDC_LxCACR_CONSTA); + pLayReg->BFCR = (pLayReg->BFCR & ~(LTDC_LxBFCR_BF1 | LTDC_LxBFCR_BF2)) | ((uint32_t)pCfg->blending & (LTDC_LxBFCR_BF1 | LTDC_LxBFCR_BF2)); + for (start = 0; start < pCfg->palettelen; start++) + pLayReg->CLUTWR = ((uint32_t)start << 24) | (pCfg->palette[start] & 0x00FFFFFF); + + // Final flags + pLayReg->CR = (pLayReg->CR & ~LTDC_LEF_MASK) | ((uint32_t)pCfg->layerflags & LTDC_LEF_MASK); +} + +static void LTDC_Init(void) { + // Set up the display scanning + uint32_t hacc, vacc; + + /* Reset the LTDC hardware module.*/ + RCC->APB2RSTR |= RCC_APB2RSTR_LTDCRST; + RCC->APB2RSTR = 0; + + /* Enable the LTDC clock.*/ + RCC->DCKCFGR = (RCC->DCKCFGR & ~RCC_DCKCFGR_PLLSAIDIVR) | (2 << 16); /* /8 */ + + // Enable the module + RCC->APB2ENR |= RCC_APB2ENR_LTDCEN; + + // Turn off the controller and its interrupts. + LTDC->GCR = 0; + LTDC->IER = 0; + LTDC_Reload(); + + // Set synchronization params + hacc = driverCfg.hsync - 1; + vacc = driverCfg.vsync - 1; + LTDC->SSCR = ((hacc << 16) & LTDC_SSCR_HSW) | ((vacc << 0) & LTDC_SSCR_VSH); + + // Set accumulated back porch params + hacc += driverCfg.hbackporch; + vacc += driverCfg.vbackporch; + LTDC->BPCR = ((hacc << 16) & LTDC_BPCR_AHBP) | ((vacc << 0) & LTDC_BPCR_AVBP); + + // Set accumulated active params + hacc += driverCfg.width; + vacc += driverCfg.height; + LTDC->AWCR = ((hacc << 16) & LTDC_AWCR_AAW) | ((vacc << 0) & LTDC_AWCR_AAH); + + // Set accumulated total params + hacc += driverCfg.hfrontporch; + vacc += driverCfg.vfrontporch; + LTDC->TWCR = ((hacc << 16) & LTDC_TWCR_TOTALW) | ((vacc << 0) & LTDC_TWCR_TOTALH); + + // Set signal polarities and other flags + LTDC->GCR = driverCfg.syncflags & (LTDC_EF_MASK & ~LTDC_EF_ENABLE); + + // Set background color + LTDC->BCCR = (LTDC->BCCR & ~0x00FFFFFF) | (driverCfg.bgcolor & 0x00FFFFFF); + + // Load the background layer + LTDC_LayerInit(LTDC_Layer1, &driverCfg.bglayer); + + // Load the foreground layer + LTDC_LayerInit(LTDC_Layer2, &driverCfg.fglayer); + + // Interrupt handling + //nvicEnableVector(STM32_LTDC_EV_NUMBER, CORTEX_PRIORITY_MASK(STM32_LTDC_EV_IRQ_PRIORITY)); + //nvicEnableVector(STM32_LTDC_ER_NUMBER, CORTEX_PRIORITY_MASK(STM32_LTDC_ER_IRQ_PRIORITY)); + // Possible flags - LTDC_IER_RRIE, LTDC_IER_LIE, LTDC_IER_FUIE, LTDC_IER_TERRIE etc + LTDC->IER = 0; + + // Set everything going + LTDC_Reload(); + LTDC->GCR |= LTDC_GCR_LTDCEN; + LTDC_Reload(); +} + +LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { + + // Initialize the private structure + g->priv = 0; + g->board = 0; + //if (!(g->priv = gfxAlloc(sizeof(fbPriv)))) + // gfxHalt("GDISP Framebuffer: Failed to allocate private memory"); + + // Init the board + init_board(g); + //((fbPriv *)g->priv)->fbi.cfg = init_board(g); + + // Initialise the ILI9341 controller + InitController(g); + + // Initialise the LTDC controller + LTDC_Init(); + + // Initialise DMA2D + //dma2dStart(&DMA2DD1, &dma2d_cfg); + //dma2d_test(); + + // Finish Init the board + post_init_board(g); + + /* Turn on the back-light */ + set_backlight(g, GDISP_INITIAL_BACKLIGHT); + + /* Initialise the GDISP structure */ + g->g.Width = driverCfg.bglayer.width; + g->g.Height = driverCfg.bglayer.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; +} + +LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) { + unsigned pos; + + #if GDISP_NEED_CONTROL + switch(g->g.Orientation) { + case GDISP_ROTATE_0: + default: + pos = PIXIL_POS(g, g->p.x, g->p.y); + break; + case GDISP_ROTATE_90: + pos = PIXIL_POS(g, g->p.y, g->g.Width-g->p.x-1); + break; + case GDISP_ROTATE_180: + pos = PIXIL_POS(g, g->g.Width-g->p.x-1, g->g.Height-g->p.y-1); + break; + case GDISP_ROTATE_270: + pos = PIXIL_POS(g, g->g.Height-g->p.y-1, g->p.x); + break; + } + #else + pos = PIXIL_POS(g, g->p.x, g->p.y); + #endif + + PIXEL_ADDR(g, pos)[0] = gdispColor2Native(g->p.color); +} + +LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) { + unsigned pos; + LLDCOLOR_TYPE color; + + #if GDISP_NEED_CONTROL + switch(g->g.Orientation) { + case GDISP_ROTATE_0: + default: + pos = PIXIL_POS(g, g->p.x, g->p.y); + break; + case GDISP_ROTATE_90: + pos = PIXIL_POS(g, g->p.y, g->g.Width-g->p.x-1); + break; + case GDISP_ROTATE_180: + pos = PIXIL_POS(g, g->g.Width-g->p.x-1, g->g.Height-g->p.y-1); + break; + case GDISP_ROTATE_270: + pos = PIXIL_POS(g, g->g.Height-g->p.y-1, g->p.x); + break; + } + #else + pos = PIXIL_POS(g, g->p.x, g->p.y); + #endif + + color = PIXEL_ADDR(g, pos)[0]; + return gdispNative2Color(color); +} + +#if GDISP_NEED_CONTROL + LLDSPEC void gdisp_lld_control(GDisplay *g) { + switch(g->p.x) { + case GDISP_CONTROL_POWER: + if (g->g.Powermode == (powermode_t)g->p.ptr) + return; + switch((powermode_t)g->p.ptr) { + case powerOff: case powerOn: case powerSleep: case powerDeepSleep: + board_power(g, (powermode_t)g->p.ptr); + break; + default: + return; + } + g->g.Powermode = (powermode_t)g->p.ptr; + return; + + case GDISP_CONTROL_ORIENTATION: + if (g->g.Orientation == (orientation_t)g->p.ptr) + return; + switch((orientation_t)g->p.ptr) { + case GDISP_ROTATE_0: + case GDISP_ROTATE_180: + if (g->g.Orientation == GDISP_ROTATE_90 || g->g.Orientation == GDISP_ROTATE_270) { + coord_t tmp; + + tmp = g->g.Width; + g->g.Width = g->g.Height; + g->g.Height = tmp; + } + break; + case GDISP_ROTATE_90: + case GDISP_ROTATE_270: + if (g->g.Orientation == GDISP_ROTATE_0 || g->g.Orientation == GDISP_ROTATE_180) { + coord_t tmp; + + tmp = g->g.Width; + g->g.Width = g->g.Height; + g->g.Height = tmp; + } + break; + default: + return; + } + g->g.Orientation = (orientation_t)g->p.ptr; + return; + + case GDISP_CONTROL_BACKLIGHT: + if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100; + board_backlight(g, (unsigned)g->p.ptr); + g->g.Backlight = (unsigned)g->p.ptr; + return; + + case GDISP_CONTROL_CONTRAST: + if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100; + board_contrast(g, (unsigned)g->p.ptr); + g->g.Contrast = (unsigned)g->p.ptr; + return; + } + } +#endif + +#endif /* GFX_USE_GDISP */ |