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>&copy; 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