#include "drawing.h" #include "display_spec.h" #include "font.h" extern uint8_t LCD_displayMap[LCD_WIDTH * LCD_HEIGHT / 8]; // This function sets a pixel on displayMap to your preferred // color. 1=Black, 0= white. void LCD_setPixel(int x, int y, enum Color bw) { // First, double check that the coordinate is in range. if ((x >= 0) && (x < LCD_WIDTH) && (y >= 0) && (y < LCD_HEIGHT)) { uint8_t shift = y % 8; if (bw) // If black, set the bit. LCD_displayMap[x + (y / 8) * LCD_WIDTH] |= 1 << shift; else // If white clear the bit. LCD_displayMap[x + (y / 8) * LCD_WIDTH] &= ~(1 << shift); } } // setLine draws a line from x0,y0 to x1,y1 with the set color. // This function was grabbed from the SparkFun ColorLCDShield // library. void LCD_setLine(int x0, int y0, int x1, int y1, enum Color bw) { int dy = y1 - y0; // Difference between y0 and y1 int dx = x1 - x0; // Difference between x0 and x1 int stepx, stepy; if (dy < 0) { dy = -dy; stepy = -1; } else stepy = 1; if (dx < 0) { dx = -dx; stepx = -1; } else stepx = 1; dy <<= 1; // dy is now 2*dy dx <<= 1; // dx is now 2*dx LCD_setPixel(x0, y0, bw); // Draw the first pixel. if (dx > dy) { int fraction = dy - (dx >> 1); while (x0 != x1) { if (fraction >= 0) { y0 += stepy; fraction -= dx; } x0 += stepx; fraction += dy; LCD_setPixel(x0, y0, bw); } } else { int fraction = dx - (dy >> 1); while (y0 != y1) { if (fraction >= 0) { x0 += stepx; fraction -= dy; } y0 += stepy; fraction += dx; LCD_setPixel(x0, y0, bw); } } } // setRect will draw a rectangle from x0,y0 top-left corner to // a x1,y1 bottom-right corner. Can be filled with the fill // parameter, and colored with bw. // This function was grabbed from the SparkFun ColorLCDShield // library. void LCD_setRect(int x0, int y0, int x1, int y1, bool fill, enum Color bw) { // check if the rectangle is to be filled if (fill == 1) { int xDiff; if (x0 > x1) xDiff = x0 - x1; //Find the difference between the x vars else xDiff = x1 - x0; while (xDiff > 0) { LCD_setLine(x0, y0, x0, y1, bw); if (x0 > x1) x0--; else x0++; xDiff--; } } else { // best way to draw an unfilled rectangle is to draw four lines LCD_setLine(x0, y0, x1, y0, bw); LCD_setLine(x0, y1, x1, y1, bw); LCD_setLine(x0, y0, x0, y1, bw); LCD_setLine(x1, y0, x1, y1, bw); } } // setCircle draws a circle centered around x0,y0 with a defined // radius. The circle can be black or white. And have a line // thickness ranging from 1 to the radius of the circle. // This function was grabbed from the SparkFun ColorLCDShield // library. void LCD_setCircle(int x0, int y0, int radius, enum Color bw, int lineThickness) { for (int r = 0; r < lineThickness; r++) { int f = 1 - radius; int ddF_x = 0; int ddF_y = -2 * radius; int x = 0; int y = radius; LCD_setPixel(x0, y0 + radius, bw); LCD_setPixel(x0, y0 - radius, bw); LCD_setPixel(x0 + radius, y0, bw); LCD_setPixel(x0 - radius, y0, bw); while (x < y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x + 1; LCD_setPixel(x0 + x, y0 + y, bw); LCD_setPixel(x0 - x, y0 + y, bw); LCD_setPixel(x0 + x, y0 - y, bw); LCD_setPixel(x0 - x, y0 - y, bw); LCD_setPixel(x0 + y, y0 + x, bw); LCD_setPixel(x0 - y, y0 + x, bw); LCD_setPixel(x0 + y, y0 - x, bw); LCD_setPixel(x0 - y, y0 - x, bw); } radius--; } } // This function will draw a char (defined in the ASCII table // near the beginning of this sketch) at a defined x and y). // The color can be either black (1) or white (0). void LCD_setChar(struct Utf8Char character, int x, int y, enum Color bw) { LCD_setCharEx(character, x, y, bw, 1); } void LCD_setCharEx(struct Utf8Char character, int x, int y, enum Color bw, uint8_t style) { const struct FontGraphic *symbol = Font_GetSymbol(character); bool bg = style & 0x80; enum FontStyle style_real = style & 0x7F; uint8_t column; // temp byte to store character's column bitmap for (int i = 0; i < 5; i++) // 5 columns (x) per character { column = symbol->columns[i]; for (int j = 0; j < 8; j++) // 8 rows (y) per character { bool bit = column & (1 << j); if (style_real == FONT_NORMAL) { if (bit) {// test bits to set pixels LCD_setPixel(x + i, y + j, bw); } else if (bg) { LCD_setPixel(x + i, y + j, !bw); } } else if (style_real == FONT_DOUBLE) { if (bit) {// test bits to set pixels LCD_setPixel(x + i * 2, y + j * 2, bw); LCD_setPixel(x + i * 2 + 1, y + j * 2, bw); LCD_setPixel(x + i * 2, y + j * 2 + 1, bw); LCD_setPixel(x + i * 2 + 1, y + j * 2 + 1, bw); } else if (bg) { LCD_setPixel(x + i * 2, y + j * 2, !bw); LCD_setPixel(x + i * 2 + 1, y + j * 2, !bw); LCD_setPixel(x + i * 2, y + j * 2 + 1, !bw); LCD_setPixel(x + i * 2 + 1, y + j * 2 + 1, !bw); } } else if (style_real == FONT_BOLD) { if (bit) {// test bits to set pixels LCD_setPixel(x + i, y + j, bw); LCD_setPixel(x + i + 1, y + j, bw); } else if (bg) { LCD_setPixel(x + i, y + j, !bw); LCD_setPixel(x + i + 1, y + j, !bw); } } } } } // setStr draws a string of characters, calling setChar with // progressive coordinates until it's done. // This function was grabbed from the SparkFun ColorLCDShield // library. void LCD_setStr(const char *dString, int x, int y, enum Color bw) { LCD_setStrEx(dString, x, y, bw, 1); } // setStr draws a string of characters, calling setChar with // progressive coordinates until it's done. // This function was grabbed from the SparkFun ColorLCDShield // library. void LCD_setStrEx(const char *dString, int x, int y, enum Color bw, uint8_t style) { struct Utf8Iterator iter; Utf8Iterator_Init(&iter, dString); bool bg = style & 0x80; enum FontStyle style_real = style & 0x7F; struct Utf8Char uchar; while ((uchar = Utf8Iterator_Next(&iter)).uint) { LCD_setCharEx(uchar, x, y, bw, style); if (style_real == FONT_NORMAL) { x += 5; if (bg) { for (int i = y; i < y + 8; i++) { LCD_setPixel(x, i, !bw); } } x++; if (x > (LCD_WIDTH - 5)) // Enables wrap around { x = 0; y += 8; } } else if (style_real == FONT_DOUBLE) { x += 10; if (bg) { for (int i = y; i < y + 16; i++) { LCD_setPixel(x, i, !bw); LCD_setPixel(x + 1, i, !bw); } } x += 2; if (x > (LCD_WIDTH - 10)) // Enables wrap around { x = 0; y += 16; } } else if (style_real == FONT_BOLD) { x += 6; if (bg) { for (int i = y; i < y + 8; i++) { LCD_setPixel(x, i, !bw); LCD_setPixel(x + 1, i, !bw); } } x += 1; if (x > (LCD_WIDTH - 6)) // Enables wrap around { x = 0; y += 8; } } } } // This function will draw an array over the screen. (For now) the // array must be the same size as the screen, covering the entirety // of the display. void LCD_setBitmap(const uint8_t *bitArray) { for (int i = 0; i < (LCD_WIDTH * LCD_HEIGHT / 8); i++) { LCD_displayMap[i] = bitArray[i]; } } // This function clears the entire display either white (0) or // black (1). // The screen won't actually clear until you call updateDisplay()! void LCD_clearDisplay(enum Color bw) { for (int i = 0; i < (LCD_WIDTH * LCD_HEIGHT / 8); i++) { if (bw) LCD_displayMap[i] = 0xFF; else LCD_displayMap[i] = 0; } } void LCD_invertDisplayData() { /* Indirect, swap bits in displayMap option: */ for (int i = 0; i < (LCD_WIDTH * LCD_HEIGHT / 8); i++) { LCD_displayMap[i] ^= 0xFF; } }