X-Git-Url: http://git.rohieb.name/hackover2013-badge-firmware.git/blobdiff_plain/9d18e10afb2439a6a9ba6978a799259746a837b7..ce00990e52808c5f8e2ceefd38f9eeb44bb96eab:/drivers/lcd/tft/drawing.c diff --git a/drivers/lcd/tft/drawing.c b/drivers/lcd/tft/drawing.c index cd612e6..e90a8e6 100644 --- a/drivers/lcd/tft/drawing.c +++ b/drivers/lcd/tft/drawing.c @@ -53,42 +53,60 @@ /* */ /**************************************************************************/ +/**************************************************************************/ +/*! + @brief Swaps values a and b +*/ +/**************************************************************************/ +void drawSwap(uint32_t a, uint32_t b) +{ + uint32_t t; + t = a; + a = b; + b = t; +} + /**************************************************************************/ /*! @brief Draws a single bitmap character */ /**************************************************************************/ -void drawCharBitmap(const uint16_t xPixel, const uint16_t yPixel, uint16_t color, const uint8_t *glyph, uint8_t glyphHeightPages, uint8_t glyphWidthBits) +void drawCharBitmap(const uint16_t xPixel, const uint16_t yPixel, uint16_t color, const char *glyph, uint8_t cols, uint8_t rows) { - uint16_t verticalPage, horizBit, currentY, currentX; - uint16_t indexIntoGlyph; + uint16_t currentY, currentX, indexIntoGlyph; + uint16_t _row, _col, _colPages; // set initial current y currentY = yPixel; currentX = xPixel; - // for each page of the glyph - for (verticalPage = glyphHeightPages; verticalPage > 0; --verticalPage) + // Figure out how many columns worth of data we have + if (cols % 8) + _colPages = cols / 8 + 1; + else + _colPages = cols / 8; + + for (_row = 0; _row < rows; _row++) { - // for each horizontol bit - for (horizBit = 0; horizBit < glyphWidthBits; ++horizBit) + for (_col = 0; _col < _colPages; _col++) { - // next byte - indexIntoGlyph = (glyphHeightPages * horizBit) + verticalPage - 1; - - currentX = xPixel + (horizBit); + if (_row == 0) + indexIntoGlyph = _col; + else + indexIntoGlyph = (_row * _colPages) + _col; + + currentY = yPixel + _row; + currentX = xPixel + (_col*8); // send the data byte if (glyph[indexIntoGlyph] & (0X80)) drawPixel(currentX, currentY, color); - if (glyph[indexIntoGlyph] & (0X40)) drawPixel(currentX, currentY - 1, color); - if (glyph[indexIntoGlyph] & (0X20)) drawPixel(currentX, currentY - 2, color); - if (glyph[indexIntoGlyph] & (0X10)) drawPixel(currentX, currentY - 3, color); - if (glyph[indexIntoGlyph] & (0X08)) drawPixel(currentX, currentY - 4, color); - if (glyph[indexIntoGlyph] & (0X04)) drawPixel(currentX, currentY - 5, color); - if (glyph[indexIntoGlyph] & (0X02)) drawPixel(currentX, currentY - 6, color); - if (glyph[indexIntoGlyph] & (0X01)) drawPixel(currentX, currentY - 7, color); + if (glyph[indexIntoGlyph] & (0X40)) drawPixel(currentX+1, currentY, color); + if (glyph[indexIntoGlyph] & (0X20)) drawPixel(currentX+2, currentY, color); + if (glyph[indexIntoGlyph] & (0X10)) drawPixel(currentX+3, currentY, color); + if (glyph[indexIntoGlyph] & (0X08)) drawPixel(currentX+4, currentY, color); + if (glyph[indexIntoGlyph] & (0X04)) drawPixel(currentX+5, currentY, color); + if (glyph[indexIntoGlyph] & (0X02)) drawPixel(currentX+6, currentY, color); + if (glyph[indexIntoGlyph] & (0X01)) drawPixel(currentX+7, currentY, color); } - // next line of pages - currentY += 8; } } @@ -330,7 +348,9 @@ void drawString(uint16_t x, uint16_t y, uint16_t color, const FONT_INFO *fontInf } // Send individual characters - drawCharBitmap(currentX, y, color, &fontInfo->data[charOffset], fontInfo->heightPages, charWidth); + // We need to manually calculate width in pages since this is screwy with variable width fonts + //uint8_t heightPages = charWidth % 8 ? charWidth / 8 : charWidth / 8 + 1; + drawCharBitmap(currentX, y, color, (const char *)(&fontInfo->data[charOffset]), charWidth, fontInfo->height); // next char X currentX += charWidth + 1; @@ -379,8 +399,8 @@ uint16_t drawGetStringWidth(const FONT_INFO *fontInfo, char *str) } } - /* return the wdith */ - return width; + /* return the width */ + return width > 0 ? width - 1 : width; } /**************************************************************************/ @@ -450,9 +470,6 @@ void drawLineDotted ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16 // Check if we can use the optimised vertical line method. // This can make a huge difference in performance, but may // not work properly on every LCD controller: - // ex.: drawCircleFilled(120, 160, 50, COLOR_RED); - // = 678834 cycles using lcdDrawVLine w/ILI9328 = 9.43mS @ 72MHz - // = 7546261 w/o lcdDrawVLine, setting each pixel = 104.8mS @ 72MHz if ((x0 == x1) && (empty == 0)) { // Warning: This may actually be slower than drawing individual pixels on @@ -649,6 +666,86 @@ void drawCircleFilled (uint16_t xCenter, uint16_t yCenter, uint16_t radius, uint } } +/**************************************************************************/ +/*! + @brief Draws a filled rounded corner + + @param[in] xCenter + The horizontal center of the circle + @param[in] yCenter + The vertical center of the circle + @param[in] radius + The circle's radius in pixels + @param[in] position + The position of the corner, which affects how it will + be rendered + @param[in] color + Color used when drawing +*/ +/**************************************************************************/ +void drawCornerFilled (uint16_t xCenter, uint16_t yCenter, uint16_t radius, drawCornerPosition_t position, uint16_t color) +{ + int16_t f = 1 - radius; + int16_t ddF_x = 1; + int16_t ddF_y = -2 * radius; + int16_t x = 0; + int16_t y = radius; + int16_t xc_px, yc_my, xc_mx, xc_py, yc_mx, xc_my; + int16_t lcdWidth = lcdGetWidth(); + + switch (position) + { + case DRAW_CORNERPOSITION_TOPRIGHT: + case DRAW_CORNERPOSITION_TOPLEFT: + if (xCenter < lcdWidth) drawLine(xCenter, yCenter-radius < 0 ? 0 : yCenter-radius, xCenter, yCenter, color); + break; + case DRAW_CORNERPOSITION_BOTTOMRIGHT: + case DRAW_CORNERPOSITION_BOTTOMLEFT: + if (xCenter < lcdWidth) drawLine(xCenter, yCenter-radius < 0 ? 0 : yCenter, xCenter, (yCenter-radius) + (2*radius), color); + break; + } + + while (x= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + xc_px = xCenter+x; + xc_mx = xCenter-x; + xc_py = xCenter+y; + xc_my = xCenter-y; + yc_mx = yCenter-x; + yc_my = yCenter-y; + + switch (position) + { + case DRAW_CORNERPOSITION_TOPRIGHT: + if ((xc_px < lcdWidth) && (xc_px >= 0)) drawLine(xc_px, yc_my, xc_px, yCenter, color); + if ((xc_py < lcdWidth) && (xc_py >= 0)) drawLine(xc_py, yc_mx, xc_py, yCenter, color); + break; + case DRAW_CORNERPOSITION_BOTTOMRIGHT: + if ((xc_px < lcdWidth) && (xc_px >= 0)) drawLine(xc_px, yCenter, xc_px, yc_my + 2*y, color); + if ((xc_py < lcdWidth) && (xc_py >= 0)) drawLine(xc_py, yCenter, xc_py, yc_mx + 2*x, color); + break; + case DRAW_CORNERPOSITION_TOPLEFT: + if ((xc_mx < lcdWidth) && (xc_mx >= 0)) drawLine(xc_mx, yc_my, xc_mx, yCenter, color); + if ((xc_my < lcdWidth) && (xc_my >= 0)) drawLine(xc_my, yc_mx, xc_my, yCenter, color); + break; + case DRAW_CORNERPOSITION_BOTTOMLEFT: + if ((xc_mx < lcdWidth) && (xc_mx >= 0)) drawLine(xc_mx, yCenter, xc_mx, yc_my + 2*y, color); + if ((xc_my < lcdWidth) && (xc_my >= 0)) drawLine(xc_my, yCenter, xc_my, yc_mx + 2*x, color); + break; + } + } +} + /**************************************************************************/ /*! @brief Draws a simple arrow of the specified width @@ -890,6 +987,122 @@ void drawRectangleRounded ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, } } +/**************************************************************************/ +/*! + @brief Draws a triangle + + @param[in] x0 + x co-ordinate for point 0 + @param[in] y0 + y co-ordinate for point 0 + @param[in] x1 + x co-ordinate for point 1 + @param[in] y1 + y co-ordinate for point 1 + @param[in] x2 + x co-ordinate for point 2 + @param[in] y2 + y co-ordinate for point 2 + @param[in] color + Color used when drawing +*/ +/**************************************************************************/ +void drawTriangle ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +{ + drawLine(x0, y0, x1, y1, color); + drawLine(x1, y1, x2, y2, color); + drawLine(x2, y2, x0, y0, color); +} + +/**************************************************************************/ +/*! + @brief Draws a filled triangle + + @param[in] x0 + x co-ordinate for point 0 + @param[in] y0 + y co-ordinate for point 0 + @param[in] x1 + x co-ordinate for point 1 + @param[in] y1 + y co-ordinate for point 1 + @param[in] x2 + x co-ordinate for point 2 + @param[in] y2 + y co-ordinate for point 2 + @param[in] color + Fill color + + @section Example + + @code + + // Draw a white triangle + drawTriangleFilled ( 100, 10, 20, 120, 230, 290, COLOR_WHITE); + // Draw black circles at each point of the triangle + drawCircleFilled(100, 10, 2, COLOR_BLACK); + drawCircleFilled(20, 120, 2, COLOR_BLACK); + drawCircleFilled(230, 290, 2, COLOR_BLACK); + + @endcode +*/ +/**************************************************************************/ +void drawTriangleFilled ( uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) +{ + // Re-order vertices by ascending Y values (smallest first) + if (y0 > y1) { + drawSwap(y0, y1); drawSwap(x0, x1); + } + if (y1 > y2) { + drawSwap(y2, y1); drawSwap(x2, x1); + } + if (y0 > y1) { + drawSwap(y0, y1); drawSwap(x0, x1); + } + + int32_t dx1, dx2, dx3; // Interpolation deltas + int32_t sx1, sx2, sy; // Scanline co-ordinates + + sx1=sx2=x0 * 1000; // Use fixed point math for x axis values + sy=y0; + + // Calculate interpolation deltas + if (y1-y0 > 0) dx1=((x1-x0)*1000)/(y1-y0); + else dx1=0; + if (y2-y0 > 0) dx2=((x2-x0)*1000)/(y2-y0); + else dx2=0; + if (y2-y1 > 0) dx3=((x2-x1)*1000)/(y2-y1); + else dx3=0; + + // Render scanlines (horizontal lines are the fastest rendering method) + if (dx1 > dx2) + { + for(; sy<=y1; sy++, sx1+=dx2, sx2+=dx1) + { + drawLine(sx1/1000, sy, sx2/1000, sy, color); + } + sx2 = x1*1000; + sy = y1; + for(; sy<=y2; sy++, sx1+=dx2, sx2+=dx3) + { + drawLine(sx1/1000, sy, sx2/1000, sy, color); + } + } + else + { + for(; sy<=y1; sy++, sx1+=dx1, sx2+=dx2) + { + drawLine(sx1/1000, sy, sx2/1000, sy, color); + } + sx1 = x1*1000; + sy = y1; + for(; sy<=y2; sy++, sx1+=dx3, sx2+=dx2) + { + drawLine(sx1/1000, sy, sx2/1000, sy, color); + } + } +} + /**************************************************************************/ /*! @brief Converts a 24-bit RGB color to an equivalent 16-bit RGB565 value @@ -970,7 +1183,7 @@ uint16_t drawBGR2RGB(uint16_t color) r = (color>>11) & 0x1f; return( (b<<11) + (g<<5) + (r<<0) ); -} +} /**************************************************************************/ /*! @@ -1062,27 +1275,17 @@ void drawProgressBar ( uint16_t x, uint16_t y, uint16_t width, uint16_t height, @code #include "drivers/lcd/tft/drawing.h" - #include "drivers/lcd/tft/fonts/dejavusansbold9.h" + #include "drivers/lcd/tft/fonts/dejavusans9.h" // Draw two buttons using Vera Sans Bold 9 - drawButton(20, 195, 200, 35, &dejaVuSansBold9ptFontInfo, 7, COLOR_DARKERGRAY, COLOR_DARKERGRAY, COLOR_WHITE, "System Settings"); - drawButton(20, 235, 200, 35, &dejaVuSansBold9ptFontInfo, 7, COLOR_LIMEGREENDIM, COLOR_LIMEGREEN, COLOR_BLACK, "System Settings"); + drawButton(20, 195, 200, 35, &dejaVuSans9ptFontInfo, 7, COLOR_GRAY_80, COLOR_GRAY_80, COLOR_WHITE, "System Settings"); + drawButton(20, 235, 200, 35, &dejaVuSans9ptFontInfo, 7, COLOR_THEME_LIMEGREEN_DARKER, COLOR_THEME_LIMEGREEN_BASE, COLOR_BLACK, "System Settings"); @endcode */ /**************************************************************************/ void drawButton(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const FONT_INFO *fontInfo, uint16_t fontHeight, uint16_t borderclr, uint16_t fillclr, uint16_t fontclr, char* text) { - uint16_t border, fill, font, activeborder, activefill, activefont; - - // Set colors - border = COLOR_GRAY_30; - fill = COLOR_GRAY_30; - font = COLOR_WHITE; - activeborder = COLOR_THEME_DEFAULT_DARKER; - activefill = COLOR_THEME_DEFAULT_BASE; - activefont = COLOR_BLACK; - // Border drawRectangleRounded(x, y, x + width, y + height, borderclr, 5, DRAW_ROUNDEDCORNERS_ALL); // Fill @@ -1131,7 +1334,6 @@ void drawButton(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const F void drawIcon16(uint16_t x, uint16_t y, uint16_t color, uint16_t icon[]) { int i; - uint16_t row; for (i = 0; i<16; i++) { if (icon[i] & (0X8000)) drawPixel(x, y+i, color);