1 /**
2 ******************************************************************************
3 * @file st7735.c
4 * @author MCD Application Team
5 * @brief This file includes the driver for ST7735 LCD mounted on the Adafruit
6 * 1.8" TFT LCD shield (reference ID 802).
7 ******************************************************************************
8 * @attention
9 *
10 * <h2><center>© Copyright (c) 2018 STMicroelectronics.
11 * All rights reserved.</center></h2>
12 *
13 * This software component is licensed by ST under BSD 3-Clause license,
14 * the "License"; You may not use this file except in compliance with the
15 * License. You may obtain a copy of the License at:
16 * opensource.org/licenses/BSD-3-Clause
17 *
18 ******************************************************************************
19 */
20
21 /* Includes ------------------------------------------------------------------*/
22 #include <rtthread.h>
23 #include <rtdevice.h>
24 #include <board.h>
25 #include "st7735.h"
26
27 #define DRV_DEBUG
28 #define LOG_TAG "st7735"
29 #include <drv_log.h>
30
31 #define IS_BOE_PANEL (0)
32
33 /** @addtogroup BSP
34 * @{
35 */
36
37 /** @addtogroup Components
38 * @{
39 */
40
41 /** @addtogroup ST7735
42 * @brief This file provides a set of functions needed to drive the
43 * ST7735 LCD.
44 * @{
45 */
46
47 /** @defgroup ST7735_Private_Types Private Types
48 * @{
49 */
50 typedef struct
51 {
52 uint32_t Width;
53 uint32_t Height;
54 uint32_t Orientation;
55 } ST7735_Ctx_t;
56 /**
57 * @}
58 */
59
60 /** @defgroup ST7735_Private_Variables Private Variables
61 * @{
62 */
63 ST7735_LCD_Drv_t ST7735_LCD_Driver =
64 {
65 ST7735_Init,
66 ST7735_DeInit,
67 ST7735_ReadID,
68 ST7735_DisplayOn,
69 ST7735_DisplayOff,
70 ST7735_SetBrightness,
71 ST7735_GetBrightness,
72 ST7735_SetOrientation,
73 ST7735_GetOrientation,
74 ST7735_SetCursor,
75 ST7735_DrawBitmap,
76 ST7735_FillRGBRect,
77 ST7735_DrawHLine,
78 ST7735_DrawVLine,
79 ST7735_FillRect,
80 ST7735_GetPixel,
81 ST7735_SetPixel,
82 ST7735_GetXSize,
83 ST7735_GetYSize,
84 };
85
86 /* The below table handle the different values to be set to Memory Data Access Control
87 depending on the orientation and pbm image writing where the data order is inverted
88 */
89 static uint32_t OrientationTab[4][2] =
90 {
91 {0x48U , 0xC8U}, /* Portrait orientation choice of LCD screen */
92 {0x88U , 0x08U}, /* Portrait rotated 180° orientation choice of LCD screen */
93 {0x28U , 0x68U}, /* Landscape orientation choice of LCD screen */
94 {0xE8U , 0xA8U} /* Landscape rotated 180° orientation choice of LCD screen */
95 };
96
97 static ST7735_Ctx_t ST7735Ctx;
98 /**
99 * @}
100 */
101
102 /** @defgroup ST7735_Private_FunctionsPrototypes Private Functions Prototypes
103 * @{
104 */
105 static int32_t ST7735_SetDisplayWindow(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Width, uint32_t Height);
106 static int32_t ST7735_ReadRegWrap(void *Handle, uint8_t Reg, uint8_t* pData);
107 static int32_t ST7735_WriteRegWrap(void *Handle, uint8_t Reg, uint8_t *pData, uint32_t Length);
108 static int32_t ST7735_SendDataWrap(void *Handle, uint8_t *pData, uint32_t Length);
109 static int32_t ST7735_RecvDataWrap(void *Handle, uint8_t *pData, uint32_t Length);
110 static int32_t ST7735_IO_Delay(ST7735_Object_t *pObj, uint32_t Delay);
111 /**
112 * @}
113 */
114
115 /** @addtogroup ST7735_Exported_Functions
116 * @{
117 */
118 /**
119 * @brief Register component IO bus
120 * @param pObj Component object pointer
121 * @param pIO Component IO structure pointer
122 * @retval Component status
123 */
ST7735_RegisterBusIO(ST7735_Object_t * pObj,ST7735_IO_t * pIO)124 int32_t ST7735_RegisterBusIO (ST7735_Object_t *pObj, ST7735_IO_t *pIO)
125 {
126 int32_t ret;
127
128 if(pObj == NULL)
129 {
130 ret = ST7735_ERROR;
131 }
132 else
133 {
134 pObj->IO.Init = pIO->Init;
135 pObj->IO.DeInit = pIO->DeInit;
136 pObj->IO.Address = pIO->Address;
137 pObj->IO.WriteReg = pIO->WriteReg;
138 pObj->IO.ReadReg = pIO->ReadReg;
139 pObj->IO.SendData = pIO->SendData;
140 pObj->IO.RecvData = pIO->RecvData;
141 pObj->IO.GetTick = pIO->GetTick;
142
143 pObj->Ctx.ReadReg = ST7735_ReadRegWrap;
144 pObj->Ctx.WriteReg = ST7735_WriteRegWrap;
145 pObj->Ctx.SendData = ST7735_SendDataWrap;
146 pObj->Ctx.RecvData = ST7735_RecvDataWrap;
147 pObj->Ctx.handle = pObj;
148
149 if(pObj->IO.Init != NULL)
150 {
151 ret = pObj->IO.Init();
152 }
153 else
154 {
155 ret = ST7735_ERROR;
156 }
157 }
158
159 return ret;
160 }
161
162 /**
163 * @brief Initialize the st7735 LCD Component.
164 * @param pObj Component object
165 * @param ColorCoding RGB mode
166 * @param Orientation Display orientation
167 * @retval Component status
168 */
ST7735_Init(ST7735_Object_t * pObj,uint32_t ColorCoding,uint32_t Orientation)169 int32_t ST7735_Init(ST7735_Object_t *pObj, uint32_t ColorCoding, uint32_t Orientation)
170 {
171 uint8_t tmp;
172 int32_t ret;
173
174 if(pObj == NULL)
175 {
176 ret = ST7735_ERROR;
177 }
178 else
179 {
180 /* Out of sleep mode, 0 args, delay 120ms */
181 tmp = 0x00U;
182 ret = st7735_write_reg(&pObj->Ctx, ST7735_SW_RESET, &tmp, 0);
183 (void)ST7735_IO_Delay(pObj, 120);
184
185 /* Out of sleep mode, 0 args, no delay */
186 tmp = 0x00U;
187 ret += st7735_write_reg(&pObj->Ctx, ST7735_SLEEP_OUT, &tmp, 1);
188
189 /* Frame rate ctrl - normal mode, 3 args:Rate = fosc/(1x2+40) * (LINE+2C+2D)*/
190 ret += st7735_write_reg(&pObj->Ctx, ST7735_FRAME_RATE_CTRL1, &tmp, 0);
191 tmp = 0x01U;
192 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
193 tmp = 0x2CU;
194 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
195 tmp = 0x2DU;
196 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
197
198 /* Frame rate control - idle mode, 3 args:Rate = fosc/(1x2+40) * (LINE+2C+2D) */
199 tmp = 0x01U;
200 ret += st7735_write_reg(&pObj->Ctx, ST7735_FRAME_RATE_CTRL2, &tmp, 1);
201 tmp = 0x2CU;
202 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
203 tmp = 0x2DU;
204 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
205
206 /* Frame rate ctrl - partial mode, 6 args: Dot inversion mode, Line inversion mode */
207 tmp = 0x01U;
208 ret += st7735_write_reg(&pObj->Ctx, ST7735_FRAME_RATE_CTRL3, &tmp, 1);
209 tmp = 0x2CU;
210 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
211 tmp = 0x2DU;
212 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
213 tmp = 0x01U;
214 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
215 tmp = 0x2CU;
216 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
217 tmp = 0x2DU;
218 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
219
220 /* Display inversion ctrl, 1 arg, no delay: No inversion */
221 tmp = 0x07U;
222 ret += st7735_write_reg(&pObj->Ctx, ST7735_FRAME_INVERSION_CTRL, &tmp, 1);
223
224 /* Power control, 3 args, no delay: -4.6V , AUTO mode */
225 tmp = 0xA2U;
226 ret += st7735_write_reg(&pObj->Ctx, ST7735_PWR_CTRL1, &tmp, 1);
227 tmp = 0x02U;
228 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
229 tmp = 0x84U;
230 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
231
232 /* Power control, 1 arg, no delay: VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD */
233 tmp = 0xC5U;
234 ret += st7735_write_reg(&pObj->Ctx, ST7735_PWR_CTRL2, &tmp, 1);
235
236 /* Power control, 2 args, no delay: Opamp current small, Boost frequency */
237 tmp = 0x0AU;
238 ret += st7735_write_reg(&pObj->Ctx, ST7735_PWR_CTRL3, &tmp, 1);
239 tmp = 0x00U;
240 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
241
242 /* Power control, 2 args, no delay: BCLK/2, Opamp current small & Medium low */
243 tmp = 0x8AU;
244 ret += st7735_write_reg(&pObj->Ctx, ST7735_PWR_CTRL4, &tmp, 1);
245 tmp = 0x2AU;
246 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
247
248 /* Power control, 2 args, no delay */
249 tmp = 0x8AU;
250 ret += st7735_write_reg(&pObj->Ctx, ST7735_PWR_CTRL5, &tmp, 1);
251 tmp = 0xEEU;
252 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
253
254 /* Power control, 1 arg, no delay */
255 tmp = 0x0EU;
256 ret += st7735_write_reg(&pObj->Ctx, ST7735_VCOMH_VCOML_CTRL1, &tmp, 1);
257
258 #if IS_BOE_PANEL
259 /* Not Invert display, no args, no delay */
260 ret += st7735_write_reg(&pObj->Ctx, ST7735_DISPLAY_INVERSION_OFF, &tmp, 0);
261 #else
262 /* Invert display, no args, no delay */
263 ret += st7735_write_reg(&pObj->Ctx, ST7735_DISPLAY_INVERSION_ON, &tmp, 0);
264 #endif
265 /* Set color mode, 1 arg, no delay */
266 ret += st7735_write_reg(&pObj->Ctx, ST7735_COLOR_MODE, (uint8_t*)&ColorCoding, 1);
267
268 /* Magical unicorn dust, 16 args, no delay */
269 tmp = 0x02U;
270 ret += st7735_write_reg(&pObj->Ctx, ST7735_PV_GAMMA_CTRL, &tmp, 1);
271 tmp = 0x1CU;
272 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
273 tmp = 0x07U;
274 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
275 tmp = 0x12U;
276 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
277 tmp = 0x37U;
278 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
279 tmp = 0x32U;
280 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
281 tmp = 0x29U;
282 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
283 tmp = 0x2DU;
284 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
285 tmp = 0x29U;
286 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
287 tmp = 0x25U;
288 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
289 tmp = 0x2BU;
290 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
291 tmp = 0x39U;
292 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
293 tmp = 0x00U;
294 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
295 tmp = 0x01U;
296 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
297 tmp = 0x03U;
298 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
299 tmp = 0x10U;
300 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
301
302 /* Sparkles and rainbows, 16 args, no delay */
303 tmp = 0x03U;
304 ret += st7735_write_reg(&pObj->Ctx, ST7735_NV_GAMMA_CTRL, &tmp, 1);
305 tmp = 0x1DU;
306 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
307 tmp = 0x07U;
308 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
309 tmp = 0x06U;
310 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
311 tmp = 0x2EU;
312 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
313 tmp = 0x2CU;
314 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
315 tmp = 0x29U;
316 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
317 tmp = 0x2DU;
318 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
319 tmp = 0x2EU;
320 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
321 tmp = 0x2EU;
322 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
323 tmp = 0x37U;
324 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
325 tmp = 0x3FU;
326 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
327 tmp = 0x00U;
328 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
329 tmp = 0x00U;
330 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
331 tmp = 0x02U;
332 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
333 tmp = 0x10U;
334 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
335
336 /* Normal display on, no args, no delay */
337 tmp = 0x00U;
338 ret += st7735_write_reg(&pObj->Ctx, ST7735_NORMAL_DISPLAY_OFF, &tmp, 1);
339
340 /* Main screen turn on, no delay */
341 ret += st7735_write_reg(&pObj->Ctx, ST7735_DISPLAY_ON, &tmp, 1);
342
343 /* Set the display Orientation and the default display window */
344 ret += ST7735_SetOrientation(pObj, Orientation);
345 }
346
347 if(ret != ST7735_OK)
348 {
349 LOG_E("error %d", ret);
350 ret = ST7735_ERROR;
351 }
352
353 return ret;
354 }
355
356 /**
357 * @brief De-Initialize the st7735 LCD Component.
358 * @param pObj Component object
359 * @retval Component status
360 */
ST7735_DeInit(ST7735_Object_t * pObj)361 int32_t ST7735_DeInit(ST7735_Object_t *pObj)
362 {
363 (void)(pObj);
364
365 return ST7735_OK;
366 }
367
368 /**
369 * @brief Get the st7735 ID.
370 * @param pObj Component object
371 * @param Id Component ID
372 * @retval The component status
373 */
ST7735_ReadID(ST7735_Object_t * pObj,uint32_t * Id)374 int32_t ST7735_ReadID(ST7735_Object_t *pObj, uint32_t *Id)
375 {
376 int32_t ret;
377 uint8_t tmp[3];
378
379 if(st7735_read_reg(&pObj->Ctx, ST7735_READ_ID1, &tmp[0]) != ST7735_OK)
380 {
381 ret = ST7735_ERROR;
382 }
383 else if(st7735_read_reg(&pObj->Ctx, ST7735_READ_ID2, &tmp[1]) != ST7735_OK)
384 {
385 ret = ST7735_ERROR;
386 }
387 else if(st7735_read_reg(&pObj->Ctx, ST7735_READ_ID3, &tmp[2]) != ST7735_OK)
388 {
389 ret = ST7735_ERROR;
390 }
391 else
392 {
393
394 *Id = ((uint32_t)tmp[2])<<0| ((uint32_t)tmp[1])<<8 | ((uint32_t)tmp[0])<<16;
395 //*Id = __rbit(*Id);
396 ret = ST7735_OK;
397 }
398
399 return ret;
400 }
401
402 /**
403 * @brief Enables the Display.
404 * @param pObj Component object
405 * @retval The component status
406 */
ST7735_DisplayOn(ST7735_Object_t * pObj)407 int32_t ST7735_DisplayOn(ST7735_Object_t *pObj)
408 {
409 int32_t ret;
410 uint8_t tmp = 0;
411
412 ret = st7735_write_reg(&pObj->Ctx, ST7735_NORMAL_DISPLAY_OFF, &tmp, 0);
413 (void)ST7735_IO_Delay(pObj, 10);
414 ret += st7735_write_reg(&pObj->Ctx, ST7735_DISPLAY_ON, &tmp, 0);
415 (void)ST7735_IO_Delay(pObj, 10);
416 ret += st7735_write_reg(&pObj->Ctx, ST7735_MADCTL, &tmp, 0);
417 tmp = (uint8_t)OrientationTab[ST7735Ctx.Orientation][1];
418 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
419 if(ret != ST7735_OK)
420 {
421 ret = ST7735_ERROR;
422 }
423
424 return ret;
425 }
426
427 /**
428 * @brief Disables the Display.
429 * @param pObj Component object
430 * @retval The component status
431 */
ST7735_DisplayOff(ST7735_Object_t * pObj)432 int32_t ST7735_DisplayOff(ST7735_Object_t *pObj)
433 {
434 int32_t ret;
435 uint8_t tmp = 0;
436
437 ret = st7735_write_reg(&pObj->Ctx, ST7735_NORMAL_DISPLAY_OFF, &tmp, 0);
438 (void)ST7735_IO_Delay(pObj, 10);
439 ret += st7735_write_reg(&pObj->Ctx, ST7735_DISPLAY_OFF, &tmp, 0);
440 (void)ST7735_IO_Delay(pObj, 10);
441 ret += st7735_write_reg(&pObj->Ctx, ST7735_MADCTL, &tmp, 0);
442 tmp = (uint8_t)OrientationTab[ST7735Ctx.Orientation][1];
443 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
444 if(ret != ST7735_OK)
445 {
446 ret = ST7735_ERROR;
447 }
448
449 return ret;
450 }
451
452 /**
453 * @brief Set the display brightness.
454 * @param pObj Component object
455 * @param Brightness display brightness to be set
456 * @retval Component status
457 */
ST7735_SetBrightness(ST7735_Object_t * pObj,uint32_t Brightness)458 int32_t ST7735_SetBrightness(ST7735_Object_t *pObj, uint32_t Brightness)
459 {
460 (void)(pObj);
461 (void)(Brightness);
462
463 /* Feature not supported */
464 return ST7735_ERROR;
465 }
466
467 /**
468 * @brief Get the display brightness.
469 * @param pObj Component object
470 * @param Brightness display brightness to be returned
471 * @retval Component status
472 */
ST7735_GetBrightness(ST7735_Object_t * pObj,uint32_t * Brightness)473 int32_t ST7735_GetBrightness(ST7735_Object_t *pObj, uint32_t *Brightness)
474 {
475 (void)(pObj);
476 (void)(Brightness);
477
478 /* Feature not supported */
479 return ST7735_ERROR;
480 }
481
482 /**
483 * @brief Set the Display Orientation.
484 * @param pObj Component object
485 * @param Orientation ST7735_ORIENTATION_PORTRAIT, ST7735_ORIENTATION_PORTRAIT_ROT180
486 * ST7735_ORIENTATION_LANDSCAPE or ST7735_ORIENTATION_LANDSCAPE_ROT180
487 * @retval The component status
488 */
ST7735_SetOrientation(ST7735_Object_t * pObj,uint32_t Orientation)489 int32_t ST7735_SetOrientation(ST7735_Object_t *pObj, uint32_t Orientation)
490 {
491 int32_t ret;
492 uint8_t tmp;
493
494 if((Orientation == ST7735_ORIENTATION_PORTRAIT) || (Orientation == ST7735_ORIENTATION_PORTRAIT_ROT180))
495 {
496 ST7735Ctx.Width = ST7735_WIDTH;
497 ST7735Ctx.Height = ST7735_HEIGHT;
498 }
499 else
500 {
501 ST7735Ctx.Width = ST7735_HEIGHT;
502 ST7735Ctx.Height = ST7735_WIDTH;
503 }
504 ST7735Ctx.Orientation = Orientation;
505
506 ret = ST7735_SetDisplayWindow(pObj, 0U, 0U, ST7735Ctx.Width, ST7735Ctx.Height);
507
508 tmp = (uint8_t)OrientationTab[Orientation][1];
509 ret += st7735_write_reg(&pObj->Ctx, ST7735_MADCTL, &tmp, 1);
510
511
512
513 if(ret != ST7735_OK)
514 {
515 ret = ST7735_ERROR;
516 }
517
518 return ret;
519 }
520
521 /**
522 * @brief Set the Display Orientation.
523 * @param pObj Component object
524 * @param Orientation ST7735_ORIENTATION_PORTRAIT, ST7735_ORIENTATION_LANDSCAPE
525 * or ST7735_ORIENTATION_LANDSCAPE_ROT180
526 * @retval The component status
527 */
ST7735_GetOrientation(ST7735_Object_t * pObj,uint32_t * Orientation)528 int32_t ST7735_GetOrientation(ST7735_Object_t *pObj, uint32_t *Orientation)
529 {
530
531 *Orientation = ST7735Ctx.Orientation;
532
533 return ST7735_OK;
534 }
535
536 /**
537 * @brief Set Cursor position.
538 * @param pObj Component object
539 * @param Xpos specifies the X position.
540 * @param Ypos specifies the Y position.
541 * @retval The component status
542 */
ST7735_SetCursor(ST7735_Object_t * pObj,uint32_t Xpos,uint32_t Ypos)543 int32_t ST7735_SetCursor(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos)
544 {
545 int32_t ret;
546 uint8_t tmp;
547
548 /* Cursor calibration */
549 if(ST7735Ctx.Orientation <= ST7735_ORIENTATION_PORTRAIT_ROT180)
550 {
551 #if IS_BOE_PANEL
552 Xpos += 24;
553 Ypos += 0;
554 #else
555 Xpos += 26;
556 Ypos += 1;
557 #endif
558 }
559 else
560 {
561 #if IS_BOE_PANEL
562 Xpos += 0;
563 Ypos += 24;
564 #else
565 Xpos += 1;
566 Ypos += 26;
567 #endif
568 }
569
570 ret = st7735_write_reg(&pObj->Ctx, ST7735_CASET, &tmp, 0);
571 tmp = (uint8_t)(Xpos >> 8U);
572 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
573 tmp = (uint8_t)(Xpos & 0xFFU);
574 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
575
576 ret += st7735_write_reg(&pObj->Ctx, ST7735_RASET, &tmp, 0);
577 tmp = (uint8_t)(Ypos >> 8U);
578 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
579 tmp = (uint8_t)(Ypos & 0xFFU);
580 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
581 ret += st7735_write_reg(&pObj->Ctx, ST7735_WRITE_RAM, &tmp, 0);
582
583 if(ret != ST7735_OK)
584 {
585 ret = ST7735_ERROR;
586 }
587
588 return ret;
589 }
590
591 /**
592 * @brief Displays a bitmap picture.
593 * @param pObj Component object
594 * @param Xpos Bmp X position in the LCD
595 * @param Ypos Bmp Y position in the LCD
596 * @param pBmp Bmp picture address.
597 * @retval The component status
598 */
ST7735_DrawBitmap(ST7735_Object_t * pObj,uint32_t Xpos,uint32_t Ypos,uint8_t * pBmp)599 int32_t ST7735_DrawBitmap(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint8_t *pBmp)
600 {
601 int32_t ret = ST7735_OK;
602 uint32_t index, size, width, height, y_pos;
603 uint8_t pixel_val[2], tmp;
604 uint8_t *pbmp;
605 uint32_t counter = 0;
606
607 /* Get bitmap data address offset */
608 index = (uint32_t)pBmp[10] + ((uint32_t)pBmp[11] << 8) + ((uint32_t)pBmp[12] << 16) + ((uint32_t)pBmp[13] << 24);
609
610 /* Read bitmap width */
611 width = (uint32_t)pBmp[18] + ((uint32_t)pBmp[19] << 8) + ((uint32_t)pBmp[20] << 16) + ((uint32_t)pBmp[21] << 24);
612
613 /* Read bitmap height */
614 height = (uint32_t)pBmp[22] + ((uint32_t)pBmp[23] << 8) + ((uint32_t)pBmp[24] << 16) + ((uint32_t)pBmp[25] << 24);
615
616 /* Read bitmap size */
617 size = (uint32_t)pBmp[2] + ((uint32_t)pBmp[3] << 8) + ((uint32_t)pBmp[4] << 16) + ((uint32_t)pBmp[5] << 24);
618 size = size - index;
619
620 pbmp = pBmp + index;
621
622 /* Remap Ypos, st7735 works with inverted X in case of bitmap */
623 /* X = 0, cursor is on Top corner */
624 y_pos = ST7735Ctx.Height - Ypos - height;
625
626 if(ST7735_SetDisplayWindow(pObj, Xpos, y_pos, width, height) != ST7735_OK)
627 {
628 ret = ST7735_ERROR;
629 }
630 else
631 {
632 /* Set GRAM write direction and BGR = 0 */
633 tmp = (uint8_t)OrientationTab[ST7735Ctx.Orientation][0];
634
635 if(st7735_write_reg(&pObj->Ctx, ST7735_MADCTL, &tmp, 1) != ST7735_OK)
636 {
637 ret = ST7735_ERROR;
638 }/* Set Cursor */
639 else if(ST7735_SetCursor(pObj, Xpos, y_pos) != ST7735_OK)
640 {
641 ret = ST7735_ERROR;
642 }
643 else
644 {
645 do
646 {
647 pixel_val[0] = *(pbmp + 1);
648 pixel_val[1] = *(pbmp);
649 if(st7735_send_data(&pObj->Ctx, pixel_val, 2U) != ST7735_OK)
650 {
651 ret = ST7735_ERROR;
652 break;
653 }
654 counter +=2U;
655 pbmp += 2;
656 }while(counter < size);
657
658 tmp = (uint8_t)OrientationTab[ST7735Ctx.Orientation][1];
659 if(st7735_write_reg(&pObj->Ctx, ST7735_MADCTL, &tmp, 1) != ST7735_OK)
660 {
661 ret = ST7735_ERROR;
662 }
663 else
664 {
665 if(ST7735_SetDisplayWindow(pObj, 0U, 0U, ST7735Ctx.Width, ST7735Ctx.Height) != ST7735_OK)
666 {
667 ret = ST7735_ERROR;
668 }
669 }
670 }
671 }
672
673 return ret;
674 }
675
676 /**
677 * @brief Draws a full RGB rectangle
678 * @param pObj Component object
679 * @param Xpos specifies the X position.
680 * @param Ypos specifies the Y position.
681 * @param pData pointer to RGB data
682 * @param Width specifies the rectangle width.
683 * @param Height Specifies the rectangle height
684 * @retval The component status
685 */
ST7735_FillRGBRect(ST7735_Object_t * pObj,uint32_t Xpos,uint32_t Ypos,uint8_t * pData,uint32_t Width,uint32_t Height)686 int32_t ST7735_FillRGBRect(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint8_t *pData, uint32_t Width, uint32_t Height)
687 {
688 int32_t ret = ST7735_OK;
689 static uint8_t pdata[640];
690 uint8_t *rgb_data = pData;
691 uint32_t i, j;
692
693 if(((Xpos + Width) > ST7735Ctx.Width) || ((Ypos + Height) > ST7735Ctx.Height))
694 {
695 ret = ST7735_ERROR;
696 }/* Set Cursor */
697 else
698 {
699 for(j = 0; j < Height; j++)
700 {
701 if(ST7735_SetCursor(pObj, Xpos, Ypos+j) != ST7735_OK)
702 {
703 ret = ST7735_ERROR;
704 }
705 else
706 {
707 for(i = 0; i < Width; i++)
708 {
709 pdata[2U*i] = (uint8_t)(*(rgb_data));
710 pdata[(2U*i) + 1U] = (uint8_t)(*(rgb_data + 1));
711 rgb_data +=2;
712 }
713 if(st7735_send_data(&pObj->Ctx, (uint8_t*)&pdata[0], 2U*Width) != ST7735_OK)
714 {
715 ret = ST7735_ERROR;
716 }
717 }
718 }
719 }
720
721 return ret;
722 }
723
724 /**
725 * @brief Draw Horizontal line.
726 * @param pObj Component object
727 * @param Xpos specifies the X position.
728 * @param Ypos specifies the Y position.
729 * @param Length specifies the Line length.
730 * @param Color Specifies the RGB color in RGB565 format
731 * @retval The component status
732 */
ST7735_DrawHLine(ST7735_Object_t * pObj,uint32_t Xpos,uint32_t Ypos,uint32_t Length,uint32_t Color)733 int32_t ST7735_DrawHLine(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Length, uint32_t Color)
734 {
735 int32_t ret = ST7735_OK;
736 uint32_t i;
737 static uint8_t pdata[640];
738
739 if((Xpos + Length) > ST7735Ctx.Width)
740 {
741 ret = ST7735_ERROR;
742 }/* Set Cursor */
743 else if(ST7735_SetCursor(pObj, Xpos, Ypos) != ST7735_OK)
744 {
745 ret = ST7735_ERROR;
746 }
747 else
748 {
749 for(i = 0; i < Length; i++)
750 {
751 /* Exchange LSB and MSB to fit LCD specification */
752 pdata[2U*i] = (uint8_t)(Color >> 8);
753 pdata[(2U*i) + 1U] = (uint8_t)(Color);
754
755 // pdata[(2U*i) + 1U] = (uint8_t)(Color >> 8);
756 // pdata[2U*i] = (uint8_t)(Color);
757 }
758 if(st7735_send_data(&pObj->Ctx, (uint8_t*)&pdata[0], 2U*Length) != ST7735_OK)
759 {
760 ret = ST7735_ERROR;
761 }
762 }
763
764 return ret;
765 }
766
767 /**
768 * @brief Draw vertical line.
769 * @param pObj Component object
770 * @param Color Specifies the RGB color
771 * @param Xpos specifies the X position.
772 * @param Ypos specifies the Y position.
773 * @param Length specifies the Line length.
774 * @retval The component status
775 */
ST7735_DrawVLine(ST7735_Object_t * pObj,uint32_t Xpos,uint32_t Ypos,uint32_t Length,uint32_t Color)776 int32_t ST7735_DrawVLine(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Length, uint32_t Color)
777 {
778 int32_t ret = ST7735_OK;
779 uint32_t counter;
780
781 if((Ypos + Length) > ST7735Ctx.Height)
782 {
783 ret = ST7735_ERROR;
784 }
785 else
786 {
787 for(counter = 0; counter < Length; counter++)
788 {
789 if(ST7735_SetPixel(pObj, Xpos, Ypos + counter, Color) != ST7735_OK)
790 {
791 ret = ST7735_ERROR;
792 break;
793 }
794 }
795 }
796
797 return ret;
798 }
799
800 /**
801 * @brief Fill rectangle
802 * @param pObj Component object
803 * @param Xpos X position
804 * @param Ypos Y position
805 * @param Width Rectangle width
806 * @param Height Rectangle height
807 * @param Color Draw color
808 * @retval Component status
809 */
ST7735_FillRect(ST7735_Object_t * pObj,uint32_t Xpos,uint32_t Ypos,uint32_t Width,uint32_t Height,uint32_t Color)810 int32_t ST7735_FillRect(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Width, uint32_t Height, uint32_t Color)
811 {
812 int32_t ret = ST7735_OK;
813 uint32_t i, y_pos = Ypos;
814
815 for(i = 0; i < Height; i++)
816 {
817 if(ST7735_DrawHLine(pObj, Xpos, y_pos, Width, Color) != ST7735_OK)
818 {
819 ret = ST7735_ERROR;
820 break;
821 }
822 y_pos++;
823 }
824
825 return ret;
826 }
827
828 /**
829 * @brief Write pixel.
830 * @param pObj Component object
831 * @param Xpos specifies the X position.
832 * @param Ypos specifies the Y position.
833 * @param Color the RGB pixel color in RGB565 format
834 * @retval The component status
835 */
ST7735_SetPixel(ST7735_Object_t * pObj,uint32_t Xpos,uint32_t Ypos,uint32_t Color)836 int32_t ST7735_SetPixel(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Color)
837 {
838 int32_t ret = ST7735_OK;
839 uint16_t color;
840
841 /* Exchange LSB and MSB to fit LCD specification */
842 color = (uint16_t)((uint16_t)Color << 8);
843 color |= (uint16_t)((uint16_t)(Color >> 8));
844
845 if((Xpos >= ST7735Ctx.Width) || (Ypos >= ST7735Ctx.Height))
846 {
847 ret = ST7735_ERROR;
848 }/* Set Cursor */
849 else if(ST7735_SetCursor(pObj, Xpos, Ypos) != ST7735_OK)
850 {
851 ret = ST7735_ERROR;
852 }
853 else
854 {
855 /* Write RAM data */
856 if(st7735_send_data(&pObj->Ctx, (uint8_t*)&color, 2) != ST7735_OK)
857 {
858 ret = ST7735_ERROR;
859 }
860 }
861
862 return ret;
863 }
864
865 /**
866 * @brief Read pixel.
867 * @param pObj Component object
868 * @param Xpos specifies the X position.
869 * @param Ypos specifies the Y position.
870 * @param Color the RGB pixel color in RGB565 format
871 * @retval The component status
872 */
ST7735_GetPixel(ST7735_Object_t * pObj,uint32_t Xpos,uint32_t Ypos,uint32_t * Color)873 int32_t ST7735_GetPixel(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t *Color)
874 {
875 int32_t ret;
876 uint8_t pixel_lsb, pixel_msb;
877 uint8_t tmp;
878
879
880 /* Set Cursor */
881 ret = ST7735_SetCursor(pObj, Xpos, Ypos);
882
883 /* Prepare to read LCD RAM */
884 ret += st7735_read_reg(&pObj->Ctx, ST7735_READ_RAM, &tmp); /* RAM read data command */
885
886 /* Dummy read */
887 ret += st7735_recv_data(&pObj->Ctx, &tmp, 1);
888
889 /* Read first part of the RGB888 data */
890 ret += st7735_recv_data(&pObj->Ctx, &pixel_lsb, 1);
891 /* Read first part of the RGB888 data */
892 ret += st7735_recv_data(&pObj->Ctx, &pixel_msb, 1);
893
894 *Color = ((uint32_t)(pixel_lsb)) + ((uint32_t)(pixel_msb) << 8);
895
896 if(ret != ST7735_OK)
897 {
898 ret = ST7735_ERROR;
899 }
900
901 return ret;
902 }
903
904 /**
905 * @brief Get the LCD pixel Width.
906 * @param pObj Component object
907 * @retval The Lcd Pixel Width
908 */
ST7735_GetXSize(ST7735_Object_t * pObj,uint32_t * XSize)909 int32_t ST7735_GetXSize(ST7735_Object_t *pObj, uint32_t *XSize)
910 {
911 (void)pObj;
912
913 *XSize = ST7735Ctx.Width;
914
915 return ST7735_OK;
916 }
917
918 /**
919 * @brief Get the LCD pixel Height.
920 * @param pObj Component object
921 * @retval The Lcd Pixel Height
922 */
ST7735_GetYSize(ST7735_Object_t * pObj,uint32_t * YSize)923 int32_t ST7735_GetYSize(ST7735_Object_t *pObj, uint32_t *YSize)
924 {
925 (void)pObj;
926
927 *YSize = ST7735Ctx.Height;
928
929 return ST7735_OK;
930 }
931
932 /**
933 * @}
934 */
935
936 /** @defgroup ST7735_Private_Functions Private Functions
937 * @{
938 */
939 /**
940 * @brief Sets a display window
941 * @param Xpos specifies the X bottom left position.
942 * @param Ypos specifies the Y bottom left position.
943 * @param Height display window height.
944 * @param Width display window width.
945 * @retval Component status
946 */
ST7735_SetDisplayWindow(ST7735_Object_t * pObj,uint32_t Xpos,uint32_t Ypos,uint32_t Width,uint32_t Height)947 static int32_t ST7735_SetDisplayWindow(ST7735_Object_t *pObj, uint32_t Xpos, uint32_t Ypos, uint32_t Width, uint32_t Height)
948 {
949 int32_t ret;
950 uint8_t tmp;
951
952 /* Cursor calibration */
953 if(ST7735Ctx.Orientation <= ST7735_ORIENTATION_PORTRAIT_ROT180)
954 {
955 #if IS_BOE_PANEL
956 Xpos += 24;
957 Ypos += 0;
958 #else
959 Xpos += 26;
960 Ypos += 1;
961 #endif
962 }
963 else
964 {
965 #if IS_BOE_PANEL
966 Xpos += 0;
967 Ypos += 24;
968 #else
969 Xpos += 1;
970 Ypos += 26;
971 #endif
972 }
973
974 /* Column addr set, 4 args, no delay: XSTART = Xpos, XEND = (Xpos + Width - 1) */
975 ret = st7735_write_reg(&pObj->Ctx, ST7735_CASET, &tmp, 0);
976 tmp = (uint8_t)(Xpos >> 8U);
977 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
978 tmp = (uint8_t)(Xpos & 0xFFU);
979 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
980 tmp = (uint8_t)((Xpos + Width - 1U) >> 8U);
981 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
982 tmp = (uint8_t)((Xpos + Width - 1U) & 0xFFU);
983 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
984
985 /* Row addr set, 4 args, no delay: YSTART = Ypos, YEND = (Ypos + Height - 1) */
986 ret += st7735_write_reg(&pObj->Ctx, ST7735_RASET, &tmp, 0);
987 tmp = (uint8_t)(Ypos >> 8U);
988 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
989 tmp = (uint8_t)(Ypos & 0xFFU);
990 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
991 tmp = (uint8_t)((Ypos + Height - 1U) >> 8U);
992 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
993 tmp = (uint8_t)((Ypos + Height - 1U) & 0xFFU);
994 ret += st7735_send_data(&pObj->Ctx, &tmp, 1);
995
996 if(ret != ST7735_OK)
997 {
998 ret = ST7735_ERROR;
999 }
1000
1001 return ret;
1002 }
1003
1004 /**
1005 * @brief Wrap component ReadReg to Bus Read function
1006 * @param Handle Component object handle
1007 * @param Reg The target register address to write
1008 * @param pData The target register value to be written
1009 * @retval Component error status
1010 */
ST7735_ReadRegWrap(void * Handle,uint8_t Reg,uint8_t * pData)1011 static int32_t ST7735_ReadRegWrap(void *Handle, uint8_t Reg, uint8_t* pData)
1012 {
1013 ST7735_Object_t *pObj = (ST7735_Object_t *)Handle;
1014
1015 return pObj->IO.ReadReg(Reg, pData);
1016 }
1017
1018 /**
1019 * @brief Wrap component WriteReg to Bus Write function
1020 * @param handle Component object handle
1021 * @param Reg The target register address to write
1022 * @param pData The target register value to be written
1023 * @param Length buffer size to be written
1024 * @retval Component error status
1025 */
ST7735_WriteRegWrap(void * Handle,uint8_t Reg,uint8_t * pData,uint32_t Length)1026 static int32_t ST7735_WriteRegWrap(void *Handle, uint8_t Reg, uint8_t *pData, uint32_t Length)
1027 {
1028 ST7735_Object_t *pObj = (ST7735_Object_t *)Handle;
1029
1030 return pObj->IO.WriteReg(Reg, pData, Length);
1031 }
1032
1033
1034 /**
1035 * @brief Wrap component SendData to Bus Write function
1036 * @param handle Component object handle
1037 * @param pData The target register value to be written
1038 * @retval Component error status
1039 */
ST7735_SendDataWrap(void * Handle,uint8_t * pData,uint32_t Length)1040 static int32_t ST7735_SendDataWrap(void *Handle, uint8_t *pData, uint32_t Length)
1041 {
1042 ST7735_Object_t *pObj = (ST7735_Object_t *)Handle;
1043
1044 return pObj->IO.SendData(pData, Length);
1045 }
1046
1047 /**
1048 * @brief Wrap component SendData to Bus Write function
1049 * @param handle Component object handle
1050 * @param pData The target register value to be written
1051 * @retval Component error status
1052 */
ST7735_RecvDataWrap(void * Handle,uint8_t * pData,uint32_t Length)1053 static int32_t ST7735_RecvDataWrap(void *Handle, uint8_t *pData, uint32_t Length)
1054 {
1055 ST7735_Object_t *pObj = (ST7735_Object_t *)Handle;
1056
1057 return pObj->IO.RecvData(pData, Length);
1058 }
1059
1060 /**
1061 * @brief ST7735 delay
1062 * @param Delay Delay in ms
1063 * @retval Component error status
1064 */
ST7735_IO_Delay(ST7735_Object_t * pObj,uint32_t Delay)1065 static int32_t ST7735_IO_Delay(ST7735_Object_t *pObj, uint32_t Delay)
1066 {
1067 rt_thread_mdelay(Delay);
1068 return ST7735_OK;
1069 }
1070
1071 /**
1072 * @}
1073 */
1074
1075 /**
1076 * @}
1077 */
1078
1079 /**
1080 * @}
1081 */
1082
1083 /**
1084 * @}
1085 */
1086
1087 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1088
1089