|
|
/************************************************************************
|
|
|
* 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;
|
|
|
}
|