int drw_aktx = 0; int drw_akty = 0; uint16_t drw_color = 0xffff; // Koordinaten, um die die Ausgabe einer Turtlegrafik "verschoben" werden kann int drw_xofs = 0; int drw_yofs = 0; /* ------------------------------------------------------------- drw_putpixel zeichnet einen einzelnen Bildpunkt auf das Display x, y : Koordinate, an der ein Bildpunkt gesetzt wird col : Farbe des Bildpunktes ------------------------------------------------------------- */ void drw_putpixel(int x, int y, uint16_t col) { putpixel(x + drw_xofs, y + drw_yofs, col); } /* ------------------------------------------------------------- drw_line Zeichnet eine Linie von den Koordinaten x0,y0 zu x1,y1 mit der angegebenen Farbe x0,y0 : Koordinate linke obere Ecke x1,y1 : Koordinate rechte untere Ecke color : Farbwert, der gezeichnet wird Linienalgorithmus nach Bresenham (www.wikipedia.org) ------------------------------------------------------------- */ void drw_line(int x0, int y0, int x1, int y1, uint16_t color) { // Linienalgorithmus nach Bresenham (www.wikipedia.org) int dx = abs(x1-x0), sx = x0 dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */ if (e2 < dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */ } } /* ------------------------------------------------------------- drw_ellipse Zeichnet eine Ellipse mit Mittelpunt an der Koordinate xm,ym mit den Hoehen- Breitenverhaeltnis a:b mit der angegebenen Farbe xm,ym : Koordinate des Mittelpunktes der Ellipse a,b : Hoehen- Breitenverhaeltnis color : Farbwert, der gezeichnet wird Ellipsenalgorithmus nach Bresenham (www.wikipedia.org) ------------------------------------------------------------- */ void drw_ellipse(int xm, int ym, int a, int b, uint16_t color ) { // Algorithmus nach Bresenham (www.wikipedia.org) int dx = 0, dy = b; // im I. Quadranten von links oben nach rechts unten long a2 = a*a, b2 = b*b; long err = b2-(2*b-1)*a2, e2; // Fehler im 1. Schritt */ do { drw_putpixel(xm+dx, ym+dy,color); // I. Quadrant drw_putpixel(xm-dx, ym+dy,color); // II. Quadrant drw_putpixel(xm-dx, ym-dy,color); // III. Quadrant drw_putpixel(xm+dx, ym-dy,color); // IV. Quadrant e2 = 2*err; if (e2 < (2*dx+1)*b2) { dx++; err += (2*dx+1)*b2; } if (e2 > -(2*dy-1)*a2) { dy--; err -= (2*dy-1)*a2; } } while (dy >= 0); while (dx++ < a) // fehlerhafter Abbruch bei flachen Ellipsen (b=1) { drw_putpixel(xm+dx, ym,color); drw_putpixel(xm-dx, ym,color); } } /* ---------------------------------------------------------- drw_fastxline zeichnet eine Linie in X-Achse mit den X Punkten x1 und x2 auf der Y-Achse y1 x1, x2 : Start-, Endpunkt der Linie y1 : Y-Koordinate der Linie color : 16 - Bit RGB565 Farbwert der gezeichnet werden soll ---------------------------------------------------------- */ void drw_fastxline(int x1, int y1, int x2, uint16_t color) { int x; if (x2 < x1) { x = x1; x1 = x2; x2 = x; } for (x= x1; x< (x2+1); x++) { drw_putpixel(x,y1, color); } } /* ------------------------------------------------------------- drw_rectangle Zeichnet ein Rechteck von den Koordinaten x0,y0 zu x1,y1 mit der angegebenen Farbe x0,y0 : Koordinate linke obere Ecke x1,y1 : Koordinate rechte untere Ecke color : Farbwert, der gezeichnet wird ------------------------------------------------------------- */ void drw_rectangle(int x1, int y1, int x2, int y2, uint16_t color) { if (x2 < x1) { int t = x1; x1 = x2; x2 = t; } if (y2 < y1) { int t = y1; y1 = y2; y2 = t; } drw_line(x1,y1,x2,y1, color); drw_line(x2,y1,x2,y2, color); drw_line(x1,y2,x2,y2, color); drw_line(x1,y1,x1,y2, color); } /* ------------------------------------------------------------- drw_fillrectangle Zeichnet ein gefuelltes Rechteck von den Koordinaten x0,y0 zu x1,y1 mit der angegebenen Farbe x0,y0 : Koordinate linke obere Ecke x1,y1 : Koordinate rechte untere Ecke color : Farbwert, der gezeichnet wird ------------------------------------------------------------- */ void drw_fillrectangle(int x1, int y1, int x2, int y2, uint16_t color) { if (x2 < x1) { int t = x1; x1 = x2; x2 = t; } if (y2 < y1) { int t = y1; y1 = y2; y2 = t; } int y; for (y = y1; y <= y2; y++) { drw_fastxline(x1, y, x2, color); } } /* ------------------------------------------------------------- drw_circle Zeichnet einen Kreis mit Mittelpunt an der Koordinate xm,ym und dem Radius r mit der angegebenen Farbe x ,y : Koordinate des Mittelpunktes der Ellipse r : Radius des Kreises color : Farbwert, der gezeichnet wird ------------------------------------------------------------- */ void drw_circle(int x, int y, int r, uint16_t color ) { drw_ellipse(x,y,r,r,color); } /* ------------------------------------------------------------- drw_fillellipse Zeichnet eine ausgefuellte Ellipse mit Mittelpunt an der Koordinate xm,ym mit den Hoehen- Breitenverhaeltnis a:b mit der angegebenen Farbe xm,ym : Koordinate des Mittelpunktes der Ellipse a,b : Hoehen- Breitenverhaeltnis color : Farbwert, der gezeichnet wird Ellipsenalgorithmus nach Bresenham (www.wikipedia.org) ------------------------------------------------------------- */ void drw_fillellipse(int xm, int ym, int a, int b, uint16_t color ) { int dx = 0, dy = b; long a2 = a*a, b2 = b*b; long err = b2-(2*b-1)*a2, e2; do { drw_fastxline(xm+dx, ym+dy,xm-dx, color); drw_fastxline(xm-dx, ym-dy,xm+dx, color); e2 = 2*err; if (e2 < (2*dx+1)*b2) { dx++; err += (2*dx+1)*b2; } if (e2 > -(2*dy-1)*a2) { dy--; err -= (2*dy-1)*a2; } } while (dy >= 0); while (dx++ < a) { drw_putpixel(xm+dx, ym,color); drw_putpixel(xm-dx, ym,color); } } /* ------------------------------------------------------------- drw_fillcircle Zeichnet einen ausgefuellten Kreis mit Mittelpunt an der Koordinate xm,ym und dem Radius r mit der angegebenen Farbe x,y : Koordinate des Mittelpunktes der Ellipse r : Radius des Kreises color : Farbwert, der gezeichnet wird ------------------------------------------------------------- */ void drw_fillcircle(int x, int y, int r, uint16_t color ) { drw_fillellipse(x,y,r,r,color); } /* ------------------------------------------------------------- cmd_getonearg liest einen Parameter als Integer ab der Stringposition 0 und gibt als Funktionsargument einen Zeiger auf den dem Argument folgenden String zurueck. *str : Zeiger auf String (PROGMEM) *value : Zeiger Speicherplatz, der den im String ent- haltenen Wert als Integer aufnimmt Rueckgabe : Zeiger auf den String, der dem Parameter folgt ------------------------------------------------------------- */ const char *cmd_getonearg(const char *str, int *value) { char ch, negativesign; char loop; int v; loop = 1; v = 0; negativesign = 0; while ((ch = pgm_read_byte(str)) && loop) { if (ch == '-') { negativesign = 1; str++; ch = pgm_read_byte(str); } if ((ch >= '0') && (ch <= '9')) { v = v * 10; v += ch - '0'; str++; } else { loop = 0; } } *value = negativesign ? -v : v; return str; } /* ------------------------------------------------------------- cmd_parse Interpretiert einen String als Anweisungen fuer einen Zeichenstift ------------------------------------------------------------- */ void cmd_parse(const char *str) { char ch; int arg1, arg2, arg3; while ((ch = pgm_read_byte(str))) { str++; switch (ch) { case 'c' : { str = cmd_getonearg(str, &arg1); drw_color = rgbfromega(arg1); break; } case 'C' : { str = cmd_getonearg(str, &arg1); if (pgm_read_byte(str) == ',') str++; str = cmd_getonearg(str, &arg2); if (pgm_read_byte(str) == ',') str++; str = cmd_getonearg(str, &arg3); drw_color = rgbfromvalue(arg1, arg2, arg3); break; } case 'r' : { str = cmd_getonearg(str, &arg1); drw_line(drw_aktx, drw_akty, drw_aktx + arg1, drw_akty, drw_color); drw_aktx += arg1; break; } case 'l' : { str = cmd_getonearg(str, &arg1); drw_line(drw_aktx, drw_akty, drw_aktx - arg1, drw_akty, drw_color); drw_aktx -= arg1; break; } case 'u' : { str = cmd_getonearg(str, &arg1); drw_line(drw_aktx, drw_akty, drw_aktx, drw_akty - arg1, drw_color); drw_akty -= arg1; break; } case 'd' : { str = cmd_getonearg(str, &arg1); drw_line(drw_aktx, drw_akty, drw_aktx, drw_akty + arg1, drw_color); drw_akty += arg1; break; } case 'k' : { str = cmd_getonearg(str, &arg1); drw_circle(drw_aktx, drw_akty, arg1, drw_color); break; } case 'K' : { str = cmd_getonearg(str, &arg1); drw_fillcircle(drw_aktx, drw_akty, arg1, drw_color); break; } case 't' : { str = cmd_getonearg(str, &arg1); str++; str = cmd_getonearg(str, &arg2); drw_rectangle(drw_aktx, drw_akty, drw_aktx + arg1, drw_akty + arg2, drw_color); break; } case 'T' : { str = cmd_getonearg(str, &arg1); str++; str = cmd_getonearg(str, &arg2); drw_fillrectangle(drw_aktx, drw_akty, drw_aktx + arg1, drw_akty + arg2, drw_color); break; } case 'P' : { str = cmd_getonearg(str, &arg1); str++; str = cmd_getonearg(str, &arg2); drw_aktx = arg1; drw_akty = arg2; break; } case 'p' : { str = cmd_getonearg(str, &arg1); str++; str = cmd_getonearg(str, &arg2); drw_line(drw_aktx, drw_akty, arg1, arg2, drw_color); drw_aktx = arg1; drw_akty = arg2; break; } case 'M' : { str = cmd_getonearg(str, &arg1); str++; str = cmd_getonearg(str, &arg2); drw_aktx += arg1; drw_akty += arg2; break; } case 'm' : { str = cmd_getonearg(str, &arg1); str++; str = cmd_getonearg(str, &arg2); drw_line(drw_aktx, drw_akty, drw_aktx + arg1, drw_akty + arg2, drw_color); drw_aktx += arg1; drw_akty += arg2; break; } default : break; } } }