drv_lcd.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-12-28 unknow copy by STemwin
  9. * 2021-12-29 xiangxistu port for lvgl <lcd_fill_array>
  10. * 2022-6-26 solar Improve the api required for resistive touch screen calibration
  11. * 2023-05-17 yuanjie parallel driver improved
  12. */
  13. #include <rtdevice.h>
  14. #include <board.h>
  15. #include "string.h"
  16. #include "drv_lcd.h"
  17. #include "drv_lcd_font.h"
  18. #define DRV_DEBUG
  19. #define LOG_TAG "drv.lcd"
  20. #include <drv_log.h>
  21. _lcd_dev lcddev;
  22. rt_uint16_t BACK_COLOR = WHITE, FORE_COLOR = BLACK;
  23. #define LCD_CLEAR_SEND_NUMBER 5760
  24. #ifdef BSP_USING_ONBOARD_LCD_PWM_BL
  25. #define PWM_BL_NAME "pwm14" /* 背光PWM设备名称 */
  26. #define PWM_BL_CHANNEL 1 /* 背光PWM通道 */
  27. #define PWM_BL_PERIOD 500000 /* 0.5ms = 2000 Hz*/
  28. struct rt_device_pwm *pwm_bl_dev = RT_NULL; /* PWM设备句柄 */
  29. #else
  30. #define LCD_BL GET_PIN(F, 9)
  31. #endif /* BSP_USING_ONBOARD_LCD_PWM_BL */
  32. #define LCD_RST GET_PIN(D, 3)
  33. #define LCD_DEVICE(dev) (struct drv_lcd_device *)(dev)
  34. struct drv_lcd_device
  35. {
  36. struct rt_device parent;
  37. struct rt_device_graphic_info lcd_info;
  38. };
  39. static struct drv_lcd_device _lcd;
  40. // 写寄存器函数
  41. // regval:寄存器值
  42. void LCD_WR_REG(uint8_t regval)
  43. {
  44. LCD->_u8_REG = regval; // 写入要写的寄存器序号
  45. }
  46. // 写LCD数据
  47. // data:要写入的值
  48. void LCD_WR_DATA16(uint16_t data)
  49. {
  50. LCD->_u16_RAM = data;
  51. }
  52. void LCD_WR_DATA8(uint8_t data)
  53. {
  54. LCD->_u8_RAM = data;
  55. }
  56. // 读LCD数据
  57. // 返回值:读到的值
  58. uint8_t LCD_RD_DATA8(void)
  59. {
  60. return LCD->_u8_RAM;
  61. }
  62. // 写寄存器
  63. // LCD_Reg:寄存器地址
  64. // LCD_RegValue:要写入的数据
  65. void LCD_WriteReg(uint8_t LCD_Reg, uint16_t LCD_RegValue)
  66. {
  67. LCD->_u8_REG = LCD_Reg; // 写入要写的寄存器序号
  68. LCD->_u16_RAM = LCD_RegValue; // 写入数据
  69. }
  70. // 读寄存器
  71. // LCD_Reg:寄存器地址
  72. // 返回值:读到的数据
  73. uint16_t LCD_ReadReg(uint16_t LCD_Reg)
  74. {
  75. LCD_WR_REG(LCD_Reg); // 写入要读的寄存器序号
  76. return LCD_RD_DATA8(); // 返回读到的值
  77. }
  78. // 开始写GRAM
  79. void LCD_WriteRAM_Prepare(void)
  80. {
  81. LCD->_u8_REG = lcddev.wramcmd;
  82. }
  83. // LCD写GRAM
  84. // RGB_Code:颜色值
  85. void LCD_WriteRAM(uint16_t RGB_Code)
  86. {
  87. LCD->_u16_RAM = RGB_Code; // 写十六位GRAM
  88. }
  89. // 从ILI93xx读出的数据为GBR格式,而我们写入的时候为RGB格式。
  90. // 通过该函数转换
  91. // c:GBR格式的颜色值
  92. // 返回值:RGB格式的颜色值
  93. uint16_t LCD_BGR2RGB(uint16_t c)
  94. {
  95. uint16_t r, g, b, rgb;
  96. b = (c >> 0) & 0x1f;
  97. g = (c >> 5) & 0x3f;
  98. r = (c >> 11) & 0x1f;
  99. rgb = (b << 11) + (g << 5) + (r << 0);
  100. return (rgb);
  101. }
  102. // 设置光标位置(对RGB屏无效)
  103. // Xpos:横坐标
  104. // Ypos:纵坐标
  105. void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
  106. {
  107. if (lcddev.id == 8552) // st7789v3
  108. {
  109. LCD_WR_REG(lcddev.setxcmd);
  110. LCD_WR_DATA16(Xpos >> 8);
  111. LCD_WR_DATA16(Xpos & 0XFF);
  112. LCD_WR_REG(lcddev.setycmd);
  113. LCD_WR_DATA16(Ypos >> 8);
  114. LCD_WR_DATA16(Ypos & 0XFF);
  115. }
  116. }
  117. // 读取个某点的颜色值
  118. // x,y:坐标
  119. // 返回值:此点的颜色
  120. void LCD_ReadPoint(char *pixel, int x, int y)
  121. {
  122. uint16_t *color = (uint16_t *)pixel;
  123. uint16_t r = 0, g = 0, b = 0;
  124. if (x >= lcddev.width || y >= lcddev.height)
  125. {
  126. *color = 0; // 超过了范围,直接返回
  127. return;
  128. }
  129. LCD_SetCursor(x, y);
  130. if (lcddev.id == 0X81b3)
  131. LCD_WR_REG(0X2E); // 9341/3510/1963 发送读GRAM指令
  132. r = LCD_RD_DATA8(); // dummy Read
  133. r = LCD_RD_DATA8(); // 实际坐标颜色
  134. b = LCD_RD_DATA8();
  135. g = r & 0XFF; // 对于9341/5310/5510,第一次读取的是RG的值,R在前,G在后,各占8位
  136. g <<= 8;
  137. *color = (((r >> 11) << 11) | ((g >> 10) << 5) | (b >> 11)); // ILI9341/NT35310/NT35510需要公式转换一下
  138. }
  139. // LCD开启显示
  140. void LCD_DisplayOn(void)
  141. {
  142. if (lcddev.id == 0X81b3)
  143. LCD_WR_REG(0X29); // 开启显示
  144. }
  145. // LCD关闭显示
  146. void LCD_DisplayOff(void)
  147. {
  148. if (lcddev.id == 0X81b3)
  149. LCD_WR_REG(0X28); // 关闭显示
  150. }
  151. #ifdef BSP_USING_ONBOARD_LCD_PWM_BL
  152. //TODO PWM14 not working
  153. // 初始化LCD背光定时器
  154. void LCD_PWM_BackLightInit()
  155. {
  156. pwm_bl_dev = (struct rt_device_pwm *)rt_device_find(PWM_BL_NAME);
  157. if(RT_NULL != pwm_bl_dev)
  158. {
  159. /* 设置PWM周期和脉冲宽度默认值 */
  160. rt_pwm_set(pwm_bl_dev, PWM_BL_CHANNEL, PWM_BL_PERIOD, 0);
  161. }
  162. else
  163. {
  164. LOG_E("pwm backlight error!");
  165. }
  166. }
  167. // TODO 反初始化LCD背光定时器
  168. // void LCD_TIM_BackLightDeinit(uint8_t value)
  169. // {
  170. // }
  171. // 设置LCD背光亮度
  172. // pwm:背光等级,0~100.越大越亮.
  173. void LCD_BackLightSet(uint8_t value)
  174. {
  175. value = value > 100 ? 100 : value;
  176. if(RT_NULL != pwm_bl_dev)
  177. {
  178. /* 设置PWM周期和脉冲宽度默认值 */
  179. rt_pwm_set(pwm_bl_dev, PWM_BL_CHANNEL, PWM_BL_PERIOD, (PWM_BL_PERIOD/100)*value);
  180. /* 使能设备 */
  181. rt_pwm_enable(pwm_bl_dev, PWM_BL_CHANNEL);
  182. LOG_D("backlight %d percent", value);
  183. }
  184. else
  185. {
  186. LOG_E("backlight set error!");
  187. }
  188. }
  189. #endif
  190. // 设置LCD的自动扫描方向(对RGB屏无效)
  191. // 注意:其他函数可能会受到此函数设置的影响(尤其是9341),
  192. // 所以,一般设置为L2R_U2D即可,如果设置为其他扫描方式,可能导致显示不正常.
  193. // dir:0~7,代表8个方向(具体定义见lcd.h)
  194. // 9341/5310/5510/1963等IC已经实际测试
  195. void LCD_Scan_Dir(uint8_t dir)
  196. {
  197. uint16_t regval = 0;
  198. uint16_t dirreg = 0;
  199. uint16_t temp;
  200. if ((lcddev.dir == 1 && lcddev.id != 0X1963) || (lcddev.dir == 0 && lcddev.id == 0X1963)) // 横屏时,对1963不改变扫描方向!竖屏时1963改变方向
  201. {
  202. switch (dir) // 方向转换
  203. {
  204. case 0:
  205. dir = 6;
  206. break;
  207. case 1:
  208. dir = 7;
  209. break;
  210. case 2:
  211. dir = 4;
  212. break;
  213. case 3:
  214. dir = 5;
  215. break;
  216. case 4:
  217. dir = 1;
  218. break;
  219. case 5:
  220. dir = 0;
  221. break;
  222. case 6:
  223. dir = 3;
  224. break;
  225. case 7:
  226. dir = 2;
  227. break;
  228. }
  229. }
  230. if (lcddev.id == 0x9341 || lcddev.id == 0X5310 || lcddev.id == 0X5510 || lcddev.id == 0X1963) // 9341/5310/5510/1963,特殊处理
  231. {
  232. switch (dir)
  233. {
  234. case L2R_U2D: // 从左到右,从上到下
  235. regval |= (0 << 7) | (0 << 6) | (0 << 5);
  236. break;
  237. case L2R_D2U: // 从左到右,从下到上
  238. regval |= (1 << 7) | (0 << 6) | (0 << 5);
  239. break;
  240. case R2L_U2D: // 从右到左,从上到下
  241. regval |= (0 << 7) | (1 << 6) | (0 << 5);
  242. break;
  243. case R2L_D2U: // 从右到左,从下到上
  244. regval |= (1 << 7) | (1 << 6) | (0 << 5);
  245. break;
  246. case U2D_L2R: // 从上到下,从左到右
  247. regval |= (0 << 7) | (0 << 6) | (1 << 5);
  248. break;
  249. case U2D_R2L: // 从上到下,从右到左
  250. regval |= (0 << 7) | (1 << 6) | (1 << 5);
  251. break;
  252. case D2U_L2R: // 从下到上,从左到右
  253. regval |= (1 << 7) | (0 << 6) | (1 << 5);
  254. break;
  255. case D2U_R2L: // 从下到上,从右到左
  256. regval |= (1 << 7) | (1 << 6) | (1 << 5);
  257. break;
  258. }
  259. if (lcddev.id == 0X5510)
  260. dirreg = 0X3600;
  261. else
  262. dirreg = 0X36;
  263. if ((lcddev.id != 0X5310) && (lcddev.id != 0X5510) && (lcddev.id != 0X1963))
  264. regval |= 0X08; // 5310/5510/1963不需要BGR
  265. LCD_WriteReg(dirreg, regval);
  266. if (lcddev.id != 0X1963) // 1963不做坐标处理
  267. {
  268. if (regval & 0X20)
  269. {
  270. if (lcddev.width < lcddev.height) // 交换X,Y
  271. {
  272. temp = lcddev.width;
  273. lcddev.width = lcddev.height;
  274. lcddev.height = temp;
  275. }
  276. }
  277. else
  278. {
  279. if (lcddev.width > lcddev.height) // 交换X,Y
  280. {
  281. temp = lcddev.width;
  282. lcddev.width = lcddev.height;
  283. lcddev.height = temp;
  284. }
  285. }
  286. }
  287. }
  288. }
  289. // 快速画点
  290. // x,y:坐标
  291. // color:颜色
  292. static void LCD_Fast_DrawPoint(const char *pixel, int x, int y)
  293. {
  294. uint16_t color = *((uint16_t *)pixel);
  295. if (lcddev.id == 0X81b3)
  296. {
  297. LCD_WR_REG(lcddev.setxcmd);
  298. LCD_WR_DATA16(x >> 8);
  299. LCD_WR_DATA16(x & 0XFF);
  300. LCD_WR_REG(lcddev.setycmd);
  301. LCD_WR_DATA16(y >> 8);
  302. LCD_WR_DATA16(y & 0XFF);
  303. }
  304. LCD->_u8_REG = lcddev.wramcmd;
  305. LCD->_u16_RAM = color;
  306. }
  307. // 设置LCD显示方向
  308. // dir:0,竖屏;1,横屏
  309. void LCD_Display_Dir(uint8_t dir)
  310. {
  311. lcddev.dir = dir; // 竖屏/横屏
  312. if (dir == 0) // 竖屏
  313. {
  314. lcddev.width = 240;
  315. lcddev.height = 240;
  316. if (lcddev.id == 0X81b3)
  317. {
  318. lcddev.wramcmd = 0X2C;
  319. lcddev.setxcmd = 0X2A;
  320. lcddev.setycmd = 0X2B;
  321. }
  322. }
  323. else // 横屏
  324. {
  325. lcddev.width = 240;
  326. lcddev.height = 240;
  327. if (lcddev.id == 0X81b3)
  328. {
  329. lcddev.wramcmd = 0X2C;
  330. lcddev.setxcmd = 0X2A;
  331. lcddev.setycmd = 0X2B;
  332. }
  333. }
  334. // TODO scan dir settings
  335. // LCD_Scan_Dir(DFT_SCAN_DIR); //默认扫描方向
  336. }
  337. rt_err_t lcd_write_half_word(const rt_uint16_t da)
  338. {
  339. LCD_WR_DATA16(change_byte_order(da));
  340. return RT_EOK;
  341. }
  342. rt_err_t lcd_write_data_buffer(const void *send_buf, rt_size_t length)
  343. {
  344. uint8_t *pdata = RT_NULL;
  345. rt_size_t len = 0;
  346. pdata = (uint8_t*)send_buf;
  347. len = length;
  348. if (pdata != RT_NULL)
  349. {
  350. while (len -- )
  351. {
  352. LCD_WR_DATA8(*pdata);
  353. pdata ++;
  354. }
  355. }
  356. return RT_EOK;
  357. }
  358. /**
  359. * Set background color and foreground color
  360. *
  361. * @param back background color
  362. * @param fore fore color
  363. *
  364. * @return void
  365. */
  366. void lcd_set_color(rt_uint16_t back, rt_uint16_t fore)
  367. {
  368. BACK_COLOR = back;
  369. FORE_COLOR = fore;
  370. }
  371. /**
  372. * Set drawing area
  373. *
  374. * @param x1 start of x position
  375. * @param y1 start of y position
  376. * @param x2 end of x position
  377. * @param y2 end of y position
  378. *
  379. * @return void
  380. */
  381. void lcd_address_set(rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
  382. {
  383. if (lcddev.id == 0X81b3) // st7789v3
  384. {
  385. LCD_WR_REG(lcddev.setxcmd);
  386. LCD_WR_DATA8(x1 >> 8);
  387. LCD_WR_DATA8(x1 & 0xff);
  388. LCD_WR_DATA8(x2 >> 8);
  389. LCD_WR_DATA8(x2 & 0xff);
  390. LCD_WR_REG(lcddev.setycmd);
  391. LCD_WR_DATA8(y1 >> 8);
  392. LCD_WR_DATA8(y1 & 0xff);
  393. LCD_WR_DATA8(y2 >> 8);
  394. LCD_WR_DATA8(y2 & 0xff);
  395. }
  396. LCD_WriteRAM_Prepare(); // 开始写入GRAM
  397. }
  398. /**
  399. * clear the lcd.
  400. *
  401. * @param color Fill color
  402. *
  403. * @return void
  404. */
  405. void lcd_clear(rt_uint16_t color)
  406. {
  407. uint32_t index = 0;
  408. uint32_t totalpoint = lcddev.width;
  409. totalpoint *= lcddev.height; // 得到总点数
  410. LCD_SetCursor(0x00, 0x0000); // 设置光标位置
  411. LCD_WriteRAM_Prepare(); // 开始写入GRAM
  412. for (index = 0; index < totalpoint; index++)
  413. {
  414. LCD->_u16_RAM = color;
  415. }
  416. }
  417. /**
  418. * display a point on the lcd.
  419. *
  420. * @param x x position
  421. * @param y y position
  422. *
  423. * @return void
  424. */
  425. void lcd_draw_point(rt_uint16_t x, rt_uint16_t y)
  426. {
  427. lcd_address_set(x, y, x, y);
  428. lcd_write_half_word(BLUE);
  429. }
  430. rt_uint16_t change_byte_order(rt_uint16_t word)
  431. {
  432. return ((word<<8)&0xff00) | ((word>>8)&0x00ff);
  433. }
  434. /**
  435. * full color on the lcd.
  436. *
  437. * @param x_start start of x position
  438. * @param y_start start of y position
  439. * @param x_end end of x position
  440. * @param y_end end of y position
  441. * @param color Fill color
  442. *
  443. * @return void
  444. */
  445. void lcd_fill(rt_uint16_t x_start, rt_uint16_t y_start, rt_uint16_t x_end, rt_uint16_t y_end, rt_uint16_t color)
  446. {
  447. rt_uint16_t i = 0, j = 0;
  448. rt_uint32_t size = 0, size_remain = 0;
  449. rt_uint8_t *fill_buf = RT_NULL;
  450. size = (x_end - x_start) * (y_end - y_start) * 2;
  451. if (size > LCD_CLEAR_SEND_NUMBER)
  452. {
  453. /* the number of remaining to be filled */
  454. size_remain = size - LCD_CLEAR_SEND_NUMBER;
  455. size = LCD_CLEAR_SEND_NUMBER;
  456. }
  457. lcd_address_set(x_start, y_start, x_end, y_end);
  458. fill_buf = (rt_uint8_t *)rt_malloc(size);
  459. if (fill_buf)
  460. {
  461. /* fast fill */
  462. while (1)
  463. {
  464. for (i = 0; i < size / 2; i++)
  465. {
  466. fill_buf[2 * i] = color >> 8;
  467. fill_buf[2 * i + 1] = color;
  468. }
  469. lcd_write_data_buffer(fill_buf, size);
  470. /* Fill completed */
  471. if (size_remain == 0)
  472. break;
  473. /* calculate the number of fill next time */
  474. if (size_remain > LCD_CLEAR_SEND_NUMBER)
  475. {
  476. size_remain = size_remain - LCD_CLEAR_SEND_NUMBER;
  477. }
  478. else
  479. {
  480. size = size_remain;
  481. size_remain = 0;
  482. }
  483. }
  484. rt_free(fill_buf);
  485. }
  486. else
  487. {
  488. for (i = y_start; i <= y_end; i++)
  489. {
  490. for (j = x_start; j <= x_end; j++)lcd_write_half_word(color);
  491. }
  492. }
  493. }
  494. /**
  495. * display a line on the lcd.
  496. *
  497. * @param x1 x1 position
  498. * @param y1 y1 position
  499. * @param x2 x2 position
  500. * @param y2 y2 position
  501. *
  502. * @return void
  503. */
  504. void lcd_draw_line(rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
  505. {
  506. rt_uint16_t t;
  507. rt_uint32_t i = 0;
  508. int xerr = 0, yerr = 0, delta_x, delta_y, distance;
  509. int incx, incy, row, col;
  510. if (y1 == y2)
  511. {
  512. /* fast draw transverse line */
  513. lcd_address_set(x1, y1, x2, y2);
  514. rt_uint8_t line_buf[480] = {0};
  515. for (i = 0; i < x2 - x1; i++)
  516. {
  517. line_buf[2 * i] = FORE_COLOR >> 8;
  518. line_buf[2 * i + 1] = FORE_COLOR;
  519. }
  520. lcd_write_data_buffer(line_buf, (x2 - x1) * 2);
  521. return ;
  522. }
  523. delta_x = x2 - x1;
  524. delta_y = y2 - y1;
  525. row = x1;
  526. col = y1;
  527. if (delta_x > 0)incx = 1;
  528. else if (delta_x == 0)incx = 0;
  529. else
  530. {
  531. incx = -1;
  532. delta_x = -delta_x;
  533. }
  534. if (delta_y > 0)incy = 1;
  535. else if (delta_y == 0)incy = 0;
  536. else
  537. {
  538. incy = -1;
  539. delta_y = -delta_y;
  540. }
  541. if (delta_x > delta_y)distance = delta_x;
  542. else distance = delta_y;
  543. for (t = 0; t <= distance + 1; t++)
  544. {
  545. lcd_draw_point(row, col);
  546. xerr += delta_x ;
  547. yerr += delta_y ;
  548. if (xerr > distance)
  549. {
  550. xerr -= distance;
  551. row += incx;
  552. }
  553. if (yerr > distance)
  554. {
  555. yerr -= distance;
  556. col += incy;
  557. }
  558. }
  559. }
  560. /**
  561. * display a rectangle on the lcd.
  562. *
  563. * @param x1 x1 position
  564. * @param y1 y1 position
  565. * @param x2 x2 position
  566. * @param y2 y2 position
  567. *
  568. * @return void
  569. */
  570. void lcd_draw_rectangle(rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
  571. {
  572. lcd_draw_line(x1, y1, x2, y1);
  573. lcd_draw_line(x1, y1, x1, y2);
  574. lcd_draw_line(x1, y2, x2, y2);
  575. lcd_draw_line(x2, y1, x2, y2);
  576. }
  577. /**
  578. * display a circle on the lcd.
  579. *
  580. * @param x x position of Center
  581. * @param y y position of Center
  582. * @param r radius
  583. *
  584. * @return void
  585. */
  586. void lcd_draw_circle(rt_uint16_t x0, rt_uint16_t y0, rt_uint8_t r)
  587. {
  588. int a, b;
  589. int di;
  590. a = 0;
  591. b = r;
  592. di = 3 - (r << 1);
  593. while (a <= b)
  594. {
  595. lcd_draw_point(x0 - b, y0 - a);
  596. lcd_draw_point(x0 + b, y0 - a);
  597. lcd_draw_point(x0 - a, y0 + b);
  598. lcd_draw_point(x0 - b, y0 - a);
  599. lcd_draw_point(x0 - a, y0 - b);
  600. lcd_draw_point(x0 + b, y0 + a);
  601. lcd_draw_point(x0 + a, y0 - b);
  602. lcd_draw_point(x0 + a, y0 + b);
  603. lcd_draw_point(x0 - b, y0 + a);
  604. a++;
  605. //Bresenham
  606. if (di < 0)di += 4 * a + 6;
  607. else
  608. {
  609. di += 10 + 4 * (a - b);
  610. b--;
  611. }
  612. lcd_draw_point(x0 + a, y0 + b);
  613. }
  614. }
  615. static void lcd_show_char(rt_uint16_t x, rt_uint16_t y, rt_uint8_t data, rt_uint32_t size)
  616. {
  617. rt_uint8_t temp;
  618. rt_uint8_t num = 0;;
  619. rt_uint8_t pos, t;
  620. rt_uint16_t colortemp = FORE_COLOR;
  621. rt_uint8_t *font_buf = RT_NULL;
  622. if (x > LCD_W - size / 2 || y > LCD_H - size)return;
  623. data = data - ' ';
  624. #ifdef ASC2_1608
  625. if (size == 16)
  626. {
  627. lcd_address_set(x, y, x + size / 2 - 1, y + size - 1);//(x,y,x+8-1,y+16-1)
  628. font_buf = (rt_uint8_t *)rt_malloc(size * size);
  629. if (!font_buf)
  630. {
  631. /* fast show char */
  632. for (pos = 0; pos < size * (size / 2) / 8; pos++)
  633. {
  634. temp = asc2_1608[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
  635. for (t = 0; t < 8; t++)
  636. {
  637. if (temp & 0x80)colortemp = FORE_COLOR;
  638. else colortemp = BACK_COLOR;
  639. lcd_write_half_word(colortemp);
  640. temp <<= 1;
  641. }
  642. }
  643. }
  644. else
  645. {
  646. for (pos = 0; pos < size * (size / 2) / 8; pos++)
  647. {
  648. temp = asc2_1608[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
  649. for (t = 0; t < 8; t++)
  650. {
  651. if (temp & 0x80)colortemp = FORE_COLOR;
  652. else colortemp = BACK_COLOR;
  653. font_buf[2 * (8 * pos + t)] = colortemp >> 8;
  654. font_buf[2 * (8 * pos + t) + 1] = colortemp;
  655. temp <<= 1;
  656. }
  657. }
  658. lcd_write_data_buffer(font_buf, size * size);
  659. rt_free(font_buf);
  660. }
  661. }
  662. else
  663. #endif
  664. #ifdef ASC2_2412
  665. if (size == 24)
  666. {
  667. lcd_address_set(x, y, x + size / 2 - 1, y + size - 1);
  668. font_buf = (rt_uint8_t *)rt_malloc(size * size);
  669. if (!font_buf)
  670. {
  671. /* fast show char */
  672. for (pos = 0; pos < (size * 16) / 8; pos++)
  673. {
  674. temp = asc2_2412[(rt_uint16_t)data * (size * 16) / 8 + pos];
  675. if (pos % 2 == 0)
  676. {
  677. num = 8;
  678. }
  679. else
  680. {
  681. num = 4;
  682. }
  683. for (t = 0; t < num; t++)
  684. {
  685. if (temp & 0x80)colortemp = FORE_COLOR;
  686. else colortemp = BACK_COLOR;
  687. lcd_write_half_word(colortemp);
  688. temp <<= 1;
  689. }
  690. }
  691. }
  692. else
  693. {
  694. for (pos = 0; pos < (size * 16) / 8; pos++)
  695. {
  696. temp = asc2_2412[(rt_uint16_t)data * (size * 16) / 8 + pos];
  697. if (pos % 2 == 0)
  698. {
  699. num = 8;
  700. }
  701. else
  702. {
  703. num = 4;
  704. }
  705. for (t = 0; t < num; t++)
  706. {
  707. if (temp & 0x80)colortemp = FORE_COLOR;
  708. else colortemp = BACK_COLOR;
  709. if (num == 8)
  710. {
  711. font_buf[2 * (12 * (pos / 2) + t)] = colortemp >> 8;
  712. font_buf[2 * (12 * (pos / 2) + t) + 1] = colortemp;
  713. }
  714. else
  715. {
  716. font_buf[2 * (8 + 12 * (pos / 2) + t)] = colortemp >> 8;
  717. font_buf[2 * (8 + 12 * (pos / 2) + t) + 1] = colortemp;
  718. }
  719. temp <<= 1;
  720. }
  721. }
  722. lcd_write_data_buffer(font_buf, size * size);
  723. rt_free(font_buf);
  724. }
  725. }
  726. else
  727. #endif
  728. #ifdef ASC2_3216
  729. if (size == 32)
  730. {
  731. lcd_address_set(x, y, x + size / 2 - 1, y + size - 1);
  732. font_buf = (rt_uint8_t *)rt_malloc(size * size);
  733. if (!font_buf)
  734. {
  735. /* fast show char */
  736. for (pos = 0; pos < size * (size / 2) / 8; pos++)
  737. {
  738. temp = asc2_3216[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
  739. for (t = 0; t < 8; t++)
  740. {
  741. if (temp & 0x80)colortemp = FORE_COLOR;
  742. else colortemp = BACK_COLOR;
  743. lcd_write_half_word(colortemp);
  744. temp <<= 1;
  745. }
  746. }
  747. }
  748. else
  749. {
  750. for (pos = 0; pos < size * (size / 2) / 8; pos++)
  751. {
  752. temp = asc2_3216[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
  753. for (t = 0; t < 8; t++)
  754. {
  755. if (temp & 0x80)colortemp = FORE_COLOR;
  756. else colortemp = BACK_COLOR;
  757. font_buf[2 * (8 * pos + t)] = colortemp >> 8;
  758. font_buf[2 * (8 * pos + t) + 1] = colortemp;
  759. temp <<= 1;
  760. }
  761. }
  762. lcd_write_data_buffer(font_buf, size * size);
  763. rt_free(font_buf);
  764. }
  765. }
  766. else
  767. #endif
  768. {
  769. LOG_E("There is no any define ASC2_1208 && ASC2_2412 && ASC2_2416 && ASC2_3216 !");
  770. }
  771. }
  772. /**
  773. * display the number on the lcd.
  774. *
  775. * @param x x position
  776. * @param y y position
  777. * @param num number
  778. * @param len length of number
  779. * @param size size of font
  780. *
  781. * @return void
  782. */
  783. void lcd_show_num(rt_uint16_t x, rt_uint16_t y, rt_uint32_t num, rt_uint8_t len, rt_uint32_t size)
  784. {
  785. lcd_show_string(x, y, size, "%d", num);
  786. }
  787. /**
  788. * display the string on the lcd.
  789. *
  790. * @param x x position
  791. * @param y y position
  792. * @param size size of font
  793. * @param p the string to be display
  794. *
  795. * @return 0: display success
  796. * -1: size of font is not support
  797. */
  798. rt_err_t lcd_show_string(rt_uint16_t x, rt_uint16_t y, rt_uint32_t size, const char *fmt, ...)
  799. {
  800. #define LCD_STRING_BUF_LEN 128
  801. va_list args;
  802. rt_uint8_t buf[LCD_STRING_BUF_LEN] = {0};
  803. rt_uint8_t *p = RT_NULL;
  804. if (size != 16 && size != 24 && size != 32)
  805. {
  806. LOG_E("font size(%d) is not support!", size);
  807. return -RT_ERROR;
  808. }
  809. va_start(args, fmt);
  810. rt_vsnprintf((char *)buf, 100, (const char *)fmt, args);
  811. va_end(args);
  812. p = buf;
  813. while (*p != '\0')
  814. {
  815. if (x > LCD_W - size / 2)
  816. {
  817. x = 0;
  818. y += size;
  819. }
  820. if (y > LCD_H - size)
  821. {
  822. y = x = 0;
  823. lcd_clear(RED);
  824. }
  825. lcd_show_char(x, y, *p, size);
  826. x += size / 2;
  827. p++;
  828. }
  829. return RT_EOK;
  830. }
  831. /**
  832. * display the image on the lcd.
  833. *
  834. * @param x x position
  835. * @param y y position
  836. * @param length length of image
  837. * @param wide wide of image
  838. * @param p image
  839. *
  840. * @return 0: display success
  841. * -1: the image is too large
  842. */
  843. rt_err_t lcd_show_image(rt_uint16_t x, rt_uint16_t y, rt_uint16_t length, rt_uint16_t wide, const rt_uint8_t *p)
  844. {
  845. RT_ASSERT(p);
  846. if (x + length > LCD_W || y + wide > LCD_H)
  847. {
  848. return -RT_ERROR;
  849. }
  850. lcd_address_set(x, y, x + length - 1, y + wide - 1);
  851. lcd_write_data_buffer(p, length * wide * 2);
  852. return RT_EOK;
  853. }
  854. #ifdef PKG_USING_QRCODE
  855. QRCode qrcode;
  856. static rt_uint8_t get_enlargement_factor(rt_uint16_t x, rt_uint16_t y, rt_uint8_t size)
  857. {
  858. rt_uint8_t enlargement_factor = 1 ;
  859. if (x + size * 8 <= LCD_W && y + size * 8 <= LCD_H)
  860. {
  861. enlargement_factor = 8;
  862. }
  863. else if (x + size * 4 <= LCD_W &&y + size * 4 <= LCD_H)
  864. {
  865. enlargement_factor = 4;
  866. }
  867. else if (x + size * 2 <= LCD_W && y + size * 2 <= LCD_H)
  868. {
  869. enlargement_factor = 2;
  870. }
  871. return enlargement_factor;
  872. }
  873. static void show_qrcode_by_point(rt_uint16_t x, rt_uint16_t y, rt_uint8_t size, rt_uint8_t enlargement_factor)
  874. {
  875. rt_uint32_t width = 0, high = 0;
  876. for (high = 0; high < size; high++)
  877. {
  878. for (width = 0; width < size; width++)
  879. {
  880. if (qrcode_getModule(&qrcode, width, high))
  881. {
  882. /* magnify pixel */
  883. for (rt_uint32_t offset_y = 0; offset_y < enlargement_factor; offset_y++)
  884. {
  885. for (rt_uint32_t offset_x = 0; offset_x < enlargement_factor; offset_x++)
  886. {
  887. lcd_draw_point(x + enlargement_factor * width + offset_x, y + enlargement_factor * high + offset_y);
  888. }
  889. }
  890. }
  891. }
  892. }
  893. }
  894. static void show_qrcode_by_line(rt_uint16_t x, rt_uint16_t y, rt_uint8_t size, rt_uint8_t enlargement_factor,rt_uint8_t *qrcode_buf)
  895. {
  896. rt_uint32_t width = 0, high = 0;
  897. for (high = 0; high < qrcode.size; high++)
  898. {
  899. for (width = 0; width < qrcode.size; width++)
  900. {
  901. if (qrcode_getModule(&qrcode, width, high))
  902. {
  903. /* magnify pixel */
  904. for (rt_uint32_t offset_y = 0; offset_y < enlargement_factor; offset_y++)
  905. {
  906. for (rt_uint32_t offset_x = 0; offset_x < enlargement_factor; offset_x++)
  907. {
  908. /* save the information of modules */
  909. qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor)] = FORE_COLOR >> 8;
  910. qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor) + 1] = FORE_COLOR;
  911. }
  912. }
  913. }
  914. else
  915. {
  916. /* magnify pixel */
  917. for (rt_uint32_t offset_y = 0; offset_y < enlargement_factor; offset_y++)
  918. {
  919. for (rt_uint32_t offset_x = 0; offset_x < enlargement_factor; offset_x++)
  920. {
  921. /* save the information of blank */
  922. qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor)] = BACK_COLOR >> 8;
  923. qrcode_buf[2 * (enlargement_factor * width + offset_x + offset_y * qrcode.size * enlargement_factor) + 1] = BACK_COLOR;
  924. }
  925. }
  926. }
  927. }
  928. /* display a line of qrcode */
  929. lcd_show_image(x, y + high * enlargement_factor, qrcode.size * enlargement_factor, enlargement_factor, qrcode_buf);
  930. }
  931. }
  932. /**
  933. * display the qrcode on the lcd.
  934. * size = (4 * version +17) * enlargement
  935. *
  936. * @param x x position
  937. * @param y y position
  938. * @param version version of qrcode
  939. * @param ecc level of error correction
  940. * @param data string
  941. * @param enlargement enlargement_factor
  942. *
  943. * @return 0: display success
  944. * -1: generate qrcode failed
  945. * -5: memory low
  946. */
  947. rt_err_t lcd_show_qrcode(rt_uint16_t x, rt_uint16_t y, rt_uint8_t version, rt_uint8_t ecc, const char *data, rt_uint8_t enlargement)
  948. {
  949. RT_ASSERT(data);
  950. rt_int8_t result = 0;
  951. rt_uint8_t enlargement_factor = 1;
  952. rt_uint8_t *qrcode_buf = RT_NULL;
  953. if (x + version * 4 + 17 > LCD_W || y + version * 4 + 17 > LCD_H)
  954. {
  955. LOG_E("The qrcode is too big!");
  956. return -RT_ERROR;
  957. }
  958. rt_uint8_t *qrcodeBytes = (rt_uint8_t *)rt_calloc(1, qrcode_getBufferSize(version));
  959. if (qrcodeBytes == RT_NULL)
  960. {
  961. LOG_E("no memory for qrcode!");
  962. return -RT_ENOMEM;
  963. }
  964. /* generate qrcode */
  965. result = qrcode_initText(&qrcode, qrcodeBytes, version, ecc, data);
  966. if (result >= 0)
  967. {
  968. /* set enlargement factor */
  969. if(enlargement == 0)
  970. {
  971. enlargement_factor = get_enlargement_factor(x, y, qrcode.size);
  972. }
  973. else
  974. {
  975. enlargement_factor = enlargement;
  976. }
  977. /* malloc memory for quick display of qrcode */
  978. qrcode_buf = rt_malloc(qrcode.size * 2 * enlargement_factor * enlargement_factor);
  979. if (qrcode_buf == RT_NULL)
  980. {
  981. /* clear lcd */
  982. lcd_fill(x, y, x + qrcode.size, y + qrcode.size, BACK_COLOR);
  983. /* draw point to display qrcode */
  984. show_qrcode_by_point(x, y, qrcode.size, enlargement_factor);
  985. }
  986. else
  987. {
  988. /* quick display of qrcode */
  989. show_qrcode_by_line(x, y, qrcode.size, enlargement_factor,qrcode_buf);
  990. }
  991. result = RT_EOK;
  992. }
  993. else
  994. {
  995. LOG_E("QRCODE(%s) generate falied(%d)\n", qrstr, result);
  996. result = -RT_ENOMEM;
  997. goto __exit;
  998. }
  999. __exit:
  1000. if (qrcodeBytes)
  1001. {
  1002. rt_free(qrcodeBytes);
  1003. }
  1004. if (qrcode_buf)
  1005. {
  1006. rt_free(qrcode_buf);
  1007. }
  1008. return result;
  1009. }
  1010. #endif
  1011. void lcd_fill_array(rt_uint16_t x_start, rt_uint16_t y_start, rt_uint16_t x_end, rt_uint16_t y_end, void *pcolor)
  1012. {
  1013. rt_uint16_t *pixel = RT_NULL;
  1014. rt_uint16_t cycle_y, x_offset = 0;
  1015. pixel = (rt_uint16_t *)pcolor;
  1016. lcd_address_set(x_start, y_start, x_end, y_end);
  1017. for (cycle_y = y_start; cycle_y <= y_end;)
  1018. {
  1019. for (x_offset = 0; x_start + x_offset <= x_end; x_offset++)
  1020. {
  1021. LCD->_u8_RAM = (*pixel)>>8;
  1022. LCD->_u8_RAM = *pixel++;
  1023. }
  1024. cycle_y++;
  1025. }
  1026. }
  1027. void LCD_DrawLine(const char *pixel, rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
  1028. {
  1029. rt_uint16_t t;
  1030. int xerr = 0, yerr = 0, delta_x, delta_y, distance;
  1031. int incx, incy, uRow, uCol;
  1032. delta_x = x2 - x1; // 计算坐标增量
  1033. delta_y = y2 - y1;
  1034. uRow = x1;
  1035. uCol = y1;
  1036. if (delta_x > 0)
  1037. incx = 1; // 设置单步方向
  1038. else if (delta_x == 0)
  1039. incx = 0; // 垂直线
  1040. else
  1041. {
  1042. incx = -1;
  1043. delta_x = -delta_x;
  1044. }
  1045. if (delta_y > 0)
  1046. incy = 1;
  1047. else if (delta_y == 0)
  1048. incy = 0; // 水平线
  1049. else
  1050. {
  1051. incy = -1;
  1052. delta_y = -delta_y;
  1053. }
  1054. if (delta_x > delta_y)
  1055. distance = delta_x; // 选取基本增量坐标轴
  1056. else
  1057. distance = delta_y;
  1058. for (t = 0; t <= distance + 1; t++) // 画线输出
  1059. {
  1060. // LCD_DrawPoint(uRow, uCol); //画点
  1061. LCD_Fast_DrawPoint(pixel, uRow, uCol);
  1062. xerr += delta_x;
  1063. yerr += delta_y;
  1064. if (xerr > distance)
  1065. {
  1066. xerr -= distance;
  1067. uRow += incx;
  1068. }
  1069. if (yerr > distance)
  1070. {
  1071. yerr -= distance;
  1072. uCol += incy;
  1073. }
  1074. }
  1075. }
  1076. void LCD_HLine(const char *pixel, int x1, int x2, int y)
  1077. {
  1078. LCD_DrawLine(pixel, x1, y, x2, y);
  1079. }
  1080. void LCD_VLine(const char *pixel, int x, int y1, int y2)
  1081. {
  1082. LCD_DrawLine(pixel, x, y1, x, y2);
  1083. }
  1084. void LCD_BlitLine(const char *pixel, int x, int y, rt_size_t size)
  1085. {
  1086. LCD_SetCursor(x, y);
  1087. LCD_WriteRAM_Prepare();
  1088. uint16_t *p = (uint16_t *)pixel;
  1089. for (; size > 0; size--, p++)
  1090. LCD->_u16_RAM = *p;
  1091. }
  1092. int drv_lcd_init(void)
  1093. {
  1094. SRAM_HandleTypeDef hsram1 = {0};
  1095. FSMC_NORSRAM_TimingTypeDef read_timing = {0};
  1096. FSMC_NORSRAM_TimingTypeDef write_timing = {0};
  1097. #ifndef BSP_USING_ONBOARD_LCD_PWM_BL
  1098. rt_pin_mode(LCD_BL, PIN_MODE_OUTPUT);
  1099. #endif /* BSP_USING_ONBOARD_LCD_PWM_BL */
  1100. rt_pin_mode(LCD_RST, PIN_MODE_OUTPUT);
  1101. rt_pin_write(LCD_RST, PIN_LOW);
  1102. rt_thread_mdelay(100);
  1103. rt_pin_write(LCD_RST, PIN_HIGH);
  1104. rt_thread_mdelay(100);
  1105. // FSMC_NORSRAM_TimingTypeDef Timing = {0};
  1106. /** Perform the SRAM1 memory initialization sequence
  1107. */
  1108. hsram1.Instance = FSMC_NORSRAM_DEVICE;
  1109. hsram1.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
  1110. /* hsram1.Init */
  1111. hsram1.Init.NSBank = FSMC_NORSRAM_BANK3;
  1112. hsram1.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
  1113. hsram1.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
  1114. hsram1.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_8;
  1115. hsram1.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
  1116. hsram1.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
  1117. hsram1.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
  1118. hsram1.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
  1119. hsram1.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
  1120. hsram1.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
  1121. hsram1.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE;
  1122. hsram1.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
  1123. hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
  1124. hsram1.Init.PageSize = FSMC_PAGE_SIZE_NONE;
  1125. // /* Timing */
  1126. read_timing.AddressSetupTime = 0XF; //地址建立时间(ADDSET)为16个HCLK 1/168M=6ns*16=96ns
  1127. read_timing.AddressHoldTime = 0x00; //地址保持时间(ADDHLD)模式A未用到
  1128. read_timing.DataSetupTime = 60; //数据保存时间为60个HCLK =6*60=360ns
  1129. read_timing.BusTurnAroundDuration = 0x00;
  1130. read_timing.CLKDivision = 0x00;
  1131. read_timing.DataLatency = 0x00;
  1132. read_timing.AccessMode = FSMC_ACCESS_MODE_A; //模式A
  1133. write_timing.AddressSetupTime =9; //地址建立时间(ADDSET)为9个HCLK =54ns
  1134. write_timing.AddressHoldTime = 0x00; //地址保持时间(A
  1135. write_timing.DataSetupTime = 8; //数据保存时间为6ns*9个HCLK=54ns
  1136. write_timing.BusTurnAroundDuration = 0x00;
  1137. write_timing.CLKDivision = 0x00;
  1138. write_timing.DataLatency = 0x00;
  1139. write_timing.AccessMode = FSMC_ACCESS_MODE_A; //模式A
  1140. if (HAL_SRAM_Init(&hsram1, &read_timing, &write_timing) != HAL_OK)
  1141. {
  1142. Error_Handler( );
  1143. }
  1144. rt_thread_mdelay(100);
  1145. // 尝试st7789v3 ID的读取
  1146. LCD_WR_REG(0X04);
  1147. lcddev.id = LCD_RD_DATA8(); // dummy read
  1148. lcddev.id = LCD_RD_DATA8(); // ID2
  1149. lcddev.id = LCD_RD_DATA8(); // ID3
  1150. lcddev.id <<= 8;
  1151. lcddev.id |= LCD_RD_DATA8();
  1152. LOG_I(" LCD ID:%x", lcddev.id); // 打印LCD ID
  1153. if (lcddev.id == 0X81b3) //st7789v3
  1154. {
  1155. //************* Start Initial Sequence **********//
  1156. /* Memory Data Access Control */
  1157. LCD_WR_REG(0x36);
  1158. LCD_WR_DATA8(0x00);
  1159. /* RGB 5-6-5-bit */
  1160. LCD_WR_REG(0x3A);
  1161. LCD_WR_DATA8(0x65);
  1162. /* Porch Setting */
  1163. LCD_WR_REG(0xB2);
  1164. LCD_WR_DATA8(0x0C);
  1165. LCD_WR_DATA8(0x0C);
  1166. LCD_WR_DATA8(0x00);
  1167. LCD_WR_DATA8(0x33);
  1168. LCD_WR_DATA8(0x33);
  1169. /* Gate Control */
  1170. LCD_WR_REG(0xB7);
  1171. LCD_WR_DATA8(0x35);
  1172. /* VCOM Setting */
  1173. LCD_WR_REG(0xBB);
  1174. LCD_WR_DATA8(0x37);
  1175. /* LCM Control */
  1176. LCD_WR_REG(0xC0);
  1177. LCD_WR_DATA8(0x2C);
  1178. /* VDV and VRH Command Enable */
  1179. LCD_WR_REG(0xC2);
  1180. LCD_WR_DATA8(0x01);
  1181. /* VRH Set */
  1182. LCD_WR_REG(0xC3);
  1183. LCD_WR_DATA8(0x12);
  1184. /* VDV Set */
  1185. LCD_WR_REG(0xC4);
  1186. LCD_WR_DATA8(0x20);
  1187. /* Frame Rate Control in Normal Mode */
  1188. LCD_WR_REG(0xC6);
  1189. LCD_WR_DATA8(0x0F);
  1190. /* Power Control 1 */
  1191. LCD_WR_REG(0xD0);
  1192. LCD_WR_DATA8(0xA4);
  1193. LCD_WR_DATA8(0xA1);
  1194. /* Positive Voltage Gamma Control */
  1195. LCD_WR_REG(0xE0);
  1196. LCD_WR_DATA8(0xD0);
  1197. LCD_WR_DATA8(0x04);
  1198. LCD_WR_DATA8(0x0D);
  1199. LCD_WR_DATA8(0x11);
  1200. LCD_WR_DATA8(0x13);
  1201. LCD_WR_DATA8(0x2B);
  1202. LCD_WR_DATA8(0x3F);
  1203. LCD_WR_DATA8(0x54);
  1204. LCD_WR_DATA8(0x4C);
  1205. LCD_WR_DATA8(0x18);
  1206. LCD_WR_DATA8(0x0D);
  1207. LCD_WR_DATA8(0x0B);
  1208. LCD_WR_DATA8(0x1F);
  1209. LCD_WR_DATA8(0x23);
  1210. /* Negative Voltage Gamma Control */
  1211. LCD_WR_REG(0xE1);
  1212. LCD_WR_DATA8(0xD0);
  1213. LCD_WR_DATA8(0x04);
  1214. LCD_WR_DATA8(0x0C);
  1215. LCD_WR_DATA8(0x11);
  1216. LCD_WR_DATA8(0x13);
  1217. LCD_WR_DATA8(0x2C);
  1218. LCD_WR_DATA8(0x3F);
  1219. LCD_WR_DATA8(0x44);
  1220. LCD_WR_DATA8(0x51);
  1221. LCD_WR_DATA8(0x2F);
  1222. LCD_WR_DATA8(0x1F);
  1223. LCD_WR_DATA8(0x1F);
  1224. LCD_WR_DATA8(0x20);
  1225. LCD_WR_DATA8(0x23);
  1226. /* Display Inversion On */
  1227. LCD_WR_REG(0x21); // 开启反色
  1228. /* TearEffect Sync On */
  1229. LCD_WR_REG(0x35); // 开启TE
  1230. LCD_WR_DATA8(0x00); // TE 同步方式:vsync 同步
  1231. /* Sleep Out */
  1232. LCD_WR_REG(0x11);
  1233. rt_thread_mdelay(120);
  1234. /* display on */
  1235. LCD_WR_REG(0x29); // 开启显示
  1236. }
  1237. // 初始化完成以后,提速
  1238. if (lcddev.id == 0X81b3) //st7789v3可以设置WR时序为最快
  1239. {
  1240. // 重新配置写时序控制寄存器的时序
  1241. FSMC_Bank1E->BWTR[6] &= ~(0XF << 0); // 地址建立时间(ADDSET)清零
  1242. FSMC_Bank1E->BWTR[6] &= ~(0XF << 8); // 数据保存时间清零
  1243. FSMC_Bank1E->BWTR[6] |= 3 << 0; // 地址建立时间(ADDSET)为3个HCLK =18ns
  1244. FSMC_Bank1E->BWTR[6] |= 2 << 8; // 数据保存时间(DATAST)为6ns*3个HCLK=18ns
  1245. }
  1246. LCD_Display_Dir(0); // 默认为横屏
  1247. #ifdef BSP_USING_ONBOARD_LCD_PWM_BL
  1248. LCD_PWM_BackLightInit();
  1249. LCD_BackLightSet(80);
  1250. #else
  1251. rt_pin_write(LCD_BL, PIN_HIGH); // 开启背光
  1252. #endif /* BSP_USING_ONBOARD_LCD_PWM_BL */
  1253. lcd_clear(WHITE);
  1254. return RT_EOK;
  1255. }
  1256. INIT_COMPONENT_EXPORT(drv_lcd_init);
  1257. struct rt_device_graphic_ops fsmc_lcd_ops =
  1258. {
  1259. LCD_Fast_DrawPoint,
  1260. LCD_ReadPoint,
  1261. LCD_HLine,
  1262. LCD_VLine,
  1263. LCD_BlitLine,
  1264. };
  1265. static rt_err_t drv_lcd_control(struct rt_device *device, int cmd, void *args)
  1266. {
  1267. struct drv_lcd_device *lcd = LCD_DEVICE(device);
  1268. switch (cmd)
  1269. {
  1270. case RTGRAPHIC_CTRL_GET_INFO:
  1271. {
  1272. struct rt_device_graphic_info *info = (struct rt_device_graphic_info *)args;
  1273. RT_ASSERT(info != RT_NULL);
  1274. // this needs to be replaced by the customer
  1275. info->pixel_format = lcd->lcd_info.pixel_format;
  1276. info->bits_per_pixel = lcd->lcd_info.bits_per_pixel;
  1277. info->width = lcddev.width;
  1278. info->height = lcddev.height;
  1279. }
  1280. break;
  1281. }
  1282. return RT_EOK;
  1283. }
  1284. #ifdef RT_USING_DEVICE_OPS
  1285. const static struct rt_device_ops lcd_ops =
  1286. {
  1287. drv_lcd_init,
  1288. RT_NULL,
  1289. RT_NULL,
  1290. RT_NULL,
  1291. RT_NULL,
  1292. drv_lcd_control};
  1293. #endif
  1294. int drv_lcd_hw_init(void)
  1295. {
  1296. rt_err_t result = RT_EOK;
  1297. struct rt_device *device = &_lcd.parent;
  1298. /* memset _lcd to zero */
  1299. memset(&_lcd, 0x00, sizeof(_lcd));
  1300. _lcd.lcd_info.bits_per_pixel = 16;
  1301. _lcd.lcd_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565;
  1302. device->type = RT_Device_Class_Graphic;
  1303. #ifdef RT_USING_DEVICE_OPS
  1304. device->ops = &lcd_ops;
  1305. #else
  1306. device->init = NULL;
  1307. device->control = drv_lcd_control;
  1308. #endif
  1309. device->user_data = &fsmc_lcd_ops;
  1310. /* register lcd device */
  1311. rt_device_register(device, "lcd", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
  1312. return result;
  1313. }
  1314. INIT_DEVICE_EXPORT(drv_lcd_hw_init);
  1315. #ifdef BSP_USING_ONBOARD_LCD_TEST
  1316. void lcd_auto_fill(void *para)
  1317. {
  1318. int num = (int)para;
  1319. do
  1320. {
  1321. lcd_clear(rt_tick_get()%65535);
  1322. rt_thread_mdelay(500);
  1323. } while (--num);
  1324. }
  1325. #include <stdlib.h> /* atoi */
  1326. void lcd_fill_test(int argc, void **argv)
  1327. {
  1328. static rt_uint8_t lcd_init = 0;
  1329. rt_device_t lcd = RT_NULL;
  1330. if (lcd_init == 0)
  1331. {
  1332. lcd_init = 1;
  1333. lcd = rt_device_find("lcd");
  1334. rt_device_init(lcd);
  1335. }
  1336. if (argc == 1)
  1337. {
  1338. lcd_auto_fill((void *)1);
  1339. }
  1340. else if (argc == 3)
  1341. {
  1342. if (rt_strcmp(argv[1], "-t") == 0)
  1343. {
  1344. rt_thread_t tid = RT_NULL;
  1345. tid = rt_thread_create("lcd_fill", lcd_auto_fill, (void *)atoi(argv[2]), 512, 23, 10);
  1346. rt_thread_startup(tid);
  1347. }
  1348. }
  1349. }
  1350. MSH_CMD_EXPORT(lcd_fill_test, lcd fill test for mcu lcd);
  1351. #endif