bounding_box_t draw_char(unsigned char c, unsigned char x, unsigned char y, ROM unsigned char *font) { unsigned int16 pos; unsigned char width; bounding_box_t ret; ret.x1 = x; ret.y1 = y; ret.x2 = x; ret.y2 = y; // Read first byte, should be 0x01 for proportional if (font[FONT_HEADER_TYPE] != FONT_TYPE_PROPORTIONAL) return ret; // Check second byte, should be 0x02 for "vertical ceiling" if (font[FONT_HEADER_ORIENTATION] != FONT_ORIENTATION_VERTICAL_CEILING) return ret; // Check that font start + number of bitmaps contains c if (!(c >= font[FONT_HEADER_START] && c <= font[FONT_HEADER_START] + font[FONT_HEADER_LETTERS])) return ret; // Adjust for start position of font vs. the char passed c -= font[FONT_HEADER_START]; // Work out where in the array the character is pos = font[c * FONT_HEADER_START + 5]; pos <<= 8; pos |= font[c * FONT_HEADER_START + 6]; // Read first byte from this position, this gives letter width width = font[pos]; // Draw left to right unsigned char i; for (i = 0; i < width; i++) { // Draw top to bottom for (unsigned char j = 0; j < font[FONT_HEADER_HEIGHT]; j++) { // Increment one data byte every 8 bits, or // at the start of a new column HiTech optimizes // the modulo, so no need to try and avoid it. if (j % 8 == 0) pos++; if (font[pos] & 1 << (j % 8)) { glcd_pixel(x + i, y + j, 1); } else { glcd_pixel(x + i, y + j, 0); } } } ret.x2 = ret.x1 + width - 1; // TODO: Return the actual height drawn, rather than the height of the // font. // TODO: Bugreport schreiben für https://github.com/edeca/Electronics; folgende Zeile ist bei dem nicht auskommentiert //ret.y2 = ret.y1 + height; ret.y2 = ret.y1 + font[FONT_HEADER_HEIGHT]; return ret; }
// Purpose: Draw a circle on a graphic LCD // Inputs: (x,y) - the center of the circle // radius - the radius of the circle // fill - YES or NO // color - ON or OFF void glcd_circle(int x, int y, int radius, int1 fill, int1 color) { signed int a, b, P; a = 0; b = radius; P = 1 - radius; do { if(fill) { glcd_line(x-a, y+b, x+a, y+b, color); glcd_line(x-a, y-b, x+a, y-b, color); glcd_line(x-b, y+a, x+b, y+a, color); glcd_line(x-b, y-a, x+b, y-a, color); } else { glcd_pixel(a+x, b+y, color); glcd_pixel(b+x, a+y, color); glcd_pixel(x-a, b+y, color); glcd_pixel(x-b, a+y, color); glcd_pixel(b+x, y-a, color); glcd_pixel(a+x, y-b, color); glcd_pixel(x-a, y-b, color); glcd_pixel(x-b, y-a, color); } if(P < 0) P+= 3 + 2*a++; else P+= 5 + 2*(a++ - b--); } while(a <= b); }
void draw_circle(char centre_x, char centre_y, char radius, char colour) { signed int x = 0; signed int y = radius; signed int p = 1 - radius; if (!radius) return; for (x = 0; x < y; x++) { if (p < 0) { p += x * 2 + 3; } else { p += x * 2 - y * 2 + 5; y--; } glcd_pixel(centre_x - x, centre_y - y, colour); glcd_pixel(centre_x - y, centre_y - x, colour); glcd_pixel(centre_x + y, centre_y - x, colour); glcd_pixel(centre_x + x, centre_y - y, colour); glcd_pixel(centre_x - x, centre_y + y, colour); glcd_pixel(centre_x - y, centre_y + x, colour); glcd_pixel(centre_x + y, centre_y + x, colour); glcd_pixel(centre_x + x, centre_y + y, colour); } }
void glcd_line(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1, unsigned int color) { int x = x1-x0; int y = y1-y0; int dx = abs(x), sx = x0<x1 ? 1 : -1; int dy = -abs(y), sy = y0<y1 ? 1 : -1; int err = dx+dy, e2; // error value e_xy for (;;) { glcd_pixel(x0,y0,color); e2 = 2*err; if (e2 >= dy) // e_xy+e_x > 0 { if (x0 == x1) break; err += dy; x0 += sx; } if (e2 <= dx) // e_xy+e_y < 0 { if (y0 == y1) break; err += dx; y0 += sy; } } }
void draw_line(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, char colour) { unsigned int xinc1, yinc1, den, num, numadd, numpixels, curpixel, xinc2, yinc2; unsigned int deltax = abs(x2 - x1); // The difference between the x's unsigned int deltay = abs(y2 - y1); // The difference between the y's unsigned int x = x1; // Start x off at the first pixel unsigned int y = y1; // Start y off at the first pixel if (x2 >= x1) { // The x-values are increasing xinc1 = 1; xinc2 = 1; } else { // The x-values are decreasing xinc1 = -1; xinc2 = -1; } if (y2 >= y1) // The y-values are increasing { yinc1 = 1; yinc2 = 1; } else // The y-values are decreasing { yinc1 = -1; yinc2 = -1; } if (deltax >= deltay) // There is at least one x-value for every y-value { xinc1 = 0; // Don't change the x when numerator >= denominator yinc2 = 0; // Don't change the y for every iteration den = deltax; num = deltax / 2; numadd = deltay; numpixels = deltax; // There are more x-values than y-values } else // There is at least one y-value for every x-value { xinc2 = 0; // Don't change the x for every iteration yinc1 = 0; // Don't change the y when numerator >= denominator den = deltay; num = deltay / 2; numadd = deltax; numpixels = deltay; // There are more y-values than x-values } for (curpixel = 0; curpixel <= numpixels; curpixel++) { glcd_pixel(x, y, colour); // Draw the current pixel num += numadd; // Increase the numerator by the top of the fraction if (num >= den) // Check if numerator >= denominator { num -= den; // Calculate the new numerator value x += xinc1; // Change the x as appropriate y += yinc1; // Change the y as appropriate } x += xinc2; // Change the x as appropriate y += yinc2; // Change the y as appropriate } }
void glcd_circle(int x0, int y0, int r, unsigned int color) { int x = -r, y = 0, err = 2-2*r, e2; do { glcd_pixel(x0-x, y0+y,color); glcd_pixel(x0+x, y0+y,color); glcd_pixel(x0+x, y0-y,color); glcd_pixel(x0-x, y0-y,color); e2 = err; if (e2 <= y) { err += ++y*2+1; if (-x == y && e2 <= x) e2 = 0; } if (e2 > x) err += ++x*2+1; } while (x <= 0); }
//****************************************************************************// // Purpose: Draw a 3D box on a graphic LCD (Ex: to make a 3D Button) // // Inputs: (x, y) - the start point // // (width, height) - size of the box // // depth - 3D depth effect ratio of the box (2 or 3 is fine) // // color - ON or OFF // // Dependencies: glcd_pixel() // //****************************************************************************// void glcd_3Dbox(int x,int y,int width, int height, int depth, int color) { int i,j; for(i=x;i<=x+width;i++) { glcd_pixel(i,y,1); glcd_pixel(i,y+height,1); } for(i=y;i<=y+height;i++) { glcd_pixel(x,i,1); glcd_pixel(x+width,i,1); } for(j=1;j<=depth;j++) { for(i=y+j;i<=y+height+j;i++) { glcd_pixel(x-j,i,1); } } for(j=1;j<=depth;j++) { for(i=x-j;i<=(x-j+width);i++) { glcd_pixel(i,y+height+j,color); } } }
//****************************************************************************// // Purpose: Draw a segment of a circle on a graphic LCD // // Inputs: (x,y) - The center of the circle // // radius - The radius of the circle // // angle_start - Start point angle of segment of circle // // angle_end - End point angle of segment of circle // // // // Example: (angle_start = 0 & angle_end = 360 draws a normal circle) // // (angle_start = 0 & angle_end = 180 draws half circle (arc) )// // // // color - ON or OFF // // Dependencies: glcd_pixel(), <math.h> // //****************************************************************************// void glcd_circle_seg(int x, int y, int radius, int angle_start, int angle_end, int color) { int x_round, y_round; float angle; #define DEGREE 2*3.14159265/360 for (angle = (float)angle_start; angle <= angle_end; angle += .9) { x_round = (sin (angle * DEGREE) * radius); y_round = (cos (angle * DEGREE) * radius); glcd_pixel(x + x_round, y + y_round, color); } }
void glcd_text57(int8 x, int8 y, char* textptr, int8 size, int1 color) #endif { int8 j, k, l, m; // Loop counters int8 pixelData[5]; // Stores character data for(; *textptr != '\0'; ++textptr, ++x)// Loop through the passed string { if(*textptr < 'S') // Checks if the letter is in the first font array memcpy(pixelData, FONT[*textptr - ' '], 5); else if(*textptr <= '~') // Check if the letter is in the second font array memcpy(pixelData, FONT2[*textptr - 'S'], 5); else memcpy(pixelData, FONT[0], 5); // Default to space // Handles newline and carriage returns switch(*textptr) { case '\n': y += 7*size + 1; continue; case '\r': x = 0; continue; } if(x+5*size >= GLCD_WIDTH) // Performs character wrapping { x = 0; // Set x at far left position y += 7*size + 1; // Set y at next position down } for(j=0; j<5; ++j, x+=size) // Loop through character byte data { for(k=0; k < 7; ++k) // Loop through the vertical pixels { if(bit_test(pixelData[j], k)) // Check if the pixel should be set { for(l=0; l < size; ++l) // These two loops change the { // character's size for(m=0; m < size; ++m) { glcd_pixel(x+m, y+k*size+l, color); // Draws the pixel } } } } } } }
//****************************************************************************// // Purpose: Write text on a graphic LCD // // Inputs: (x,y) - The upper left coordinate of the first letter // // textptr - A pointer to an array of text to display // // size - The size of the text: 1 = 5x7, 2 = 10x14, ... // // color - ON or OFF // // Dependencies: glcd_pixel() // //****************************************************************************// void glcd_text57(int x, int y, char* textptr, int size, int color) { int j, k, l, m; // Contadores de bucle uint8 pixelData[5]; // Datos a imprimir for(; *textptr != '\0'; ++textptr, ++x) // Bucle sobre las letras a escribir { if(*textptr < 'S') // Compruebo si estoy en el primer vector de letras memcpy(pixelData, FONT[*textptr - ' '],5); else if(*textptr <= '~') // Compruebo si salte al segundo vector de letras memcpy(pixelData, FONT2[*textptr - 'S'],5); else memcpy(pixelData, FONT[0], 5); // Definido para el espacio // cambio de linea y retorno de carro switch(*textptr) { case '\n': y += 7*size + 1; continue; case '\r': x = 0; continue; } if(x+5*size >= GLCD_WIDTH) // Performs character wrapping { x = 0; // Set x at far left position y += 7*size + 1; // Set y at next position down } for(j=0; j<5; ++j, x+=size) // Loop through character byte data { for(k=0; k < 7; ++k) // Loop through the vertical pixels { if(((pixelData[j] & (1<<k)) != 0)) // Check if the pixel should be set { for(l=0; l < size; ++l) // These two loops change the { // character's size for(m=0; m < size; ++m) { glcd_pixel(x+m, y+k*size+l, color); // Draws the pixel } } } } } } }
void glcd_rect(int8 x1, int8 y1, int8 x2, int8 y2, int1 fill, int1 color) #endif { if(fill) { #ifdef LARGE_LCD int16 i, xmin, xmax, ymin, ymax; #else int8 i, xmin, xmax, ymin, ymax; #endif if(x1 < x2) // Find x min and max { xmin = x1; xmax = x2; } else { xmin = x2; xmax = x1; } if(y1 < y2) // Find the y min and max { ymin = y1; ymax = y2; } else { ymin = y2; ymax = y1; } for(; xmin <= xmax; ++xmin) { for(i=ymin; i<=ymax; ++i) { glcd_pixel(xmin, i, color); } } } else { glcd_line(x1, y1, x2, y1, color); // Draw the 4 sides glcd_line(x1, y2, x2, y2, color); glcd_line(x1, y1, x1, y2, color); glcd_line(x2, y1, x2, y2, color); } }
void glcd_circle(int8 x, int8 y, int8 radius, int1 fill, int1 color) #endif { #ifdef LARGE_LCD signed int16 a, b, P; #else signed int8 a, b, P; #endif a = 0; b = radius; P = 1 - radius; do { if(fill) { glcd_line(x-a, y+b, x+a, y+b, color); glcd_line(x-a, y-b, x+a, y-b, color); glcd_line(x-b, y+a, x+b, y+a, color); glcd_line(x-b, y-a, x+b, y-a, color); } else { glcd_pixel(a+x, b+y, color); glcd_pixel(b+x, a+y, color); glcd_pixel(x-a, b+y, color); glcd_pixel(x-b, a+y, color); glcd_pixel(b+x, y-a, color); glcd_pixel(a+x, y-b, color); glcd_pixel(x-a, y-b, color); glcd_pixel(x-b, y-a, color); } if(P < 0) P += 3 + 2 * a++; else P += 5 + 2 * (a++ - b--); } while(a <= b); }
// Purpose: Write text on a graphic LCD // Inputs: (x,y) - The upper left coordinate of the first letter // textptr - A pointer to an array of text to display // size - The size of the text: 1 = 5x7, 2 = 10x14, ... // color - ON or OFF void glcd_text57(int x, int y, char* textptr, int size, int1 color) { int i, j, k, l, m; // Loop counters BYTE pixelData[5]; // Stores character data for(i=0; textptr[i] != '\0'; ++i, ++x) // Loop through the passed string { if(textptr[i] < 'S') // Checks if the letter is in the first text array memcpy(pixelData, TEXT[textptr[i]-' '], 5); else if(textptr[i] <= '~') // Check if the letter is in the second array memcpy(pixelData, TEXT2[textptr[i]-'S'], 5); else memcpy(pixelData, TEXT[0], 5); // Default to space if(x+5*size >= GLCD_WIDTH) // Performs character wrapping { x = 0; // Set x at far left position y += 7*size + 1; // Set y at next position down } for(j=0; j<5; ++j, x+=size) // Loop through character byte data { for(k=0; k<7*size; ++k) // Loop through the vertical pixels { if(bit_test(pixelData[j], k)) // Check if the pixel should be set { for(l=0; l<size; ++l) // The next two loops change the { // character's size for(m=0; m<size; ++m) { glcd_pixel(x+m, y+k*size+l, color); // Draws the pixel } } } } } } }
void glcd_line(int8 x1, int8 y1, int8 x2, int8 y2, int1 color) #endif { int16 dy, dx; signed int8 addx=1, addy=1; signed int16 P, diff; #ifdef LARGE_LCD int16 i=0; dx = abs((signed int16)(x2 - x1)); dy = abs((signed int16)(y2 - y1)); #else int8 i=0; dx = abs((signed int8)(x2 - x1)); dy = abs((signed int8)(y2 - y1)); #endif if(x1 > x2) addx = -1; if(y1 > y2) addy = -1; if(dx >= dy) { dy *= 2; P = dy - dx; diff = P - dx; for(; i<=dx; ++i) { glcd_pixel(x1, y1, color); if(P < 0) { P += dy; x1 += addx; } else { P += diff; x1 += addx; y1 += addy; } } } else { dx *= 2; P = dx - dy; diff = P - dy; for(; i<=dy; ++i) { glcd_pixel(x1, y1, color); if(P < 0) { P += dx; y1 += addy; } else { P += diff; x1 += addx; y1 += addy; } } } }
// Purpose: Draw a line on a graphic LCD using Bresenham's // line drawing algorithm // Inputs: (x1, y1) - the start coordinate // (x2, y2) - the end coordinate // color - ON or OFF // Dependencies: glcd_pixel() void glcd_line(int x1, int y1, int x2, int y2, int1 color) { signed int x, y, addx, addy, dx, dy; signed long P; int i; dx = abs((signed int)(x2 - x1)); dy = abs((signed int)(y2 - y1)); x = x1; y = y1; if(x1 > x2) addx = -1; else addx = 1; if(y1 > y2) addy = -1; else addy = 1; if(dx >= dy) { P = 2*dy - dx; for(i=0; i<=dx; ++i) { glcd_pixel(x, y, color); if(P < 0) { P += 2*dy; x += addx; } else { P += 2*dy - 2*dx; x += addx; y += addy; } } } else { P = 2*dx - dy; for(i=0; i<=dy; ++i) { glcd_pixel(x, y, color); if(P < 0) { P += 2*dx; y += addy; } else { P += 2*dx - 2*dy; x += addx; y += addy; } } } }
// Purpose: Draw a bar (wide line) on a graphic LCD // Inputs: (x1, y1) - the start coordinate // (x2, y2) - the end coordinate // width - The number of pixels wide // color - ON or OFF void glcd_bar(int x1, int y1, int x2, int y2, int width, int1 color) { signed int x, y, addx, addy, j; signed long P, dx, dy, c1, c2; int i; dx = abs((signed int)(x2 - x1)); dy = abs((signed int)(y2 - y1)); x = x1; y = y1; c1 = -dx*x1 - dy*y1; c2 = -dx*x2 - dy*y2; if(x1 > x2) { addx = -1; c1 = -dx*x2 - dy*y2; c2 = -dx*x1 - dy*y1; } else addx = 1; if(y1 > y2) { addy = -1; c1 = -dx*x2 - dy*y2; c2 = -dx*x1 - dy*y1; } else addy = 1; if(dx >= dy) { P = 2*dy - dx; for(i=0; i<=dx; ++i) { for(j=-(width/2); j<width/2+width%2; ++j) { if(dx*x+dy*(y+j)+c1 >= 0 && dx*x+dy*(y+j)+c2 <=0) glcd_pixel(x, y+j, color); } if(P < 0) { P += 2*dy; x += addx; } else { P += 2*dy - 2*dx; x += addx; y += addy; } } } else { P = 2*dx - dy; for(i=0; i<=dy; ++i) { if(P < 0) { P += 2*dx; y += addy; } else { P += 2*dx - 2*dy; x += addx; y += addy; } for(j=-(width/2); j<width/2+width%2; ++j) { if(dx*x+dy*(y+j)+c1 >= 0 && dx*x+dy*(y+j)+c2 <=0) glcd_pixel(x+j, y, color); } } } }
void glcd_bar(int8 x1, int8 y1, int8 x2, int8 y2, int8 width, int1 color) #endif { int8 half_width; signed int16 dy, dx; signed int8 addx=1, addy=1, j; signed int16 P, diff, c1, c2; #ifdef LARGE_LCD int16 i=0; dx = abs((signed int16)(x2 - x1)); dy = abs((signed int16)(y2 - y1)); #else int8 i=0; dx = abs((signed int8)(x2 - x1)); dy = abs((signed int8)(y2 - y1)); #endif half_width = width/2; c1 = -(dx*x1 + dy*y1); c2 = -(dx*x2 + dy*y2); if(x1 > x2) { signed int16 temp; temp = c1; c1 = c2; c2 = temp; addx = -1; } if(y1 > y2) { signed int16 temp; temp = c1; c1 = c2; c2 = temp; addy = -1; } if(dx >= dy) { P = 2*dy - dx; diff = P - dx; for(i=0; i<=dx; ++i) { for(j=-half_width; j<half_width+width%2; ++j) { #ifdef LARGE_LCD int16 temp; #else int8 temp; #endif temp = dx*x1+dy*(y1+j); // Use more RAM to increase speed if(temp+c1 >= 0 && temp+c2 <=0) glcd_pixel(x1, y1+j, color); } if(P < 0) { P += 2*dy; x1 += addx; } else { P += diff; x1 += addx; y1 += addy; } } } else { P = 2*dx - dy; diff = P - dy; for(i=0; i<=dy; ++i) { if(P < 0) { P += 2*dx; y1 += addy; } else { P += diff; x1 += addx; y1 += addy; } for(j=-half_width; j<half_width+width%2; ++j) { #ifdef LARGE_LCD int16 temp; #else int8 temp; #endif temp = dx*x1+dy*(y1+j); // Use more RAM to increase speed if(temp+c1 >= 0 && temp+c2 <=0) glcd_pixel(x1+j, y1, color); } } } }