]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained/libboard_samv7-ek/source/lcd_draw.c
Update version number ready for V8.2.1 release.
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained / libboard_samv7-ek / source / lcd_draw.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2011, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 /**\r
31  * \file\r
32  *\r
33  * Implementation of draw function on LCD, Include draw text, image\r
34  * and basic shapes (line, rectangle, circle).\r
35  *\r
36  */\r
37 \r
38 /*----------------------------------------------------------------------------\r
39  *        Headers\r
40  *----------------------------------------------------------------------------*/\r
41 \r
42 #include "board.h"\r
43 \r
44 #include <stdint.h>\r
45 #include <string.h>\r
46 #include <assert.h>\r
47 \r
48 \r
49 static LcdColor_t gLcdPixelCache[LCD_DATA_CACHE_SIZE];\r
50 /*----------------------------------------------------------------------------\r
51  *        Exported functions\r
52  *----------------------------------------------------------------------------*/\r
53 \r
54 \r
55 /**\r
56  * \brief Convert 24 bit RGB color into 5-6-5 rgb color space.\r
57  *\r
58  * Initialize the LcdColor_t cache with the color pattern.\r
59  * \param x  24-bits RGB color.\r
60  * \return 0 for successfull operation.\r
61  */\r
62 static uint32_t LCD_SetColor( uint32_t dwRgb24Bits )\r
63 {\r
64     uint32_t i ;\r
65 \r
66     /* Fill the cache with selected color */\r
67     for ( i = 0 ; i < LCD_DATA_CACHE_SIZE ; ++i )\r
68     {\r
69         gLcdPixelCache[i] = dwRgb24Bits ;\r
70     }\r
71 \r
72     return 0;\r
73\r
74 \r
75 /**\r
76  * \brief Check Box coordinates. Return upper left and bottom right coordinates.\r
77  *\r
78  * \param pX1      X-coordinate of upper-left corner on LCD.\r
79  * \param pY1      Y-coordinate of upper-left corner on LCD.\r
80  * \param pX2      X-coordinate of lower-right corner on LCD.\r
81  * \param pY2      Y-coordinate of lower-right corner on LCD.\r
82  */\r
83 static void CheckBoxCoordinates( uint32_t *pX1, uint32_t *pY1, uint32_t *pX2, uint32_t *pY2 )\r
84 {\r
85     uint32_t dw;\r
86 \r
87     if ( *pX1 >= BOARD_LCD_WIDTH )\r
88     {\r
89         *pX1 = BOARD_LCD_WIDTH-1 ;\r
90     }\r
91     if ( *pX2 >= BOARD_LCD_WIDTH )\r
92     {\r
93         *pX2 = BOARD_LCD_WIDTH-1 ;\r
94     }\r
95     if ( *pY1 >= BOARD_LCD_HEIGHT )\r
96     {\r
97         *pY1 = BOARD_LCD_HEIGHT-1 ;\r
98     }\r
99     if ( *pY2 >= BOARD_LCD_HEIGHT )\r
100     {\r
101         *pY2 = BOARD_LCD_HEIGHT-1 ;\r
102     }\r
103     if (*pX1 > *pX2)\r
104     {\r
105         dw = *pX1;\r
106         *pX1 = *pX2;\r
107         *pX2 = dw;\r
108     }\r
109     if (*pY1 > *pY2)\r
110     {\r
111         dw = *pY1;\r
112         *pY1 = *pY2;\r
113         *pY2 = dw;\r
114     }\r
115 }\r
116 /**\r
117  * \brief Fills the given LCD buffer with a particular color.\r
118  *\r
119  * \param color  Fill color.\r
120  */\r
121 void LCDD_Fill( uint32_t dwColor )\r
122 {\r
123     uint32_t dw ;\r
124 \r
125     //    LCD_SetCursor( 0, 0 ) ;\r
126     ILI9488_WriteRAM_Prepare() ;\r
127 \r
128     for ( dw = BOARD_LCD_WIDTH * BOARD_LCD_HEIGHT; dw > 0; dw-- )\r
129     {\r
130         ILI9488_WriteRAM( dwColor ) ;\r
131     }\r
132 }\r
133 \r
134 /**\r
135  * \brief Draw a pixel on LCD of given color.\r
136  *\r
137  * \param x  X-coordinate of pixel.\r
138  * \param y  Y-coordinate of pixel.\r
139  * \param color  Pixel color.\r
140  */\r
141 extern void LCDD_DrawPixel( uint32_t x, uint32_t y, uint32_t color )\r
142 {\r
143     ILI9488_SetCursor( x, y ) ;\r
144     ILI9488_WriteRAM_Prepare() ;\r
145     ILI9488_WriteRAM( color ) ;\r
146 }\r
147 \r
148 \r
149 \r
150 /**\r
151  * \brief Read a pixel from LCD.\r
152  *\r
153  * \param x  X-coordinate of pixel.\r
154  * \param y  Y-coordinate of pixel.\r
155  *\r
156  * \return color  Readed pixel color.\r
157  */\r
158 extern uint32_t LCDD_ReadPixel( uint32_t x, uint32_t y )\r
159 {\r
160     uint32_t color;\r
161 \r
162     ILI9488_SetCursor(x, y);\r
163     ILI9488_ReadRAM_Prepare();\r
164     color = ILI9488_ReadRAM();\r
165 \r
166     return color;\r
167 }\r
168 \r
169 /*\r
170  * \brief Draw a line on LCD, horizontal and vertical line are supported.\r
171  *\r
172  * \param x         X-coordinate of line start.\r
173  * \param y         Y-coordinate of line start.\r
174  * \param length    line length.\r
175  * \param direction line direction: 0 - horizontal, 1 - vertical.\r
176  * \param color     Pixel color.\r
177  */\r
178 extern void LCDD_DrawLine( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 , uint32_t color )\r
179 {\r
180     if (( dwY1 == dwY2 ) || (dwX1 == dwX2))\r
181     {\r
182         LCDD_DrawRectangleWithFill( dwX1, dwY1, dwX2, dwY2, color );\r
183     }\r
184     else\r
185     {\r
186         LCDD_DrawLineBresenham( dwX1, dwY1, dwX2, dwY2 , color) ;\r
187     }\r
188 \r
189 }\r
190 \r
191 \r
192 \r
193 /*\r
194  * \brief Draw a line on LCD, which is not horizontal or vertical.\r
195  *\r
196  * \param x         X-coordinate of line start.\r
197  * \param y         Y-coordinate of line start.\r
198  * \param length    line length.\r
199  * \param direction line direction: 0 - horizontal, 1 - vertical.\r
200  * \param color     LcdColor_t color.\r
201  */\r
202 extern uint32_t LCDD_DrawLineBresenham( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 , uint32_t color)\r
203 {\r
204     int dx, dy ;\r
205     int i ;\r
206     int xinc, yinc, cumul ;\r
207     int x, y ;\r
208 \r
209     x = dwX1 ;\r
210     y = dwY1 ;\r
211     dx = dwX2 - dwX1 ;\r
212     dy = dwY2 - dwY1 ;\r
213 \r
214     xinc = ( dx > 0 ) ? 1 : -1 ;\r
215     yinc = ( dy > 0 ) ? 1 : -1 ;\r
216     dx = ( dx > 0 ) ? dx : -dx ;\r
217     dy = ( dy > 0 ) ? dy : -dy ;\r
218 \r
219     LCDD_DrawPixel(x , y , color);\r
220 \r
221     if ( dx > dy )\r
222     {\r
223         cumul = dx / 2 ;\r
224         for ( i = 1 ; i <= dx ; i++ )\r
225         {\r
226             x += xinc ;\r
227             cumul += dy ;\r
228 \r
229             if ( cumul >= dx )\r
230             {\r
231                 cumul -= dx ;\r
232                 y += yinc ;\r
233             }\r
234             LCDD_DrawPixel(x , y , color);\r
235         }\r
236     }\r
237     else\r
238     {\r
239         cumul = dy / 2 ;\r
240         for ( i = 1 ; i <= dy ; i++ )\r
241         {\r
242             y += yinc ;\r
243             cumul += dx ;\r
244 \r
245             if ( cumul >= dy )\r
246             {\r
247                 cumul -= dy ;\r
248                 x += xinc ;\r
249             }\r
250 \r
251             LCDD_DrawPixel(x , y , color);\r
252         }\r
253     }\r
254 \r
255     return 0 ;\r
256 }\r
257 \r
258 /*\r
259  * \brief Draws a rectangle on LCD, at the given coordinates.\r
260  *\r
261  * \param x      X-coordinate of upper-left rectangle corner.\r
262  * \param y      Y-coordinate of upper-left rectangle corner.\r
263  * \param width  Rectangle width in pixels.\r
264  * \param height  Rectangle height in pixels.\r
265  * \param color  Rectangle color.\r
266  */\r
267 extern void LCDD_DrawRectangle( uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t color )\r
268 {\r
269 \r
270     LCDD_DrawRectangleWithFill(x, y, width, y, color);\r
271     LCDD_DrawRectangleWithFill(x, height, width, height, color);\r
272 \r
273     LCDD_DrawRectangleWithFill(x, y, x, height, color);\r
274     LCDD_DrawRectangleWithFill(width, y, width, height, color);\r
275 }\r
276 \r
277 /*\r
278  * \brief Draws a rectangle with fill inside on LCD, at the given coordinates.\r
279  *\r
280  * \param x      X-coordinate of upper-left rectangle corner.\r
281  * \param y      Y-coordinate of upper-left rectangle corner.\r
282  * \param width  Rectangle width in pixels.\r
283  * \param height  Rectangle height in pixels.\r
284  * \param color  Rectangle color.\r
285  */\r
286 extern void LCDD_DrawRectangleWithFill( uint32_t dwX, uint32_t dwY, uint32_t dwWidth, uint32_t dwHeight, uint32_t dwColor )\r
287 {\r
288     uint32_t size, blocks;\r
289 \r
290     CheckBoxCoordinates(&dwX, &dwY, &dwWidth, &dwHeight);\r
291     LCD_SetColor(dwColor);\r
292     ILI9488_SetWindow( dwX, dwY, dwWidth, dwHeight ) ;\r
293 \r
294     size = (dwWidth - dwX + 1) * (dwHeight - dwY + 1);\r
295 \r
296     /* Send pixels blocks => one LCD IT / block */\r
297     blocks = size / LCD_DATA_CACHE_SIZE;\r
298 \r
299     ILI9488_WriteRAM_Prepare() ;\r
300 \r
301     while (blocks--)\r
302     {\r
303         ILI9488_WriteRAMBuffer(gLcdPixelCache, LCD_DATA_CACHE_SIZE);\r
304     }\r
305     /* Send remaining pixels */\r
306     ILI9488_WriteRAMBuffer(gLcdPixelCache, size % LCD_DATA_CACHE_SIZE);\r
307     ILI9488_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ;\r
308     //    LCD_SetCursor( 0, 0 ) ;\r
309 }\r
310 \r
311 /**\r
312  * \brief Draws a circle on LCD, at the given coordinates.\r
313  *\r
314  * \param x      X-coordinate of circle center.\r
315  * \param y      Y-coordinate of circle center.\r
316  * \param r      circle radius.\r
317  * \param color  circle color.\r
318  */\r
319 extern uint32_t LCDD_DrawCircle( uint32_t x, uint32_t y, uint32_t r, uint32_t color )\r
320 {\r
321     signed int    d;    /* Decision Variable */\r
322     uint32_t  curX; /* Current X Value */\r
323     uint32_t  curY; /* Current Y Value */\r
324 \r
325     d = 3 - (r << 1);\r
326     curX = 0;\r
327     curY = r;\r
328 \r
329     while (curX <= curY)\r
330     {\r
331         LCDD_DrawPixel(x + curX, y + curY, color);\r
332         LCDD_DrawPixel(x + curX, y - curY, color);\r
333         LCDD_DrawPixel(x - curX, y + curY, color);\r
334         LCDD_DrawPixel(x - curX, y - curY, color);\r
335         LCDD_DrawPixel(x + curY, y + curX, color);\r
336         LCDD_DrawPixel(x + curY, y - curX, color);\r
337         LCDD_DrawPixel(x - curY, y + curX, color);\r
338         LCDD_DrawPixel(x - curY, y - curX, color);\r
339 \r
340         if (d < 0) {\r
341             d += (curX << 2) + 6;\r
342         }\r
343         else {\r
344             d += ((curX - curY) << 2) + 10;\r
345             curY--;\r
346         }\r
347         curX++;\r
348     }\r
349     return 0;\r
350 }\r
351 \r
352 \r
353 extern uint32_t LCD_DrawFilledCircle( uint32_t dwX, uint32_t dwY, uint32_t dwRadius, uint32_t color)\r
354 {\r
355     signed int d ; /* Decision Variable */\r
356     uint32_t dwCurX ; /* Current X Value */\r
357     uint32_t dwCurY ; /* Current Y Value */\r
358     uint32_t dwXmin, dwYmin;\r
359 \r
360     if (dwRadius == 0)\r
361     {\r
362         return 0;\r
363     }\r
364     d = 3 - (dwRadius << 1) ;\r
365     dwCurX = 0 ;\r
366     dwCurY = dwRadius ;\r
367 \r
368     while ( dwCurX <= dwCurY )\r
369     {\r
370         dwXmin = (dwCurX > dwX) ? 0 : dwX-dwCurX;\r
371         dwYmin = (dwCurY > dwY) ? 0 : dwY-dwCurY;\r
372         LCDD_DrawRectangleWithFill( dwXmin, dwYmin, dwX+dwCurX, dwYmin ,color) ;\r
373         LCDD_DrawRectangleWithFill( dwXmin, dwY+dwCurY, dwX+dwCurX, dwY+dwCurY, color ) ;\r
374         dwXmin = (dwCurY > dwX) ? 0 : dwX-dwCurY;\r
375         dwYmin = (dwCurX > dwY) ? 0 : dwY-dwCurX;\r
376         LCDD_DrawRectangleWithFill( dwXmin, dwYmin, dwX+dwCurY, dwYmin, color  ) ;\r
377         LCDD_DrawRectangleWithFill( dwXmin, dwY+dwCurX, dwX+dwCurY, dwY+dwCurX, color  ) ;\r
378 \r
379         if ( d < 0 )\r
380         {\r
381             d += (dwCurX << 2) + 6 ;\r
382         }\r
383         else\r
384         {\r
385             d += ((dwCurX - dwCurY) << 2) + 10;\r
386             dwCurY-- ;\r
387         }\r
388 \r
389         dwCurX++ ;\r
390     }\r
391 \r
392     return 0 ;\r
393 }\r
394 /**\r
395  * \brief Draws a string inside a LCD buffer, at the given coordinates. Line breaks\r
396  * will be honored.\r
397  *\r
398  * \param x        X-coordinate of string top-left corner.\r
399  * \param y        Y-coordinate of string top-left corner.\r
400  * \param pString  String to display.\r
401  * \param color    String color.\r
402  */\r
403 extern void LCDD_DrawString( uint32_t x, uint32_t y, const uint8_t *pString, uint32_t color )\r
404 {\r
405     uint32_t xorg = x ;\r
406 \r
407     while ( *pString != 0 )\r
408     {\r
409         if ( *pString == '\n' )\r
410         {\r
411             y += gFont.height + 2 ;\r
412             x = xorg ;\r
413         }\r
414         else\r
415         {\r
416             LCDD_DrawChar( x, y, *pString, color ) ;\r
417             x += gFont.width + 2 ;\r
418         }\r
419 \r
420         pString++ ;\r
421     }\r
422 }\r
423 \r
424 /**\r
425  * \brief Draws a string inside a LCD buffer, at the given coordinates\r
426  * with given background color. Line breaks will be honored.\r
427  *\r
428  * \param x         X-coordinate of string top-left corner.\r
429  * \param y         Y-coordinate of string top-left corner.\r
430  * \param pString   String to display.\r
431  * \param fontColor String color.\r
432  * \param bgColor   Background color.\r
433  */\r
434 extern void LCDD_DrawStringWithBGColor( uint32_t x, uint32_t y, const char *pString, uint32_t fontColor, uint32_t bgColor )\r
435 {\r
436     unsigned xorg = x;\r
437 \r
438     while ( *pString != 0 )\r
439     {\r
440         if ( *pString == '\n' )\r
441         {\r
442             y += gFont.height + 2 ;\r
443             x = xorg ;\r
444         }\r
445         else\r
446         {\r
447             LCDD_DrawCharWithBGColor( x, y, *pString, fontColor, bgColor ) ;\r
448             x += gFont.width + 2;\r
449         }\r
450 \r
451         pString++;\r
452     }\r
453 }\r
454 \r
455 /**\r
456  * \brief Returns the width & height in pixels that a string will occupy on the screen\r
457  * if drawn using LCDD_DrawString.\r
458  *\r
459  * \param pString  String.\r
460  * \param pWidth   Pointer for storing the string width (optional).\r
461  * \param pHeight  Pointer for storing the string height (optional).\r
462  *\r
463  * \return String width in pixels.\r
464  */\r
465 extern void LCDD_GetStringSize( const uint8_t *pString, uint32_t *pWidth, uint32_t *pHeight )\r
466 {\r
467     uint32_t width = 0;\r
468     uint32_t height = gFont.height;\r
469 \r
470     while ( *pString != 0 )\r
471     {\r
472         if ( *pString == '\n' )\r
473         {\r
474             height += gFont.height + 2 ;\r
475         }\r
476         else\r
477         {\r
478             width += gFont.width + 2 ;\r
479         }\r
480 \r
481         pString++ ;\r
482     }\r
483 \r
484     if ( width > 0 )\r
485     {\r
486         width -= 2;\r
487     }\r
488 \r
489     if ( pWidth != NULL )\r
490     {\r
491         *pWidth = width;\r
492     }\r
493 \r
494     if ( pHeight != NULL )\r
495     {\r
496         *pHeight = height ;\r
497     }\r
498 }\r
499 \r
500 /*\r
501  * \brief Draw a raw image at given position on LCD.\r
502  *\r
503  * \param x         X-coordinate of image start.\r
504  * \param y         Y-coordinate of image start.\r
505  * \param pImage    Image buffer.\r
506  * \param width     Image width.\r
507  * \param height    Image height.\r
508  */\r
509 extern void LCDD_DrawImage( uint32_t dwX, uint32_t dwY, const LcdColor_t *pImage, uint32_t dwWidth, uint32_t dwHeight )\r
510 {\r
511     uint32_t size;\r
512 \r
513 \r
514     /* Determine the refresh window area */\r
515     /* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */\r
516     CheckBoxCoordinates(&dwX, &dwY, &dwWidth, &dwHeight);\r
517     ILI9488_SetWindow(dwX, dwY, dwWidth, dwHeight);\r
518 \r
519     /* Prepare to write in GRAM */\r
520     ILI9488_WriteRAM_Prepare();\r
521 \r
522     size = (dwWidth - dwX + 1) * (dwHeight - dwY + 1);\r
523 \r
524     ILI9488_WriteRAMBuffer(pImage, size);\r
525 \r
526     ILI9488_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ;\r
527 }\r
528 \r
529 /*\r
530  * \brief Draw a raw image at given position on LCD.\r
531  *\r
532  * \param dwX         X-coordinate of image start.\r
533  * \param dwY         Y-coordinate of image start.\r
534  * \param pGIMPImage  Image data.\r
535  */\r
536 void LCDD_DrawGIMPImage( uint32_t dwX, uint32_t dwY, const SGIMPImage* pGIMPImage )\r
537 {\r
538     uint32_t dw ;\r
539     register uint32_t dwLength ;\r
540     uint8_t* pucData ;\r
541     LcdColor_t *pData;\r
542 \r
543     // Draw raw RGB bitmap\r
544     //    CheckBoxCoordinates(&dwX, &dwY, &dwWidth, &dwHeight);\r
545     ILI9488_SetWindow( dwX, dwY, pGIMPImage->dwWidth, pGIMPImage->dwHeight ) ;\r
546     //    LCD_SetCursor( dwX, dwY ) ;\r
547 \r
548     ILI9488_WriteRAM_Prepare() ;\r
549 \r
550     dwLength = pGIMPImage->dwWidth*pGIMPImage->dwHeight ;\r
551     pucData = pGIMPImage->pucPixel_data ;\r
552     for ( dw=0; dw < dwLength; dw++ )\r
553     {\r
554         *pData  = ((*pucData++)<<16) ;\r
555         *pData |= ((*pucData++)<<8) ;\r
556         *pData |= (*pucData++) ;\r
557         ILI9488_WriteRAM(*pData);\r
558     }\r
559 \r
560     ILI9488_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ;\r
561 }\r
562 \r
563 /*\r
564  * \brief Clear a window with an color.\r
565  *\r
566  * \param dwX         X-coordinate of the window.\r
567  * \param dwY         Y-coordinate of the window.\r
568  * \param dwWidth     window width.\r
569  * \param dwHeight    window height.\r
570  * \param dwColor     background color\r
571  */\r
572 extern void LCDD_ClearWindow( uint32_t dwX, uint32_t dwY, uint32_t dwWidth, uint32_t dwHeight, uint32_t dwColor )\r
573 {\r
574     uint32_t dw ;\r
575 \r
576 \r
577     ILI9488_SetWindow( dwX, dwY, dwWidth, dwHeight ) ;\r
578     ILI9488_WriteRAM_Prepare() ;\r
579 \r
580     for ( dw = dwWidth * dwHeight; dw > 0; dw-- )\r
581     {\r
582         ILI9488_WriteRAM( dwColor ) ;\r
583     }\r
584 }\r