Source file: /~heha/Mikrocontroller/Displays/utft/Kalender.zip/ILI9341/calib.cpp

#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-80