热度 12
2016-5-6 10:50
1256 次阅读|
1 个评论
这个程序演示了在STM32F746DISC开发板上显示分形(MandelBrot set),实现了缩放、移动、参数显示等功能。一个手指可以拖动图形,两个手指靠近或分开可以缩放。 此外使用了Guess算法减少计算次数,加快显示速度。 参考代码: #include "mbed.h" #include "LCD_DISCO_F746NG.h" #include "TS_DISCO_F746NG.h" #include math.h #define ITERATION 150 #define BAILOUT 4 LCD_DISCO_F746NG lcd; TS_DISCO_F746NG ts; TS_StateTypeDef TS_State; uint8_t ts_nb = 0; uint16_t tsx0 , tsy0 ; uint16_t tsx , tsy ; uint8_t tscnt = 0; double zoom = 1; Timer tmr; uint8_t msg ; uint16_t screen_width, screen_height; double mx1, my1, mx2, my2; uint16_t calcMandelBrot(double x, double y) { uint16_t i; double xx, yy, tx, ty; xx = yy = 0; i = 0; while((i ITERATION) ((xx*xx + yy*yy) BAILOUT)) { tx = xx*xx - yy*yy + x; ty = 2*xx*yy + y; xx = tx; yy = ty; i++; } return i; } uint8_t c ; void rectMandelBrot(double x1, double y1, double x2, double y2) { double dx, dy; uint16_t i, j, n; uint32_t color; lcd.SetTextColor(LCD_COLOR_BLACK); lcd.FillRect(0, 0, screen_width, screen_height); lcd.SetTextColor(LCD_COLOR_WHITE); sprintf((char *)msg, "%10f", x1); lcd.DisplayStringAt(screen_width+5, 224, msg, LEFT_MODE); sprintf((char *)msg, "%10f", y1); lcd.DisplayStringAt(screen_width+5, 236, msg, LEFT_MODE); sprintf((char *)msg, "%10f", x2); lcd.DisplayStringAt(screen_width+5, 248, msg, LEFT_MODE); sprintf((char *)msg, "%10f", y2); lcd.DisplayStringAt(screen_width+5, 260, msg, LEFT_MODE); sprintf((char *)msg, " %10f", zoom); lcd.DisplayStringAt(screen_width+5, 212, msg, LEFT_MODE); tmr.reset(); tmr.start(); dx = (x2 - x1)/screen_width; dy = (y2 - y1)/screen_height; /* for(i = 0; i screen_width; i++) { for(j = 0; j screen_height; j++) { color = calcMandelBrot(x1 + dx*i, y1 + dy*j); lcd.DrawPixel(i, j, 0xFF000000 | (color14) | (color 4)); } }*/ for(i = 0; i screen_width/4; i++) { ts.GetState(TS_State); if (TS_State.touchDetected) return; for(j = 0; j screen_height/4; j++) { c = calcMandelBrot(x1 + 4*dx*i, y1 + 4*dy*j); lcd.DrawPixel(4*i, 4*j, 0xFF000000 | (c 4)); } } for(i = 0; i screen_width/4; i++) { ts.GetState(TS_State); if (TS_State.touchDetected) return; for(j = 0; j screen_height/4; j++) { if((c == c ) (c == c ) (c == c )) { lcd.SetTextColor(0xFF000000 | (c 4)); lcd.FillRect(i*4, j*4, 4, 4); } else { for(n = 1; n 16; n++) { color = calcMandelBrot(x1 + dx*(4*i+(n/4)), y1 + dy*(4*j+(n%4))); lcd.DrawPixel(4*i+(n/4), 4*j+(n%4), 0xFF000000 | (color4)); } } } } tmr.stop(); sprintf((char *)msg, " %6d ms", tmr.read_ms()); lcd.SetTextColor(LCD_COLOR_WHITE); lcd.SetBackColor(LCD_COLOR_BLACK); lcd.DisplayStringAt(screen_width+5, 20, msg, LEFT_MODE); } int main() { uint8_t status; uint8_t prev_nb_touches = 0; double cx, cy, lx, ly; status = ts.Init(lcd.GetXSize(), lcd.GetYSize()); if (status != TS_OK) { lcd.Clear(LCD_COLOR_RED); lcd.SetBackColor(LCD_COLOR_RED); lcd.SetTextColor(LCD_COLOR_WHITE); lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT FAIL", CENTER_MODE); while(1); } lcd.Clear(LCD_COLOR_BLACK); lcd.SetFont(Font12); lcd.SetTextColor(LCD_COLOR_WHITE); lcd.SetBackColor(LCD_COLOR_BLACK); screen_width = lcd.GetXSize() - 120; screen_height = lcd.GetYSize(); lcd.DisplayStringAt(screen_width+5, 0, (uint8_t *)"Elapsed:", LEFT_MODE); lcd.DisplayStringAt(screen_width+5, 200, (uint8_t *)"Zoom:", LEFT_MODE); mx1 = -2.5; my1 = -2.5; mx2 = 2.5; my2 = 2.5; rectMandelBrot(mx1, my1, mx2, my2); status = 0; while(1) { wait(0.01); ts.GetState(TS_State); if (TS_State.touchDetected) { if(TS_State.touchDetected != prev_nb_touches) { status = 0; tscnt = 0; prev_nb_touches = TS_State.touchDetected; } if(tscnt 10) { tscnt++; if(tscnt == 9) { ts_nb = TS_State.touchDetected; lcd.SetTextColor(LCD_COLOR_BLACK); lcd.FillRect(screen_width+5, 60, 120, 48); } continue; } switch(ts_nb) { case 1: if(status == 0) { status = 1; tsx0 = TS_State.touchX ; tsy0 = TS_State.touchY ; } tsx = TS_State.touchX ; tsy = TS_State.touchY ; lcd.SetTextColor(LCD_COLOR_LIGHTBLUE); sprintf((char *)msg, "%3d", TS_State.touchX ); lcd.DisplayStringAt(screen_width+5, 60, msg, LEFT_MODE); sprintf((char *)msg, "%3d", TS_State.touchY ); lcd.DisplayStringAt(screen_width+5, 72, msg, LEFT_MODE); break; case 2: if(status == 0) { status = 1; tsx0 = TS_State.touchX ; tsy0 = TS_State.touchY ; tsx0 = TS_State.touchX ; tsy0 = TS_State.touchY ; } tsx = TS_State.touchX ; tsy = TS_State.touchY ; tsx = TS_State.touchX ; tsy = TS_State.touchY ; lcd.SetTextColor(LCD_COLOR_LIGHTBLUE); sprintf((char *)msg, "%3d", TS_State.touchX ); lcd.DisplayStringAt(screen_width+5, 60, msg, LEFT_MODE); sprintf((char *)msg, "%3d", TS_State.touchY ); lcd.DisplayStringAt(screen_width+5, 72, msg, LEFT_MODE); sprintf((char *)msg, "%3d", TS_State.touchX ); lcd.DisplayStringAt(screen_width+5, 84, msg, LEFT_MODE); sprintf((char *)msg, "%3d", TS_State.touchY ); lcd.DisplayStringAt(screen_width+5, 96, msg, LEFT_MODE); break; } } else { if(status) { lcd.SetTextColor(LCD_COLOR_YELLOW); status = 0; tscnt = 0; switch(ts_nb) { case 1: if((abs(tsx - tsx0 ) 20) || (abs(tsy - tsy0 ) 20)) { lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)" - ", LEFT_MODE); cx = (tsx - tsx0 )*(mx2 - mx1)/screen_width; cy = (tsy - tsy0 )*(my2 - my1)/screen_height; mx1 -= cx; mx2 -= cx; my1 -= cy; my2 -= cy; rectMandelBrot(mx1, my1, mx2, my2); } break; case 2: if(((tsx -tsx )*(tsx -tsx ) + 20) ((tsx0 -tsx0 )*(tsx0 -tsx0 ))) { lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)"out", LEFT_MODE); zoom = zoom /2; cx = (tsx0 + tsx0 )/2; cy = (tsy0 + tsy0 )/2; lx = (mx2 - mx1); ly = (my2 - my1); cx = cx * (mx2 - mx1) / screen_width + mx1; cy = cy * (my2 - my1) / screen_height + my1; mx1 = cx - lx; mx2 = cx + lx; my1 = cy - ly; my2 = cy + ly; rectMandelBrot(mx1, my1, mx2, my2); } else if(((tsx -tsx )*(tsx -tsx )) ((tsx0 -tsx0 )*(tsx0 -tsx0 ) + 20)) { lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)"in ", LEFT_MODE); zoom = zoom*2; cx = (tsx0 + tsx0 )/2; cy = (tsy0 + tsy0 )/2; lx = (mx2 - mx1)/4; ly = (my2 - my1)/4; cx = cx * (mx2 - mx1) / screen_width + mx1; cy = cy * (my2 - my1) / screen_height + my1; mx1 = cx - lx; mx2 = cx + lx; my1 = cy - ly; my2 = cy + ly; rectMandelBrot(mx1, my1, mx2, my2); } break; } } } } } 目前已知问题,手势识别还不够灵敏,等待进一步改进。