#include <avr/io.h>
#include <util/delay.h>
#include "UTFT.h"
#include "TouchScreen.h"
#include "calib.h"
int wwtrafo(int x,int a,int e,int A,int E) {
return (long)(x-a)*(E-A)/(e-a)+A;
}
extern TouchScreen ts;
bool waitTouch(int sec10) {
for (;;) {
if (ts.isTouching()) return true;
if (!--sec10) return false;
_delay_ms(100); // frisst Strom!! Besser: Sleep+Interrupt
}
}
void Rahmen(int top=19, int bot=2);
extern UTFT dc;
extern const byte ArialBP24[] PROGMEM;
#define COLOR_BACK RGB(200,200,200)
calib_t calib; // Fürs restliche Programm wirksame Kalibrierdaten
POINT touch;
static POINT pos[4]; // Unkalibrierte Touchpositionen der Kreise
void calib_t::getPoint() {
touch.x=wwtrafo(ts.readTouch(ts.TOUCH_X^dc.orient&1),calib.l,calib.r,0,dc.getDisplayXSize());
touch.y=wwtrafo(ts.readTouch(ts.TOUCH_Y^dc.orient&1),calib.t,calib.b,0,dc.getDisplayYSize());
}
#define RADIUS 20
// Malt einen der vier Kreise in die Bildecken
static void circle(byte index) {
index^=dc.orient>>1; // Eckenzuordnung invertieren
dc.fillCircle(
index&1?dc.getDisplayXSize()-RADIUS:RADIUS,
index&2?dc.getDisplayYSize()-RADIUS:RADIUS,
RADIUS);
}
bool calibrate() {
dc.clrClip();
Rahmen(42,42);
int mx=dc.getDisplayXSize()>>1;
int my=dc.getDisplayYSize()>>1;
dc.gotoXY(mx,0);
dc.print(F("Touchscreen"));
dc.gotoXY(mx,dc.getFontHeight());
dc.print(F("kalibrieren"));
dc.setColor(COLOR_BACK);
dc.fillRectW(2,42,236,236);
dc.setColor(COLOR_RED);
for (byte i=0; i<4; i++) circle(i);
dc.setFont(ArialBP24);
dc.align=2;
dc.setColor(COLOR_BLUE);
dc.setBackColor(COLOR_BACK);
dc.gotoXY(mx,my-dc.getFontHeight());
dc.print(F("Bitte alle vier Kreise"));
dc.gotoXY(mx,my);
dc.print(F("1× mittig antippen!"));
dc.setColor(COLOR_GREEN);
for (byte clicked=0; clicked!=0x0F;) {// Positionen erledigt (Bitmaske)
if (!waitTouch(300)) return false; // 30 s Inaktivität? Zurück!
int x=ts.readTouch(ts.TOUCH_X^dc.orient&1);
int y=ts.readTouch(ts.TOUCH_Y^dc.orient&1);
byte i=0; // Quadrant bestimmen
if (x<0x180) ;
else if (x<0x280) return false; // in der Mitte: Nicht kalibrieren!
else i|=1;
if (y<0x180) ;
else if (y<0x280) return false; // in der Mitte: Nicht kalibrieren!
else i|=2; // Quadrant gefunden
pos[i].x=x;
pos[i].y=y; // Messwerte ablegen, notfalls überschreiben
byte mask=1<<i;
if (!(clicked&mask)) {
circle(i); // Roten Kreis in Grün umwandeln
clicked|=mask; // als erledigt markieren
}
#ifdef DEBUG
dc.gotoXY(mx-100,my+dc.getFontHeight());
dc.printf(F("%d: %d,%d"),i,x,y);
#endif
_delay_ms(100);
}
/* Messwerte auf Bildränder extrapolieren und abspeichern
l-calib.l r-l calib.r-r
--------- = ---------------- = ---------
Radius Xsize - 2*Radius Radius
Radius * (r-l)
calib.l = l - ----------------
Xsize - 2*Radius
Radius * (r-l)
calib.r = r + ----------------
Xsize - 2*Radius
*/
int l=(pos[0].x+pos[2].x)>>1; // linke Position (Mittel)
int r=(pos[1].x+pos[3].x)>>1; // rechte Position (Mittel)
int a=(long)RADIUS*(r-l)/(dc.getDisplayXSize()-2*RADIUS);
calib.l=l-a;
calib.r=r+a;
// dasselbe in Y-Richtung
l=(pos[0].y+pos[1].y)>>1;
r=(pos[2].y+pos[3].y)>>1;
a=(long)RADIUS*(r-l)/(dc.getDisplayYSize()-2*RADIUS);
calib.t=l-a;
calib.b=r+a;
#ifdef DEBUG
dc.gotoXY(mx-100,my+dc.getFontHeight());
dc.printf(F("l,r: %d,%d"),calib.l,calib.r);
dc.gotoXY(mx-100,my+(dc.getFontHeight()<<1));
dc.printf(F("t,b: %d,%d"),calib.t,calib.b);
_delay_ms(2000);
#endif
return true;
}
Detected encoding: UTF-8 | 0
|