drv_lcd.c 40 KB

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