Library files for using Seeed Studio TFT Touch Shield for Arduino (ST7781R controller) together with ELMICRO TestBed for mbed. Featuring a short example program of how to calibrate the touch screen. Some basic drawing functions are also included (circle, rectangle, lines, text).

Dependencies:   mbed

touch.cpp

Committer:
elmicro
Date:
2012-06-28
Revision:
0:db0d63650413

File content as of revision 0:db0d63650413:

#include <LPC17xx.h>
#include "touch.h"
#include "shortcuts.h"

struct tinit TFTData;

void TouchInit(void)
{
    LPC_SC->PCONP           |= (BIT12);         //Enable power to ADC block    
    LPC_ADC->ADCR           =   BIT8 |          //ADC clock is (25MHz/5)
                                BIT21;          //enable ADC
}

/* ===================================================================
    routine:    GetPressure
    purpose:    Hardware driver for sampling the touch screen using
                four ADC-channels                
    parameters: none
    returns:    raw value from ADC corresponding to pressure of
                touch input    
    note:       "Pressure" actually means how much display area is
                supposed to pressure
    date:       2012-06-27
    author:     Stefan Guenther
                Elektronikladen | ELMICRO
  -------------------------------------------------------------------*/
unsigned int GetPressure(void)
{
	int tmp;

	LPC_PINCON->PINSEL1	&= ~0x4000;		        //Y-
	LPC_PINCON->PINSEL1	|= 0x10000;		        //X-
	LPC_PINCON->PINSEL1	|= 0x40000;		        //Y+
	LPC_PINCON->PINSEL1	&= ~0x100000;	        //X+
	LPC_GPIO0->FIODIR   |= BIT23|BIT26;	        //X- and Y+ as output
	LPC_GPIO0->FIOCLR    = BIT23;               //X- is GND
	LPC_GPIO0->FIOSET    = BIT26;	            //Y+ is VCC (3V3)
	LPC_ADC->ADCR       &= ~0xFF;               
	LPC_ADC->ADCR       |= BIT1;                //set X- as ADC input
	LPC_ADC->ADCR       |= BIT24;				//start sampling
	while(!(LPC_ADC->ADGDR&BIT31));             //wait for ADC
	
	tmp = (LPC_ADC->ADGDR&0xFFF0)>>4;           //store ADC value
	LPC_ADC->ADCR       &= ~0xFF;
	LPC_ADC->ADCR       |= BIT2;                //set Y+ as ADC input
	LPC_ADC->ADCR       |= BIT24;			    //start another ADC sampling
	while(!(LPC_ADC->ADGDR&BIT31));             //wait for it

	//calculate pressure value out of the two samples
	//and invert it by subtracting from 2^12
	return(4096 - (tmp - ( (LPC_ADC->ADGDR&0xFFF0) >>4 ) ) );		
} 


/* ===================================================================
    routine:    GetTouchX
    purpose:    Hardware driver for sampling the touch screen using
                four ADC-channels
    parameters: none
    returns:    raw value from ADC corresponding to X coordinate of
                touch input    
    date:       2012-06-27
    author:     Stefan Guenther
                Elektronikladen | ELMICRO
  -------------------------------------------------------------------*/
unsigned int GetTouchX(void)
{
	LPC_PINCON->PINSEL1	|= 0x4000;		//connects to Y- signal
	LPC_PINCON->PINSEL1	&= ~0x10000;	//            X-
	LPC_PINCON->PINSEL1	|= 0x40000;	    //            Y+
	LPC_PINCON->PINSEL1	&= ~0x100000;	//            X+
	LPC_GPIO0->FIODIR   |= BIT24|BIT26;	//X+ and X- as output
	LPC_GPIO0->FIOCLR    = BIT24;       //X- set to GND
	LPC_GPIO0->FIOSET    = BIT26;	    //X+ set to VCC (3V3)
	LPC_ADC->ADCR       &= ~0xFF;       //clear active ADC channel information
	LPC_ADC->ADCR       |= BIT2;        //set Y- as active ADC channel
	LPC_ADC->ADCR       |= BIT24;	    //start ADC sampling
	while(!(LPC_ADC->ADGDR&BIT31));     //wait until ADC completes operation
	
	return((LPC_ADC->ADGDR&0xFFF0)>>4); //extract the 12bit-information
}


/* ===================================================================
    routine:    GetTouchY
    purpose:    Hardware driver for sampling the touch screen using
                four ADC-channels
    parameters: none
    returns:    raw value from ADC corresponding to Y coordinate of
                touch input    
    date:       2012-06-27
    author:     Stefan Guenther
                Elektronikladen | ELMICRO
  -------------------------------------------------------------------*/
unsigned int GetTouchY(void)
{
	LPC_PINCON->PINSEL1	&= ~0x4000;		//Y-
	LPC_PINCON->PINSEL1	|= 0x10000;		//X-
	LPC_PINCON->PINSEL1	&= ~0x40000;	//Y+
	LPC_PINCON->PINSEL1	|= 0x100000;	//X+
	LPC_GPIO0->FIODIR   |= BIT23|BIT25;	//Y+ and Y- as output
	LPC_GPIO0->FIOCLR    = BIT23;
	LPC_GPIO0->FIOSET    = BIT25;	
	LPC_ADC->ADCR       &= ~0xFF;
	LPC_ADC->ADCR       |= BIT3;
	LPC_ADC->ADCR       |= BIT24;			
	while(!(LPC_ADC->ADGDR&BIT31));
	
	return((LPC_ADC->ADGDR&0xFFF0)>>4);
}


/* ===================================================================
    routine:    GetRawTouch
    purpose:    Reads input values from Touchscreen without 
                processing them (mainly useful for doing a calibration)
    parameters: <*x,y,z>        pointers to coordinate variables
    returns:    1   if touch was recognized
                0   if no touch occured                
    note:       For code explanation, look the GetPoint() function
    date:       2012-06-27
    author:     Stefan Guenther
                Elektronikladen | ELMICRO
  -------------------------------------------------------------------*/
unsigned char GetRawTouch(unsigned int *x, unsigned int *y, unsigned int *z)
{
	unsigned int x1, x2, y1, y2, z1, z2;

	z1 = GetPressure();

	if(z1>1500)
	{
		x1 = GetTouchX();
		y1 = GetTouchY();			
		
		z2 = GetPressure();
		if(z2>1500)
		{
			x2 = GetTouchX();
			y2 = GetTouchY();

			if( ( (x1>x2-20) && (x1<x2+20) ) && ( (y1>y2-20) && (y1<y2+20) ) )
			{
				*x = (x1+x2) / 2;
				*y = (y1+y2) / 2;
				*z = (z1+z2) / 2;
				
				return 1;
			} 
		}
	}
	return 0;	
}


/* ===================================================================
    routine:    MapX
    purpose:    Maps/alligns X-coordinate of touch input onto LCD's
                pixel grid
    parameters: <x>     touch coordinate
    returns:    pixel coordinate of touch input
    date:       2012-06-27
    author:     Stefan Guenther
                Elektronikladen | ELMICRO
  -------------------------------------------------------------------*/
unsigned int MapX(unsigned int x)
{
	if(x>TFTData.Xmin)
	{
		x = x-TFTData.Xmin;
		x = (x*1000) / TFTData.Xscale;
		if(x>TFTData.XRes - 1) x = TFTData.XRes - 1;			
	} else {
		x = 0;
	}	
	return x;
}


/* ===================================================================
    routine:    MapY
    purpose:    Maps/alligns Y-coordinate of touch input onto LCD's
                pixel grid
    parameters: <x>     touch coordinate
    returns:    pixel coordinate of touch input
    date:       2012-06-27
    author:     Stefan Guenther
                Elektronikladen | ELMICRO
  -------------------------------------------------------------------*/
unsigned int MapY(unsigned int y)
{
	if(y>TFTData.Ymin)                                      //Y input larger than the expected minimum?
	{
		y = y - TFTData.Ymin;                               //subtract offset from Y coordinate
		y = (y*1000) / TFTData.Yscale;                      //scale according to touch screen's parameter
		                                                    //(this results in an alignment between touch
		                                                    //input and output pixel grid)
		if(y>TFTData.YRes - 1) y = TFTData.YRes - 1;	    //prevent "out of pixel boundary"
	} else {
		y = 0;                                              //sampled Y-coordinate was lower than touch		
	}	                                                    //screen's expected minimum, so keep Y in boundary
	return y;                                               
}


/* ===================================================================
    routine:    GetPoint
    purpose:    Reads and processes touch input
    parameters: <*x, *y>    pointers to coordinate variables
    returns:    1   if touch input was recognized
                0   if no touch occured

    note:       An oversampling (x2) is done to increase noise
                immunity.
                A pressure value of 1500 has to be read to trigger
                the further processing - a lower value could improve
                touch sensitivity but also increases the risk of 
                sampling noise instead of touch inputs.
    date:       2012-06-27
    author:     Stefan Guenther
                Elektronikladen | ELMICRO
  -------------------------------------------------------------------*/
unsigned char GetPoint(unsigned int *x, unsigned int *y)
{
	unsigned int x1, x2, y1, y2, z1, z2;
	
	z1 = GetPressure();                             //check for pressure onto touch screen
	if(z1>1500)                                     //pressure above threshold?
	{
		x1 = MapX(GetTouchX());                     //read touch coordinates
		y1 = MapY(GetTouchY());	                    
		
		z2 = GetPressure();                         //oversampling - start second input read
		if(z2>1500)                                 //the second pressure was also above threshold?
		{
			x2 = MapX(GetTouchX());                 //sample again
			y2 = MapY(GetTouchY());
            
            /* check if both samples were nearly the same 
               increase the '2' to improve sensitivity */            
			if( ( (x1>x2 - 2) && (x1<x2+2) ) && ( (y1>y2 - 2) && (y1<y2 + 2) ) )
			{
				*x = (x1+x2) / 2;                   //do a simple meridian calculation
				*y = (y1+y2) / 2;                   //on both samples and both coordinates
				
				return 1;                           //touch input was processed!
			} 
		}
	}
    return 0;                                       //no touch input was processed!
}