From e2ec8539a88412bb2f402efe92c1b309e44532a8 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Mon, 18 May 2015 16:43:52 +0200 Subject: [PATCH] Cleaner registers for stm32f429 --- kandinsky/Makefile | 2 ++ kandinsky/include/kandinsky.h | 7 ++++ kandinsky/include/kandinsky/line.h | 8 +++++ kandinsky/include/kandinsky/point.h | 11 ++++++ kandinsky/src/framebuffer.h | 7 ++++ kandinsky/src/line.c | 8 +++++ platform/stm32f429/init_lcd.c | 52 ++++++++++++++++++----------- platform/stm32f429/registers/ltdc.h | 24 +++++++------ platform/stm32f429/registers/rcc.h | 5 +++ 9 files changed, 94 insertions(+), 30 deletions(-) create mode 100644 kandinsky/Makefile create mode 100644 kandinsky/include/kandinsky.h create mode 100644 kandinsky/include/kandinsky/line.h create mode 100644 kandinsky/include/kandinsky/point.h create mode 100644 kandinsky/src/framebuffer.h create mode 100644 kandinsky/src/line.c diff --git a/kandinsky/Makefile b/kandinsky/Makefile new file mode 100644 index 000000000..c480a32d3 --- /dev/null +++ b/kandinsky/Makefile @@ -0,0 +1,2 @@ +CFLAGS += -Ikandinsky/include +objs += $(addprefix kandinsky/src/, line.o) diff --git a/kandinsky/include/kandinsky.h b/kandinsky/include/kandinsky.h new file mode 100644 index 000000000..b7ca2876a --- /dev/null +++ b/kandinsky/include/kandinsky.h @@ -0,0 +1,7 @@ +#ifndef KANDINSKY_KANDINSKY_H +#define KANDINSKY_KANDINSKY_H + +#include +#include + +#endif diff --git a/kandinsky/include/kandinsky/line.h b/kandinsky/include/kandinsky/line.h new file mode 100644 index 000000000..034219c43 --- /dev/null +++ b/kandinsky/include/kandinsky/line.h @@ -0,0 +1,8 @@ +#ifndef KANDINSKY_LINE_H +#define KANDINSKY_LINE_H + +#include + +void KDDrawLine(kdpoint_t * p1, kdpoint_t * p2); + +#endif diff --git a/kandinsky/include/kandinsky/point.h b/kandinsky/include/kandinsky/point.h new file mode 100644 index 000000000..98b8f4a89 --- /dev/null +++ b/kandinsky/include/kandinsky/point.h @@ -0,0 +1,11 @@ +#ifndef KANDINSKY_POINT_H +#define KANDINSKY_POINT_H + +#include + +typedef struct { + uint16_t x; + uint16_t y; +} kdpoint_t; + +#endif diff --git a/kandinsky/src/framebuffer.h b/kandinsky/src/framebuffer.h new file mode 100644 index 000000000..6e5d8b924 --- /dev/null +++ b/kandinsky/src/framebuffer.h @@ -0,0 +1,7 @@ +typedef uint8_t kdpixel_t; + +#define FRAMEBUFFER_WIDTH 240 +#define FRAMEBUFFER_HEIGHT 320 +#define FRAMEBUFFER_ADDRESS (kdpixel_t *)(0x2001D400) + +#define PIXEL(x,y) *(kdpixel_t *)(FRAMEBUFFER_ADDRESS + y*FRAMEBUFFER_WIDTH + x) diff --git a/kandinsky/src/line.c b/kandinsky/src/line.c new file mode 100644 index 000000000..f6597f330 --- /dev/null +++ b/kandinsky/src/line.c @@ -0,0 +1,8 @@ +#include +#include "framebuffer.h" + +void KDDrawLine(kdpoint_t * p1, kdpoint_t * p2) { + for (int i=0; i<10; i++) { + PIXEL(i,i) = 0xFF; + } +} diff --git a/platform/stm32f429/init_lcd.c b/platform/stm32f429/init_lcd.c index 886ded651..25ae7195d 100644 --- a/platform/stm32f429/init_lcd.c +++ b/platform/stm32f429/init_lcd.c @@ -99,8 +99,6 @@ static void init_rgb_interface() { init_rgb_timings(); // init_rgb_layers(); - // Now let's actually enable the LTDC - LTDC_GCR |= LTDC_LTDCEN; } struct gpio_pin { @@ -157,20 +155,29 @@ static void init_rgb_clocks() { // STEP 2 : Configure the required Pixel clock following the panel datasheet // - // We're setting PLLSAIN = 192, PLLSAIR = 4, and PLLSAIDIVR = 0x2 meaning divide-by-8 - // So with a f(PLLSAI clock input) = 1MHz - // we get f(VCO clock) = PLLSAIN * fPPLSAI = 192 MHz - // and f(PLL LCD clock) = fVCO / PLLSAIR = 48 MHz - // and eventually f(LCD_CLK) = fPLLLCD/8 = 6 MHz + // The pixel clock derives from the PLLSAI clock through various multipliers/dividers. + // Here is the exact sequence : + // PXL = PLL_LCD/RCC_DCKCFGR.PLLSAIDIVR; + // PLL_LCD = VCO/RCC_PLLSAICFGR.PLLSAIR; + // VCO = PLLSAI * (RCC_PLLSAICFG.PLLSAIN / RCC_PLLCFGR.PLLM); + // PLLSAI = HSE or HSI + // + // The multipliers have the following constraints : + // 2 <= PLLM <= 63 + // 49 <= PLLSAIN <= 432 + // 2 <= PLLSAIR <= 7 + // 2 ≤ PLLSAIDIVR ≤ 16, (set as a power of two, use macro) + // + // By default, PLLSAI = HSI = 16MHz and RCC_PLLCFGR.PLLM = 16. This gives, in MHZ: + // PXL = SAIN/(SAIR*SAIDIVR); + // + // // FIXME: Maybe make this calculation dynamic? + // Per the panel doc, we want a clock of 6 MHz. + // 6 = 192/(4*8), hence: - int pllsain = 192; - int pllsair = 4; - int pllsaidivr = 0x2; // This value means "divide by 8" - //FIXME: A macro here - - REGISTER_SET_VALUE(RCC_PLLSAICFGR, PLLSAIR, pllsair); - REGISTER_SET_VALUE(RCC_PLLSAICFGR, PLLSAIN, pllsain); - REGISTER_SET_VALUE(RCC_DCKCFGR, PLLSAIDIVR, pllsaidivr); + REGISTER_SET_VALUE(RCC_PLLSAICFGR, PLLSAIN, 192); + REGISTER_SET_VALUE(RCC_PLLSAICFGR, PLLSAIR, 4); + REGISTER_SET_VALUE(RCC_DCKCFGR, PLLSAIDIVR, RCC_PLLSAIDIVR_DIV8); // Now let's enable the PLL/PLLSAI clocks RCC_CR |= (PLLSAION | PLLON); @@ -204,6 +211,7 @@ static void init_rgb_timings() { /*- HSYNC and VSYNC Width: Horizontal and Vertical Synchronization width configured by programming a value of HSYNC Width - 1 and VSYNC Width - 1 in the LTDC_SSCR register. */ + LTDC_SSCR = LTDC_VSH(lcd_panel_vsync-1) | LTDC_HSW(lcd_panel_hsync-1); @@ -238,10 +246,13 @@ static void init_rgb_timings() { /* STEP 4 : Configure the synchronous signals and clock polarity in the LTDC_GCR register */ - LTDC_GCR = LTDC_LTDCEN; + LTDC_GCR |= LTDC_PCPOL; + + // FIXME: Later: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 + LTDC_BCCR = 0x00FF00FF; /* @@ -264,15 +275,15 @@ static void init_rgb_layers() { LTDC_LWHPCR(LTDC_LAYER1) = LTDC_WHSTPOS(lcd_panel_hsync+lcd_panel_hbp) | - LTDC_WHSPPOS(lcd_panel_hsync+lcd_panel_hbp+lcd_panel_hadr); + LTDC_WHSPPOS(lcd_panel_hsync+lcd_panel_hbp+lcd_panel_hadr-1); //FIXME: Why -1? LTDC_LWVPCR(LTDC_LAYER1) = LTDC_WVSTPOS(lcd_panel_vsync+lcd_panel_vbp) | - LTDC_WVSPPOS(lcd_panel_vsync+lcd_panel_vbp+lcd_panel_vadr); + LTDC_WVSPPOS(lcd_panel_vsync+lcd_panel_vbp+lcd_panel_vadr-1); LTDC_LPFCR(LTDC_LAYER1) = LTDC_PF_L8; - LTDC_LCFBAR(LTDC_LAYER1) = (uint32_t)&_framebuffer_start; + LTDC_LCFBAR(LTDC_LAYER1) = (uint32_t)(&_framebuffer_start); LTDC_LCFBLR(LTDC_LAYER1) = LTDC_CFBLL(243) | // Number of bytes per lines in the framebuffer. 240 * 4 (RGBA888). +3, per doc; @@ -289,6 +300,9 @@ static void init_rgb_layers() { // STEP 10: Reload the shadow register // Ask for immediate reload LTDC_SRCR = LTDC_IMR; + + // Now let's actually enable the LTDC + LTDC_GCR |= LTDC_LTDCEN; } // Panel diff --git a/platform/stm32f429/registers/ltdc.h b/platform/stm32f429/registers/ltdc.h index c41b40548..d49ed3af8 100644 --- a/platform/stm32f429/registers/ltdc.h +++ b/platform/stm32f429/registers/ltdc.h @@ -68,6 +68,8 @@ #define HIGH_BIT_DRW 14 #define LTDC_DEN (1<<16) #define LTDC_PCPOL (1<<28) +// When PCPOL=0, data is on the rising-edge +// When PCPOL=1, data is on the falling-edge #define LTDC_DEPOL (1<<29) #define LTDC_VSPOL (1<<30) #define LTDC_HSPOL (1<<31) @@ -79,6 +81,16 @@ #define LTDC_IMR (1<<0) #define LTDC_VBR (1<<1) +// LTDC background color configuration register + +#define LTDC_BCCR LTDC_REGISTER_AT(0x2C) + +#define LOW_BIT_BCBLUE 0 +#define HIGH_BIT_BCBLUE 7 +#define LOW_BIT_BCGREEN 8 +#define HIGH_BIT_BCGREEN 15 +#define LOW_BIT_BCRED 16 +#define HIGH_BIT_BCRED 23 // LTDC layer control registers @@ -112,7 +124,7 @@ // LTDC layer pixel format configuration registers -#define LTDC_LPFCR(layer) LTDC_LAYER_REGISTER_AT(layer,0x88) +#define LTDC_LPFCR(layer) LTDC_LAYER_REGISTER_AT(layer,0x94) #define LTDC_PF_ARGB8888 0 #define LTDC_PF_RGB888 1 @@ -150,16 +162,6 @@ #define LTDC_CFBLNR(v) REGISTER_FIELD_VALUE(LTDC_CFBLNR,v) #if 0 - -typedef struct { - unsigned int BCBLUE:8; - unsigned int BCGREEN:8; - unsigned int BCRED:8; - unsigned int :8; -} LTDC_BCCR_t; - -extern LTDC_BCCR_t * LTDC_BCCR; - typedef struct { unsigned int LIE:1; unsigned int FUIE:1; diff --git a/platform/stm32f429/registers/rcc.h b/platform/stm32f429/registers/rcc.h index 231656645..f1219e9d1 100644 --- a/platform/stm32f429/registers/rcc.h +++ b/platform/stm32f429/registers/rcc.h @@ -97,6 +97,11 @@ #define RCC_DCKCFGR RCC_REGISTER_AT(0x8C) +#define RCC_PLLSAIDIVR_DIV2 0 +#define RCC_PLLSAIDIVR_DIV4 1 +#define RCC_PLLSAIDIVR_DIV8 2 +#define RCC_PLLSAIDIVR_DIV16 3 + #define LOW_BIT_PLLIS2DIVQ 0 #define HIGH_BIT_PLLIS2DIVQ 4 #define LOW_BIT_PLLSAIDIVQ 8