/* ------------------------------------------------------- fraktal_speedtest.c Testprogramm um festzustellen, wie schnell ein Apfelmaennchen berechnet werden kann MCU : ATmega328p Takt : 15.04.2025 R. Seelig ------------------------------------------------------ */ /* ------------------------------------------------------- In tftdisplay.h wird angegeben, wie das Display angeschlossen werden muss.. Aktuell ist dieses: #define pindefs 2 in tft_pindefs.h wird dieses ausgewertet. ------------------------------------------------------- */ #include #include #include #include #include #include "tftdisplay.h" #include "my_printf.h" #define printf tiny_printf #define delay _delay_ms volatile uint32_t millis = 0; struct colvalue { uint8_t r; uint8_t g; uint8_t b; }; ISR (TIMER1_COMPA_vect) { millis++; } void timer1_init(void) { /* --------------------------------------------- CS10 / CS11 / CS12 sind Steuerbits des Taktvorteilers. CS 12 | CS11 | CS10 ---------------------------------------------- 0 0 0 kein Takt, Timer gestoppt 0 0 1 clk / 1 (kein Teiler) 0 1 0 clk / 8 0 1 1 clk / 64 1 0 0 clk / 256 1 0 1 clk / 1024 ---------------------------------------------- */ TCCR1B = 1 << WGM12 | 1 << CS10; OCR1A = F_CPU / 1000; // 1000 = Reloadwert fuer 16 MHz TCNT1 = 0; TIMSK1 = 1 << OCIE1A; sei(); } /* -------------------------------------------------------- my_putchar wird von my-printf / printf aufgerufen und hier muss eine Zeichenausgabefunktion angegeben sein, auf das printf dann schreibt ! -------------------------------------------------------- */ void my_putchar(char ch) { lcd_putchar(ch); } // fuer Mandelbrot #define graphwidth _yres #define graphheight _xres /* ------------------------------------------------------- mandelbrot Fraktalgenerator ------------------------------------------------------- */ void mandelbrot(uint16_t ofsx, uint16_t ofsy) { uint16_t k, kt, x, y; float dx, dy, xmin, xmax, ymin, ymax; float jx, jy, wx, wy, tx, ty, r, m; struct colvalue mrgb; kt= 100; m= 4.0; xmin= 1.7; xmax= -0.8; ymin= -1.0; ymax= 1.0; // alternative Zahlenwerte // xmin= -0.5328; xmax= -0.2078; ymin= 0.3742; ymax= 0.892; dx= (float)(xmax-xmin) / graphwidth; dy= (float) (ymax-ymin) / graphheight; for (x= 0; x< graphwidth; x++) { jx= xmin + ((float)x*dx); for (y= 0; y< graphheight; y++) { jy= ymin+((float)y*dy); k= 0; wx= 0.0; wy= 0.0; do { tx= wx*wx-(wy*wy+jx); ty= 2.0f * wx*wy+jy; wx= tx; wy= ty; r= wx*wx+wy+wy; k++; } while ((r < m) & (k < kt)); if (k< 3) {mrgb.b= k * 20; } if ((k> 2) && (k< 35)) { mrgb.b= k * 9; mrgb.g = k; mrgb.r= k*2 ; } if (k> 34) { mrgb.r= ( 128 ); mrgb.g= (k * 3 ); mrgb.b= (k); } if (k> 90) { mrgb.r= 0, mrgb.g= 0; mrgb.b= 0; } putpixel(ofsx+x,ofsy+y,rgbfromvalue(mrgb.r, mrgb.g, mrgb.b)); } } } // Hier folgen Funktionen zum Zeichnen von Linien und Kreisen // die es zwar auch schon in st77xx_display.c gibt. Dort wird je- // doch aus Geschwindigkeitsgruenden darauf verzichtet, ob sich // ein zu setzender Pixel im Bereich der darstellbaren // Koordinaten des Displays befinden. Hier jedoch findet eine // Ueberpruefung statt /* ------------------------------------------------------------- putpixel2 ------------------------------------------------------------- */ void putpixel2(int x, int y, uint16_t color) { if ((x > -1) && (x < _xres) && (y > -1) && (y < _yres)) putpixel(x,y,color); } /* ------------------------------------------------------------- line2 Linienalgorithmus nach Bresenham (www.wikipedia.org) ------------------------------------------------------------- */ void line2(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 */ } } /* ------------------------------------------------------------- ellipse2 Algorithmus nach Bresenham (www.wikipedia.org) ------------------------------------------------------------- */ void ellipse2(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 { putpixel2(xm+dx, ym+dy,color); // I. Quadrant putpixel2(xm-dx, ym+dy,color); // II. Quadrant putpixel2(xm-dx, ym-dy,color); // III. Quadrant putpixel2(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) { putpixel2(xm+dx, ym,color); // -> Spitze der Ellipse vollenden putpixel2(xm-dx, ym,color); } } /* ------------------------------------------------------------- circle2 ------------------------------------------------------------- */ void circle2(int x, int y, int r, uint16_t color ) { ellipse2(x,y,r,r,color); } /* ------------------------------------------------------------- _rand_lfsr_update, _rand_gen_32b, my_rand durch die Compileroptien nostdlib ist keine rand() Funktion verfuegbar. Zufallszahlengenerator ueber 2 rueck- gekoppelte Schieberegister die ihrerseits miteinander XOR verknuepft werden. ------------------------------------------------------------- */ static uint32_t _rand_lfsr = 0x747AA32F; // Startpunkt des Schieberegisters uint8_t _rand_lfsr_update(void) { uint32_t bit_31 = _rand_lfsr & 0x80000000; uint32_t bit_21 = (_rand_lfsr << 10) & 0x80000000; uint32_t bit_01 = (_rand_lfsr << 30) & 0x80000000; uint32_t bit_00 = (_rand_lfsr << 31) & 0x80000000; uint32_t msb = bit_31 ^ bit_21 ^ bit_01 ^ bit_00; _rand_lfsr = (_rand_lfsr >> 1) | msb; return msb >> 31; } uint32_t _rand_gen_32b(void) { uint32_t rand_out = 0; uint8_t bits = 32; while(bits--) { rand_out = rand_out << 1; rand_out |= _rand_lfsr_update(); } return rand_out; } int my_rand(void) { uint32_t rand_out = 0; uint32_t rand_a = _rand_gen_32b(); int32_t rand_b = _rand_gen_32b(); rand_out = rand_a ^ rand_b; return abs(rand_out); } #define mandel_speedtest 0 #define linienkreise_speedtest 1 /* ------------------------------------------------------- M-A-I-N ------------------------------------------------------- */ int main(void) { uint8_t y,x; uint8_t yofs; uint32_t prog_millis; uint16_t sek, hsek; lcd_init(); lcd_enable(); timer1_init(); lcd_orientation(0); // Ausgabeposition auf dem Display textcolor= rgbfromega(14); bkcolor= 0; clrscr(); #if (mandel_speedtest == 1) lcd_orientation(2); textcolor= rgbfromega(14); bkcolor= rgbfromega(9); clrscr(); prog_millis= millis; mandelbrot(0,0); prog_millis= millis-prog_millis; sek= prog_millis / 1000; hsek= (prog_millis % 1000) / 100; lcd_orientation(0); bkcolor= rgbfromega(0); textcolor= rgbfromega(7); gotoxy(0,0); printf("ATmega328"); gotoxy(0,1); printf("Zeit: %d.%d sek",sek,hsek); gotoxy(0,1); printf("Zeit: %d.%d sek",prog_millis / 1000, (prog_millis / 100) % 10); while(1); #endif #if (linienkreise_speedtest == 1) int x1,x2,y1,y2,rcol,r; uint16_t i; // 2000 Linien zeichnen textcolor= rgbfromega(15); bkcolor= 0; clrscr(); prog_millis= millis; for (i= 1; i< 2000; i++) { x1= my_rand() % _xres; x2= my_rand() % _xres; y1= my_rand() % _yres; y2= my_rand() % _yres; rcol = my_rand() % 0x10000; line2(x1, y1, x2, y2, rcol); } // 2000 Kreise zeichnen clrscr(); for (i= 1; i< 2000; i++) { x1= my_rand() % _xres; y1= my_rand() % _yres; r= (my_rand() % _xres)+1; rcol = my_rand() % 0x10000; circle2(x1, y1, r, rcol); } prog_millis= millis-prog_millis; sek= prog_millis / 1000; hsek= (prog_millis % 1000) / 100; lcd_orientation(0); bkcolor= rgbfromega(0); textcolor= rgbfromega(7); gotoxy(0,0); printf("ATmega328"); gotoxy(0,1); printf("Zeit: %d.%d sek",sek,hsek); gotoxy(0,1); printf("Zeit: %d.%d sek",prog_millis / 1000, (prog_millis / 100) % 10); while(1); #endif }