GadgetSeed  0.9.6
32f469i-disc_lcd.c
[詳解]
1 /** @file
2  @brief STM32F469I Discovery LCD ドライバ
3 
4  @date 2018.08.15
5  @author Takashi SHUDO
6 */
7 
8 #include "device.h"
9 #include "device/video_ioctl.h"
10 #include "timer.h"
11 #include "tkprintf.h"
12 #include "graphics.h"
13 
14 #include "stm32469i_discovery_lcd.h"
15 
16 #define LCD_WIDTH 800 // 幅
17 #define LCD_HEIGHT 480 // 高さ
18 
19 #define __ATTR_FRAMEBUFFER __attribute__ ((section(".extram"))) __attribute__ ((aligned (4)))
20 unsigned char lcd_f_buffer_main[LCD_WIDTH * LCD_HEIGHT * 4] __ATTR_FRAMEBUFFER;
21 unsigned char lcd_f_buffer_sub [LCD_WIDTH * LCD_HEIGHT * 4] __ATTR_FRAMEBUFFER;
22 
23 LTDC_HandleTypeDef hltdc_discovery;
24 DSI_HandleTypeDef hdsi_discovery;
25 
26 static void init_framebuf(void)
27 {
28  unsigned char *p;
29 
30  for(p=&lcd_f_buffer_main[0];
31  p<&lcd_f_buffer_main[LCD_WIDTH * LCD_HEIGHT * 4];
32  p++) {
33  *p = 0; // Black
34  }
35 
36  for(p=&lcd_f_buffer_sub[0];
37  p<&lcd_f_buffer_sub[LCD_WIDTH * LCD_HEIGHT * 4];
38  p++) {
39  *p = 0; // Black
40  }
41 }
42 
43 extern LTDC_HandleTypeDef hltdc_eval;
44 extern DSI_HandleTypeDef hdsi_eval;
45 DSI_VidCfgTypeDef hdsivideo_handle;
46 
47 static uint8_t LCD_Init(void)
48 {
49  DSI_PLLInitTypeDef dsiPllInit;
50  DSI_PHY_TimerTypeDef PhyTimings;
51  static RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
52  uint32_t LcdClock = 19200; /*!< LcdClk = 19200 kHz */
53 
54  uint32_t laneByteClk_kHz = 0;
55  uint32_t VSA; /*!< Vertical start active time in units of lines */
56  uint32_t VBP; /*!< Vertical Back Porch time in units of lines */
57  uint32_t VFP; /*!< Vertical Front Porch time in units of lines */
58  uint32_t VACT; /*!< Vertical Active time in units of lines = imageSize Y in pixels to display */
59  uint32_t HSA; /*!< Horizontal start active time in units of lcdClk */
60  uint32_t HBP; /*!< Horizontal Back Porch time in units of lcdClk */
61  uint32_t HFP; /*!< Horizontal Front Porch time in units of lcdClk */
62  uint32_t HACT; /*!< Horizontal Active time in units of lcdClk = imageSize X in pixels to display */
63 
64 
65  /* Toggle Hardware Reset of the DSI LCD using
66  * its XRES signal (active low) */
67  BSP_LCD_Reset();
68 
69  /* Call first MSP Initialize only in case of first initialization
70  * This will set IP blocks LTDC, DSI and DMA2D
71  * - out of reset
72  * - clocked
73  * - NVIC IRQ related to IP blocks enabled
74  */
75  BSP_LCD_MspInit();
76 
77 /*************************DSI Initialization***********************************/
78 
79  /* Base address of DSI Host/Wrapper registers to be set before calling De-Init */
80  hdsi_eval.Instance = DSI;
81 
82  HAL_DSI_DeInit(&(hdsi_eval));
83 
84 #if !defined(USE_STM32469I_DISCO_REVA)
85  dsiPllInit.PLLNDIV = 125;
86  dsiPllInit.PLLIDF = DSI_PLL_IN_DIV2;
87  dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1;
88 #else
89  dsiPllInit.PLLNDIV = 100;
90  dsiPllInit.PLLIDF = DSI_PLL_IN_DIV5;
91  dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1;
92 #endif
93  laneByteClk_kHz = 62500; /* 500 MHz / 8 = 62.5 MHz = 62500 kHz */
94 
95  /* Set number of Lanes */
96  hdsi_eval.Init.NumberOfLanes = DSI_TWO_DATA_LANES;
97 
98  /* TXEscapeCkdiv = f(LaneByteClk)/15.62 = 4 */
99  hdsi_eval.Init.TXEscapeCkdiv = laneByteClk_kHz/15620;
100 
101  HAL_DSI_Init(&(hdsi_eval), &(dsiPllInit));
102 
103  /* The following values are same for portrait and landscape orientations */
104  VSA = OTM8009A_480X800_VSYNC; /* 10 */
105  VBP = OTM8009A_480X800_VBP; /* 15 */
106  VFP = OTM8009A_480X800_VFP; /* 16 */
107  HSA = OTM8009A_480X800_HSYNC; /* 2 */
108  HBP = OTM8009A_480X800_HBP; /* 20 */
109  HFP = OTM8009A_480X800_HFP; /* 20 */
110  HACT = OTM8009A_800X480_WIDTH; /* 800 */
111  VACT = OTM8009A_800X480_HEIGHT; /* 480 */
112 
113  hdsivideo_handle.VirtualChannelID = LCD_OTM8009A_ID;
114  hdsivideo_handle.ColorCoding = LCD_DSI_PIXEL_DATA_FMT_RBG888;
115  hdsivideo_handle.VSPolarity = DSI_VSYNC_ACTIVE_HIGH;
116  hdsivideo_handle.HSPolarity = DSI_HSYNC_ACTIVE_HIGH;
117  hdsivideo_handle.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;
118  hdsivideo_handle.Mode = DSI_VID_MODE_BURST; /* Mode Video burst ie : one LgP per line */
119  hdsivideo_handle.NullPacketSize = 0xFFF;
120  hdsivideo_handle.NumberOfChunks = 0;
121  hdsivideo_handle.PacketSize = HACT; /* Value depending on display orientation choice portrait/landscape */
122  hdsivideo_handle.HorizontalSyncActive = (HSA * laneByteClk_kHz) / LcdClock;
123  hdsivideo_handle.HorizontalBackPorch = (HBP * laneByteClk_kHz) / LcdClock;
124  hdsivideo_handle.HorizontalLine = ((HACT + HSA + HBP + HFP) * laneByteClk_kHz) / LcdClock; /* Value depending on display orientation choice portrait/landscape */
125  hdsivideo_handle.VerticalSyncActive = VSA;
126  hdsivideo_handle.VerticalBackPorch = VBP;
127  hdsivideo_handle.VerticalFrontPorch = VFP;
128  hdsivideo_handle.VerticalActive = VACT; /* Value depending on display orientation choice portrait/landscape */
129 
130  /* Enable or disable sending LP command while streaming is active in video mode */
131  hdsivideo_handle.LPCommandEnable = DSI_LP_COMMAND_ENABLE; /* Enable sending commands in mode LP (Low Power) */
132 
133  /* Largest packet size possible to transmit in LP mode in VSA, VBP, VFP regions */
134  /* Only useful when sending LP packets is allowed while streaming is active in video mode */
135  hdsivideo_handle.LPLargestPacketSize = 16;
136 
137  /* Largest packet size possible to transmit in LP mode in HFP region during VACT period */
138  /* Only useful when sending LP packets is allowed while streaming is active in video mode */
139  hdsivideo_handle.LPVACTLargestPacketSize = 0;
140 
141 
142  /* Specify for each region of the video frame, if the transmission of command in LP mode is allowed in this region */
143  /* while streaming is active in video mode */
144  hdsivideo_handle.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE; /* Allow sending LP commands during HFP period */
145  hdsivideo_handle.LPHorizontalBackPorchEnable = DSI_LP_HBP_ENABLE; /* Allow sending LP commands during HBP period */
146  hdsivideo_handle.LPVerticalActiveEnable = DSI_LP_VACT_ENABLE; /* Allow sending LP commands during VACT period */
147  hdsivideo_handle.LPVerticalFrontPorchEnable = DSI_LP_VFP_ENABLE; /* Allow sending LP commands during VFP period */
148  hdsivideo_handle.LPVerticalBackPorchEnable = DSI_LP_VBP_ENABLE; /* Allow sending LP commands during VBP period */
149  hdsivideo_handle.LPVerticalSyncActiveEnable = DSI_LP_VSYNC_ENABLE; /* Allow sending LP commands during VSync = VSA period */
150 
151  /* Configure DSI Video mode timings with settings set above */
152  HAL_DSI_ConfigVideoMode(&(hdsi_eval), &(hdsivideo_handle));
153 
154  /* Configure DSI PHY HS2LP and LP2HS timings */
155  PhyTimings.ClockLaneHS2LPTime = 35;
156  PhyTimings.ClockLaneLP2HSTime = 35;
157  PhyTimings.DataLaneHS2LPTime = 35;
158  PhyTimings.DataLaneLP2HSTime = 35;
159  PhyTimings.DataLaneMaxReadTime = 0;
160  PhyTimings.StopWaitTime = 10;
161  HAL_DSI_ConfigPhyTimer(&hdsi_eval, &PhyTimings);
162 
163 
164 /*************************End DSI Initialization*******************************/
165 
166 
167 /************************LTDC Initialization***********************************/
168 
169  /* Timing Configuration */
170  hltdc_eval.Init.HorizontalSync = (HSA - 1);
171  hltdc_eval.Init.AccumulatedHBP = (HSA + HBP - 1);
172  hltdc_eval.Init.AccumulatedActiveW = (HACT + HSA + HBP - 1);
173  hltdc_eval.Init.TotalWidth = (HACT + HSA + HBP + HFP - 1);
174 
175  /* Initialize the LCD pixel width and pixel height */
176  hltdc_eval.LayerCfg->ImageWidth = HACT;
177  hltdc_eval.LayerCfg->ImageHeight = VACT;
178 
179 
180  /* LCD clock configuration */
181  /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
182  /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 Mhz */
183  /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192 MHz / 5 = 38.4 MHz */
184  /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_2 = 38.4 MHz / 2 = 19.2 MHz */
185  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
186  PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;
187  PeriphClkInitStruct.PLLSAI.PLLSAIR = 5;
188  PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_2;
189  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
190 
191  /* Background value */
192  hltdc_eval.Init.Backcolor.Blue = 0;
193  hltdc_eval.Init.Backcolor.Green = 0;
194  hltdc_eval.Init.Backcolor.Red = 0;
195  hltdc_eval.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
196  hltdc_eval.Instance = LTDC;
197 
198  /* Get LTDC Configuration from DSI Configuration */
199  HAL_LTDC_StructInitFromVideoConfig(&(hltdc_eval), &(hdsivideo_handle));
200 
201  /* Initialize the LTDC */
202  HAL_LTDC_Init(&hltdc_eval);
203 
204  /* Enable the DSI host and wrapper after the LTDC initialization
205  To avoid any synchronization issue, the DSI shall be started after enabling the LTDC */
206 
207  HAL_DSI_Start(&(hdsi_eval));
208 
209 #if !defined(DATA_IN_ExtSDRAM)
210  /* Initialize the SDRAM */
211  BSP_SDRAM_Init();
212 #endif /* DATA_IN_ExtSDRAM */
213 
214  /* Initialize the font */
215  BSP_LCD_SetFont(&LCD_DEFAULT_FONT);
216 
217 /************************End LTDC Initialization*******************************/
218 
219 
220 /***********************OTM8009A Initialization********************************/
221 
222  /* Initialize the OTM8009A LCD Display IC Driver (KoD LCD IC Driver)
223  * depending on configuration set in 'hdsivideo_handle'.
224  */
225  OTM8009A_Init(OTM8009A_FORMAT_RGB888, OTM8009A_ORIENTATION_LANDSCAPE);
226 
227 /***********************End OTM8009A Initialization****************************/
228 
229  return LCD_OK;
230 }
231 
232 static void Display_DSIIF_Init(void)
233 {
234  LCD_Init();
235  BSP_LCD_DisplayOff();
236 
237  BSP_LCD_LayerDefaultInit(LTDC_ACTIVE_LAYER_BACKGROUND, (uint32_t)lcd_f_buffer_sub);
238  BSP_LCD_SelectLayer(LTDC_ACTIVE_LAYER_BACKGROUND);
239  BSP_LCD_Clear(LCD_COLOR_BLACK);
240 
241  BSP_LCD_LayerDefaultInit(LTDC_ACTIVE_LAYER_FOREGROUND, (uint32_t)lcd_f_buffer_main);
242  BSP_LCD_SelectLayer(LTDC_ACTIVE_LAYER_FOREGROUND);
243  BSP_LCD_Clear(LCD_COLOR_BLACK);
244 
245  BSP_LCD_SetColorKeying(1, 0);
246 
247  BSP_LCD_SelectLayer(LTDC_ACTIVE_LAYER_BACKGROUND);
248  BSP_LCD_DisplayOn();
249 }
250 
251 static int lcd_register(struct st_device *dev, char *param)
252 {
253  ((struct st_video_info *)(dev->info))->frame_buf_ptr[0] = lcd_f_buffer_main;
254  ((struct st_video_info *)(dev->info))->frame_buf_ptr[1] = lcd_f_buffer_sub;
255  ((struct st_video_info *)(dev->info))->mem_size = sizeof(lcd_f_buffer_main);
256 
257  Display_DSIIF_Init();
258  init_framebuf();
259 
260  return 0;
261 }
262 
263 static int lcd_ioctl(struct st_device *dev, unsigned int com, unsigned int arg, void *param)
264 {
265  switch(com) {
267  switch(arg) {
268  case 0:
269  BSP_LCD_SetLayerAddress(1, (uint32_t)lcd_f_buffer_main);
270  break;
271 
272  case 1:
273  BSP_LCD_SetLayerAddress(1, (uint32_t)lcd_f_buffer_sub);
274  break;
275 
276  default:
277  return -1;
278  break;
279  }
280  break;
281 
282  case IOCMD_VIDEO_CLEAR:
283  {
284  init_framebuf();
285  }
286  break;
287 
288  default:
289  SYSERR_PRINT("Unknow command %08lX arg %08lX\n", com, arg);
290  return -1;
291  }
292 
293  return 0;
294 }
295 
296 static struct st_video_info lcd_info = {
298  .width = LCD_WIDTH,
299  .height = LCD_HEIGHT,
300  .color_depth = VCOLORDEP_32,
301  .frame_num = 2,
302  .frame_buf_ptr = { 0, 0 },
303  .mem_size = 0,
304 };
305 
306 const struct st_device lcd_device = {
308  .explan = "STM32F469I-Discovery LCD",
309  .info = (void *)&lcd_info,
310  .register_dev = lcd_register,
311  .ioctl = lcd_ioctl,
312 };
#define VCOLORDEP_32
32ビットカラー
Definition: video_ioctl.h:28
void * info
デバイス情報データポインタ
Definition: device.h:28
#define IOCMD_VIDEO_CLEAR
全画面初期化
Definition: video_ioctl.h:52
画像表示デバイスドライバ ioctl 用マクロ定義
画像表示デバイス情報
Definition: video_ioctl.h:30
カーネルタイマ
unsigned short type
ビデオデバイスタイプ(VIDEOTYPE_*)
Definition: video_ioctl.h:31
カーネル用機能限定printf
unsigned int mem_size
フレームバッファメモリサイズ
Definition: video_ioctl.h:37
#define IOCMD_VIDEO_SETDISPFRAME
表示フレーム番号を設定する
Definition: video_ioctl.h:47
#define VIDEOTYPE_FRAMEBUF
カラーフレームバッファ(描画同期無し)
Definition: video_ioctl.h:21
unsigned char * frame_buf_ptr[MAX_FRAMEBUF]
フレームバッファポインタ
Definition: video_ioctl.h:36
#define DEF_DEV_NAME_VIDEO
標準ビデオデバイス名
Definition: video_ioctl.h:16
デバイスドライバAPI
デバイスドライバ構造体
Definition: device.h:25
static uint8_t LCD_Init(void)
char name[MAX_DEVNAMELRN]
デバイス名文字列
Definition: device.h:26
グラフィックライブラリ