diff --git a/platform/ili9341/ili9341.c b/platform/ili9341/ili9341.c index de73b8d1a..1037eaada 100644 --- a/platform/ili9341/ili9341.c +++ b/platform/ili9341/ili9341.c @@ -17,7 +17,9 @@ enum { DISPON = 0x29, // Display on RAMWR = 0x2C, // Memory write PIXSET = 0x3A, // Pixel format set - FRMCTR1 = 0xB1A // Frame rate control in normal/full-color mode + IFMODE = 0xB0, // RGB interface signal control + FRMCTR1 = 0xB1, // Frame rate control in normal/full-color mode + IFCTL = 0xF6 // Interface control }; typedef struct { @@ -47,6 +49,11 @@ static instruction_t initialisation_sequence[] = { //FIXME // Display + // RGB Interface mode //FIXME: explain + COMMAND(IFMODE), DATA(0xC0), + + COMMAND(IFCTL), DATA(0x01), DATA(0x00), DATA(0x06), + // Entry mode set, skipped COMMAND(SLPOUT), DELAY(100), @@ -66,7 +73,7 @@ void perform_instruction(ili9341_t * c, instruction_t * instruction) { } } -void ili9341_initialize(ili9341_t * c) { +void ili9341_initialize(ili9341_t * c, bool rgb) { // Falling edge on CSX c->chip_select_pin_write(0); @@ -76,7 +83,7 @@ void ili9341_initialize(ili9341_t * c) { perform_instruction(c, instruction++); } -#define FILL_SCREEN_UPON_INIT 0 +#define FILL_SCREEN_UPON_INIT 1 #if FILL_SCREEN_UPON_INIT // This would draw stuff on the screen diff --git a/platform/ili9341/ili9341.h b/platform/ili9341/ili9341.h index 14fb4dc89..ba4e7feab 100644 --- a/platform/ili9341/ili9341.h +++ b/platform/ili9341/ili9341.h @@ -14,6 +14,6 @@ typedef struct { void (*spi_write)(char * data, size_t size); } ili9341_t; -void ili9341_initialize(ili9341_t * controller); +void ili9341_initialize(ili9341_t * controller, bool enable_rgb_interface); void ili9341_set_gamma(ili9341_t * controller); #endif diff --git a/platform/stm32f429/init_lcd.c b/platform/stm32f429/init_lcd.c index 981362121..93ec5f0f8 100644 --- a/platform/stm32f429/init_lcd.c +++ b/platform/stm32f429/init_lcd.c @@ -91,11 +91,16 @@ static void init_spi_port() { static void init_rgb_gpios(); static void init_rgb_clocks(); static void init_rgb_timings(); +//static void init_rgb_layers(); static void init_rgb_interface() { init_rgb_gpios(); init_rgb_clocks(); init_rgb_timings(); +// init_rgb_layers(); + + // Now let's actually enable the LTDC + LTDC_GCR |= LTDC_LTDCEN; } struct gpio_pin { @@ -229,10 +234,17 @@ static void init_rgb_timings() { LTDC_GCR = LTDC_LTDCEN; // Not setting the "Active low" bits since they are 0 by default, which we want // Same for the pixel clock, we don't want it inverted + + + + /* } static void init_rgb_layers() { -#if 0 +*/ + + + /* STEP 7: Configure the Layer1/2 parameters by programming: – The Layer window horizontal and vertical position in the LTDC_LxWHPCR and LTDC_WVPCR registers. The layer window must be in the active data area. – The pixel input format in the LTDC_LxPFCR register @@ -243,52 +255,34 @@ static void init_rgb_layers() { – If needed, configure the default color and the blending factors respectively in the LTDC_LxDCCR and LTDC_LxBFCR registers */ - long * LTDC_L1WHPCR = (long *)(LCD_TFT_BASE + 0x88); // Window horizontal position config - *LTDC_L1WHPCR = set_bits(*LTDC_L1WHPCR, 11, 0, lcd_panel_hsync+lcd_panel_hbp); - *LTDC_L1WHPCR = set_bits(*LTDC_L1WHPCR, 27, 16, lcd_panel_hsync+lcd_panel_hbp+lcd_panel_hadr); + LTDC_LWHPCR(LTDC_LAYER1) = + LTDC_WHSTPOS(lcd_panel_hsync+lcd_panel_hbp) | + LTDC_WHSPPOS(lcd_panel_hsync+lcd_panel_hbp+lcd_panel_hadr); - long * LTDC_L1WVPCR = (long *)(LCD_TFT_BASE + 0x8C); // Window vertical position config - *LTDC_L1WVPCR = set_bits(*LTDC_L1WVPCR, 11, 0, lcd_panel_vsync+lcd_panel_vbp); - *LTDC_L1WVPCR = set_bits(*LTDC_L1WVPCR, 27, 16, lcd_panel_vsync+lcd_panel_vbp+lcd_panel_vadr); + LTDC_LWVPCR(LTDC_LAYER1) = + LTDC_WVSTPOS(lcd_panel_vsync+lcd_panel_vbp) | + LTDC_WVSPPOS(lcd_panel_vsync+lcd_panel_vbp+lcd_panel_vadr); - long * LTDC_L1PFCR = (long *)(LCD_TFT_BASE + 0x94); // Frame buffer pixel format - *LTDC_L1PFCR = set_bits(*LTDC_L1PFCR, 2, 0, 0x0); // 0x0 = ARGB8888 + LTDC_LPFCR(LTDC_LAYER1) = LTDC_PF_ARGB8888; - long * LTDC_L1CFBAR = (long *)(LCD_TFT_BASE + 0xAC); // Frame buffer address - *LTDC_L1CFBAR = 0x2000000; +// long * LTDC_L1CFBAR = (long *)(LCD_TFT_BASE + 0xAC); // Frame buffer address +// *LTDC_L1CFBAR = 0x2000000; - long * LTDC_L1CFBLR = (long *)(LCD_TFT_BASE + 0xB0); // Frame buffer length - *LTDC_L1CFBLR = set_bits(*LTDC_L1CFBLR, 28, 16, 960); // Number of bytes per lines in the framebuffer. 240 * 4 (RGBA888) - *LTDC_L1CFBLR = set_bits(*LTDC_L1CFBLR, 12, 0, 963); // The doc says "length + 3". Here goes... + LTDC_LCFBLR(LTDC_LAYER1) = + LTDC_CFBLL(963) | // Number of bytes per lines in the framebuffer. 240 * 4 (RGBA888) + LTDC_CFBP(960); // The doc says "length + 3". Here goes... - long * LTDC_L1CFBLNR = (long *)(LCD_TFT_BASE + 0xB4); - *LTDC_L1CFBLNR = set_bits(*LTDC_L1CFBLNR, 10, 0, 320); // Number of lines - - /* - long * LTDC_L2WHPCR = (long *)(LCD_TFT_BASE + 0x108); - *LTDC_L2WHPCR = set_bits(*LTDC_L2WHPCR, 11, 0, lcd_panel_hsync+lcd_panel_hbp); - *LTDC_L2WHPCR = set_bits(*LTDC_L2WHPCR, 27, 16, lcd_panel_hsync+lcd_panel_hbp+lcd_panel_hadr); - long * LTDC_L2WWPCR = (long *)(LCD_TFT_BASE + 0x10C); - *LTDC_L2WVPCR = set_bits(*LTDC_L2WVPCR, 11, 0, lcd_panel_vsync+lcd_panel_vbp); - *LTDC_L2WVPCR = set_bits(*LTDC_L2WVPCR, 27, 16, lcd_panel_vsync+lcd_panel_vbp+lcd_panel_vadr); - long * LTDC_L2PFCR = (long *)(LCD_TFT_BASE + 0x114); - long * LTDC_L2CFBAR = (long *)(LCD_TFT_BASE + 0x12C); - long * LTDC_L2CFBLNR = (long *)(LCD_TFT_BASE + 0x134); - long * LTDC_L2CR = (long *)(LCD_TFT_BASE + 0x104); - */ + LTDC_LCFBLNR(LTDC_LAYER1) = LTDC_CFBLNR(320); // Number of lines // STEP 8 : Enable layer 1 - long * LTDC_L1CR = (long *)(LCD_TFT_BASE + 0x84); - *LTDC_L1CR = set_bits(*LTDC_L1CR, 4, 4, 0x0); // bit 4 = CLUTEN: Disable color look-up table - *LTDC_L1CR = set_bits(*LTDC_L1CR, 1, 1, 0x0); // bit 1 = COLKEN: Color keying, disabledd - *LTDC_L1CR = set_bits(*LTDC_L1CR, 0, 0, 0x1); // bit 1 = LEN, LayerENable: Enable + // Don't enable color keying nor color look-up table + LTDC_LCR(LTDC_LAYER1) = LTDC_LEN; // STEP 9 : If needed, enable color keing and dithering // STEP 10: Reload the shadow register - long * LTDC_SRCR = (long *)(LCD_TFT_BASE + 0x24); - *LTDC_SRCR = set_bits(*LTDC_SRCR, 1, 1, 0x1); // Ask for reload on next VBLANK -#endif + // Ask for immediate reload + LTDC_SRCR = LTDC_IMR; } // Panel @@ -304,7 +298,7 @@ static ili9341_t panel = { }; static void init_panel() { - ili9341_initialize(&panel); + ili9341_initialize(&panel, 1); } static void spi_5_write(char * data, size_t size) { diff --git a/platform/stm32f429/registers/ltdc.h b/platform/stm32f429/registers/ltdc.h index a51bc796f..c41b40548 100644 --- a/platform/stm32f429/registers/ltdc.h +++ b/platform/stm32f429/registers/ltdc.h @@ -5,7 +5,11 @@ #define LTDC_BASE 0x40016800 +#define LTDC_LAYER1 0 +#define LTDC_LAYER2 1 + #define LTDC_REGISTER_AT(offset) (*(volatile uint32_t *)(LTDC_BASE+offset)) +#define LTDC_LAYER_REGISTER_AT(layer, offset) LTDC_REGISTER_AT(offset+(0x80*layer)) // LTDC synchronization size configuration register @@ -13,10 +17,10 @@ #define LOW_BIT_VSH 0 #define HIGH_BIT_VSH 10 -#define LTDC_VSH(v) REGISTER_FIELD_VALUE(VSH, v) +#define LTDC_VSH(v) REGISTER_FIELD_VALUE(VSH,v) #define LOW_BIT_HSW 16 #define HIGH_BIT_HSW 27 -#define LTDC_HSW(v) REGISTER_FIELD_VALUE(HSW, v) +#define LTDC_HSW(v) REGISTER_FIELD_VALUE(HSW,v) // LTDC back porch configuration register @@ -24,10 +28,10 @@ #define LOW_BIT_AVBP 0 #define HIGH_BIT_AVBP 10 -#define LTDC_AVBP(v) REGISTER_FIELD_VALUE(AVBP, v) +#define LTDC_AVBP(v) REGISTER_FIELD_VALUE(AVBP,v) #define LOW_BIT_AHBP 16 #define HIGH_BIT_AHBP 27 -#define LTDC_AHBP(v) REGISTER_FIELD_VALUE(AHBP, v) +#define LTDC_AHBP(v) REGISTER_FIELD_VALUE(AHBP,v) // LTDC active width configuration register @@ -35,10 +39,10 @@ #define LOW_BIT_AAH 0 #define HIGH_BIT_AAH 10 -#define LTDC_AAH(v) REGISTER_FIELD_VALUE(AAH, v) +#define LTDC_AAH(v) REGISTER_FIELD_VALUE(AAH,v) #define LOW_BIT_AAW 16 #define HIGH_BIT_AAW 27 -#define LTDC_AAW(v) REGISTER_FIELD_VALUE(AAW, v) +#define LTDC_AAW(v) REGISTER_FIELD_VALUE(AAW,v) // LTDC total width configuration register @@ -46,10 +50,10 @@ #define LOW_BIT_TOTALH 0 #define HIGH_BIT_TOTALH 10 -#define LTDC_TOTALH(v) REGISTER_FIELD_VALUE(TOTALH, v) +#define LTDC_TOTALH(v) REGISTER_FIELD_VALUE(TOTALH,v) #define LOW_BIT_TOTALW 16 #define HIGH_BIT_TOTALW 27 -#define LTDC_TOTALW(v) REGISTER_FIELD_VALUE(TOTALW, v) +#define LTDC_TOTALW(v) REGISTER_FIELD_VALUE(TOTALW,v) // LTDC global control register @@ -75,17 +79,76 @@ #define LTDC_IMR (1<<0) #define LTDC_VBR (1<<1) -// LTDC layer control register -#define LTDC_LAYER1 0 -#define LTDC_LAYER2 1 +// LTDC layer control registers -#define LTDC_LCR(layer) LTDC_REGISTER_AT(0x84+(0x80*layer)) +#define LTDC_LCR(layer) LTDC_LAYER_REGISTER_AT(layer,0x84) #define LTDC_LEN (1<<0) #define LTDC_COLKEN (1<<1) #define LTDC_CLUTEN (1<<4) +// LTDC layer window horizontal position configuration registers + +#define LTDC_LWHPCR(layer) LTDC_LAYER_REGISTER_AT(layer,0x88) + +#define LOW_BIT_LTDC_WHSTPOS 0 +#define HIGH_BIT_LTDC_WHSTPOS 11 +#define LTDC_WHSTPOS(v) REGISTER_FIELD_VALUE(LTDC_WHSTPOS,v) +#define LOW_BIT_LTDC_WHSPPOS 16 +#define HIGH_BIT_LTDC_WHSPPOS 27 +#define LTDC_WHSPPOS(v) REGISTER_FIELD_VALUE(LTDC_WHSPPOS,v) + +// LTDC layer window vertical position configuration registers + +#define LTDC_LWVPCR(layer) LTDC_LAYER_REGISTER_AT(layer,0x8C) + +#define LOW_BIT_LTDC_WVSTPOS 0 +#define HIGH_BIT_LTDC_WVSTPOS 11 +#define LTDC_WVSTPOS(v) REGISTER_FIELD_VALUE(LTDC_WVSTPOS,v) +#define LOW_BIT_LTDC_WVSPPOS 16 +#define HIGH_BIT_LTDC_WVSPPOS 27 +#define LTDC_WVSPPOS(v) REGISTER_FIELD_VALUE(LTDC_WVSPPOS,v) + +// LTDC layer pixel format configuration registers + +#define LTDC_LPFCR(layer) LTDC_LAYER_REGISTER_AT(layer,0x88) + +#define LTDC_PF_ARGB8888 0 +#define LTDC_PF_RGB888 1 +#define LTDC_PF_RGB565 2 +#define LTDC_PF_ARGB1555 3 +#define LTDC_PF_ARGB4444 4 +#define LTDC_PF_L8 5 +#define LTDC_PF_AL44 6 +#define LTDC_PF_AL88 7 + +#define LOW_BIT_LTDC_PF 0 +#define HIGH_BIT_LTDC_PF 2 + +// LTDC layer color frame buffer address registers + +#define LTDC_LCFBAR(layer) LTDC_LAYER_REGISTER_AT(layer,0xAC) + +// LTDC layer color frame buffer length registers + +#define LTDC_LCFBLR(layer) LTDC_LAYER_REGISTER_AT(layer,0xB0) + +#define LOW_BIT_LTDC_CFBLL 0 +#define HIGH_BIT_LTDC_CFBLL 12 +#define LTDC_CFBLL(v) REGISTER_FIELD_VALUE(LTDC_CFBLL,v) +#define LOW_BIT_LTDC_CFBP 16 +#define HIGH_BIT_LTDC_CFBP 28 +#define LTDC_CFBP(v) REGISTER_FIELD_VALUE(LTDC_CFBP,v) + +// LTDC layer color frame buffer line registers + +#define LTDC_LCFBLNR(layer) LTDC_LAYER_REGISTER_AT(layer,0xB4) + +#define LOW_BIT_LTDC_CFBLNR 0 +#define HIGH_BIT_LTDC_CFBLNR 10 +#define LTDC_CFBLNR(v) REGISTER_FIELD_VALUE(LTDC_CFBLNR,v) + #if 0 typedef struct {