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 * 2023-03-24 spaceman the first version
9 */
10
11 #include <board.h>
12
13 #ifdef BSP_USING_LCD_SPI
14 #include <drv_spi.h>
15 #include <drv_lcd_spi.h>
16 #include <drv_lcd_spi_ext.h>
17 #include <lcd_port.h>
18 #include <string.h>
19
20 #define DRV_DEBUG
21 #define LOG_TAG "drv.lcd"
22 #include <drv_log.h>
23
24 #define ABS(X) ((X) > 0 ? (X) : -(X))
25
26 static struct drv_lcd_device _lcd;
27 static rt_uint8_t lcd_bn = 0;
28
29 // 因为这类SPI的屏幕,每次更新显示时,需要先配置坐标区域、再写显存,
30 // 在显示字符时,如果是一个个点去写坐标写显存,会非常慢,
31 // 因此开辟一片缓冲区,先将需要显示的数据写进缓冲区,最后再批量写入显存。
32 // 用户可以根据实际情况去修改此处缓冲区的大小,
33 // 例如,用户需要显示32*32的汉字时,需要的大小为 32*32*2 = 2048 字节(每个像素点占2字节)
34 static uint16_t LCD_Buff[1024]; // LCD缓冲区,16位宽(每个像素点占2字节)
35
set_lcd_backlight(rt_uint8_t value)36 static void set_lcd_backlight(rt_uint8_t value)
37 {
38 if (value)
39 rt_pin_write(LCD_BACKLIGHT_PIN, PIN_HIGH);
40 else
41 rt_pin_write(LCD_BACKLIGHT_PIN, PIN_LOW);
42 lcd_bn = value;
43 }
44
get_lcd_backlight(void)45 static rt_uint8_t get_lcd_backlight(void)
46 {
47 return lcd_bn;
48 }
49
lcd_writecommand(uint8_t lcd_command)50 static void lcd_writecommand(uint8_t lcd_command)
51 {
52 rt_pin_write(LCD_CMD_DATA_PIN, PIN_LOW); // cmd
53 rt_spi_send((struct rt_spi_device *)_lcd.lcd_spi_dev, &lcd_command, 1);
54 }
55
lcd_writedata_8bit(uint8_t lcd_data)56 static void lcd_writedata_8bit(uint8_t lcd_data)
57 {
58 rt_pin_write(LCD_CMD_DATA_PIN, PIN_HIGH); // data
59 rt_spi_send((struct rt_spi_device *)_lcd.lcd_spi_dev, &lcd_data, 1);
60 }
61
lcd_writedata_16bit(uint16_t lcd_data)62 static void lcd_writedata_16bit(uint16_t lcd_data)
63 {
64 uint8_t lcd_data_buff[2]; // 数据发送区
65 lcd_data_buff[0] = lcd_data >> 8; // 将数据拆分
66 lcd_data_buff[1] = lcd_data;
67
68 rt_pin_write(LCD_CMD_DATA_PIN, PIN_HIGH); // data
69 rt_spi_send((struct rt_spi_device *)_lcd.lcd_spi_dev, lcd_data_buff, 2);
70 }
71
lcd_writebuff(uint16_t * databuff,uint16_t datasize)72 void lcd_writebuff(uint16_t *databuff, uint16_t datasize)
73 {
74 struct stm32_spi *spi_drv = rt_container_of(((struct rt_spi_device *)_lcd.lcd_spi_dev)->bus, struct stm32_spi, spi_bus);
75 SPI_HandleTypeDef *spi_handle = &spi_drv->handle;
76
77 rt_pin_write(LCD_CMD_DATA_PIN, PIN_HIGH); // data
78
79 // Additional setting (FifoThreshold) are required here, so we do not use rt_spi_configure
80 spi_handle->Init.DataSize = SPI_DATASIZE_16BIT;
81 spi_handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_02DATA;
82 HAL_SPI_Init(spi_handle);
83
84 rt_spi_send((struct rt_spi_device *)_lcd.lcd_spi_dev, databuff, datasize);
85
86 spi_handle->Init.DataSize = SPI_DATASIZE_8BIT;
87 spi_handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_08DATA;
88 HAL_SPI_Init(spi_handle);
89 }
90
lcd_setaddress(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)91 void lcd_setaddress(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
92 {
93 lcd_writecommand(0x2a); // 列地址设置,即X坐标
94 lcd_writedata_16bit(x1);
95 lcd_writedata_16bit(x2);
96
97 lcd_writecommand(0x2b); // 行地址设置,即Y坐标
98 lcd_writedata_16bit(y1);
99 lcd_writedata_16bit(y2);
100
101 lcd_writecommand(0x2c); // 开始写入显存,即要显示的颜色数据
102 }
103
lcd_clear(uint32_t color)104 void lcd_clear(uint32_t color)
105 {
106 rt_err_t res;
107 struct stm32_spi *spi_drv = rt_container_of(((struct rt_spi_device *)_lcd.lcd_spi_dev)->bus, struct stm32_spi, spi_bus);
108 SPI_HandleTypeDef *spi_handle = &spi_drv->handle;
109
110 lcd_setaddress(0, 0, LCD_WIDTH - 1, LCD_HEIGHT - 1); // 设置坐标
111
112 rt_pin_write(LCD_CMD_DATA_PIN, PIN_HIGH); // data
113
114 // Additional setting (FifoThreshold) are required here, so we do not use rt_spi_configure
115 spi_handle->Init.DataSize = SPI_DATASIZE_16BIT;
116 spi_handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_02DATA;
117 HAL_SPI_Init(spi_handle);
118
119 rt_pin_write(LCD_SPI_DEV_CS_PIN, PIN_LOW); // cs
120 res = SPI_Transmit_Ext((uint16_t)color, LCD_WIDTH * LCD_HEIGHT);
121 rt_pin_write(LCD_SPI_DEV_CS_PIN, PIN_HIGH); // cs
122 if(res != RT_EOK)
123 LOG_E("SPI_Transmit_Ext error: %d", res);
124
125 spi_handle->Init.DataSize = SPI_DATASIZE_8BIT;
126 spi_handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_08DATA;
127 HAL_SPI_Init(spi_handle);
128 }
129
lcd_clearrect(uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint32_t color)130 void lcd_clearrect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color)
131 {
132 rt_err_t res;
133 struct stm32_spi *spi_drv = rt_container_of(((struct rt_spi_device *)_lcd.lcd_spi_dev)->bus, struct stm32_spi, spi_bus);
134 SPI_HandleTypeDef *spi_handle = &spi_drv->handle;
135
136 lcd_setaddress(x, y, x + width - 1, y + height - 1); // 设置坐标
137
138 rt_pin_write(LCD_CMD_DATA_PIN, PIN_HIGH); // data
139
140 // Additional setting (FifoThreshold) are required here, so we do not use rt_spi_configure
141 spi_handle->Init.DataSize = SPI_DATASIZE_16BIT;
142 spi_handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_02DATA;
143 HAL_SPI_Init(spi_handle);
144
145 rt_pin_write(LCD_SPI_DEV_CS_PIN, PIN_LOW); // cs
146 res = SPI_Transmit_Ext((uint16_t)color, width * height);
147 rt_pin_write(LCD_SPI_DEV_CS_PIN, PIN_HIGH); // cs
148 if(res != RT_EOK)
149 LOG_E("SPI_Transmit_Ext error: %d", res);
150
151 spi_handle->Init.DataSize = SPI_DATASIZE_8BIT;
152 spi_handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_08DATA;
153 HAL_SPI_Init(spi_handle);
154 }
155
lcd_copybuffer(uint16_t x,uint16_t y,uint16_t width,uint16_t height,uint16_t * databuff)156 void lcd_copybuffer(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t *databuff)
157 {
158 rt_err_t res;
159 struct stm32_spi *spi_drv = rt_container_of(((struct rt_spi_device *)_lcd.lcd_spi_dev)->bus, struct stm32_spi, spi_bus);
160 SPI_HandleTypeDef *spi_handle = &spi_drv->handle;
161
162 lcd_setaddress(x, y, x + width - 1, y + height - 1); // 设置坐标
163
164 rt_pin_write(LCD_CMD_DATA_PIN, PIN_HIGH); // data
165
166 // Additional setting (FifoThreshold) are required here, so we do not use rt_spi_configure
167 spi_handle->Init.DataSize = SPI_DATASIZE_16BIT;
168 spi_handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_02DATA;
169 HAL_SPI_Init(spi_handle);
170
171 rt_pin_write(LCD_SPI_DEV_CS_PIN, PIN_LOW); // cs
172 res = SPI_TransmitBuffer_Ext(databuff, width * height);
173 rt_pin_write(LCD_SPI_DEV_CS_PIN, PIN_HIGH); // cs
174 if(res != RT_EOK)
175 LOG_E("SPI_TransmitBuffer_Ext error: %d", res);
176
177 spi_handle->Init.DataSize = SPI_DATASIZE_8BIT;
178 spi_handle->Init.FifoThreshold = SPI_FIFO_THRESHOLD_08DATA;
179 HAL_SPI_Init(spi_handle);
180 }
181
lcd_drawpoint(uint16_t x,uint16_t y,uint32_t color)182 void lcd_drawpoint(uint16_t x, uint16_t y, uint32_t color)
183 {
184 lcd_setaddress(x, y, x, y); // 设置坐标
185 lcd_writedata_16bit(color);
186 }
187
lcd_drawline(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,uint32_t color)188 void lcd_drawline(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint32_t color)
189 {
190 int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
191 yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,
192 curpixel = 0;
193
194 deltax = ABS(x2 - x1); /* The difference between the x's */
195 deltay = ABS(y2 - y1); /* The difference between the y's */
196 x = x1; /* Start x off at the first pixel */
197 y = y1; /* Start y off at the first pixel */
198
199 if (x2 >= x1) /* The x-values are increasing */
200 {
201 xinc1 = 1;
202 xinc2 = 1;
203 } else /* The x-values are decreasing */
204 {
205 xinc1 = -1;
206 xinc2 = -1;
207 }
208
209 if (y2 >= y1) /* The y-values are increasing */
210 {
211 yinc1 = 1;
212 yinc2 = 1;
213 } else /* The y-values are decreasing */
214 {
215 yinc1 = -1;
216 yinc2 = -1;
217 }
218
219 if (deltax >= deltay) /* There is at least one x-value for every y-value */
220 {
221 xinc1 = 0; /* Don't change the x when numerator >= denominator */
222 yinc2 = 0; /* Don't change the y for every iteration */
223 den = deltax;
224 num = deltax / 2;
225 numadd = deltay;
226 numpixels = deltax; /* There are more x-values than y-values */
227 } else /* There is at least one y-value for every x-value */
228 {
229 xinc2 = 0; /* Don't change the x for every iteration */
230 yinc1 = 0; /* Don't change the y when numerator >= denominator */
231 den = deltay;
232 num = deltay / 2;
233 numadd = deltax;
234 numpixels = deltay; /* There are more y-values than x-values */
235 }
236 for (curpixel = 0; curpixel <= numpixels; curpixel++) {
237 lcd_drawpoint(x, y, color); /* Draw the current pixel */
238 num += numadd; /* Increase the numerator by the top of the fraction */
239 if (num >= den) /* Check if numerator >= denominator */
240 {
241 num -= den; /* Calculate the new numerator value */
242 x += xinc1; /* Change the x as appropriate */
243 y += yinc1; /* Change the y as appropriate */
244 }
245 x += xinc2; /* Change the x as appropriate */
246 y += yinc2; /* Change the y as appropriate */
247 }
248 }
249
lcd_drawline_v(uint16_t x,uint16_t y,uint16_t height,uint32_t color)250 void lcd_drawline_v(uint16_t x, uint16_t y, uint16_t height, uint32_t color)
251 {
252 uint16_t i; // 计数变量
253 for (i = 0; i < height; i++) {
254 LCD_Buff[i] = color; // 写入缓冲区
255 }
256 lcd_setaddress(x, y, x, y + height - 1); // 设置坐标
257 lcd_writebuff(LCD_Buff, height); // 写入显存
258 }
259
lcd_drawline_h(uint16_t x,uint16_t y,uint16_t width,uint32_t color)260 void lcd_drawline_h(uint16_t x, uint16_t y, uint16_t width, uint32_t color)
261 {
262 uint16_t i; // 计数变量
263 for (i = 0; i < width; i++) {
264 LCD_Buff[i] = color; // 写入缓冲区
265 }
266 lcd_setaddress(x, y, x + width - 1, y); // 设置坐标
267 lcd_writebuff(LCD_Buff, width); // 写入显存
268 }
269
stm32_lcd_init(struct drv_lcd_device * lcd)270 static rt_err_t stm32_lcd_init(struct drv_lcd_device *lcd)
271 {
272 rt_err_t result;
273 struct rt_spi_configuration cfg;
274
275 result = rt_hw_spi_device_attach(LCD_SPI_BUS_NAME, LCD_SPI_DEV_NAME, LCD_SPI_DEV_CS_PIN);
276
277 lcd->lcd_spi_dev = rt_device_find(LCD_SPI_DEV_NAME);
278 cfg.data_width = 8;
279 cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB | RT_SPI_3WIRE;
280 cfg.max_hz = LCD_SPI_MAX_SPEED;
281 rt_spi_configure((struct rt_spi_device *)lcd->lcd_spi_dev, &cfg);
282
283 rt_pin_mode(LCD_BACKLIGHT_PIN, PIN_MODE_OUTPUT);
284 rt_pin_mode(LCD_CMD_DATA_PIN, PIN_MODE_OUTPUT);
285
286 // init lcd
287 rt_thread_mdelay(10);
288 lcd_writecommand(0x36); // 显存访问控制 指令,用于设置访问显存的方式
289 lcd_writedata_8bit(0x00); // 配置成 从上到下、从左到右,RGB像素格式 垂直显示
290 // lcd_writedata_8bit(0x70); // 横屏显示
291 // lcd_writedata_8bit(0xA0); // 横屏显示,并上下翻转,RGB像素格式
292 // lcd_writedata_8bit(0xC0); // 垂直显示,并上下翻转,RGB像素格式
293
294 lcd_writecommand(0x3A); // 接口像素格式 指令,用于设置使用 12位、16位还是18位色
295 lcd_writedata_8bit(0x05); // 此处配置成 16位 像素格式
296
297 // 接下来很多都是电压设置指令,直接使用厂家给设定值
298 lcd_writecommand(0xB2);
299 lcd_writedata_8bit(0x0C);
300 lcd_writedata_8bit(0x0C);
301 lcd_writedata_8bit(0x00);
302 lcd_writedata_8bit(0x33);
303 lcd_writedata_8bit(0x33);
304
305 lcd_writecommand(0xB7); // 栅极电压设置指令
306 lcd_writedata_8bit(0x35); // VGH = 13.26V,VGL = -10.43V
307
308 lcd_writecommand(0xBB); // 公共电压设置指令
309 lcd_writedata_8bit(0x19); // VCOM = 1.35V
310
311 lcd_writecommand(0xC0);
312 lcd_writedata_8bit(0x2C);
313
314 lcd_writecommand(0xC2); // VDV 和 VRH 来源设置
315 lcd_writedata_8bit(0x01); // VDV 和 VRH 由用户自由配置
316
317 lcd_writecommand(0xC3); // VRH电压 设置指令
318 lcd_writedata_8bit(0x12); // VRH电压 = 4.6+( vcom+vcom offset+vdv)
319
320 lcd_writecommand(0xC4); // VDV电压 设置指令
321 lcd_writedata_8bit(0x20); // VDV电压 = 0v
322
323 lcd_writecommand(0xC6); // 正常模式的帧率控制指令
324 lcd_writedata_8bit(0x0F); // 设置屏幕控制器的刷新帧率为60帧
325
326 lcd_writecommand(0xD0); // 电源控制指令
327 lcd_writedata_8bit(0xA4); // 无效数据,固定写入0xA4
328 lcd_writedata_8bit(0xA1); // AVDD = 6.8V ,AVDD = -4.8V ,VDS = 2.3V
329
330 lcd_writecommand(0xE0); // 正极电压伽马值设定
331 lcd_writedata_8bit(0xD0);
332 lcd_writedata_8bit(0x04);
333 lcd_writedata_8bit(0x0D);
334 lcd_writedata_8bit(0x11);
335 lcd_writedata_8bit(0x13);
336 lcd_writedata_8bit(0x2B);
337 lcd_writedata_8bit(0x3F);
338 lcd_writedata_8bit(0x54);
339 lcd_writedata_8bit(0x4C);
340 lcd_writedata_8bit(0x18);
341 lcd_writedata_8bit(0x0D);
342 lcd_writedata_8bit(0x0B);
343 lcd_writedata_8bit(0x1F);
344 lcd_writedata_8bit(0x23);
345
346 lcd_writecommand(0xE1); // 负极电压伽马值设定
347 lcd_writedata_8bit(0xD0);
348 lcd_writedata_8bit(0x04);
349 lcd_writedata_8bit(0x0C);
350 lcd_writedata_8bit(0x11);
351 lcd_writedata_8bit(0x13);
352 lcd_writedata_8bit(0x2C);
353 lcd_writedata_8bit(0x3F);
354 lcd_writedata_8bit(0x44);
355 lcd_writedata_8bit(0x51);
356 lcd_writedata_8bit(0x2F);
357 lcd_writedata_8bit(0x1F);
358 lcd_writedata_8bit(0x1F);
359 lcd_writedata_8bit(0x20);
360 lcd_writedata_8bit(0x23);
361
362 lcd_writecommand(0x21); // 打开反显,因为面板是常黑型,操作需要反过来
363
364 // 退出休眠指令,LCD控制器在刚上电、复位时,会自动进入休眠模式 ,因此操作屏幕之前,需要退出休眠
365 lcd_writecommand(0x11); // 退出休眠 指令
366 rt_thread_mdelay(120); // 需要等待120ms,让电源电压和时钟电路稳定下来
367
368 // 打开显示指令,LCD控制器在刚上电、复位时,会自动关闭显示
369 lcd_writecommand(0x29); // 打开显示
370
371 // set spi handler to ensure SPI_Transmit_Ext/SPI_TransmitBuffer_Ext function can be used
372 struct stm32_spi *spi_drv = rt_container_of(((struct rt_spi_device *)lcd->lcd_spi_dev)->bus, struct stm32_spi, spi_bus);
373 SPI_HandleTypeDef *spi_handle = &spi_drv->handle;
374 Set_SPI_Handle_Ext(spi_handle);
375
376 lcd_clear(0xFFFFFF); // 清屏
377
378 // 全部设置完毕之后,打开背光
379 set_lcd_backlight(1);
380
381 LOG_D("lcd init ok");
382
383 // lcd_drawline_v(120, 0, LCD_HEIGHT, 0xffaaff);
384 // lcd_drawline_h(0, 120, LCD_WIDTH, 0xffaaff);
385
386 return result;
387 }
388
drv_lcd_init(struct rt_device * device)389 static rt_err_t drv_lcd_init(struct rt_device *device)
390 {
391 struct drv_lcd_device *lcd = LCD_DEVICE(device);
392 return stm32_lcd_init(lcd);
393 }
394
drv_lcd_control(struct rt_device * device,int cmd,void * args)395 static rt_err_t drv_lcd_control(struct rt_device *device, int cmd, void *args)
396 {
397 struct drv_lcd_device *lcd = LCD_DEVICE(device);
398
399 switch (cmd) {
400 case RTGRAPHIC_CTRL_RECT_UPDATE: {
401 lcd_setaddress(0, 0, lcd->lcd_info.width - 1, lcd->lcd_info.height - 1);
402 lcd_writebuff((uint16_t*)lcd->lcd_info.framebuffer, LCD_BUF_SIZE / 2); // 16 bit write buffer
403 } break;
404
405 case RTGRAPHIC_CTRL_GET_INFO: {
406 struct rt_device_graphic_info *info = (struct rt_device_graphic_info *)args;
407
408 RT_ASSERT(info != RT_NULL);
409 info->pixel_format = lcd->lcd_info.pixel_format;
410 info->bits_per_pixel = 16;
411 info->width = lcd->lcd_info.width;
412 info->height = lcd->lcd_info.height;
413 info->framebuffer = lcd->lcd_info.framebuffer;
414 } break;
415
416 case RTGRAPHIC_CTRL_SET_BRIGHTNESS: {
417 set_lcd_backlight(*((rt_uint8_t *)args));
418 } break;
419
420 case RTGRAPHIC_CTRL_GET_BRIGHTNESS: {
421 *((rt_uint8_t *)args) = get_lcd_backlight();
422 } break;
423
424 default:
425 return -RT_EINVAL;
426 }
427
428 return RT_EOK;
429 }
430
431 #ifdef RT_USING_DEVICE_OPS
432 const static struct rt_device_ops lcd_ops =
433 {
434 drv_lcd_init,
435 RT_NULL,
436 RT_NULL,
437 RT_NULL,
438 RT_NULL,
439 drv_lcd_control
440 };
441 #endif
442
set_pixel(const char * pixel,int x,int y)443 static void set_pixel(const char *pixel, int x, int y)
444 {
445 lcd_drawpoint(x, y, *pixel);
446 }
447
draw_hline(const char * pixel,int x1,int x2,int y)448 void draw_hline(const char *pixel, int x1, int x2, int y)
449 {
450 lcd_drawline_h(x1, y, ABS(x2 - x1), *((uint16_t*)pixel));
451 }
452
draw_vline(const char * pixel,int x,int y1,int y2)453 void draw_vline(const char *pixel, int x, int y1, int y2)
454 {
455 lcd_drawline_v(x, y1, ABS(y2 - y1), *((uint16_t*)pixel));
456 }
457
458 const static struct rt_device_graphic_ops lcd_graphic_ops =
459 {
460 set_pixel,
461 RT_NULL,
462 draw_hline,
463 draw_vline,
464 RT_NULL
465 };
466
drv_hw_lcd_init(void)467 int drv_hw_lcd_init(void)
468 {
469 rt_err_t result = RT_EOK;
470 struct rt_device *device = &_lcd.parent;
471
472 /* memset _lcd to zero */
473 memset(&_lcd, 0x00, sizeof(_lcd));
474
475 /* init lcd_lock semaphore */
476 result = rt_sem_init(&_lcd.lcd_lock, "lcd_lock", 0, RT_IPC_FLAG_FIFO);
477 if (result != RT_EOK) {
478 LOG_E("init semaphore failed!\n");
479 result = -RT_ENOMEM;
480 goto __exit;
481 }
482
483 /* config LCD dev info */
484 _lcd.lcd_info.height = LCD_HEIGHT;
485 _lcd.lcd_info.width = LCD_WIDTH;
486 _lcd.lcd_info.bits_per_pixel = LCD_BITS_PER_PIXEL;
487 _lcd.lcd_info.pixel_format = LCD_PIXEL_FORMAT;
488
489 /* malloc memory for Triple Buffering */
490 _lcd.lcd_info.framebuffer = rt_malloc_align(LCD_BUF_SIZE, 32);
491 _lcd.back_buf = rt_malloc_align(LCD_BUF_SIZE, 32);
492 _lcd.front_buf = rt_malloc_align(LCD_BUF_SIZE, 32);
493 if (_lcd.lcd_info.framebuffer == RT_NULL || _lcd.back_buf == RT_NULL || _lcd.front_buf == RT_NULL) {
494 LOG_E("init frame buffer failed!\n");
495 result = -RT_ENOMEM;
496 goto __exit;
497 }
498
499 /* memset buff to 0xFF */
500 memset(_lcd.lcd_info.framebuffer, 0xFF, LCD_BUF_SIZE);
501 memset(_lcd.back_buf, 0xFF, LCD_BUF_SIZE);
502 memset(_lcd.front_buf, 0xFF, LCD_BUF_SIZE);
503
504 device->type = RT_Device_Class_Graphic;
505 #ifdef RT_USING_DEVICE_OPS
506 device->ops = &lcd_ops;
507 #else
508 device->init = drv_lcd_init;
509 device->control = drv_lcd_control;
510 #endif
511 device->user_data = (void*)&lcd_graphic_ops;
512
513 /* register lcd device */
514 rt_device_register(device, "lcd", RT_DEVICE_FLAG_RDWR);
515
516 /* init stm32 spi lcd */
517 if (rt_device_init(device) != RT_EOK) {
518 result = -RT_ERROR;
519 goto __exit;
520 }
521
522 __exit:
523 if (result != RT_EOK) {
524 rt_sem_delete(&_lcd.lcd_lock);
525
526 if (_lcd.lcd_info.framebuffer) {
527 rt_free_align(_lcd.lcd_info.framebuffer);
528 }
529
530 if (_lcd.back_buf) {
531 rt_free_align(_lcd.back_buf);
532 }
533
534 if (_lcd.front_buf) {
535 rt_free_align(_lcd.front_buf);
536 }
537 }
538 return result;
539 }
540 INIT_DEVICE_EXPORT(drv_hw_lcd_init);
541
542 #ifdef DRV_DEBUG
543 #ifdef FINSH_USING_MSH
lcd_test()544 int lcd_test()
545 {
546 struct drv_lcd_device *lcd;
547 lcd = (struct drv_lcd_device *)rt_device_find("lcd");
548
549 rt_device_open((rt_device_t)lcd, RT_DEVICE_FLAG_RDWR);
550
551 while (1) {
552 /* red */
553 for (int i = 0; i < LCD_BUF_SIZE / 2; i++) {
554 lcd->lcd_info.framebuffer[2 * i] = 0x00;
555 lcd->lcd_info.framebuffer[2 * i + 1] = 0xF8;
556 }
557 // lcd_clear(0xFFFF00);
558 rt_device_control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
559 rt_thread_mdelay(1000);
560 /* green */
561 for (int i = 0; i < LCD_BUF_SIZE / 2; i++) {
562 lcd->lcd_info.framebuffer[2 * i] = 0xE0;
563 lcd->lcd_info.framebuffer[2 * i + 1] = 0x07;
564 }
565 // lcd_clear(0xFF00FF);
566 rt_device_control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
567 rt_thread_mdelay(1000);
568 /* blue */
569 for (int i = 0; i < LCD_BUF_SIZE / 2; i++) {
570 lcd->lcd_info.framebuffer[2 * i] = 0x1F;
571 lcd->lcd_info.framebuffer[2 * i + 1] = 0x00;
572 }
573 // lcd_clear(0x00FFFF);
574 rt_device_control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
575 rt_thread_mdelay(1000);
576 }
577 }
578 MSH_CMD_EXPORT(lcd_test, lcd_test);
579
lcd_auto_fill(void * para)580 void lcd_auto_fill(void *para)
581 {
582 int num = (int)para;
583 do
584 {
585 lcd_clear(rt_tick_get());
586 rt_thread_mdelay(1000);
587 }while(--num);
588 }
589
590 #include <stdlib.h> /* atoi */
lcd_fill(int argc,void ** argv)591 void lcd_fill(int argc, void **argv)
592 {
593 static rt_uint8_t lcd_init = 0;
594 rt_device_t lcd = RT_NULL;
595
596 if(lcd_init == 0)
597 {
598 lcd_init = 1;
599
600 lcd = rt_device_find("lcd");
601 rt_device_init(lcd);
602 }
603
604 if(argc == 1)
605 {
606 lcd_auto_fill((void *)1);
607 }
608 else if(argc == 3)
609 {
610 if(rt_strcmp(argv[1], "-t")==0)
611 {
612 rt_thread_t tid = RT_NULL;
613 tid = rt_thread_create("lcd_fill", lcd_auto_fill, (void *)atoi(argv[2]), 512, 23,10);
614 rt_thread_startup(tid);
615 }
616 }
617 }
618 MSH_CMD_EXPORT(lcd_fill, lcd fill test for mcu lcd);
619 #endif /* FINSH_USING_MSH */
620 #endif /* DRV_DEBUG */
621 #endif /* BSP_USING_LCD */
622