1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2011, Atmel Corporation
\r
6 * All rights reserved.
\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
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\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
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
30 /** \addtogroup lcdd_draw
\r
32 * Implementation of draw function on LCD, Include draw text, image
\r
33 * and basic shapes (line, rectangle, circle).
\r
39 /*----------------------------------------------------------------------------
\r
41 *----------------------------------------------------------------------------*/
\r
49 /*----------------------------------------------------------------------------
\r
51 *----------------------------------------------------------------------------*/
\r
53 /** Front color cache */
\r
54 static uint32_t dwFrontColor;
\r
56 /*----------------------------------------------------------------------------
\r
58 *----------------------------------------------------------------------------*/
\r
63 static void _HideCanvas(void)
\r
65 //LCDD_EnableLayer(LCDD_GetCanvas()->bLayer, 0);
\r
71 static void _ShowCanvas(void)
\r
73 //LCDD_EnableLayer(LCDD_GetCanvas()->bLayer, 1);
\r
78 * \param dwColor Pixel color.
\r
80 static void _SetFrontColor(uint32_t dwColor)
\r
82 dwFrontColor = dwColor;
\r
86 * \brief Draw a pixel on LCD of front color.
\r
88 * \param dwX X-coordinate of pixel.
\r
89 * \param dwY Y-coordinate of pixel.
\r
91 static void _DrawPixel( uint32_t dwX, uint32_t dwY )
\r
93 sLCDDLayer *pDisp = LCDD_GetCanvas();
\r
94 uint8_t* buffer = pDisp->pBuffer;
\r
95 uint16_t w = pDisp->wImgW;
\r
96 //uint16_t h = pDisp->wImgH;
\r
97 uint16_t cw = pDisp->bMode/8; /* color width */
\r
98 uint32_t rw = w * cw; /* row width in bytes */
\r
102 if (buffer == NULL)
\r
105 if (rw & 0x3) rw = (rw | 0x3) + 1; /* 4-byte aligned rows */
\r
106 pPix = &buffer[dwY * rw + cw * dwX];
\r
108 switch (pDisp->bMode)
\r
110 case 16: /* TRGB 1555 */
\r
111 pPix[0] = (dwFrontColor ) & 0xFF;
\r
112 pPix[1] = (dwFrontColor >> 8) & 0xFF;
\r
114 case 24: /* RGB 888 */
\r
115 pPix[0] = (dwFrontColor ) & 0xFF;
\r
116 pPix[1] = (dwFrontColor >> 8) & 0xFF;
\r
117 pPix[2] = (dwFrontColor >> 16) & 0xFF;
\r
119 case 32: /* ARGB 8888 */
\r
120 pPix[0] = (dwFrontColor ) & 0xFF;
\r
121 pPix[1] = (dwFrontColor >> 8) & 0xFF;
\r
122 pPix[2] = (dwFrontColor >> 16) & 0xFF;
\r
123 pPix[3] = (dwFrontColor >> 24) & 0xFF;
\r
129 * \brief Fill rectangle with front color.
\r
130 * \param dwX1 X-coordinate of top left.
\r
131 * \param dwY1 Y-coordinate of top left.
\r
132 * \param dwX2 X-coordinate of bottom right.
\r
133 * \param dwY1 Y-coordinate of bottom right.
\r
135 static void _FillRect( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 )
\r
137 sLCDDLayer *pDisp = LCDD_GetCanvas();
\r
138 uint16_t w = pDisp->wImgW;
\r
139 uint16_t cw = pDisp->bMode/8; /* color width */
\r
140 uint32_t rw = w * cw; /* row width in bytes */
\r
141 uint8_t *base = pDisp->pBuffer;
\r
142 uint8_t *buffer = pDisp->pBuffer;
\r
143 uint32_t fillStart, fillEnd;
\r
145 if (buffer == NULL) return;
\r
147 /* 4-byte aligned rows */
\r
148 if (rw & 0x3) rw = (rw | 0x3) + 1;
\r
149 /* Buffer address for the starting row */
\r
150 base = &buffer[dwY1*rw];
\r
152 fillStart = dwX1 * cw;
\r
153 fillEnd = dwX2 * cw;
\r
155 #if 1 /* Memcopy pixel */
\r
157 for (; dwY1 <= dwY2; dwY1 ++)
\r
159 for (i = fillStart; i <= fillEnd; i += cw)
\r
161 memcpy(&buffer[i], &dwFrontColor, cw);
\r
163 buffer = &buffer[rw];
\r
167 #if 0 /* Pixel by pixel */
\r
168 for (; dwY1 <= dwY2; dwY1 ++)
\r
170 for (i = dwX1; i <= dwX2; i ++)
\r
172 _DrawPixel(i, dwY1);
\r
177 #if 0 /* Optimized */
\r
179 for (i = fillStart; i <= fillEnd; i += cw)
\r
181 memcpy(&base[i], &dwFrontColor, cw);
\r
183 /* Next rows, copy first */
\r
184 buffer = &base[rw + fillStart];
\r
185 for (i = dwY1 + 1; i <= dwY2; i ++)
\r
187 memcpy(buffer, &base[fillStart], fillEnd - fillStart + cw);
\r
188 buffer = &buffer[rw];
\r
194 * \brief Draw a line on LCD, which is not horizontal or vertical.
\r
196 * \param dwX1 X-coordinate of line start.
\r
197 * \param dwY1 Y-coordinate of line start.
\r
198 * \param dwX2 X-coordinate of line end.
\r
199 * \param dwY2 Y-coordinate of line end.
\r
201 static uint32_t _DrawLineBresenham( uint32_t dwX1, uint32_t dwY1,
\r
202 uint32_t dwX2, uint32_t dwY2 )
\r
206 int xinc, yinc, cumul ;
\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
219 _DrawPixel( x, y ) ;
\r
224 for ( i = 1 ; i <= dx ; i++ )
\r
234 _DrawPixel( x, y ) ;
\r
240 for ( i = 1 ; i <= dy ; i++ )
\r
251 _DrawPixel( x, y ) ;
\r
260 /*----------------------------------------------------------------------------
\r
261 * Exported functions
\r
262 *----------------------------------------------------------------------------*/
\r
265 * \brief Fills the given LCD buffer with a particular color.
\r
267 * \param color Fill color.
\r
269 void LCDD_Fill( uint32_t dwColor )
\r
271 sLCDDLayer *pDisp = LCDD_GetCanvas();
\r
272 _SetFrontColor(dwColor);
\r
274 _FillRect( 0, 0, pDisp->wImgW, pDisp->wImgH );
\r
278 void LCDD_Fill0(void)
\r
280 sLCDDLayer *pDisp = LCDD_GetCanvas();
\r
282 _SetFrontColor(0xFF0000);
\r
283 _FillRect( 0, 0, pDisp->wImgW/3, pDisp->wImgH );
\r
284 _SetFrontColor(0x00FF00);
\r
285 _FillRect( pDisp->wImgW/3, 0, pDisp->wImgW/3+pDisp->wImgW/3, pDisp->wImgH );
\r
286 _SetFrontColor(0x0000FF);
\r
287 _FillRect( pDisp->wImgW/3+pDisp->wImgW/3, 0, pDisp->wImgW, pDisp->wImgH );
\r
291 * \brief Draw a pixel on LCD of given color.
\r
293 * \param x X-coordinate of pixel.
\r
294 * \param y Y-coordinate of pixel.
\r
295 * \param color Pixel color.
\r
297 extern void LCDD_DrawPixel( uint32_t x, uint32_t y, uint32_t color )
\r
299 _SetFrontColor(color);
\r
306 * \brief Read a pixel from LCD.
\r
308 * \param x X-coordinate of pixel.
\r
309 * \param y Y-coordinate of pixel.
\r
311 * \return color Readed pixel color.
\r
313 extern uint32_t LCDD_ReadPixel( uint32_t x, uint32_t y )
\r
315 sLCDDLayer *pDisp = LCDD_GetCanvas();
\r
316 uint8_t* buffer = pDisp->pBuffer;
\r
317 uint16_t w = pDisp->wImgW;
\r
318 //uint16_t h = pDisp->wImgH;
\r
319 uint16_t cw = pDisp->bMode/8; /* color width */
\r
320 uint32_t rw = w * cw; /* row width in bytes */
\r
322 uint32_t color = 0;
\r
324 if (buffer == NULL) return 0;
\r
326 if (rw & 0x3) rw = (rw | 0x3) + 1; /* 4-byte aligned rows */
\r
327 pPix = &buffer[x * rw + cw * y];
\r
329 switch (pDisp->bMode)
\r
331 case 16: /* TRGB 1555 */
\r
332 color = pPix[0] | (pPix[1] << 8);
\r
334 case 24: /* RGB 888 */
\r
335 color = pPix[0] | (pPix[1] << 8) | (pPix[2] << 16);
\r
337 case 32: /* ARGB 8888 */
\r
338 color = pPix[0] | (pPix[1] << 8) | (pPix[2] << 16) | (pPix[3] << 24);
\r
345 * \brief Draw a line on LCD, horizontal and vertical line are supported.
\r
347 * \param x1 X-coordinate of line start.
\r
348 * \param y1 Y-coordinate of line start.
\r
349 * \param x2 X-coordinate of line end.
\r
350 * \param y2 Y-coordinate of line end.
\r
351 * \param color Pixel color.
\r
353 extern void LCDD_DrawLine( uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2, uint32_t color )
\r
355 _SetFrontColor(color);
\r
356 if ( (x1 == x2) || (y1 == y2) )
\r
358 LCDD_DrawFilledRectangle(x1, y1, x2, y2, color);
\r
363 _DrawLineBresenham(x1, y1, x2, y2);
\r
369 * \brief Draws a rectangle on LCD, at the given coordinates.
\r
371 * \param x X-coordinate of upper-left rectangle corner.
\r
372 * \param y Y-coordinate of upper-left rectangle corner.
\r
373 * \param width Rectangle width in pixels.
\r
374 * \param height Rectangle height in pixels.
\r
375 * \param color Rectangle color.
\r
377 extern void LCDD_DrawRectangle( uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t color )
\r
379 uint32_t x1 = x + width - 1;
\r
380 uint32_t y1 = y + height - 1;
\r
382 _SetFrontColor(color);
\r
384 _FillRect(x , y , x1, y );
\r
385 _FillRect(x1, y , x1, y1);
\r
386 _FillRect(x , y , x , y1);
\r
387 _FillRect(x , y1, x1, y1);
\r
392 * \brief Draws a rectangle with fill inside on LCD, at the given coordinates.
\r
394 * \param dwX1 X-coordinate of upper-left rectangle corner.
\r
395 * \param dwY1 Y-coordinate of upper-left rectangle corner.
\r
396 * \param dwX2 X-coordinate of down-right rectangle corner.
\r
397 * \param dwY2 Y-coordinate of down-right rectangle corner.
\r
398 * \param color Rectangle color.
\r
400 extern void LCDD_DrawFilledRectangle( uint32_t dwX1, uint32_t dwY1,
\r
401 uint32_t dwX2, uint32_t dwY2,
\r
404 _SetFrontColor(dwColor);
\r
406 _FillRect(dwX1, dwY1, dwX2, dwY2);
\r
411 * \brief Draws a circle on LCD, at the given coordinates.
\r
413 * \param dwX X-coordinate of circle center.
\r
414 * \param dwY Y-coordinate of circle center.
\r
415 * \param dwR circle radius.
\r
416 * \param dwColor circle color.
\r
418 extern void LCDD_DrawCircle( uint32_t dwX, uint32_t dwY, uint32_t dwR, uint32_t dwColor )
\r
420 int32_t d; /* Decision Variable */
\r
421 uint32_t curX; /* Current X Value */
\r
422 uint32_t curY; /* Current Y Value */
\r
424 if (dwR == 0) return;
\r
425 _SetFrontColor(dwColor);
\r
427 d = 3 - (dwR << 1);
\r
432 while (curX <= curY)
\r
434 _DrawPixel(dwX + curX, dwY + curY);
\r
435 _DrawPixel(dwX + curX, dwY - curY);
\r
436 _DrawPixel(dwX - curX, dwY + curY);
\r
437 _DrawPixel(dwX - curX, dwY - curY);
\r
438 _DrawPixel(dwX + curY, dwY + curX);
\r
439 _DrawPixel(dwX + curY, dwY - curX);
\r
440 _DrawPixel(dwX - curY, dwY + curX);
\r
441 _DrawPixel(dwX - curY, dwY - curX);
\r
444 d += (curX << 2) + 6;
\r
447 d += ((curX - curY) << 2) + 10;
\r
457 * \brief Draws a filled circle on LCD, at the given coordinates.
\r
459 * \param dwX X-coordinate of circle center.
\r
460 * \param dwY Y-coordinate of circle center.
\r
461 * \param dwR circle radius.
\r
462 * \param dwColor circle color.
\r
464 void LCDD_DrawFilledCircle( uint32_t dwX, uint32_t dwY, uint32_t dwR, uint32_t dwColor )
\r
466 signed int d ; // Decision Variable
\r
467 uint32_t dwCurX ; // Current X Value
\r
468 uint32_t dwCurY ; // Current Y Value
\r
469 uint32_t dwXmin, dwYmin;
\r
471 if (dwR == 0) return;
\r
472 _SetFrontColor(dwColor);
\r
474 d = 3 - (dwR << 1) ;
\r
479 while ( dwCurX <= dwCurY )
\r
481 dwXmin = (dwCurX > dwX) ? 0 : dwX-dwCurX;
\r
482 dwYmin = (dwCurY > dwY) ? 0 : dwY-dwCurY;
\r
483 _FillRect( dwXmin, dwYmin, dwX+dwCurX, dwYmin ) ;
\r
484 _FillRect( dwXmin, dwY+dwCurY, dwX+dwCurX, dwY+dwCurY ) ;
\r
485 dwXmin = (dwCurY > dwX) ? 0 : dwX-dwCurY;
\r
486 dwYmin = (dwCurX > dwY) ? 0 : dwY-dwCurX;
\r
487 _FillRect( dwXmin, dwYmin, dwX+dwCurY, dwYmin ) ;
\r
488 _FillRect( dwXmin, dwY+dwCurX, dwX+dwCurY, dwY+dwCurX ) ;
\r
492 d += (dwCurX << 2) + 6 ;
\r
496 d += ((dwCurX - dwCurY) << 2) + 10;
\r
506 * \brief Draws a string inside a LCD buffer, at the given coordinates. Line breaks
\r
509 * \param x X-coordinate of string top-left corner.
\r
510 * \param y Y-coordinate of string top-left corner.
\r
511 * \param pString String to display.
\r
512 * \param color String color.
\r
514 extern void LCDD_DrawString( uint32_t x, uint32_t y, const char *pString, uint32_t color )
\r
519 if (*pString == '\n')
\r
521 y += gFont.height + 2; x = xorg;
\r
525 LCDD_DrawChar(x, y, *pString, color);
\r
526 x += gFont.width + 2;
\r
533 * \brief Draws a string inside a LCD buffer, at the given coordinates
\r
534 * with given background color. Line breaks will be honored.
\r
536 * \param x X-coordinate of string top-left corner.
\r
537 * \param y Y-coordinate of string top-left corner.
\r
538 * \param pString String to display.
\r
539 * \param fontColor String color.
\r
540 * \param bgColor Background color.
\r
542 extern void LCDD_DrawStringWithBGColor( uint32_t x, uint32_t y, const char *pString, uint32_t fontColor, uint32_t bgColor )
\r
547 if (*pString == '\n')
\r
549 y += gFont.height + 2; x = xorg;
\r
553 LCDD_DrawCharWithBGColor(x, y, *pString, fontColor, bgColor);
\r
554 x += gFont.width + 2;
\r
561 * \brief Returns the width & height in pixels that a string will occupy on the screen
\r
562 * if drawn using LCDD_DrawString.
\r
564 * \param pString String.
\r
565 * \param pWidth Pointer for storing the string width (optional).
\r
566 * \param pHeight Pointer for storing the string height (optional).
\r
568 * \return String width in pixels.
\r
570 extern void LCDD_GetStringSize( const char *pString, uint32_t *pWidth, uint32_t *pHeight )
\r
572 uint32_t width = 0;
\r
573 uint32_t height = gFont.height;
\r
576 if (*pString == '\n') height += gFont.height + 2;
\r
577 else width += gFont.height + 2;
\r
580 if (width > 0) width -= 2;
\r
582 if (pWidth) *pWidth = width;
\r
583 if (pHeight)*pHeight = height;
\r
587 * \brief Draw a raw image at given position on LCD.
\r
589 * \param x X-coordinate of image start.
\r
590 * \param y Y-coordinate of image start.
\r
591 * \param pImage Image buffer.
\r
592 * \param width Image width.
\r
593 * \param height Image height.
\r
595 void LCDD_DrawImage( uint32_t dwX, uint32_t dwY, const uint8_t *pImage, uint32_t dwWidth, uint32_t dwHeight )
\r
597 sLCDDLayer *pDisp = LCDD_GetCanvas();
\r
598 uint16_t cw = pDisp->bMode/8; /* color width */
\r
599 uint32_t rw = pDisp->wImgW * cw; /* Row width in bytes */
\r
600 uint32_t rws = dwWidth * cw; /* Source Row Width */
\r
601 uint32_t rl = (rw & 0x3) ? ((rw | 0x3) + 1) : rw; /* Aligned length*/
\r
602 uint32_t rls = (rws & 0x3) ? ((rws | 0x3) + 1) : rws; /* Aligned length */
\r
603 uint8_t *pSrc, *pDst;
\r
606 pSrc = (uint8_t*)pImage;
\r
607 pDst = pDisp->pBuffer;
\r
608 pDst = &pDst[dwX*cw + dwY*rl];
\r
610 for (i = 0; i < dwHeight; i ++)
\r
612 memcpy(pDst, pSrc, rws);
\r
620 * \brief Clear a window with an color.
\r
622 * \param dwX X-coordinate of the window.
\r
623 * \param dwY Y-coordinate of the window.
\r
624 * \param dwWidth window width.
\r
625 * \param dwHeight window height.
\r
626 * \param dwColor background color
\r
628 extern void LCDD_ClearWindow( uint32_t dwX, uint32_t dwY, uint32_t dwWidth, uint32_t dwHeight, uint32_t dwColor )
\r
630 _SetFrontColor(dwColor);
\r
632 _FillRect(0, 0, dwX + dwWidth - 1, dwY + dwHeight - 1);
\r