//ys_drv_touch_generic_int035.c
//drv_touch_generic.c
//INT035 Touch Driver (touch controller: MAX11802 SPI interface)
// 2017.08.15 by YSDK Design
//////////////////////////////////////////////////////////////////////

#include <sys/attribs.h>
#include <sys/kmem.h>
#include "system/int/sys_int.h"
#include "system/touch/sys_touch.h"
#include "system/ports/sys_ports.h"
#include "driver/touch/generic/drv_touch_generic.h"



//******************************************************************************
// Local functions
//******************************************************************************
void _DRV_TOUCH_INT035_HardwareInit (void *initValues);
void _DRV_TOUCH_INT035_CalculateCalPoints (void);


// Current values for X and Y channels
volatile short adcX = -1;
volatile short adcY = -1;


/* Driver instance object */
static DRV_TOUCH_GENERIC_OBJECT sGENERICDriverInstances[1];
static DRV_TOUCH_GENERIC_CLIENT_OBJECT sGENERICClientInstances[1];

// *****************************************************************************
/* Function:
SYS_MODULE_OBJ DRV_TOUCH_GENERIC_Initialize ( const SYS_MODULE_INDEX index,
const SYS_MODULE_INIT * const init )

Summary:
Initializes GENERIC Touch controller(MAX11802).

Description:
This function initializes the GENERIC Touch controller(MAX11802) .
*/

SYS_MODULE_OBJ DRV_TOUCH_GENERIC_Initialize( const SYS_MODULE_INDEX index,
const SYS_MODULE_INIT * const init )
{
DRV_TOUCH_GENERIC_OBJECT * pDrvInstance = (DRV_TOUCH_GENERIC_OBJECT *) NULL;

_DRV_TOUCH_INT035_HardwareInit(0);

return (SYS_MODULE_OBJ)pDrvInstance;
}

void DRV_TOUCH_GENERIC_Deinitialize ( SYS_MODULE_OBJ object )
{
}

// *****************************************************************************
/* Function:
void DRV_TOUCH_GENERIC_Tasks ( SYS_MODULE_OBJ object );

Summary:
Maintains the driver's state machine and implements its task queue
processing.

Description:
This routine is used to maintain the driver's internal state
machine and implement its command queue processing. It is always called
from SYS_Tasks() function. This routine detects a touch press position.
*/
void DRV_TOUCH_GENERIC_Tasks ( SYS_MODULE_OBJ object ) // called by system_tasks.c
{
DRV_TOUCH_GENERIC_PositionDetect();
}

/**************************************************************************
Function:
SYS_STATUS DRV_TOUCH_GENERIC_Status ( SYS_MODULE_OBJ object )

Summary:
Provides the current status of the GENERIC driver module.

Description:
This function provides the current status of the GENERIC driver module.
*/

SYS_STATUS DRV_TOUCH_GENERIC_Status ( SYS_MODULE_OBJ object )
{
DRV_TOUCH_GENERIC_OBJECT * pDrvInstance = (DRV_TOUCH_GENERIC_OBJECT *)object;
return pDrvInstance->status;
}


/**************************************************************************
Function:
DRV_HANDLE DRV_TOUCH_GENERIC_Open ( const SYS_MODULE_INDEX drvIndex,
const DRV_IO_INTENT intent )

Summary:
Opens the specified GENERIC driver instance and returns a handle to it.

Description:
This routine opens the specified GENERIC driver instance and provides a
handle that must be provided to all other client-level operations to
identify the caller and the instance of the driver. The ioIntent
parameter defines how the client interacts with this driver instance.
*/

DRV_HANDLE DRV_TOUCH_GENERIC_Open ( const SYS_MODULE_INDEX index, const DRV_IO_INTENT intent )
{
return (DRV_HANDLE)NULL;
}

// *****************************************************************************
/* Function:
void DRV_TOUCH_GENERIC_Close ( DRV_HANDLE handle )

Summary:
Closes an opened instance of the GENERIC driver

Description:
This function closes an opened instance of the GENERIC driver, invalidating
the handle.
*/
void DRV_TOUCH_GENERIC_Close ( DRV_HANDLE handle )
{
return;
}

short DRV_TOUCH_GENERIC_PositionDetect(void)
{
DRV_TOUCH_GENERIC_OBJECT * pDrvInstance = (DRV_TOUCH_GENERIC_OBJECT *) &sGENERICDriverInstances[0];

ys_TouchDetectPosition(); //Position detedted
adcX = ys_TouchGetX();
adcY = ys_TouchGetY();

pDrvInstance->touchStatus = DRV_TOUCH_POSITION_SINGLE; //essential

return 0;
}

/*********************************************************************
* Function: short DRV_TOUCH_GENERIC_TouchGetX( uint8_t touchNumber )
*
* PreCondition: none
*
* Input: none
*
* Output: x coordinate
*
* Side Effects: none
*
* Overview: returns x coordinate if touch screen is pressed
* and -1 if not
*
* Note: none
*
********************************************************************/
short DRV_TOUCH_GENERIC_TouchGetX( uint8_t touchNumber )
{
short tempX;

tempX = ys_TouchGetX();

return tempX;
}


/*********************************************************************
Function:
DRV_TOUCH_POSITION_SINGLE DRV_TOUCH_GENERIC_TouchStatus( const SYS_MODULE_INDEX index )

Summary:
Returns the status of the current touch input.

Description:
It returns the status of the current touch input.

Parameters
None.

Returns
It returns the status of the current touch input.

*/
DRV_TOUCH_POSITION_STATUS DRV_TOUCH_GENERIC_TouchStatus( const SYS_MODULE_INDEX index )
{
DRV_TOUCH_GENERIC_OBJECT * pDrvInstance = (DRV_TOUCH_GENERIC_OBJECT *)&sGENERICDriverInstances[index];
return (pDrvInstance->touchStatus);
}


/*********************************************************************
Function:
void DRV_TOUCH_GENERIC_TouchDataRead( const SYS_MODULE_INDEX index )

Summary:
Notifies the driver that the current touch data has been read

Description:
Notifies the driver that the current touch data has been read

Parameters
None.

Returns
None.

*/
void DRV_TOUCH_GENERIC_TouchDataRead( const SYS_MODULE_INDEX index )
{
DRV_TOUCH_GENERIC_OBJECT * pDrvInstance = (DRV_TOUCH_GENERIC_OBJECT *)&sGENERICDriverInstances[index];
pDrvInstance->touchStatus = DRV_TOUCH_POSITION_NONE;
}


/*********************************************************************
* Function: short DRV_TOUCH_GENERIC_TouchGetRawX()
*
* PreCondition: none
*
* Input: none
*
* Output: x coordinate
*
* Side Effects: none
*
* Overview: returns x coordinate if touch screen is pressed
* and -1 if not
*
* Note: none
*
********************************************************************/
short DRV_TOUCH_GENERIC_TouchGetRawX(void)
{
return adcX;
}

/*********************************************************************
* Function: short DRV_TOUCH_GENERIC_TouchGetY( uint8_t touchNumber )
*
* PreCondition: none
*
* Input: none
*
* Output: y coordinate
*
* Side Effects: none
*
* Overview: returns y coordinate if touch screen is pressed
* and -1 if not
*
* Note: none
*
********************************************************************/
short DRV_TOUCH_GENERIC_TouchGetY( uint8_t touchNumber )
{
short tempY;

tempY = ys_TouchGetY();

return tempY;
}

/*********************************************************************
* Function: short DRV_TOUCH_GENERIC_TouchGetRawY()
*
* PreCondition: none
*
* Input: none
*
* Output: y coordinate
*
* Side Effects: none
*
* Overview: returns y coordinate if touch screen is pressed
* and -1 if not
*
* Note: none
*
********************************************************************/
short DRV_TOUCH_GENERIC_TouchGetRawY(void)
{
return adcY;
}

/*********************************************************************
* Function: void DRV_TOUCH_GENERIC_TouchStoreCalibration(void)
*
* PreCondition: Non-volatile memory initialization function must be called before
*
* Input: none
*
* Output: none
*
* Side Effects: none
*
* Overview: stores calibration parameters into non-volatile memory
*
* Note: none
*
********************************************************************/
void DRV_TOUCH_GENERIC_TouchStoreCalibration(void)
{
}

/*********************************************************************
* Function: void DRV_TOUCH_GENERIC_CalibrationSet(void)
*
* PreCondition: Non-volatile memory initialization function must be called before
*
* Input: none
*
* Output: none
*
* Side Effects: none
*
* Overview: loads calibration parameters from non-volatile memory
*
* Note: none
*
********************************************************************/
void DRV_TOUCH_GENERIC_CalibrationSet(DRV_TOUCH_SAMPLE_POINTS * samplePoints)
{
}


/*********************************************************************
* Function: void _DRV_TOUCH_INT035_HardwareInit(void)
*
* PreCondition: none
*
* Input: none
*
* Output: none
*
* Side Effects: none
*
* Overview: Initializes touch screen module.
*
* Note: none
*
********************************************************************/
void _DRV_TOUCH_INT035_HardwareInit(void *initValues) //
{
ys_TouchHardwareInit();
}

/*********************************************************************
* Function: void _DRV_TOUCH_INT035_CalculateCalPoints(void)
*
* PreCondition: InitGraph() must be called before
*
* Input: none
*
* Output: none
*
* Side Effects: none
*
* Overview: gets values for 3 touches
*
* Note: none
*
********************************************************************/
void _DRV_TOUCH_INT035_CalculateCalPoints(void)
{
}


#define DISP_HOR_RESOLUTION 320
#define DISP_VER_RESOLUTION 240


short ys_xRaw,ys_yRaw; // x coordinate, y coordinate
int touch_delay_Clock = 200000000; //200MHz

void touch_delay_us(volatile unsigned int usec) //1usec delay
{
volatile int count;

count = (int)(touch_delay_Clock/20000000)*usec;


do //actual survey: at 200MH (Clock=200000000)
{ //delay_us(1000):1000.4usec delay_us(100):100.6usec delay_us(10):10.5usec delay_us(1):1.5usec
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");asm("NOP");
asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP");

count--;
}while(count != 0);


}

void touch_delay_ms(volatile unsigned int msec) //1msec delay
{
volatile unsigned int i; //actual survey: at200MH (Clock=200000000)//delay_ms(1): 1.0006msec delay_ms(100):100.04msec

for(i=0; i<msec; i++)
touch_delay_us(1000);
}


void ys_TouchHardwareInit(void) //Initialize
{
InitBitBangedIO(); //Initialize : TP_SCK,TP_SI,TP_SO pin
TPIRQConfig(); //TP_TIRQ pin Mode set

//Note: The following configuration is intended for the
//Displaytech Ltd. INT035TFT, INT043BTFT, INT057ATFT, and INT070ATFT

//General configuration
ys_TPWriteCommand(0x01,0x67); //DOUT bus holder enabled, IRQ pullup,
//edge interrupt, 128us edge time
//Measurement resolution
ys_TPWriteCommand(0x02,0x00); //Defaults
//Measurement averaging
ys_TPWriteCommand(0x03,0xA0); //8 samples X and Y
//ADC Samplint Time
ys_TPWriteCommand(0x04,0x50); //32us X, 8us Y
//Panel timing configuration
ys_TPWriteCommand(0x05,0x20); //X,Y 50us
//Delayed conversion
ys_TPWriteCommand(0x06,0x20); //X,Y 50us
//Touch detect pullup timing
ys_TPWriteCommand(0x07,0x77); //Rough 500us, fine 800us
//Autonomous mode timing
ys_TPWriteCommand(0x08,0x00); //Defaults
//Aperture configuration
ys_TPWriteCommand(0x09,0x00); //Defaults (unused)
//AUX measurement configuration
ys_TPWriteCommand(0x0A,0x00); //Defaults (unused)
//Operating mode configuration
ys_TPWriteCommand(0x0B,0x04); //X,Y position averaging
}


//-----------------------------------------------------------------
static void ys_TPWriteCommand(unsigned char cmd, unsigned char dat) //command Write
{
TPCSLow(); //CS = 0
ys_TPWriteByte((cmd<<1)|0x00); // Set b0 = 0 --> write mode sent
ys_TPWriteByte(dat); //Write the data
TPCSHigh(); //CS = 1
}


//------------------------------------------------------------------
static void ys_TPWriteByte(unsigned char value) //1 byte write
{
unsigned char mask = 0x80; //Writing mask

while(mask)
{
TPSCLLow(); //Trigger the clock
if(mask & value) //Write the bit
TPMOSIHigh();
else
TPMOSILow();

touch_delay_us(10); //10usec wait //Wait for the device to read
TPSCLHigh(); //Reset the clock


touch_delay_us(10); //10usec wait
mask >>= 1; //Increment the mask
}

TPSCLLow(); //Make sure the clock is low
}

//------------------------------------------------------------------------
static unsigned char ys_TPReadByte(void) //1 byte read
{
unsigned char mask = 0x80; //Read mask
unsigned char value = 0x00; //Read value

while(mask)
{
TPSCLLow(); //Set the clock low

touch_delay_us(10); //10usec wait //Wait for the device to set the bit
if(TPMISORead()) //Set the value
value |= mask;
TPSCLHigh(); //Set the clock high

touch_delay_us(10); //10usec wait
mask >>= 1; //Increment the mask
}
TPSCLLow(); //Reset the clock

return value;
}



//------------------------------------------------------------------------
static unsigned char ys_TPReadCommand(unsigned char cmd) //command read
{
unsigned char dat; //Read data

TPCSLow(); //CS = 0
ys_TPWriteByte((cmd<<1)|0x01); //b0 = 1 --> read mode sent
dat = ys_TPReadByte(); //Read the data
TPCSHigh(); //Reset the CS

return dat;
}





#define MAX_JUMP (10*4096/DISP_HOR_RESOLUTION) //Noise rejection threshold

//---------------------------------------------------------------------------
short ys_TouchDetectPosition(void) //touch position detect
{

unsigned char dat;

unsigned short x, y; //Read x and y values
static short lastX=0, lastY=0; //For noise rejection

dat = ys_TPReadCommand(0x00); //Read the status

if(dat & 0x02) //Touch present?
{
TPCSLow(); //Command a conversion (x,y)
ys_TPWriteByte(0xE0);
TPCSHigh();

touch_delay_ms(2);
TPCSLow(); //Read the positions
ys_TPWriteByte(0xA5);
x = ys_TPReadByte()<<8;
x |= ys_TPReadByte();
y = ys_TPReadByte()<<8;
y |= ys_TPReadByte();
x >>= 4;
y >>= 4;
TPCSHigh();

//Error checking
if((lastX != -1 && lastY != -1) &&
(abs((short)x - lastX) > MAX_JUMP ||
abs((4096 - (short)y) - lastY) > MAX_JUMP))
//abs((short)y - lastY) > MAX_JUMP))
{
ys_xRaw = -1;
ys_yRaw = -1;
}
else
{
ys_xRaw = (short)x;
ys_yRaw = (short)y;
ys_yRaw = 4096 - ys_yRaw;
}


}
else
{
ys_xRaw = -1;
ys_yRaw = -1;
}

lastX = ys_xRaw;
lastY = ys_yRaw;

return 0;




}


//---------------------------------------------------------------------------
short ys_TouchGetX(void)
{
if(ys_xRaw == -1) //-1 indicates no touch present
return -1;
else //Scale the xRaw value from 12-bits
#if (DISP_ORIENTATION == 0)
return (short)(DISP_HOR_RESOLUTION*ys_xRaw/4096);
#elif (DISP_ORIENTATION == 90)
return (short)(DISP_VER_RESOLUTION*xRaw/4096);
#endif
}

//------------------------------------------------------------------------------
short ys_TouchGetRawX(void)
{
return (short)ys_xRaw;
}


//-------------------------------------------------------------------------------
short ys_TouchGetY(void)
{
if(ys_yRaw == -1) //-1 indicates no touch
return -1;
else
#if (DISP_ORIENTATION == 0) //Scale the raw value from 12-bits
#ifdef TOUCH_INVERT_Y //Invert the Y value
return (shortT)(DISP_VER_RESOLUTION*(4096-ys_yRaw)/4096);
#else
return (short)(DISP_VER_RESOLUTION*(ys_yRaw)/4096);
#endif
#elif (DISP_ORIENTATION == 90)
return (SHORT)(DISP_HOR_RESOLUTION*(4096-ys_yRaw)/4096);
#endif
}



//------------------------------------------------
short ys_TouchGetRawY(void)
{
return (short)ys_yRaw;
}