Skip to content

Commit 0e7cc0c

Browse files
committed
LCD demo for STM32F7 Discovery board
1 parent ce35f6a commit 0e7cc0c

File tree

7 files changed

+9962
-0
lines changed

7 files changed

+9962
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#
2+
# This file is part of the libopencm3 project.
3+
#
4+
# This library is free software: you can redistribute it and/or modify
5+
# it under the terms of the GNU Lesser General Public License as published by
6+
# the Free Software Foundation, either version 3 of the License, or
7+
# (at your option) any later version.
8+
#
9+
# This library is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU Lesser General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU Lesser General Public License
15+
# along with this library. If not, see <http://www.gnu.org/licenses/>.
16+
#
17+
18+
OBJS = clock.o \
19+
RGB_565_480_272.o \
20+
21+
BINARY = lcd_demo
22+
23+
LDSCRIPT = ../stm32f7-discovery.ld
24+
25+
include ../../Makefile.include
26+

examples/stm32/f7/stm32f7-discovery/lcd-demo/RGB_565_480_272.c

Lines changed: 9648 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
extern const struct {
3+
unsigned int width;
4+
unsigned int height;
5+
unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
6+
unsigned char pixel_data[480 * 272 * 2 + 1];
7+
} RGB_565_480_272;
8+
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* This file is part of the libopencm3 project.
3+
*
4+
* Copyright (C) 2013 Chuck McManis <[email protected]>
5+
* Copyright (C) 2016 Maxime Vincent <[email protected]>
6+
*
7+
* This library is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Lesser General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public License
18+
* along with this library. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
/*
22+
* Now this is just the clock setup code from systick-blink as it is the
23+
* transferrable part.
24+
*/
25+
26+
#include <libopencm3/stm32/rcc.h>
27+
#include <libopencm3/stm32/gpio.h>
28+
#include <libopencm3/cm3/nvic.h>
29+
#include <libopencm3/cm3/systick.h>
30+
31+
/* Common function descriptions */
32+
#include "clock.h"
33+
34+
/* milliseconds since boot */
35+
static volatile uint32_t system_millis;
36+
37+
/* Called when systick fires */
38+
void sys_tick_handler(void)
39+
{
40+
system_millis++;
41+
}
42+
43+
/* simple sleep for delay milliseconds */
44+
void msleep(uint32_t delay)
45+
{
46+
uint32_t wake = system_millis + delay;
47+
while (wake > system_millis);
48+
}
49+
50+
/* Getter function for the current time */
51+
uint32_t mtime(void)
52+
{
53+
return system_millis;
54+
}
55+
56+
/*
57+
* clock_setup(void)
58+
*
59+
* This function sets up both the base board clock rate
60+
* and a 1khz "system tick" count. The SYSTICK counter is
61+
* a standard feature of the Cortex-M series.
62+
*/
63+
void clock_setup(void)
64+
{
65+
/* Base board frequency, set to 216MHz */
66+
rcc_clock_setup_hse_3v3(&hse_25mhz_3v3[CLOCK_3V3_216MHZ]);
67+
68+
/* clock rate / 216000 to get 1mS interrupt rate */
69+
systick_set_reload(216000);
70+
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
71+
systick_counter_enable();
72+
73+
/* this done last */
74+
systick_interrupt_enable();
75+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* This include file describes the functions exported by clock.c
3+
*/
4+
#ifndef __CLOCK_H
5+
#define __CLOCK_H
6+
7+
/*
8+
* Definitions for functions being abstracted out
9+
*/
10+
void msleep(uint32_t);
11+
uint32_t mtime(void);
12+
void clock_setup(void);
13+
14+
#endif /* generic header protector */
15+
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/* Includes ------------------------------------------------------------------*/
2+
#include <libopencm3/stm32/rcc.h>
3+
#include <libopencm3/stm32/gpio.h>
4+
#include <libopencm3/stm32/ltdc.h>
5+
#include "RGB_565_480_272.h"
6+
#include "rk043fn48h.h"
7+
8+
/* Private function prototypes -----------------------------------------------*/
9+
static void lcd_config(void);
10+
static void lcd_pinmux(void);
11+
static void lcd_clock(void);
12+
static void lcd_config_layer(void);
13+
14+
/* Private functions ---------------------------------------------------------*/
15+
16+
void lcd_pinmux(void)
17+
{
18+
/* Enable the LTDC Clock */
19+
rcc_periph_clock_enable(RCC_LTDC);
20+
21+
/* Enable GPIOs clock */
22+
rcc_periph_clock_enable(RCC_GPIOE);
23+
rcc_periph_clock_enable(RCC_GPIOG);
24+
rcc_periph_clock_enable(RCC_GPIOI);
25+
rcc_periph_clock_enable(RCC_GPIOJ);
26+
rcc_periph_clock_enable(RCC_GPIOK);
27+
28+
/*** LTDC Pins configuration ***/
29+
gpio_mode_setup(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO4);
30+
gpio_set_output_options(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO4);
31+
gpio_set_af(GPIOE, GPIO_AF14, GPIO4);
32+
33+
/* GPIOG configuration */
34+
gpio_mode_setup(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO12);
35+
gpio_set_output_options(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO12);
36+
gpio_set_af(GPIOG, GPIO_AF9, GPIO12);
37+
38+
/* GPIOI LTDC alternate configuration */
39+
gpio_mode_setup(GPIOI, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO8 | GPIO9 | GPIO10 | GPIO14 | GPIO15);
40+
gpio_set_output_options(GPIOI, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO8 | GPIO9 | GPIO10 | GPIO14 | GPIO15);
41+
gpio_set_af(GPIOI, GPIO_AF14, GPIO8 | GPIO9 | GPIO10 | GPIO14 | GPIO15);
42+
43+
/* GPIOJ configuration */
44+
gpio_mode_setup(GPIOJ, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 |
45+
GPIO5 | GPIO6 | GPIO7 | GPIO8 | GPIO9 |
46+
GPIO10 | GPIO11 | GPIO13 | GPIO14 | GPIO15);
47+
gpio_set_output_options(GPIOJ, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 |
48+
GPIO5 | GPIO6 | GPIO7 | GPIO8 | GPIO9 |
49+
GPIO10 | GPIO11 | GPIO13 | GPIO14 | GPIO15);
50+
gpio_set_af(GPIOJ, GPIO_AF14, GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 |
51+
GPIO5 | GPIO6 | GPIO7 | GPIO8 | GPIO9 |
52+
GPIO10 | GPIO11 | GPIO13 | GPIO14 | GPIO15);
53+
54+
/* GPIOK configuration */
55+
gpio_mode_setup(GPIOK, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO0 | GPIO1 | GPIO2 | GPIO4 | GPIO5 | GPIO6 | GPIO7);
56+
gpio_set_output_options(GPIOK, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO0 | GPIO1 | GPIO2 | GPIO4 | GPIO5 | GPIO6 | GPIO7);
57+
gpio_set_af(GPIOK, GPIO_AF14, GPIO0 | GPIO1 | GPIO2 | GPIO4 | GPIO5 | GPIO6 | GPIO7);
58+
59+
/* LCD_DISP GPIO configuration */
60+
gpio_mode_setup(GPIOI, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO12);
61+
gpio_set_output_options(GPIOI, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO12);
62+
63+
/* LCD_BL_CTRL GPIO configuration */
64+
gpio_mode_setup(GPIOK, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO3);
65+
gpio_set_output_options(GPIOK, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO3);
66+
67+
/* Assert display enable LCD_DISP pin */
68+
gpio_set(GPIOI, GPIO12);
69+
70+
/* Assert backlight LCD_BL_CTRL pin */
71+
gpio_set(GPIOK, GPIO3);
72+
}
73+
74+
static void lcd_config_layer(void)
75+
{
76+
/* Windowing configuration */
77+
ltdc_setup_windowing(LTDC_LAYER_2, 480, 272);
78+
79+
/* Specifies the pixel format */
80+
ltdc_set_pixel_format(LTDC_LAYER_2, LTDC_LxPFCR_RGB565);
81+
82+
/* Default color values */
83+
ltdc_set_default_colors(LTDC_LAYER_2, 0, 0, 0, 0);
84+
/* Constant alpha */
85+
ltdc_set_constant_alpha(LTDC_LAYER_2, 255);
86+
87+
/* Blending factors */
88+
ltdc_set_blending_factors(LTDC_LAYER_2, LTDC_LxBFCR_BF1_CONST_ALPHA, LTDC_LxBFCR_BF2_CONST_ALPHA);
89+
90+
/* Framebuffer address */
91+
ltdc_set_fbuffer_address(LTDC_LAYER_2, (uint32_t)&RGB_565_480_272.pixel_data);
92+
93+
/* Configures the color frame buffer pitch in byte */
94+
ltdc_set_fb_line_length(LTDC_LAYER_2, 2*480, 2*480); /* RGB565 is 2 bytes/pixel */
95+
96+
/* Configures the frame buffer line number */
97+
ltdc_set_fb_line_count(LTDC_LAYER_2, 272);
98+
99+
/* Enable layer 1 */
100+
ltdc_layer_ctrl_enable(LTDC_LAYER_2, LTDC_LxCR_LAYER_ENABLE);
101+
102+
/* Sets the Reload type */
103+
ltdc_reload(LTDC_SRCR_IMR);
104+
}
105+
106+
/**
107+
* @brief LCD Configuration.
108+
* @note This function Configure tha LTDC peripheral :
109+
* 1) Configure the Pixel Clock for the LCD
110+
* 2) Configure the LTDC Timing and Polarity
111+
* 3) Configure the LTDC Layer 1 :
112+
* - The frame buffer is located at FLASH memory
113+
* - The Layer size configuration : 480x272
114+
* @retval
115+
* None
116+
*/
117+
static void lcd_config(void)
118+
{
119+
/* LTDC Initialization */
120+
ltdc_ctrl_disable(LTDC_GCR_HSPOL_ACTIVE_HIGH); /* Active Low Horizontal Sync */
121+
ltdc_ctrl_disable(LTDC_GCR_VSPOL_ACTIVE_HIGH); /* Active Low Vertical Sync */
122+
ltdc_ctrl_disable(LTDC_GCR_DEPOL_ACTIVE_HIGH); /* Active Low Date Enable */
123+
ltdc_ctrl_disable(LTDC_GCR_PCPOL_ACTIVE_HIGH); /* Active Low Pixel Clock */
124+
125+
/* Configure the LTDC */
126+
ltdc_set_tft_sync_timings(RK043FN48H_HSYNC, RK043FN48H_VSYNC,
127+
RK043FN48H_HBP, RK043FN48H_VBP,
128+
RK043FN48H_WIDTH, RK043FN48H_HEIGHT,
129+
RK043FN48H_HFP, RK043FN48H_VFP);
130+
131+
ltdc_set_background_color(0, 0, 0);
132+
ltdc_ctrl_enable(LTDC_GCR_LTDC_ENABLE);
133+
134+
/* Configure the Layer*/
135+
lcd_config_layer();
136+
137+
}
138+
139+
140+
static void lcd_clock(void)
141+
{
142+
/* LCD clock configuration */
143+
/* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
144+
/* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */
145+
/* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 Mhz */
146+
/* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_4 = 38.4/4 = 9.6Mhz */
147+
148+
/* Disable PLLSAI */
149+
RCC_CR &= ~RCC_CR_PLLSAION;
150+
while((RCC_CR & (RCC_CR_PLLSAIRDY))) {};
151+
152+
/* N and R are needed,
153+
* P and Q are not needed for LTDC */
154+
RCC_PLLSAICFGR &= ~RCC_PLLSAICFGR_PLLSAIN_MASK;
155+
RCC_PLLSAICFGR |= 192 << RCC_PLLSAICFGR_PLLSAIN_SHIFT;
156+
RCC_PLLSAICFGR &= ~RCC_PLLSAICFGR_PLLSAIR_MASK;
157+
RCC_PLLSAICFGR |= 5 << RCC_PLLSAICFGR_PLLSAIR_SHIFT;
158+
RCC_DCKCFGR1 &= ~RCC_DCKCFGR1_PLLSAIDIVR_MASK;
159+
RCC_DCKCFGR1 |= RCC_DCKCFGR1_PLLSAIDIVR_DIVR_4;
160+
161+
/* Enable PLLSAI */
162+
RCC_CR |= RCC_CR_PLLSAION;
163+
while(!(RCC_CR & (RCC_CR_PLLSAIRDY))) {};
164+
}
165+
166+
int main(void)
167+
{
168+
lcd_pinmux();
169+
lcd_clock();
170+
lcd_config(); /* Configure LCD : Only one layer is used */
171+
172+
while (1) {}
173+
}
174+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef __RK043FN48H_H
2+
#define __RK043FN48H_H
3+
4+
#include <stdint.h>
5+
6+
#define RK043FN48H_WIDTH ((uint16_t)480) /* LCD PIXEL WIDTH */
7+
#define RK043FN48H_HEIGHT ((uint16_t)272) /* LCD PIXEL HEIGHT */
8+
#define RK043FN48H_HSYNC ((uint16_t)41) /* Horizontal synchronization */
9+
#define RK043FN48H_HBP ((uint16_t)13) /* Horizontal back porch */
10+
#define RK043FN48H_HFP ((uint16_t)32) /* Horizontal front porch */
11+
#define RK043FN48H_VSYNC ((uint16_t)10) /* Vertical synchronization */
12+
#define RK043FN48H_VBP ((uint16_t)2) /* Vertical back porch */
13+
#define RK043FN48H_VFP ((uint16_t)2) /* Vertical front porch */
14+
#define RK043FN48H_FREQUENCY_DIVIDER 5 /* LCD Frequency divider */
15+
16+
#endif /* __RK043FN48H_H */

0 commit comments

Comments
 (0)