Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

478 linhas
12 KiB

/************************************************************************
  * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved.
  * @file     rtp.c
  * @author   UartTFT Application Team
  * @version  V1.0.0
  * @date     2023-02-24
  * @brief     
 *************************************************************************/
#include "rtp.h"
#include "tp_drv.h"
#include "i2c_drv.h"
#include "uart_drv.h"
#include "iomacros.h"
uint8_t Rtp_Cor = 0;
void LT_TpDelay(void)
{
	uint8_t t = 1;
	while (t--)
	{
		__NOP();
		__NOP();
		__NOP();
		__NOP();
		__NOP();
		__NOP();
	}
}
#define CMD_RDX 0XD0
#define CMD_RDY 0X90
// SPI write data
void TP_Write_Byte(uint8_t num)
{
	uint8_t count = 0;
	for (count = 0; count < 8; count++)
	{
		if (num & 0x80)
			TDIN_SET;
		else
			TDIN_RESET;
		num <<= 1;
		TCLK_RESET;
		DelayUS(8);
		TCLK_SET;
		DelayUS(8);
	}
}
// SPI read data
// Read adc value from touch screen IC
// CMD:instruct
// Return value: read data
int16_t TP_Read_AD(CMD)
{
	uint8_t count = 0;
	uint16_t Num = 0;
	TCLK_RESET; // Lower the clock first
	TDIN_RESET; // Pull down the data cable
	TCS_RESET; // Select touch screen IC
	TP_Write_Byte(CMD);
	DelayUS(8); // The maximum conversion time of ADS7846 is 6us
	TCLK_RESET;
	DelayUS(8);
	TCLK_SET;
	DelayUS(8);
	TCLK_RESET;
	DelayUS(8);
	for (count = 0; count < 16; count++) // Read 16-bit data, only the upper 12 bits are valid
	{
		Num <<= 1;
		TCLK_RESET; // Falling edge effective
		DelayUS(8);
		TCLK_SET;
		DelayUS(8);
		if (GET_SDO_Bit)
			Num++;
		// printf("eport=%d\r\n",EPORT_ReadGpioData(EPORT_PIN3));
	}
	Num >>= 4;
	// Only the upper 12 bits are valid.
	TCS_SET; // Release the selection
	return Num;
}
//Read a coordinate value (x or y)
//Read READ continuously_ TIMES secondary data is arranged in ascending order,
//Then remove the lowest and highest LOST_ Number of VALs, take the average value
//Xy: Instruction (CMD_RDX/CMD_RDY)
//Return value: read data
#define READ_TIMES 8 // Reads
#define LOST_VAL 2	 // Discard value
uint16_t TP_Read_XOY(uint8_t xy)
{
	uint16_t i, j;
	uint16_t buf[READ_TIMES];
	uint16_t sum = 0;
	uint16_t temp;
	for (i = 0; i < READ_TIMES; i++)
		buf[i] = TP_Read_AD(xy);
	for (i = 0; i < READ_TIMES - 1; i++) // sort
	{
		for (j = i + 1; j < READ_TIMES; j++)
		{
			if (buf[i] > buf[j]) // Ascending
			{
				temp = buf[i];
				buf[i] = buf[j];
				buf[j] = temp;
			}
		}
	}
	sum = 0;
	for (i = LOST_VAL; i < READ_TIMES - LOST_VAL; i++)
		sum += buf[i];
	temp = sum / (READ_TIMES - 2 * LOST_VAL);
	return temp;
}
/********************************************************************************
* Function Name	: TP_Read_XY
* Description  	: Read the touch screen IC for two consecutive times, and the deviation between the two times cannot exceed.
* Input        	: - x,y: Read coordinate value
* Output       	: None
* Return       	: 0:error  1:ok
*********************************************************************************/
uint8_t TP_Read_XY(uint16_t *x, uint16_t *y)
{
	*x = TP_Read_XOY(CMD_RDX);
	*y = TP_Read_XOY(CMD_RDY);
	if (*x > 4095 || *y > 4095)
		return 0; // Reading failed
	//	printf("%d %d\r\n",*x,*y);
	return 1;
}
/********************************************************************************
* Function Name	: TP_Read_XY2
* Description  	: Read the touch screen IC for two consecutive times, and the deviation between the two times cannot exceed.
* Input        	: - x,y: Read coordinate value
* Output       	: None
* Return       	: 0:error  1:ok
*********************************************************************************/
#define ERR_RANGE 50 // Error range
uint8_t TP_Read_XY2(uint16_t *x, uint16_t *y)
{
	uint16_t x1, y1;
	uint16_t x2, y2;
	uint8_t flag;
	flag = TP_Read_XY(&x1, &y1);
	if (flag == 0)
		return (0);
	flag = TP_Read_XY(&x2, &y2);
	if (flag == 0)
		return (0);
	if (((x2 <= x1 && x1 < x2 + ERR_RANGE) || (x1 <= x2 && x2 < x1 + ERR_RANGE)) // 前后两次采样在+-50内
		&& ((y2 <= y1 && y1 < y2 + ERR_RANGE) || (y1 <= y2 && y2 < y1 + ERR_RANGE)))
	{
		*x = (x1 + x2) / 2;
		*y = (y1 + y2) / 2;
		return 1;
	}
	else
	{
		return 0;
	}
}
// Display correction point
void LT_TpDrawTouchPoint(uint16_t x, uint16_t y, uint32_t color)
{
	LT768_DrawLine(x - 12, y, x + 13, y, color); // Horizontal line
	LT768_DrawLine(x, y - 12, x, y + 13, color); // Vertical line
	LT768_DrawCircle(x, y, 6, color);			 // Draw center circle
}
/********************************************************************************
* Function Name	: TP_Read_XY2
* Description  	: touch scan.
* Input        	: None
* Output       	: None
* Return       	: 0:have touch event  1:no touch event
*********************************************************************************/
uint8_t LT_TpScan(void)
{
	if ((EPORT_ReadGpioData(EPORT_PIN4) == 0))
	{
		if (TP_Read_XY2(&gTpInfo.px, &gTpInfo.py))
		{
			Backlight_count = 0;
			//Backlight_touch = 1;
			if ((Backlight_flag == 0 || Backlight_touch == 2 ) && var[2 * 0x700e + 1] == 1 )
			{
				if (buzzer && Backlight_flag == 0)
					touch_buzzer();
				
				Set_Timer1_Compare_Buffer(gDutyBuf[var[0x7001 * 2 + 1]]);
				
				if (var[0x700f * 2 + 1] == 0)
					Start_PWM1();
				
				Backlight_touch = 2;
				gTpInfo.sta = 0;
				First_press = 0;
				Backlight_flag = 1;
			}
			else
			{
				gTpInfo.x[0] = gTpInfo.xfac * gTpInfo.px + gTpInfo.xoff;
				gTpInfo.y[0] = gTpInfo.yfac * gTpInfo.py + gTpInfo.yoff;
				if (gTpInfo.x[0] > LCD_XSIZE_TFT)
					gTpInfo.x[0] = LCD_XSIZE_TFT;
				if (gTpInfo.y[0] > LCD_YSIZE_TFT)
					gTpInfo.y[0] = LCD_YSIZE_TFT;
				
				if(scr_flag == 3)
				{
					if(scr_x != 0 || scr_y != 0)
						//LT768_DrawCircle_Fill(gTpInfo.x[0],gTpInfo.y[0],3,Red);
						LT768_DrawQuadrilateral_Fill(scr_x, scr_y + 3, scr_x + 3, scr_y, gTpInfo.x[0] + 3, gTpInfo.y[0], gTpInfo.x[0], gTpInfo.y[0] + 3, Red);
					scr_x = gTpInfo.x[0];
					scr_y = gTpInfo.y[0];
				}
				if (First_press == 0)
				{
					First_press = 1;
					First_pressX = gTpInfo.x[0];
					First_pressY = gTpInfo.y[0];
				}
				/* debug
					printf("X=%d Y=%d \r\n",gTpInfo.x[0],gTpInfo.y[0]);
				*/
				
				if (gTpInfo.sta == 0)
					gTpInfo.sta = 1;
				return 1;
			}
		}
		else
		{
			return 0;
		}
	}
	else
	{
		if(scr_flag == 3)
		{
			scr_x = 0;
			scr_y = 0;
		}
		gTpInfo.sta = 0;
		if(Backlight_flag == 1) Backlight_touch = 0;
		/* debug
			printf("x=%d y=%d\r\n",gTpInfo.x[0],gTpInfo.y[0]);
			printf("gTpInfo.sta=%d \r\n",gTpInfo.sta);
		*/
		return 0;
	}
}
uint8_t LT_TpAdjustScan(void)
{
	
	if (EPORT_ReadGpioData(EPORT_PIN4) == 0) //&& Rtp_temp==1)
	{
		if (TP_Read_XY2(&gTpInfo.px, &gTpInfo.py))
		{
			gTpInfo.x[0] = gTpInfo.xfac * gTpInfo.px + gTpInfo.xoff;
			gTpInfo.y[0] = gTpInfo.yfac * gTpInfo.py + gTpInfo.yoff;
		}
		if (gTpInfo.x[0] > LCD_XSIZE_TFT)
			gTpInfo.x[0] = LCD_XSIZE_TFT;
		if (gTpInfo.y[0] > LCD_YSIZE_TFT)
			gTpInfo.y[0] = LCD_YSIZE_TFT;
		if (gTpInfo.sta == 0)
			gTpInfo.sta = 1;
		return 1;
	}
	else
	{
		gTpInfo.sta = 0;
		/* debug
			printf("x=%d    y=%d\r\n",gTpInfo.x[0],gTpInfo.y[0]);
		*/
		return 0;
	}
}
// Prompt string
uint8_t *const TP_REMIND_MSG_TBL = (uint8_t *)"Please correct the resistance screen";
// Touch screen calibration
// Get four calibration parameters
uint8_t LT_TpAdjust(void)
{
	uint8_t cnt = 0;
	uint16_t outTime = 0;
	uint16_t d1, d2;
	uint32_t temp1, temp2;
	uint16_t posTemp[2][4] = {0};
	float fac;
	Canvas_Image_Start_address(0);
	Canvas_image_width(LCD_XSIZE_TFT);
	LT768_DrawSquare_Fill(0, 0, LCD_XSIZE_TFT, LCD_YSIZE_TFT, White);
	LT768_Select_Internal_Font_Init(32, 1, 1, 0, 0);
	LT768_Print_Internal_Font_String(40, 40, Red, White, (char *)TP_REMIND_MSG_TBL);
	LT_TpDrawTouchPoint(20, 20, Red);
	while (1)
	{                                                      
		
		WDT_FeedDog(); //Clear watchdog
		LT_TpAdjustScan();
		
		if (gTpInfo.sta == 1)
		{
			outTime = 0;
			gTpInfo.sta = 2;
			posTemp[0][cnt] = gTpInfo.px;
			posTemp[1][cnt] = gTpInfo.py;
			cnt++;
			switch (cnt)
			{
			case 1:
				LT768_DrawSquare_Fill(0, 0, LCD_XSIZE_TFT, LCD_YSIZE_TFT, White);
				LT_TpDrawTouchPoint(LCD_XSIZE_TFT - 20, 20, Red);
				break;
			case 2:
				LT768_DrawSquare_Fill(0, 0, LCD_XSIZE_TFT, LCD_YSIZE_TFT, White);
				LT_TpDrawTouchPoint(20, LCD_YSIZE_TFT - 20, Red);
				break;
			case 3:
				LT768_DrawSquare_Fill(0, 0, LCD_XSIZE_TFT, LCD_YSIZE_TFT, White);
				LT_TpDrawTouchPoint(LCD_XSIZE_TFT - 20, LCD_YSIZE_TFT - 20, Red);
				break;
			case 4: 
				temp1 = abs(posTemp[0][0] - posTemp[0][1]);
				temp2 = abs(posTemp[1][0] - posTemp[1][1]);
				temp1 *= temp1;
				temp2 *= temp2;
				d1 = sqrt(temp1 + temp2);
				temp1 = abs(posTemp[0][2] - posTemp[0][3]);
				temp2 = abs(posTemp[1][2] - posTemp[1][3]);
				temp1 *= temp1;
				temp2 *= temp2;
				d2 = sqrt(temp1 + temp2);
				fac = (float)d1 / d2;
				if (fac < 0.95f || fac > 1.05f || d1 == 0 || d2 == 0)
				{
					cnt = 0;
					LT_TpDrawTouchPoint(LCD_XSIZE_TFT - 20, LCD_YSIZE_TFT - 20, White);
					LT_TpDrawTouchPoint(20, 20, Red);
					LT768_Print_Internal_Font_String(200, 180, Red, White, "Check Failure,Please recheck!");
					continue;
				}
				// Calculate the ratio of the left and right sides
				temp1 = abs(posTemp[0][0] - posTemp[0][2]);
				temp2 = abs(posTemp[1][0] - posTemp[1][2]);
				temp1 *= temp1;
				temp2 *= temp2;
				d1 = sqrt(temp1 + temp2);
				temp1 = abs(posTemp[0][1] - posTemp[0][3]);
				temp2 = abs(posTemp[1][1] - posTemp[1][3]);
				temp1 *= temp1;
				temp2 *= temp2;
				d2 = sqrt(temp1 + temp2);
				if (fac < 0.95f || fac > 1.05f || d1 == 0 || d2 == 0)
				{
					cnt = 0;
					LT_TpDrawTouchPoint(LCD_XSIZE_TFT - 20, LCD_YSIZE_TFT - 20, White);
					LT_TpDrawTouchPoint(20, 20, Red);
					LT768_Print_Internal_Font_String(200, 180, Red, White, "Check Failure,Please recheck!");
					continue;
				}
				// 计算相对侧的长度比例
				temp1 = abs(posTemp[0][0] - posTemp[0][3]);
				temp2 = abs(posTemp[1][0] - posTemp[1][3]);
				temp1 *= temp1;
				temp2 *= temp2;
				d1 = sqrt(temp1 + temp2);
				temp1 = abs(posTemp[0][1] - posTemp[0][2]);
				temp2 = abs(posTemp[1][1] - posTemp[1][2]);
				temp1 *= temp1;
				temp2 *= temp2;
				d2 = sqrt(temp1 + temp2);
				fac = (float)d1 / d2;
				if (fac < 0.95f || fac > 1.05f || d1 == 0 || d2 == 0) 
				{
					cnt = 0;
					LT_TpDrawTouchPoint(LCD_XSIZE_TFT - 20, LCD_YSIZE_TFT - 20, White);
					LT_TpDrawTouchPoint(20, 20, Red);
					LT768_Print_Internal_Font_String(200, 180, Red, White, "Check Failure,Please recheck!");
					continue;
				}
				/* If the ratio of the upper and lower sides, the ratio of the left and right sides, 
					and the ratio of the diagonal side are all within the range, the four correction points meet the requirements*/
				gTpInfo.xfac = (float)(LCD_XSIZE_TFT - 40) / (posTemp[0][1] - posTemp[0][0]);
				gTpInfo.xoff = (LCD_XSIZE_TFT - gTpInfo.xfac * (posTemp[0][1] + posTemp[0][0])) / 2;
				gTpInfo.yfac = (float)(LCD_YSIZE_TFT - 40) / (posTemp[1][2] - posTemp[1][0]);
				gTpInfo.yoff = (LCD_YSIZE_TFT - gTpInfo.yfac * (posTemp[1][2] + posTemp[1][0])) / 2;
				gTpxfac.xfac = gTpInfo.xfac;
				gTpxoff.xoff = gTpInfo.xoff;
				gTpyfac.yfac = gTpInfo.yfac;
				gTpyoff.yoff = gTpInfo.yoff;
				LT768_DrawSquare_Fill(0, 0, LCD_XSIZE_TFT, LCD_YSIZE_TFT, White);
				LT768_Print_Internal_Font_String(200, 180, Red, White, "Touch Screen Adjust OK!"); // Calibration successful
				DelayMS(1000);
				//								printf("%f",gTpInfo.xfac);
				//								printf("%f",gTpInfo.xoff);
				//								printf("%f",gTpInfo.yfac);
				//								printf("%f",gTpInfo.yoff);
				// Save 4 parameters
				LT_TpSaveAdjdata();
				return 1;
			}
		}
		DelayMS(10);
		outTime++;
		if (outTime > 4000)
		{
			// Get the 4 parameters previously saved
			LT_TpGetAdjdata();
			LT768_DrawSquare_Fill(0, 0, LCD_XSIZE_TFT, LCD_YSIZE_TFT, White);
			LT768_Print_Internal_Font_String(200, 180, Red, White, "Touch Screen Adjust Failure!"); // Calibration failed
			return 1;
		}
	}
}
uint8_t LT_TpInit(void)
{
	RTP_io_Init();
	DelayMS(10);
	if (LT_TpGetAdjdata() != 1)
	{
		Display_ON();
		DelayMS(100);
		LT768_PWM1_Init(1, 0, 5, 800, 450);
		Rtp_Cor = 1;
		LT_TpAdjust();
	}
	Rtp_Cor = 0;
	TP_Read_XY2(&gTpInfo.px, &gTpInfo.py);
	gTpInfo.scan = LT_TpScan;
	return 1;
}