/*****************************************************************************
* | File      	:   GT7385.c
* | Author      :   Waveshare team
* | Function    :   GT7385 driver
* | Info        :
*               GT7385 driver and data processing
*----------------
* |	This version:   V1.0
* | Date        :   2019-3-5
* | Info        :

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to  whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
******************************************************************************/
#include "GT7385.h"


UWORD x[CT_MAX_TOUCH] = {0}, y[CT_MAX_TOUCH] = {0}, z=0;
UWORD Color[CT_MAX_TOUCH] = {LCD_COLOR_BLUE,LCD_COLOR_GREEN,LCD_COLOR_RED,LCD_COLOR_MAGENTA,LCD_COLOR_YELLOW,LCD_COLOR_WHITE,LCD_COLOR_BROWN,LCD_COLOR_DARKCYAN,LCD_COLOR_GRAY,LCD_COLOR_ORANGE};
UWORD temp=0;
GT7385_Dev Dev_Now,Dev_Backup;

/******************************************************************************
function:	GT7385 reset
******************************************************************************/
static void GT7385_Reset()
{
	GPIO_InitTypeDef GPIO_InitStruct;

	DEV_Set_GPIOMode(DEV_INT_PIN, 0);
	
	HAL_GPIO_WritePin(DEV_RST_PIN, GPIO_PIN_RESET);    
	DEV_Delay_ms(100);
	HAL_GPIO_WritePin(DEV_INT_PIN, GPIO_PIN_RESET);    
	DEV_Delay_ms(100);
	HAL_GPIO_WritePin(DEV_RST_PIN, GPIO_PIN_SET);    
	DEV_Delay_ms(200);
	
	GPIO_InitStruct.Pin = INT_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(INT_GPIO_Port, &GPIO_InitStruct);
	
	DEV_Delay_ms(100);
}

/******************************************************************************
function:	Write data to the GT7385 register
parameter:
    reg   :   Register address
		buf		£º	Data to send
		len		£º	Length of data sent
******************************************************************************/
static uint8_t GT7385_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
{
	uint8_t i;
	uint8_t ret=0;
	I2C_Start();	
  I2C_Send_Byte(CT_CMD_WR);   
	I2C_Wait_Ack();
	I2C_Send_Byte(reg>>8);   	
	I2C_Wait_Ack(); 	 										  		   
	I2C_Send_Byte(reg&0XFF);   	
	I2C_Wait_Ack();  
	for(i=0;i<len;i++)
	{	   
    I2C_Send_Byte(buf[i]);  
		ret=I2C_Wait_Ack();
		if(ret)break;  
	}
  I2C_Stop();					
	return ret; 
}

/******************************************************************************
function:	Read data from the GT7385 register
parameter:
    reg   :   Register address
		buf		£º	Read data
		len		£º	Read the length of the data
******************************************************************************/
static void GT7385_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
{
	uint8_t i;
 	I2C_Start();	
 	I2C_Send_Byte(CT_CMD_WR);  
	I2C_Wait_Ack();
 	I2C_Send_Byte(reg>>8);   
	I2C_Wait_Ack(); 	 										  		   
 	I2C_Send_Byte(reg&0XFF);   	
	I2C_Wait_Ack();  
 	I2C_Stop();  
	
 	I2C_Start();  	 	   
	I2C_Send_Byte(CT_CMD_RD);     
	I2C_Wait_Ack();	   
	for(i=0;i<len;i++)
	{	   
		buf[i]=I2C_Read_Byte(i==(len-1)?0:1); 
	} 
  I2C_Stop();   
}

/******************************************************************************
function:	Read the ID of the GT7385
******************************************************************************/
static uint8_t GT7385_Read_ID(void)
{
	uint8_t buf[4] = {0xAA, 0x00, 0x56, 0x00};
	
	GT7385_WR_Reg(GT7385_COMMAND_REG, buf, 3);
	HAL_Delay(100);
	
	GT7385_RD_Reg(GT7385_PRODUCT_ID_REG, buf, 4);
	printf("TouchPad_ID: 0x%x, 0x%x, 0x%x, 0x%x\r\n",buf[0],buf[1],buf[2],buf[3]);
	return *buf;
}

/******************************************************************************
function:	Read the firmware version of the GT7385
******************************************************************************/
static uint16_t GT7385_Read_FirmwareVersion(void)
{
	uint8_t buf[3],FW_CID;
	uint16_t FW;

	GT7385_RD_Reg(GT7385_FIRMWARE_VERSION_REG, buf, 3);
	
	FW_CID = (buf[0]>>4) * 10 + buf[0]&0x0f ;
	FW = ((buf[1]>>4) * 10 + buf[1]&0x0f) * 100 + (buf[2]>>4) * 10 + buf[2]&0x0f;

	printf("FirmwareVersion_CID:  0x%x\r\nFirmwareVersion: 0x%x, 0x%x\r\n",buf[0],buf[1],buf[2]);
	return FW;
}

/******************************************************************************
function:	Read the firmware version of the GT7385
******************************************************************************/
void GT7385_Scan(void)
{
	uint8_t buf[81];
  uint8_t Clearbuf = 0;
	uint8_t i;

	//Determine if the interruption is generated
	if (Dev_Now.Touch == 1)
	{
		
		GT7385_RD_Reg(GT7385_READ_XY_REG, buf, 1);		
		
		if ((buf[0]&0x80) == 0x00)
		{
			GT7385_WR_Reg(GT7385_READ_XY_REG, (uint8_t *)&Clearbuf, 1);
			DEV_Delay_ms(10);
		}
		else
		{
			Dev_Now.TouchpointFlag = buf[0];
			Dev_Now.TouchCount = buf[0]&0x0f;
			if (Dev_Now.TouchCount > 10)
			{
				GT7385_WR_Reg(GT7385_READ_XY_REG, (uint8_t *)&Clearbuf, 1);
				return ;
			}
			
			GT7385_RD_Reg(GT7385_READ_XY_REG+1, &buf[1], Dev_Now.TouchCount*8);
			GT7385_WR_Reg(GT7385_READ_XY_REG, (uint8_t *)&Clearbuf, 1);
			
			
			for (i=0;i<Dev_Now.TouchCount;i++)
			{
				Dev_Now.Touchkeytrackid[i] = buf[1 + 8 * i];
				Dev_Now.X[i] = ((uint16_t)buf[3 + 8 * i] << 8) + buf[2 + 8 * i];
				Dev_Now.Y[i] = ((uint16_t)buf[5 + 8 * i] << 8) + buf[4 + 8 * i];
				Dev_Now.S[i] = ((uint16_t)buf[7 + 8 * i] << 8) + buf[6 + 8 * i];
			}
			
			if(z > Dev_Now.TouchCount){
				for(i = z; i != Dev_Now.TouchCount; i--){
					Paint_DrawLine(0 , y[i-1]+3, GT7385_MAX_WIDTH, y[i-1]+3, LCD_COLOR_BLACK, LINE_STYLE_SOLID, DOT_PIXEL_1X1);
					Paint_DrawLine(x[i-1]+3, 0, x[i-1]+3, GT7385_MAX_HEIGHT, LCD_COLOR_BLACK, LINE_STYLE_SOLID, DOT_PIXEL_1X1);
					Paint_DrawCircle( x[i-1]+3 , y[i-1]+3 , Circle_Radius, LCD_COLOR_BLACK, DRAW_FILL_FULL, DOT_PIXEL_1X1);
				}
			}
			
			for (i=0;i<Dev_Now.TouchCount;i++)
			{	
				if(Dev_Now.Y[i]<Circle_Radius)Dev_Now.Y[i]=Circle_Radius;
				if(Dev_Now.Y[i]>GT7385_MAX_HEIGHT-Circle_Radius)Dev_Now.Y[i]=GT7385_MAX_HEIGHT-Circle_Radius;
				if(Dev_Now.X[i]<Circle_Radius)Dev_Now.X[i]=Circle_Radius;
				if(Dev_Now.X[i]>GT7385_MAX_WIDTH-Circle_Radius)Dev_Now.X[i]=GT7385_MAX_WIDTH-Circle_Radius;
				
				Dev_Backup.X[i] = Dev_Now.X[i];
				Dev_Backup.Y[i] = Dev_Now.Y[i];
				Dev_Backup.TouchCount = Dev_Now.TouchCount;		
				printf("x = %d   y=  %d \r\n",Dev_Now.X[i], Dev_Now.Y[i]);

				//Clear the last displayed coordinates
				if(x[i] != Dev_Now.X[i] || y[i]  != Dev_Now.Y[i]){
					Paint_DrawLine(0 , y[i]+3, GT7385_MAX_WIDTH, y[i]+3, LCD_COLOR_BLACK, LINE_STYLE_SOLID, DOT_PIXEL_1X1);
					Paint_DrawLine(x[i]+3, 0, x[i]+3, GT7385_MAX_HEIGHT, LCD_COLOR_BLACK, LINE_STYLE_SOLID, DOT_PIXEL_1X1);
					Paint_DrawCircle( x[i]+3 , y[i]+3 , Circle_Radius, LCD_COLOR_BLACK, DRAW_FILL_FULL, DOT_PIXEL_1X1);
				}
				//Display coordinates
				Paint_DrawLine(Dev_Now.X[i]+3, 0, Dev_Now.X[i]+3, GT7385_MAX_HEIGHT, Color[i], LINE_STYLE_SOLID, DOT_PIXEL_1X1);
				Paint_DrawLine(0 , Dev_Now.Y[i]+3, GT7385_MAX_WIDTH, Dev_Now.Y[i]+3, Color[i], LINE_STYLE_SOLID, DOT_PIXEL_1X1);
				Paint_DrawCircle(Dev_Now.X[i]+3 , Dev_Now.Y[i]+3 , Circle_Radius, Color[i], DRAW_FILL_FULL, DOT_PIXEL_1X1);
				
				x[i]  = Dev_Now.X[i];
				y[i]  = Dev_Now.Y[i];
			}
			z = Dev_Now.TouchCount;
		}
//		Dev_Now.Touch = 0;
	}
}

void GT7385_Init(void)
{
	printf("GT7385_Init\r\n");
	GT7385_Reset();
	GT7385_Read_ID();
	GT7385_Read_FirmwareVersion();
	while(1)
	{
		GT7385_Scan();
	}
}
