drv_lcd.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2017-08-08 Yang the first version
  9. */
  10. #include <board.h>
  11. #include <rtdevice.h>
  12. #include <drv_lcd.h>
  13. #include <string.h>
  14. #include "fsl_iocon.h"
  15. #include "fsl_sctimer.h"
  16. #include "fsl_lcdc.h"
  17. static rt_uint16_t *lcd_framebuffer = RT_NULL;
  18. static rt_uint16_t *_rt_framebuffer = RT_NULL;
  19. #define RT_HW_LCD_WIDTH 480
  20. #define RT_HW_LCD_HEIGHT 272
  21. static struct rt_device_graphic_info _lcd_info;
  22. static struct rt_device lcd;
  23. #define LCD_PANEL_CLK (9 * 1000000UL)
  24. #define LCD_PPL 480
  25. #define LCD_HSW 2
  26. #define LCD_HFP 8
  27. #define LCD_HBP 43
  28. #define LCD_LPP 272
  29. #define LCD_VSW 10
  30. #define LCD_VFP 4
  31. #define LCD_VBP 12
  32. #define LCD_POL_FLAGS kLCDC_InvertVsyncPolarity | kLCDC_InvertHsyncPolarity
  33. #define LCD_WIDTH 480
  34. #define LCD_HEIGHT 272
  35. #define LCD_BITS_PER_PIXEL 16
  36. static void lcd_gpio_init(void)
  37. {
  38. const uint32_t port2_pin11_config = (
  39. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_PWR */
  40. IOCON_PIO_MODE_INACT | /* No addition pin function */
  41. IOCON_PIO_INV_DI | /* Input function is not inverted */
  42. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  43. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  44. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  45. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  46. );
  47. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN11_IDX, port2_pin11_config); /* PORT2 PIN11 (coords: K3) is configured as LCD_PWR */
  48. const uint32_t port2_pin13_config = (
  49. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_DCLK */
  50. IOCON_PIO_MODE_INACT | /* No addition pin function */
  51. IOCON_PIO_INV_DI | /* Input function is not inverted */
  52. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  53. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  54. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  55. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  56. );
  57. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN13_IDX, port2_pin13_config); /* PORT2 PIN13 (coords: P7) is configured as LCD_DCLK */
  58. const uint32_t port2_pin14_config = (
  59. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_FP */
  60. IOCON_PIO_MODE_INACT | /* No addition pin function */
  61. IOCON_PIO_INV_DI | /* Input function is not inverted */
  62. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  63. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  64. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  65. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  66. );
  67. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN14_IDX, port2_pin14_config); /* PORT2 PIN14 (coords: L7) is configured as LCD_FP */
  68. const uint32_t port2_pin15_config = (
  69. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_AC */
  70. IOCON_PIO_MODE_INACT | /* No addition pin function */
  71. IOCON_PIO_INV_DI | /* Input function is not inverted */
  72. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  73. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  74. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  75. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  76. );
  77. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN15_IDX, port2_pin15_config); /* PORT2 PIN15 (coords: M8) is configured as LCD_AC */
  78. const uint32_t port2_pin16_config = (
  79. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_LP */
  80. IOCON_PIO_MODE_INACT | /* No addition pin function */
  81. IOCON_PIO_INV_DI | /* Input function is not inverted */
  82. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  83. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  84. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  85. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  86. );
  87. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN16_IDX, port2_pin16_config); /* PORT2 PIN16 (coords: L8) is configured as LCD_LP */
  88. const uint32_t port2_pin21_config = (
  89. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(3) */
  90. IOCON_PIO_MODE_INACT | /* No addition pin function */
  91. IOCON_PIO_INV_DI | /* Input function is not inverted */
  92. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  93. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  94. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  95. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  96. );
  97. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN21_IDX, port2_pin21_config); /* PORT2 PIN21 (coords: L10) is configured as LCD_VD(3) */
  98. const uint32_t port2_pin22_config = (
  99. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(4) */
  100. IOCON_PIO_MODE_INACT | /* No addition pin function */
  101. IOCON_PIO_INV_DI | /* Input function is not inverted */
  102. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  103. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  104. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  105. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  106. );
  107. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN22_IDX, port2_pin22_config); /* PORT2 PIN22 (coords: K10) is configured as LCD_VD(4) */
  108. const uint32_t port2_pin23_config = (
  109. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(5) */
  110. IOCON_PIO_MODE_INACT | /* No addition pin function */
  111. IOCON_PIO_INV_DI | /* Input function is not inverted */
  112. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  113. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  114. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  115. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  116. );
  117. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN23_IDX, port2_pin23_config); /* PORT2 PIN23 (coords: M14) is configured as LCD_VD(5) */
  118. const uint32_t port2_pin24_config = (
  119. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(6) */
  120. IOCON_PIO_MODE_INACT | /* No addition pin function */
  121. IOCON_PIO_INV_DI | /* Input function is not inverted */
  122. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  123. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  124. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  125. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  126. );
  127. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN24_IDX, port2_pin24_config); /* PORT2 PIN24 (coords: K14) is configured as LCD_VD(6) */
  128. const uint32_t port2_pin25_config = (
  129. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(7) */
  130. IOCON_PIO_MODE_INACT | /* No addition pin function */
  131. IOCON_PIO_INV_DI | /* Input function is not inverted */
  132. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  133. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  134. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  135. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  136. );
  137. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN25_IDX, port2_pin25_config); /* PORT2 PIN25 (coords: J11) is configured as LCD_VD(7) */
  138. const uint32_t port2_pin27_config = (
  139. IOCON_PIO_FUNC0 | /* Pin is configured as PIO2_27 */
  140. IOCON_PIO_MODE_PULLUP | /* Selects pull-up function */
  141. IOCON_PIO_INV_DI | /* Input function is not inverted */
  142. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  143. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  144. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  145. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  146. );
  147. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN27_IDX, port2_pin27_config); /* PORT2 PIN27 (coords: H14) is configured as PIO2_27 */
  148. const uint32_t port2_pin28_config = (
  149. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(10) */
  150. IOCON_PIO_MODE_INACT | /* No addition pin function */
  151. IOCON_PIO_INV_DI | /* Input function is not inverted */
  152. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  153. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  154. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  155. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  156. );
  157. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN28_IDX, port2_pin28_config); /* PORT2 PIN28 (coords: G13) is configured as LCD_VD(10) */
  158. const uint32_t port2_pin29_config = (
  159. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(11) */
  160. IOCON_PIO_MODE_INACT | /* No addition pin function */
  161. IOCON_PIO_INV_DI | /* Input function is not inverted */
  162. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  163. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  164. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  165. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  166. );
  167. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN29_IDX, port2_pin29_config); /* PORT2 PIN29 (coords: G11) is configured as LCD_VD(11) */
  168. const uint32_t port2_pin30_config = (
  169. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(12) */
  170. IOCON_PIO_MODE_INACT | /* No addition pin function */
  171. IOCON_PIO_INV_DI | /* Input function is not inverted */
  172. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  173. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  174. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  175. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  176. );
  177. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN30_IDX, port2_pin30_config); /* PORT2 PIN30 (coords: F12) is configured as LCD_VD(12) */
  178. const uint32_t port2_pin31_config = (
  179. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(13) */
  180. IOCON_PIO_MODE_INACT | /* No addition pin function */
  181. IOCON_PIO_INV_DI | /* Input function is not inverted */
  182. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  183. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  184. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  185. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  186. );
  187. IOCON_PinMuxSet(IOCON, PORT2_IDX, PIN31_IDX, port2_pin31_config); /* PORT2 PIN31 (coords: D14) is configured as LCD_VD(13) */
  188. const uint32_t port3_pin0_config = (
  189. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(14) */
  190. IOCON_PIO_MODE_INACT | /* No addition pin function */
  191. IOCON_PIO_INV_DI | /* Input function is not inverted */
  192. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  193. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  194. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  195. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  196. );
  197. IOCON_PinMuxSet(IOCON, PORT3_IDX, PIN0_IDX, port3_pin0_config); /* PORT3 PIN0 (coords: D12) is configured as LCD_VD(14) */
  198. const uint32_t port3_pin1_config = (
  199. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(15) */
  200. IOCON_PIO_MODE_INACT | /* No addition pin function */
  201. IOCON_PIO_INV_DI | /* Input function is not inverted */
  202. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  203. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  204. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  205. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  206. );
  207. IOCON_PinMuxSet(IOCON, PORT3_IDX, PIN1_IDX, port3_pin1_config); /* PORT3 PIN1 (coords: D11) is configured as LCD_VD(15) */
  208. const uint32_t port3_pin5_config = (
  209. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(19) */
  210. IOCON_PIO_MODE_INACT | /* No addition pin function */
  211. IOCON_PIO_INV_DI | /* Input function is not inverted */
  212. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  213. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  214. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  215. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  216. );
  217. IOCON_PinMuxSet(IOCON, PORT3_IDX, PIN5_IDX, port3_pin5_config); /* PORT3 PIN5 (coords: B10) is configured as LCD_VD(19) */
  218. const uint32_t port3_pin6_config = (
  219. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(20) */
  220. IOCON_PIO_MODE_INACT | /* No addition pin function */
  221. IOCON_PIO_INV_DI | /* Input function is not inverted */
  222. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  223. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  224. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  225. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  226. );
  227. IOCON_PinMuxSet(IOCON, PORT3_IDX, PIN6_IDX, port3_pin6_config); /* PORT3 PIN6 (coords: C9) is configured as LCD_VD(20) */
  228. const uint32_t port3_pin7_config = (
  229. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(21) */
  230. IOCON_PIO_MODE_INACT | /* No addition pin function */
  231. IOCON_PIO_INV_DI | /* Input function is not inverted */
  232. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  233. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  234. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  235. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  236. );
  237. IOCON_PinMuxSet(IOCON, PORT3_IDX, PIN7_IDX, port3_pin7_config); /* PORT3 PIN7 (coords: B8) is configured as LCD_VD(21) */
  238. const uint32_t port3_pin8_config = (
  239. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(22) */
  240. IOCON_PIO_MODE_INACT | /* No addition pin function */
  241. IOCON_PIO_INV_DI | /* Input function is not inverted */
  242. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  243. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  244. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  245. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  246. );
  247. IOCON_PinMuxSet(IOCON, PORT3_IDX, PIN8_IDX, port3_pin8_config); /* PORT3 PIN8 (coords: A7) is configured as LCD_VD(22) */
  248. const uint32_t port3_pin9_config = (
  249. IOCON_PIO_FUNC1 | /* Pin is configured as LCD_VD(23) */
  250. IOCON_PIO_MODE_INACT | /* No addition pin function */
  251. IOCON_PIO_INV_DI | /* Input function is not inverted */
  252. IOCON_PIO_DIGITAL_EN | /* Enables digital function */
  253. IOCON_PIO_INPFILT_OFF | /* Input filter disabled */
  254. IOCON_PIO_SLEW_STANDARD | /* Standard mode, output slew rate control is enabled */
  255. IOCON_PIO_OPENDRAIN_DI /* Open drain is disabled */
  256. );
  257. IOCON_PinMuxSet(IOCON, PORT3_IDX, PIN9_IDX, port3_pin9_config); /* PORT3 PIN9 (coords: C7) is configured as LCD_VD(23) */
  258. }
  259. void LCD_IRQHandler(void)
  260. {
  261. uint32_t intStatus = LCDC_GetEnabledInterruptsPendingStatus(LCD);
  262. LCDC_ClearInterruptsStatus(LCD, intStatus);
  263. if (intStatus & kLCDC_VerticalCompareInterrupt)
  264. {
  265. //s_frameEndFlag = true;
  266. }
  267. //__DSB();
  268. }
  269. /* RT-Thread Device Interface */
  270. static rt_err_t rt_lcd_init(rt_device_t dev)
  271. {
  272. /* Route Main clock to LCD. */
  273. CLOCK_AttachClk(kMCLK_to_LCD_CLK);
  274. CLOCK_SetClkDiv(kCLOCK_DivLcdClk, 1, true);
  275. /*LCD管脚配置*/
  276. lcd_gpio_init();
  277. /* Set the back light PWM. */
  278. {
  279. sctimer_config_t config;
  280. sctimer_pwm_signal_param_t pwmParam;
  281. uint32_t event;
  282. CLOCK_AttachClk(kMCLK_to_SCT_CLK);
  283. CLOCK_SetClkDiv(kCLOCK_DivSctClk, 2, true);
  284. SCTIMER_GetDefaultConfig(&config);
  285. SCTIMER_Init(SCT0, &config);
  286. pwmParam.output = kSCTIMER_Out_5;
  287. pwmParam.level = kSCTIMER_HighTrue;
  288. pwmParam.dutyCyclePercent = 5;
  289. SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 1000U, CLOCK_GetFreq(kCLOCK_Sct), &event);
  290. }
  291. lcd_framebuffer = rt_malloc_align(sizeof(rt_uint16_t) * RT_HW_LCD_HEIGHT * RT_HW_LCD_WIDTH, 32);
  292. rt_memset(lcd_framebuffer, 0, sizeof(rt_uint16_t) * RT_HW_LCD_HEIGHT * RT_HW_LCD_WIDTH);
  293. {
  294. /* Initialize the display. */
  295. lcdc_config_t lcdConfig;
  296. LCDC_GetDefaultConfig(&lcdConfig);
  297. lcdConfig.panelClock_Hz = LCD_PANEL_CLK;
  298. lcdConfig.ppl = LCD_PPL;
  299. lcdConfig.hsw = LCD_HSW;
  300. lcdConfig.hfp = LCD_HFP;
  301. lcdConfig.hbp = LCD_HBP;
  302. lcdConfig.lpp = LCD_LPP;
  303. lcdConfig.vsw = LCD_VSW;
  304. lcdConfig.vfp = LCD_VFP;
  305. lcdConfig.vbp = LCD_VBP;
  306. lcdConfig.polarityFlags = LCD_POL_FLAGS;
  307. lcdConfig.upperPanelAddr = (uint32_t)lcd_framebuffer;//VRAM_ADDR;
  308. lcdConfig.bpp = kLCDC_16BPP565;
  309. lcdConfig.display = kLCDC_DisplayTFT;
  310. lcdConfig.swapRedBlue = true;
  311. LCDC_Init(LCD, &lcdConfig, CLOCK_GetFreq(kCLOCK_LCD));
  312. /* Trigger interrupt at start of every vertical back porch. */
  313. LCDC_SetVerticalInterruptMode(LCD, kLCDC_StartOfBackPorch);
  314. LCDC_EnableInterrupts(LCD, kLCDC_VerticalCompareInterrupt);
  315. NVIC_EnableIRQ(LCD_IRQn);
  316. LCDC_Start(LCD);
  317. LCDC_PowerUp(LCD);
  318. }
  319. return RT_EOK;
  320. }
  321. static rt_err_t rt_lcd_control(rt_device_t dev, int cmd, void *args)
  322. {
  323. switch (cmd)
  324. {
  325. case RTGRAPHIC_CTRL_RECT_UPDATE:
  326. {
  327. struct rt_device_rect_info *rect_info = (struct rt_device_rect_info *)args;
  328. /* 先指向绘图 buff 显示 */
  329. LCD->UPBASE = (rt_uint32_t)_rt_framebuffer;
  330. /* 从绘图 buff copy 数据到显示 buff */
  331. if (rect_info->width * rect_info->height < RT_HW_LCD_WIDTH * RT_HW_LCD_HEIGHT / 5 * 3)
  332. {
  333. int index = 0;
  334. rt_uint8_t *p = (rt_uint8_t *)lcd_framebuffer;
  335. rt_uint8_t *q = (rt_uint8_t *)_rt_framebuffer;
  336. p += (rect_info->x + rect_info->y * RT_HW_LCD_WIDTH) * sizeof(rt_uint16_t);
  337. q += (rect_info->x + rect_info->y * RT_HW_LCD_WIDTH) * sizeof(rt_uint16_t);
  338. for (index = 0; index < rect_info->height; index ++)
  339. {
  340. memcpy((void *)p, (void *)q, sizeof(rt_uint16_t) * rect_info->width);
  341. p += RT_HW_LCD_WIDTH * sizeof(rt_uint16_t);
  342. q += RT_HW_LCD_WIDTH * sizeof(rt_uint16_t);
  343. }
  344. }
  345. else
  346. {
  347. memcpy((void *)lcd_framebuffer, _rt_framebuffer, sizeof(rt_uint16_t)*RT_HW_LCD_HEIGHT * RT_HW_LCD_WIDTH);
  348. }
  349. /* 指回显示 buff */
  350. LCD->UPBASE = (rt_uint32_t)lcd_framebuffer;
  351. rt_kprintf("====> rect_info : %d %d %d %d\n", rect_info->x, rect_info->y, rect_info->width, rect_info->height);
  352. }
  353. break;
  354. case RTGRAPHIC_CTRL_POWERON:
  355. break;
  356. case RTGRAPHIC_CTRL_POWEROFF:
  357. break;
  358. case RTGRAPHIC_CTRL_GET_INFO:
  359. memcpy(args, &_lcd_info, sizeof(_lcd_info));
  360. break;
  361. case RTGRAPHIC_CTRL_SET_MODE:
  362. break;
  363. }
  364. return RT_EOK;
  365. }
  366. rt_uint16_t* get_lcd_framebuffer(void)
  367. {
  368. return lcd_framebuffer;
  369. }
  370. void lcd_clear(rt_uint16_t color)
  371. {
  372. volatile rt_uint16_t *p = (rt_uint16_t *)lcd_framebuffer;
  373. int x, y;
  374. for (y = 0; y <= RT_HW_LCD_HEIGHT; y++)
  375. {
  376. for (x = 0; x <= RT_HW_LCD_WIDTH; x++)
  377. {
  378. *p++ = color; /* red */
  379. }
  380. }
  381. }
  382. void rt_hw_lcd_init(void)
  383. {
  384. _rt_framebuffer = rt_malloc_align(sizeof(rt_uint16_t) * RT_HW_LCD_HEIGHT * RT_HW_LCD_WIDTH, 32);
  385. if (_rt_framebuffer == RT_NULL) return; /* no memory yet */
  386. _lcd_info.bits_per_pixel = LCD_BITS_PER_PIXEL;
  387. _lcd_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565; // RTGRAPHIC_PIXEL_FORMAT_ARGB888
  388. _lcd_info.framebuffer = (void *)_rt_framebuffer;
  389. _lcd_info.width = RT_HW_LCD_WIDTH;
  390. _lcd_info.height = RT_HW_LCD_HEIGHT;
  391. /* init device structure */
  392. lcd.type = RT_Device_Class_Graphic;
  393. lcd.init = rt_lcd_init;
  394. lcd.open = RT_NULL;
  395. lcd.close = RT_NULL;
  396. lcd.control = rt_lcd_control;
  397. lcd.user_data = (void *)&_lcd_info;
  398. /* register lcd device to RT-Thread */
  399. rt_device_register(&lcd, "lcd", RT_DEVICE_FLAG_RDWR);
  400. rt_lcd_init(&lcd);
  401. }
  402. void lcd_test(void)
  403. {
  404. lcd_clear(0xf800);
  405. rt_thread_delay(200);
  406. lcd_clear(0x07e0);
  407. rt_thread_delay(200);
  408. lcd_clear(0x001f);
  409. rt_thread_delay(200);
  410. }
  411. #ifdef RT_USING_FINSH
  412. #include <finsh.h>
  413. FINSH_FUNCTION_EXPORT(lcd_clear, lcd_clear);
  414. FINSH_FUNCTION_EXPORT(lcd_test, lcd_test);
  415. #ifdef FINSH_USING_MSH
  416. MSH_CMD_EXPORT(lcd_clear, lcd_clear);
  417. MSH_CMD_EXPORT(lcd_test, lcd_test);
  418. #endif
  419. #endif