diff --git a/include/libopencm3/stm32/f4/ltdc.h b/include/libopencm3/stm32/f4/ltdc.h new file mode 100644 index 00000000..81da8ec9 --- /dev/null +++ b/include/libopencm3/stm32/f4/ltdc.h @@ -0,0 +1,173 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2014 Oliver Meier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + + +#ifndef LIBOPENCM3_STM32_F4_LTDC_H_ +#define LIBOPENCM3_STM32_F4_LTDC_H_ + + +#include +#include "memorymap.h" + +/** + * LTDC + */ + + +#define LTDC_SSCR (MMIO32(LTDC_BASE + 0x08)) +#define LTDC_BPCR (MMIO32(LTDC_BASE + 0x0C)) +#define LTDC_AWCR (MMIO32(LTDC_BASE + 0x10)) +#define LTDC_TWCR (MMIO32(LTDC_BASE + 0x14)) +#define LTDC_GCR (MMIO32(LTDC_BASE + 0x18)) +#define LTDC_SRCR (MMIO32(LTDC_BASE + 0x24)) +#define LTDC_BCCR (MMIO32(LTDC_BASE + 0x2C)) +#define LTDC_IER (MMIO32(LTDC_BASE + 0x34)) +#define LTDC_ISR (MMIO32(LTDC_BASE + 0x38)) +#define LTDC_ICR (MMIO32(LTDC_BASE + 0x3C)) +#define LTDC_LIPCR (MMIO32(LTDC_BASE + 0x40)) +#define LTDC_CPSR (MMIO32(LTDC_BASE + 0x44)) +#define LTDC_CDSR (MMIO32(LTDC_BASE + 0x48)) +/* x == LTDC_LAYER_x */ +#define LTDC_LxCR(x) (MMIO32(LTDC_BASE + 0x84+0x80*(x-1))) +#define LTDC_LxWHPCR(x) (MMIO32(LTDC_BASE + 0x88+0x80*(x-1))) +#define LTDC_LxWVPCR(x) (MMIO32(LTDC_BASE + 0x8C+0x80*(x-1))) +#define LTDC_LxCKCR(x) (MMIO32(LTDC_BASE + 0x90+0x80*(x-1))) +#define LTDC_LxPFCR(x) (MMIO32(LTDC_BASE + 0x94+0x80*(x-1))) +#define LTDC_LxCACR(x) (MMIO32(LTDC_BASE + 0x98+0x80*(x-1))) +#define LTDC_LxDCCR(x) (MMIO32(LTDC_BASE + 0x9C+0x80*(x-1))) +#define LTDC_LxBFCR(x) (MMIO32(LTDC_BASE + 0xA0+0x80*(x-1))) +#define LTDC_LxCFBAR(x) (MMIO32(LTDC_BASE + 0xAC+0x80*(x-1))) +#define LTDC_LxCFBLR(x) (MMIO32(LTDC_BASE + 0xB0+0x80*(x-1))) +#define LTDC_LxCFBLNR(x) (MMIO32(LTDC_BASE + 0xB4+0x80*(x-1))) +#define LTDC_LxCLUTWR(x) (MMIO32(LTDC_BASE + 0xC4+0x80*(x-1))) + +#define LTDC_LAYER_1 1 +#define LTDC_LAYER_2 2 + + +/* GCR - control register */ +#define LTDC_GCR_LTDC_ENABLE (1<<0) +#define LTDC_GCR_DITHER_ENABLE (1<<16) + +#define LTDC_GCR_PCPOL_ACTIVE_LOW (0<<28) +#define LTDC_GCR_PCPOL_ACTIVE_HIGH (1<<28) + +#define LTDC_GCR_DEPOL_ACTIVE_LOW (0<<29) +#define LTDC_GCR_DEPOL_ACTIVE_HIGH (1<<29) + +#define LTDC_GCR_VSPOL_ACTIVE_LOW (0<<30) +#define LTDC_GCR_VSPOL_ACTIVE_HIGH (1<<30) + +#define LTDC_GCR_HSPOL_ACTIVE_LOW (0<<31) +#define LTDC_GCR_HSPOL_ACTIVE_HIGH (1<<31) + +/* LTDC_BCCR - reload control */ +#define LTDC_SRCR_RELOAD_IMR (1<<0) +#define LTDC_SRCR_RELOAD_VBR (1<<1) + +/* LTDC_CDSR - display status register */ +#define LTDC_CDSR_VDES (1<<0) +#define LTDC_CDSR_HDES (1<<1) +#define LTDC_CDSR_VSYNCS (1<<2) +#define LTDC_CDSR_HSYNCS (1<<3) + +/* LTDC_LxCR - layer control */ +#define LTDC_LxCR_LAYER_ENABLE (1<<0) +#define LTDC_LxCR_COLKEY_ENABLE (1<<1) +#define LTDC_LxCR_COLTAB_ENABLE (1<<4) + +/* LTDC_LxPFCR - Pixel formats */ +#define LTDC_LxPFCR_ARGB8888 (0b000) +#define LTDC_LxPFCR_RGB888 (0b001) +#define LTDC_LxPFCR_RGB565 (0b010) +#define LTDC_LxPFCR_ARGB1555 (0b011) +#define LTDC_LxPFCR_ARGB4444 (0b100) +#define LTDC_LxPFCR_L8 (0b101) +#define LTDC_LxPFCR_AL44 (0b110) +#define LTDC_LxPFCR_AL88 (0b111) + +/* LTDC_LxBFCR - Blending factors - BF1 */ +#define LTDC_LxBFCR_BF1_CONST_ALPHA (0b100) +#define LTDC_LxBFCR_BF1_PIXEL_ALPHA_x_CONST_ALPHA (0b110) +/* LTDC_LxBFCR - Blending factors - BF2 */ +#define LTDC_LxBFCR_BF2_CONST_ALPHA (0b101) +#define LTDC_LxBFCR_BF2_PIXEL_ALPHA_x_CONST_ALPHA (0b111) + +/** + * simple helper macros + */ + +/* global */ +#define ltdc_ctrl_enable(ctrl_flags) \ + LTDC_GCR |= ctrl_flags +#define ltdc_ctrl_disable(ctrl_flags) \ + LTDC_GCR &= ~(ctrl_flags) +#define ltdc_reload(reload_flags) \ + LTDC_SRCR = reload_flags +#define ltdc_set_background_color(r,g,b) \ + LTDC_BCCR = (((r)&255)<<16) | (((g)&255)<<8) | (((b)&255)<<0); +#define ltdc_get_current_position(x,y) \ + { y=LTDC_CPSR; x=y>>16; y&=0xffff; } +#define ltdc_get_current_position_x() \ + (LTDC_CPSR>>16) +#define ltdc_get_current_position_y() \ + (LTDC_CPSR&0xffff) +#define ltdc_get_display_status(status_flags) \ + (LTDC_CDSR&(status_flags)) +/* layers */ +#define ltdc_layer_ctrl_enable(layer,ctrl_flags) \ + LTDC_LxCR(layer) |= ctrl_flags +#define ltdc_layer_ctrl_disable(layer,ctrl_flags) \ + LTDC_LxCR(layer) &= ~(ctrl_flags) +#define ltdc_set_color_key(layer,r,g,b) \ + LTDC_LxCKCR(layer) = ((((r)&255)<<16) | (((g)&255)<<8) | (((b)&255)<<0)) +#define ltdc_set_pixel_format(layer,format) \ + LTDC_LxPFCR(layer) = format +#define ltdc_set_constant_alpha(layer,alpha) \ + LTDC_LxCACR(layer) = ((alpha)&255) +#define ltdc_set_default_colors(layer,a,r,g,b) \ + LTDC_LxDCCR(layer) = \ + ((((a)&255)<<24) | (((r)&255)<<16) | (((g)&255)<<8) | (((b)&255)<<0)) +#define ltdc_set_blending_factors(layer,bf1,bf2) \ + LTDC_LxBFCR(layer) = ((bf1)<<8) | ((bf2)<<0) +#define ltdc_set_fbuffer_address(layer,address) \ + LTDC_LxCFBAR(layer) = (uint32_t)address +#define ltdc_set_fb_line_length(layer,len,pitch) \ + LTDC_LxCFBLR(layer) = ((((pitch)&0x1FFF)<<16) | (((len)&0x1FFF)<<0)) +#define ltdc_set_fb_line_count(layer, linecount) \ + LTDC_LxCFBLNR(layer) = (((linecount)&0x3FF)<<0) + +/** + * more complicated helper functions + */ +void ltdc_set_tft_sync_timings( + uint16_t sync_width, uint16_t sync_height, + uint16_t h_back_porch, uint16_t v_back_porch, + uint16_t active_width, uint16_t active_height, + uint16_t h_front_porch, uint16_t v_front_porch +); +void ltdc_setup_windowing( + uint8_t layer_number, + uint16_t h_back_porch, uint16_t v_back_porch, + uint16_t active_width, uint16_t active_height +); + + + +#endif /* LIBOPENCM3_STM32_F4_LTDC_H_ */ diff --git a/include/libopencm3/stm32/f4/memorymap.h b/include/libopencm3/stm32/f4/memorymap.h index b567dad6..2e2995ec 100644 --- a/include/libopencm3/stm32/f4/memorymap.h +++ b/include/libopencm3/stm32/f4/memorymap.h @@ -96,6 +96,7 @@ #define SPI6_BASE (PERIPH_BASE_APB2 + 0x5400) #define SAI1_BASE (PERIPH_BASE_APB2 + 0x5800) #define LCD_TFT_BASE (PERIPH_BASE_APB2 + 0x6800) +#define LTDC_BASE LCD_TFT_BASE /* PERIPH_BASE_APB2 + 0x6C00 (0x4001 6C00 - 0x4001 FFFF): Reserved */ /* AHB1 */ diff --git a/include/libopencm3/stm32/f4/rcc.h b/include/libopencm3/stm32/f4/rcc.h index 184f2ded..15cca24f 100644 --- a/include/libopencm3/stm32/f4/rcc.h +++ b/include/libopencm3/stm32/f4/rcc.h @@ -81,9 +81,13 @@ /* RCC_BASE + 0x7c Reserved */ #define RCC_SSCGR MMIO32(RCC_BASE + 0x80) #define RCC_PLLI2SCFGR MMIO32(RCC_BASE + 0x84) +#define RCC_PLLSAICFGR MMIO32(RCC_BASE + 0x88) +#define RCC_DCKCFGR MMIO32(RCC_BASE + 0x8C) /* --- RCC_CR values ------------------------------------------------------- */ +#define RCC_CR_PLLSAIRDY (1 << 29) +#define RCC_CR_PLLSAION (1 << 28) #define RCC_CR_PLLI2SRDY (1 << 27) #define RCC_CR_PLLI2SON (1 << 26) #define RCC_CR_PLLRDY (1 << 25) @@ -481,6 +485,22 @@ /* RCC_PLLI2SCFGR[14:6]: PLLI2SN */ #define RCC_PLLI2SCFGR_PLLI2SN_SHIFT 6 +/* --- RCC_DCKCFGR values -------------------------------------------------- */ +#define RCC_DCKCFGR_PLLSAIDIVR_MSK (0x3<<16) +#define RCC_DCKCFGR_PLLSAIDIVR_DIVR_2 (0x0) +#define RCC_DCKCFGR_PLLSAIDIVR_DIVR_4 (0x1) +#define RCC_DCKCFGR_PLLSAIDIVR_DIVR_8 (0x2) +#define RCC_DCKCFGR_PLLSAIDIVR_DIVR_16 (0x3) + +/* PLLSAI1 helper macros */ +#define rcc_pllsai_enable() RCC_CR |= RCC_CR_PLLSAION +#define rcc_pllsai_ready() (RCC_CR & RCC_CR_PLLSAIRDY) +/* pllsain=49..432, pllsaiq=2..15, pllsair=2..7 */ +#define rcc_pllsai_config(pllsain,pllsaiq,pllsair) \ + RCC_PLLSAICFGR = (((pllsain&0x1ff)<<6) | ((pllsaiq&0xF)<<24) | ((pllsair&0x7)<<28)) +#define rcc_ltdc_set_clock_divr(pllsaidivr) \ + RCC_DCKCFGR = (((RCC_DCKCFGR & ~RCC_DCKCFGR_PLLSAIDIVR_MSK)|((pllsaidivr&0x3)<<16))) + /* --- Variable definitions ------------------------------------------------ */ extern uint32_t rcc_ahb_frequency; extern uint32_t rcc_apb1_frequency; @@ -597,6 +617,9 @@ enum rcc_periph_clken { RCC_TIM11 = _REG_BIT(0x44, 18), RCC_SPI5 = _REG_BIT(0x44, 20),/* F2xx, F3xx */ RCC_SPI6 = _REG_BIT(0x44, 21),/* F2xx, F3xx */ + RCC_SAI1EN = _REG_BIT(0x44, 22),/* F42x, F43x */ + RCC_LTDC = _REG_BIT(0x44, 26),/* F42x, F43x */ + /* BDCR */ RCC_RTC = _REG_BIT(0x70, 15), @@ -751,6 +774,8 @@ enum rcc_periph_rst { RST_TIM11 = _REG_BIT(0x24, 18), RST_SPI5 = _REG_BIT(0x24, 20),/* F2xx, F3xx */ RST_SPI6 = _REG_BIT(0x24, 21),/* F2xx, F3xx */ + RST_SAI1RST = _REG_BIT(0x24, 22),/* F42x, F43x */ + RST_LTDC = _REG_BIT(0x24, 26),/* F42x, F43x */ }; #undef _REG_BIT diff --git a/lib/stm32/f4/ltdc.c b/lib/stm32/f4/ltdc.c new file mode 100644 index 00000000..c4fb9efc --- /dev/null +++ b/lib/stm32/f4/ltdc.c @@ -0,0 +1,90 @@ +/** @defgroup ltdc_file LTDC + * + * @ingroup STM32F4xx + * + * @brief libopencm3 STM32F4xx LTDC + * + * @version 1.0.0 + * + * @author @htmlonly © @endhtmlonly 2014 + * Oliver Meier + * + * @date 5 December 2014 + * + * This library supports the LCD controller (LTDC) in the STM32F4 + * series of ARM Cortex Microcontrollers by ST Microelectronics. + * + * For the STM32F4xx, LTDC is described in LCD-TFT Controller (LTDC) + * section 16 of the STM32F4xx Reference Manual (RM0090,Rev8). + * + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2014 Oliver Meier + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + + +#include + + +void ltdc_set_tft_sync_timings( + uint16_t sync_width, uint16_t sync_height, + uint16_t h_back_porch, uint16_t v_back_porch, + uint16_t active_width, uint16_t active_height, + uint16_t h_front_porch, uint16_t v_front_porch +) { + assert((active_width <= 0x400) && (active_height <= 0x300)); + + uint16_t w,h; + w=sync_width -1; + h=sync_height -1; + assert((w&0xfff == w) && (h&0x7ff == h)); + LTDC_SSCR = (w<<16) | (h<<0); + + w+=h_back_porch; + h+=v_back_porch; + assert((w&0xfff == w) && (h&0x7ff == h)); + LTDC_BPCR = (w<<16) | (h<<0); + + w+=active_width; + h+=active_height; + assert((w&0xfff == w) && (h&0x7ff == h)); + LTDC_AWCR = (w<<16) | (h<<0); + + w+=h_front_porch; + h+=v_front_porch; + assert((w&0xfff == w) && (h&0x7ff == h)); + LTDC_TWCR = (w<<16) | (h<<0); +} +void ltdc_setup_windowing( + uint8_t layer_number, + uint16_t h_back_porch, uint16_t v_back_porch, + uint16_t active_width, uint16_t active_height +) { + active_width += h_back_porch-1; + active_height += v_back_porch-1; + assert( + (h_back_porch&0xfff == h_back_porch) && (v_back_porch &0xfff == v_back_porch) && + (active_width&0xfff == active_width) && (active_height&0xfff == active_height) + ); + LTDC_LxWHPCR(layer_number) = (active_width <<16) | (h_back_porch<<0); + LTDC_LxWVPCR(layer_number) = (active_height<<16) | (v_back_porch<<0); +} +