998 lines
24 KiB
C
998 lines
24 KiB
C
|
#include <stdio.h>
|
|||
|
#include <math.h>
|
|||
|
#include <stdlib.h>
|
|||
|
|
|||
|
#include "FreeRTOS.h"
|
|||
|
#include "chip.h"
|
|||
|
#include "board.h"
|
|||
|
#include "touch.h"
|
|||
|
|
|||
|
#if !defined(VG_ONLY) && !defined(AWTK)
|
|||
|
#include "lvgl/lvgl.h"
|
|||
|
#else
|
|||
|
typedef int16_t lv_coord_t;
|
|||
|
typedef uint8_t lv_indev_state_t;
|
|||
|
typedef struct {
|
|||
|
lv_coord_t x;
|
|||
|
lv_coord_t y;
|
|||
|
} lv_point_t;
|
|||
|
|
|||
|
enum { LV_INDEV_STATE_REL = 0, LV_INDEV_STATE_PR };
|
|||
|
|
|||
|
enum {
|
|||
|
LV_KEY_UP = 17, /*0x11*/
|
|||
|
LV_KEY_DOWN = 18, /*0x12*/
|
|||
|
LV_KEY_RIGHT = 19, /*0x13*/
|
|||
|
LV_KEY_LEFT = 20, /*0x14*/
|
|||
|
LV_KEY_ESC = 27, /*0x1B*/
|
|||
|
LV_KEY_DEL = 127, /*0x7F*/
|
|||
|
LV_KEY_BACKSPACE = 8, /*0x08*/
|
|||
|
LV_KEY_ENTER = 10, /*0x0A, '\n'*/
|
|||
|
LV_KEY_NEXT = 9, /*0x09, '\t'*/
|
|||
|
LV_KEY_PREV = 11, /*0x0B, '*/
|
|||
|
LV_KEY_HOME = 2, /*0x02, STX*/
|
|||
|
LV_KEY_END = 3, /*0x03, ETX*/
|
|||
|
};
|
|||
|
|
|||
|
typedef struct {
|
|||
|
lv_point_t point; /**< For LV_INDEV_TYPE_POINTER the currently pressed point*/
|
|||
|
uint32_t key; /**< For LV_INDEV_TYPE_KEYPAD the currently pressed key*/
|
|||
|
uint32_t btn_id; /**< For LV_INDEV_TYPE_BUTTON the currently pressed button*/
|
|||
|
int16_t enc_diff; /**< For LV_INDEV_TYPE_ENCODER number of steps since the previous read*/
|
|||
|
|
|||
|
lv_indev_state_t state; /**< LV_INDEV_STATE_REL or LV_INDEV_STATE_PR*/
|
|||
|
} lv_indev_data_t;
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef ADC_TOUCH
|
|||
|
|
|||
|
#define TOUCH_STATE_IDLE 0
|
|||
|
#define TOUCH_STATE_START 1
|
|||
|
#define TOUCH_STATE_SAMPLE 2
|
|||
|
#define TOUCH_STATE_STOP 3
|
|||
|
|
|||
|
#define MAX_POINT_POOL_SIZE 2
|
|||
|
#define FILTER_MAX 3
|
|||
|
|
|||
|
#define MAXPANADCLEN 20
|
|||
|
|
|||
|
typedef struct {
|
|||
|
int x;
|
|||
|
int y;
|
|||
|
} POINT;
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
UINT16 adcX;
|
|||
|
UINT16 adcY;
|
|||
|
} PAN_DATA;
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
UINT32 *pValue;
|
|||
|
UINT32 header;
|
|||
|
UINT32 trail;
|
|||
|
UINT32 quelen;
|
|||
|
} ADCValueQueue;
|
|||
|
|
|||
|
static calibration cal;
|
|||
|
static UINT32 lg_ulTouchMachineState = TOUCH_STATE_IDLE;
|
|||
|
static POINT lg_stLastMovePoint;
|
|||
|
ADCValueQueue panADCXQueue;
|
|||
|
ADCValueQueue panADCYQueue;
|
|||
|
UINT32 PANADC_X[MAXPANADCLEN];
|
|||
|
UINT32 PANADC_Y[MAXPANADCLEN];
|
|||
|
|
|||
|
static INT32 Queue_ADCValue_Init(ADCValueQueue *pQueue, UINT32 *pValue, UINT32 quelen)
|
|||
|
{
|
|||
|
INT32 ret=0;
|
|||
|
|
|||
|
if((pQueue != 0) && (pValue != 0) && (quelen > 0))
|
|||
|
{
|
|||
|
pQueue->pValue = pValue;
|
|||
|
pQueue->quelen = quelen;
|
|||
|
pQueue->header = 0;
|
|||
|
pQueue->trail = 0;
|
|||
|
ret =1;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
static INT32 Queue_ADCValue_Length(ADCValueQueue *pQueue)
|
|||
|
{
|
|||
|
INT32 queuelen=0;
|
|||
|
|
|||
|
if(pQueue != 0)
|
|||
|
{
|
|||
|
if(pQueue->trail < pQueue->header)
|
|||
|
{
|
|||
|
queuelen = pQueue->quelen +(pQueue->trail- pQueue->header);
|
|||
|
}
|
|||
|
else
|
|||
|
queuelen = pQueue->trail- pQueue->header;
|
|||
|
}
|
|||
|
|
|||
|
return queuelen;
|
|||
|
}
|
|||
|
|
|||
|
static INT32 Queue_ADCValue_Add(ADCValueQueue *pQueue,unsigned int value)
|
|||
|
{
|
|||
|
INT32 ret=0;
|
|||
|
UINT32 *pValue=0;
|
|||
|
|
|||
|
if(pQueue != 0)
|
|||
|
{
|
|||
|
pValue = pQueue->pValue + pQueue->trail;
|
|||
|
*pValue = value;
|
|||
|
|
|||
|
pQueue->trail++;
|
|||
|
if(pQueue->trail >= pQueue->quelen)
|
|||
|
{
|
|||
|
pQueue->trail = 0;
|
|||
|
}
|
|||
|
|
|||
|
if(pQueue->trail == pQueue->header)
|
|||
|
{
|
|||
|
pQueue->header++;
|
|||
|
if(pQueue->header >= pQueue->quelen)
|
|||
|
{
|
|||
|
pQueue->header = 1;
|
|||
|
pQueue->trail=0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ret=1;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
static INT32 Queue_ADCValue_Read(ADCValueQueue *pQueue, UINT32 *pValue)
|
|||
|
{
|
|||
|
INT32 ret=0;
|
|||
|
UINT32 *pHeaderValue=0;
|
|||
|
|
|||
|
if((pQueue != 0) && (pValue != 0))
|
|||
|
{
|
|||
|
if(Queue_ADCValue_Length(pQueue) > 0)
|
|||
|
{
|
|||
|
pHeaderValue = pQueue->pValue + pQueue->header;
|
|||
|
*pValue = *pHeaderValue;
|
|||
|
|
|||
|
pQueue->header++;
|
|||
|
if(pQueue->header >= pQueue->quelen)
|
|||
|
{
|
|||
|
pQueue->header = 0;
|
|||
|
}
|
|||
|
|
|||
|
ret=1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
//////////////////////////////////////////////////
|
|||
|
static UINT32 GetADCTouch(PAN_DATA *pPan)
|
|||
|
{
|
|||
|
UINT32 panX;
|
|||
|
UINT32 panY;
|
|||
|
|
|||
|
INT32 ret=0;
|
|||
|
|
|||
|
if(pPan != 0)
|
|||
|
{
|
|||
|
ret = Queue_ADCValue_Read(&panADCXQueue,&panX);
|
|||
|
if(ret==1)
|
|||
|
{
|
|||
|
ret = Queue_ADCValue_Read(&panADCYQueue,&panY);
|
|||
|
if(ret == 1)
|
|||
|
{
|
|||
|
pPan->adcX = panX;
|
|||
|
pPan->adcY = panY;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
static void CalcCoord(PAN_DATA *pPan, POINT *pPT);
|
|||
|
|
|||
|
#define TOUCH_DOT_REGION 10
|
|||
|
|
|||
|
extern void SendTouchInputEventFromISR(lv_indev_data_t *indata);
|
|||
|
|
|||
|
/***********************************************************************************************
|
|||
|
通过大量试验发现触摸屏存在的问题有
|
|||
|
1: 触摸刚开始的几个点可能任意哪个点或者哪几个点会有较大偏差;
|
|||
|
2: 释放前的采样点很大几率不准确。
|
|||
|
|
|||
|
为了应对各种错误情况,采取的措施有
|
|||
|
1: 首先简单地丢弃掉最后一个采样点
|
|||
|
2: 提高采样频率,保证最开始的几个采样点都在一个比较小的范围
|
|||
|
内(即使快速滑动,刚开始不会有很大速度,因此也能保证起始点
|
|||
|
比较聚集)。在这种前提下提取开始采样时的若干个点进行分析,
|
|||
|
找出坐标值比较接近的点数最多的点,其他点则认为是错误点丢
|
|||
|
弃掉,如果找不到的话则认为所有点都不稳定,重新再提取之后
|
|||
|
的若干个点进行分析。
|
|||
|
*************************************************************************************************/
|
|||
|
#define SCOPE_ADJUST 8
|
|||
|
|
|||
|
#define ANALYSIS_POINT_SUCCESS 3
|
|||
|
#define ANALYSIS_POINT_COUNT 5
|
|||
|
#define DISCARD_POINT_COUNT 2
|
|||
|
#define POINT_POOL_SIZE (ANALYSIS_POINT_COUNT+DISCARD_POINT_COUNT)
|
|||
|
|
|||
|
#define MYABS(x) (((x)>=0) ? (x) : (-(x)))
|
|||
|
/*
|
|||
|
*********************************************************************************************************
|
|||
|
* Description: 分析采样最开始的若干点,丢弃错误点
|
|||
|
*
|
|||
|
* Arguments : point[] : 采样点坐标值数组
|
|||
|
num : 用于分析的采样点个数
|
|||
|
*
|
|||
|
* Returns : 有效点的个数,返回0表示所有点都无效
|
|||
|
|
|||
|
* Notes : 剩余的有效点重新从原数组起始位置开始依次放置
|
|||
|
*********************************************************************************************************
|
|||
|
*/
|
|||
|
static int Touch_Start_Analyse(POINT point[], int num)
|
|||
|
{
|
|||
|
int i, j;
|
|||
|
int key[ANALYSIS_POINT_COUNT] = {0};
|
|||
|
int near_by_point[ANALYSIS_POINT_COUNT] = {0};
|
|||
|
int effective_near_by_points[ANALYSIS_POINT_COUNT] = {0};
|
|||
|
int max = -1;
|
|||
|
int samplecnt = 0;
|
|||
|
|
|||
|
if(num > ANALYSIS_POINT_COUNT)
|
|||
|
num = ANALYSIS_POINT_COUNT;
|
|||
|
|
|||
|
for(i=0; i<num; i++)
|
|||
|
{
|
|||
|
//计算每个点和其接近的点的个数并记录下距离最近的点
|
|||
|
near_by_point[i] = 1;
|
|||
|
for(j=0; j<num; j++)
|
|||
|
{
|
|||
|
if(j == i)
|
|||
|
continue;
|
|||
|
|
|||
|
if(MYABS(point[i].x - point[j].x)<SCOPE_ADJUST && MYABS(point[i].y - point[j].y)<SCOPE_ADJUST)
|
|||
|
{
|
|||
|
key[i]++;
|
|||
|
near_by_point[j] = 1;
|
|||
|
}
|
|||
|
else
|
|||
|
near_by_point[j] = 0;
|
|||
|
}
|
|||
|
|
|||
|
//筛选出相近点数最多的点并记录下与其距离最近的点位置
|
|||
|
if(key[i] > max)
|
|||
|
{
|
|||
|
max = key[i];
|
|||
|
for(j=0;j<num;j++)
|
|||
|
{
|
|||
|
effective_near_by_points[j] = near_by_point[j];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//有效点个数不够,判定所有点都不稳定全部丢弃
|
|||
|
if(max < ANALYSIS_POINT_SUCCESS-1)
|
|||
|
return 0;
|
|||
|
|
|||
|
//移除所有无效点,有效点从原数组位置0开始依次放置
|
|||
|
for(i=0; i<num; i++)
|
|||
|
{
|
|||
|
if(effective_near_by_points[i])
|
|||
|
{
|
|||
|
point[samplecnt] = point[i];
|
|||
|
samplecnt++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return samplecnt;
|
|||
|
}
|
|||
|
|
|||
|
static void Handler_Touch_IntEvent(UINT32 ulEvent, UINT32 lpParam, UINT32 wParam)
|
|||
|
{
|
|||
|
static int s_SampleCnt;
|
|||
|
static int s_PoolIndex;
|
|||
|
static POINT s_PointPool[POINT_POOL_SIZE];
|
|||
|
|
|||
|
switch(lg_ulTouchMachineState)
|
|||
|
{
|
|||
|
case TOUCH_STATE_IDLE:
|
|||
|
if(ulEvent == TOUCH_START_EVENT)
|
|||
|
{
|
|||
|
lg_ulTouchMachineState = TOUCH_STATE_START;
|
|||
|
s_SampleCnt = 0;
|
|||
|
s_PoolIndex = 0;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case TOUCH_STATE_START:
|
|||
|
if(ulEvent == TOUCH_STOP_EVENT)
|
|||
|
{
|
|||
|
lg_ulTouchMachineState = TOUCH_STATE_IDLE;
|
|||
|
}
|
|||
|
else if(ulEvent == TOUCH_SAMPLE_EVENT)
|
|||
|
{
|
|||
|
POINT pt;
|
|||
|
PAN_DATA stPanData;
|
|||
|
lv_indev_data_t indata = {0};
|
|||
|
int i;
|
|||
|
|
|||
|
//get cordinate
|
|||
|
stPanData.adcX = lpParam;
|
|||
|
stPanData.adcY = wParam;
|
|||
|
CalcCoord(&stPanData, &pt);
|
|||
|
if(pt.x < 0 || pt.y < 0)
|
|||
|
return;
|
|||
|
|
|||
|
if(pt.x < 0 || pt.x >= LCD_WIDTH || pt.y < 0 || pt.y >= LCD_HEIGHT)
|
|||
|
return;
|
|||
|
|
|||
|
//防止ANALYSIS_POINT_START个点内包含最后要丢弃的点,刚开始要暂存
|
|||
|
//ANALYSIS_POINT_START + DISCARD_POINT_END个点
|
|||
|
if(s_SampleCnt < ANALYSIS_POINT_COUNT + DISCARD_POINT_COUNT)
|
|||
|
{
|
|||
|
s_PointPool[s_SampleCnt++] = pt;
|
|||
|
if(s_SampleCnt < ANALYSIS_POINT_COUNT + DISCARD_POINT_COUNT)
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
s_SampleCnt = Touch_Start_Analyse(s_PointPool, ANALYSIS_POINT_COUNT);
|
|||
|
if(s_SampleCnt == 0)
|
|||
|
{
|
|||
|
for(i=0; i<DISCARD_POINT_COUNT; i++)
|
|||
|
s_PointPool[i] = s_PointPool[ANALYSIS_POINT_COUNT+i];
|
|||
|
s_SampleCnt = DISCARD_POINT_COUNT;
|
|||
|
return;
|
|||
|
}
|
|||
|
//send press event
|
|||
|
indata.point.x = s_PointPool[0].x;
|
|||
|
indata.point.y = s_PointPool[0].y;
|
|||
|
indata.state = LV_INDEV_STATE_PR;
|
|||
|
SendTouchInputEventFromISR(&indata);
|
|||
|
|
|||
|
lg_ulTouchMachineState = TOUCH_STATE_SAMPLE;
|
|||
|
|
|||
|
//将为满足最后丢弃任务而暂存的点复制到分析后剩余点之后
|
|||
|
for(i=0; i<DISCARD_POINT_COUNT; i++)
|
|||
|
s_PointPool[s_SampleCnt + i] = s_PointPool[ANALYSIS_POINT_COUNT+i];
|
|||
|
s_PoolIndex = 1;
|
|||
|
//计算此时剩余的未操作的有效点数
|
|||
|
s_SampleCnt = s_SampleCnt - 1 + DISCARD_POINT_COUNT;
|
|||
|
//send move event in the pool
|
|||
|
while(s_SampleCnt > DISCARD_POINT_COUNT)
|
|||
|
{
|
|||
|
int xdiff, ydiff;
|
|||
|
unsigned int totaldiff;
|
|||
|
|
|||
|
xdiff = s_PointPool[s_PoolIndex].x - lg_stLastMovePoint.x;
|
|||
|
ydiff = s_PointPool[s_PoolIndex].y - lg_stLastMovePoint.y;
|
|||
|
totaldiff = xdiff * xdiff + ydiff * ydiff;
|
|||
|
if(totaldiff > 4)
|
|||
|
{
|
|||
|
indata.point.x = s_PointPool[s_PoolIndex].x;
|
|||
|
indata.point.y = s_PointPool[s_PoolIndex].y;
|
|||
|
indata.state = LV_INDEV_STATE_PR;
|
|||
|
SendTouchInputEventFromISR(&indata);
|
|||
|
lg_stLastMovePoint.x = s_PointPool[s_PoolIndex].x;
|
|||
|
lg_stLastMovePoint.y = s_PointPool[s_PoolIndex].y;
|
|||
|
}
|
|||
|
s_PoolIndex++;
|
|||
|
s_SampleCnt--;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case TOUCH_STATE_SAMPLE:
|
|||
|
if(ulEvent == TOUCH_SAMPLE_EVENT)
|
|||
|
{
|
|||
|
//caculate move center cordinate
|
|||
|
//if move, then send move event
|
|||
|
PAN_DATA stPanData;
|
|||
|
POINT pt;
|
|||
|
int xDiff = 0, yDiff = 0;
|
|||
|
unsigned int totalDiff = 0;
|
|||
|
|
|||
|
//get cordinate
|
|||
|
stPanData.adcX = lpParam;
|
|||
|
stPanData.adcY = wParam;
|
|||
|
CalcCoord(&stPanData, &pt);
|
|||
|
if(pt.x < 0 || pt.y < 0)
|
|||
|
return;
|
|||
|
|
|||
|
if(pt.x < 0 || pt.x >= LCD_WIDTH || pt.y < 0 || pt.y >= LCD_HEIGHT)
|
|||
|
return;
|
|||
|
|
|||
|
if(s_SampleCnt < DISCARD_POINT_COUNT)
|
|||
|
{
|
|||
|
int index = (s_PoolIndex+s_SampleCnt++) % POINT_POOL_SIZE;
|
|||
|
|
|||
|
s_PointPool[index] = pt;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
xDiff = s_PointPool[s_PoolIndex].x - lg_stLastMovePoint.x;
|
|||
|
yDiff = s_PointPool[s_PoolIndex].y - lg_stLastMovePoint.y;
|
|||
|
totalDiff = xDiff * xDiff + yDiff * yDiff;
|
|||
|
if(totalDiff > 4)
|
|||
|
{
|
|||
|
lv_indev_data_t indata = {0};
|
|||
|
|
|||
|
indata.point.x = s_PointPool[s_PoolIndex].x;
|
|||
|
indata.point.y = s_PointPool[s_PoolIndex].y;
|
|||
|
indata.state = LV_INDEV_STATE_PR;
|
|||
|
SendTouchInputEventFromISR(&indata);
|
|||
|
lg_stLastMovePoint.x = s_PointPool[s_PoolIndex].x;
|
|||
|
lg_stLastMovePoint.y = s_PointPool[s_PoolIndex].y;
|
|||
|
}
|
|||
|
s_PointPool[(s_PoolIndex+DISCARD_POINT_COUNT)%POINT_POOL_SIZE] = pt;
|
|||
|
s_PoolIndex = (s_PoolIndex+1)%POINT_POOL_SIZE;
|
|||
|
}
|
|||
|
else if(ulEvent == TOUCH_STOP_EVENT)
|
|||
|
{
|
|||
|
lv_indev_data_t indata = {0};
|
|||
|
|
|||
|
//send release event
|
|||
|
indata.point.x = lg_stLastMovePoint.x;
|
|||
|
indata.point.y = lg_stLastMovePoint.y;
|
|||
|
indata.state = LV_INDEV_STATE_REL;
|
|||
|
SendTouchInputEventFromISR(&indata);
|
|||
|
lg_ulTouchMachineState = TOUCH_STATE_IDLE;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case TOUCH_STATE_STOP:
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
static volatile UINT32 lg_bTouchStart = 0;
|
|||
|
static UINT32 CheckTouchStart()
|
|||
|
{
|
|||
|
return lg_bTouchStart == 1;
|
|||
|
}
|
|||
|
|
|||
|
static UINT32 CheckTouchStop()
|
|||
|
{
|
|||
|
return lg_bTouchStart == 0;
|
|||
|
}
|
|||
|
|
|||
|
static UINT32 GetTouchSampleCounter()
|
|||
|
{
|
|||
|
return Queue_ADCValue_Length(&panADCXQueue);
|
|||
|
}
|
|||
|
|
|||
|
static UINT32 lg_bTouchAdjusted = 0;
|
|||
|
void TouchEventHandler(UINT32 ulEvent, UINT32 lpParam, UINT32 wParam)
|
|||
|
{
|
|||
|
if(lg_bTouchAdjusted)
|
|||
|
{
|
|||
|
Handler_Touch_IntEvent(ulEvent, lpParam, wParam);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
|
|||
|
if(ulEvent == TOUCH_START_EVENT)
|
|||
|
{
|
|||
|
lg_bTouchStart = 1;
|
|||
|
Queue_ADCValue_Init(&panADCXQueue, PANADC_X, MAXPANADCLEN);
|
|||
|
Queue_ADCValue_Init(&panADCYQueue, PANADC_Y, MAXPANADCLEN);
|
|||
|
}
|
|||
|
else if(ulEvent == TOUCH_SAMPLE_EVENT)
|
|||
|
{
|
|||
|
Queue_ADCValue_Add(&panADCXQueue,lpParam);
|
|||
|
Queue_ADCValue_Add(&panADCYQueue,wParam);
|
|||
|
}
|
|||
|
else if(ulEvent == TOUCH_STOP_EVENT)
|
|||
|
{
|
|||
|
lg_bTouchStart = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/***************************************************************************************
|
|||
|
触摸屏坐标校验代码
|
|||
|
***************************************************************************************/
|
|||
|
|
|||
|
|
|||
|
#define GRID_RANGE 12
|
|||
|
#define HIT_RANGE 2
|
|||
|
#define ABS_HIT ((GRID_RANGE+HIT_RANGE)*2)
|
|||
|
|
|||
|
#define TOUCH_HIGH_EXACTION 0
|
|||
|
#define TOUCH_MID_EXACTION 0
|
|||
|
#define TOUCH_LOW_EXACTION 1
|
|||
|
|
|||
|
|
|||
|
#define TOUCH_REVISE_DEBUG 1
|
|||
|
|
|||
|
#if TOUCH_REVISE_DEBUG
|
|||
|
#define TOUCH_DEBUG_MSG(fmt, args...) printf(fmt, ##args)
|
|||
|
#else
|
|||
|
#define TOUCH_DEBUG_MSG(fmt, args...)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#define SYSTEM_ERROR 100.0
|
|||
|
|
|||
|
#define SCALE_AERROR 2// 3 这里考虑触摸屏的差异修改20130618
|
|||
|
#define SCALE_DERROR 5
|
|||
|
static double abs_ax,abs_dx,abs_ly,abs_ry;
|
|||
|
static double abs_lx,abs_rx;
|
|||
|
static double abs_err1,abs_err2,abs_err3,abs_err4,abs_err5;
|
|||
|
static double abs_cx,abs_cy;
|
|||
|
static int lg_direction = 0;
|
|||
|
|
|||
|
#if TOUCH_HIGH_EXACTION
|
|||
|
#define SYSTEM_ERROR1 100.0
|
|||
|
#elif TOUCH_MID_EXACTION
|
|||
|
#define SYSTEM_ERROR1 150.0
|
|||
|
#elif TOUCH_LOW_EXACTION
|
|||
|
#define SYSTEM_ERROR1 200.0
|
|||
|
#else
|
|||
|
#define SYSTEM_ERROR1 150.0
|
|||
|
#endif
|
|||
|
|
|||
|
/* static void InitializeCalibration(int a0, int a1, int a2, int a3, int a4, int a5, int a6)
|
|||
|
{
|
|||
|
cal.a[0] = a0;
|
|||
|
cal.a[1] = a1;
|
|||
|
cal.a[2] = a2;
|
|||
|
cal.a[3] = a3;
|
|||
|
cal.a[4] = a4;
|
|||
|
cal.a[5] = a5;
|
|||
|
cal.a[6] = a6;
|
|||
|
} */
|
|||
|
|
|||
|
static void SaveCalibration(calibration *pCalibration)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
static int perform_calibration(calibration *cal) {
|
|||
|
int j;
|
|||
|
float n, x, y, x2, y2, xy, z, zx, zy;
|
|||
|
float det, a, b, c, e, f, i;
|
|||
|
float scaling = 65536.0;
|
|||
|
|
|||
|
// Get sums for matrix
|
|||
|
n = x = y = x2 = y2 = xy = 0;
|
|||
|
for(j=0;j<5;j++) {
|
|||
|
n += 1.0;
|
|||
|
x += (float)cal->x[j];
|
|||
|
y += (float)cal->y[j];
|
|||
|
x2 += (float)(cal->x[j]*cal->x[j]);
|
|||
|
y2 += (float)(cal->y[j]*cal->y[j]);
|
|||
|
xy += (float)(cal->x[j]*cal->y[j]);
|
|||
|
}
|
|||
|
|
|||
|
// Get determinant of matrix -- check if determinant is too small
|
|||
|
det = n*(x2*y2 - xy*xy) + x*(xy*y - x*y2) + y*(x*xy - y*x2);
|
|||
|
if(det < 0.1 && det > -0.1) {
|
|||
|
printf("ts_calibrate: determinant is too small -- %f\n",det);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
// Get elements of inverse matrix
|
|||
|
a = (x2*y2 - xy*xy)/det;
|
|||
|
b = (xy*y - x*y2)/det;
|
|||
|
c = (x*xy - y*x2)/det;
|
|||
|
e = (n*y2 - y*y)/det;
|
|||
|
f = (x*y - n*xy)/det;
|
|||
|
i = (n*x2 - x*x)/det;
|
|||
|
|
|||
|
// Get sums for x calibration
|
|||
|
z = zx = zy = 0;
|
|||
|
for(j=0;j<5;j++) {
|
|||
|
z += (float)cal->xfb[j];
|
|||
|
zx += (float)(cal->xfb[j]*cal->x[j]);
|
|||
|
zy += (float)(cal->xfb[j]*cal->y[j]);
|
|||
|
}
|
|||
|
|
|||
|
// Now multiply out to get the calibration for framebuffer x coord
|
|||
|
cal->a[0] = (int)((a*z + b*zx + c*zy)*(scaling));
|
|||
|
cal->a[1] = (int)((b*z + e*zx + f*zy)*(scaling));
|
|||
|
cal->a[2] = (int)((c*z + f*zx + i*zy)*(scaling));
|
|||
|
|
|||
|
// Get sums for y calibration
|
|||
|
z = zx = zy = 0;
|
|||
|
for(j=0;j<5;j++) {
|
|||
|
z += (float)cal->yfb[j];
|
|||
|
zx += (float)(cal->yfb[j]*cal->x[j]);
|
|||
|
zy += (float)(cal->yfb[j]*cal->y[j]);
|
|||
|
}
|
|||
|
|
|||
|
// Now multiply out to get the calibration for framebuffer y coord
|
|||
|
cal->a[3] = (int)((a*z + b*zx + c*zy)*(scaling));
|
|||
|
cal->a[4] = (int)((b*z + e*zx + f*zy)*(scaling));
|
|||
|
cal->a[5] = (int)((c*z + f*zx + i*zy)*(scaling));
|
|||
|
|
|||
|
// If we got here, we're OK, so assign scaling to a[6] and return
|
|||
|
cal->a[6] = (int)scaling;
|
|||
|
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
void CleanTouchAdjustParameter(void)
|
|||
|
{
|
|||
|
Queue_ADCValue_Init(&panADCXQueue, PANADC_X, MAXPANADCLEN);
|
|||
|
Queue_ADCValue_Init(&panADCYQueue, PANADC_Y, MAXPANADCLEN);
|
|||
|
lg_bTouchAdjusted = 0;
|
|||
|
}
|
|||
|
|
|||
|
void TouchInit(void)
|
|||
|
{
|
|||
|
CleanTouchAdjustParameter();
|
|||
|
}
|
|||
|
|
|||
|
static void CalcCoord(PAN_DATA *pPan, POINT *pPT)
|
|||
|
{
|
|||
|
pPT->x = (pPan->adcX * cal.a[1] + pPan->adcY * cal.a[2] + cal.a[0])/cal.a[6];
|
|||
|
pPT->y = (pPan->adcX * cal.a[4] + pPan->adcY * cal.a[5] + cal.a[3])/cal.a[6];
|
|||
|
}
|
|||
|
|
|||
|
static unsigned int GetTouchHit(PAN_DATA *pPan)
|
|||
|
{
|
|||
|
unsigned int PanReq;
|
|||
|
PAN_DATA Pan[50];
|
|||
|
unsigned int i, Count;
|
|||
|
|
|||
|
for(i = 0; i < 50; i++)
|
|||
|
{
|
|||
|
Pan[i].adcX = 0xFFFF;
|
|||
|
Pan[i].adcY = 0xFFFF;
|
|||
|
}
|
|||
|
|
|||
|
ReStartCheck:
|
|||
|
while(!CheckTouchStart());
|
|||
|
while(!CheckTouchStop());
|
|||
|
if(GetTouchSampleCounter() < 16)
|
|||
|
goto ReStartCheck;
|
|||
|
|
|||
|
AIC_DisableIT(ADC_IRQn);
|
|||
|
while(1)
|
|||
|
{
|
|||
|
PanReq = GetADCTouch(&Pan[49]);
|
|||
|
|
|||
|
if(PanReq==0)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
for(i = 0; i < 49; i++)
|
|||
|
{
|
|||
|
Pan[i].adcX = Pan[i+1].adcX;
|
|||
|
Pan[i].adcY = Pan[i+1].adcY;
|
|||
|
}
|
|||
|
}
|
|||
|
AIC_EnableIT(ADC_IRQn);
|
|||
|
|
|||
|
Count = 0;
|
|||
|
|
|||
|
for(i = 0; i < 49; i++)
|
|||
|
{
|
|||
|
if(Pan[i].adcY < 0xFFF)
|
|||
|
{
|
|||
|
Count++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pPan->adcX = Pan[49-Count/2].adcX;
|
|||
|
pPan->adcY = Pan[49-Count/2].adcY;
|
|||
|
|
|||
|
|
|||
|
TOUCH_DEBUG_MSG("Hit Count = %d\n", Count);
|
|||
|
TOUCH_DEBUG_MSG("pPan->adcX=%d\n",pPan->adcX);
|
|||
|
TOUCH_DEBUG_MSG("pPan->adcY=%d\n",pPan->adcY);
|
|||
|
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
static void ClearBitmap(lv_color_t color, const lv_area_t * area, lv_color_t * color_p)
|
|||
|
{
|
|||
|
/*Truncate the area to the screen*/
|
|||
|
int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
|
|||
|
int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
|
|||
|
int32_t act_x2 = area->x2 > LCD_WIDTH - 1 ? LCD_WIDTH - 1 : area->x2;
|
|||
|
int32_t act_y2 = area->y2 > LCD_HEIGHT - 1 ? LCD_HEIGHT - 1 : area->y2;
|
|||
|
|
|||
|
/*32 or 24 bit per pixel*/
|
|||
|
if(LCD_BPP == 32) {
|
|||
|
uint32_t * fbp32 = (uint32_t *)color_p;
|
|||
|
int32_t x, y;
|
|||
|
for(y = act_y1; y <= act_y2; y++) {
|
|||
|
fbp32 = (uint32_t *)color_p + y * LCD_WIDTH;
|
|||
|
for (x = act_x1; x <= act_x2; x++)
|
|||
|
fbp32[x] = color.full;
|
|||
|
}
|
|||
|
}
|
|||
|
/*16 bit per pixel*/
|
|||
|
else if(LCD_BPP == 16) {
|
|||
|
uint16_t * fbp16 = (uint16_t *)color_p;
|
|||
|
int32_t x, y;
|
|||
|
for(y = act_y1; y <= act_y2; y++) {
|
|||
|
fbp16 = (uint16_t *)color_p + y * LCD_WIDTH;
|
|||
|
for (x = act_x1; x <= act_x2; x++)
|
|||
|
fbp16[x] = color.full;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static void PutHitCursor(int x, int y)
|
|||
|
{
|
|||
|
lv_area_t area;
|
|||
|
area.x1 = x - GRID_RANGE;
|
|||
|
area.y1 = y;
|
|||
|
area.x2 = x + GRID_RANGE + HIT_RANGE - 1;
|
|||
|
area.y2 = y + HIT_RANGE - 1;
|
|||
|
ClearBitmap(LV_COLOR_WHITE, &area, (lv_color_t*)ark_lcd_get_virt_addr());
|
|||
|
area.x1 = x;
|
|||
|
area.y1 = y - GRID_RANGE;
|
|||
|
area.x2 = x + HIT_RANGE - 1;
|
|||
|
area.y2 = y + GRID_RANGE + HIT_RANGE - 1;
|
|||
|
ClearBitmap(LV_COLOR_WHITE, &area, (lv_color_t*)ark_lcd_get_virt_addr());
|
|||
|
area.x1 = x;
|
|||
|
area.y1 = y;
|
|||
|
area.x2 = x + HIT_RANGE - 1;
|
|||
|
area.y2 = y + HIT_RANGE - 1;
|
|||
|
ClearBitmap(LV_COLOR_BLACK, &area, (lv_color_t*)ark_lcd_get_virt_addr());
|
|||
|
CP15_clean_dcache_for_dma((uint32_t)(lv_color_t*)ark_lcd_get_virt_addr(),
|
|||
|
(uint32_t)(lv_color_t*)ark_lcd_get_virt_addr() + FB_SIZE);
|
|||
|
}
|
|||
|
|
|||
|
static void ClrHitCursor(int x, int y)
|
|||
|
{
|
|||
|
lv_area_t area;
|
|||
|
area.x1 = x - GRID_RANGE;
|
|||
|
area.y1 = y - GRID_RANGE;
|
|||
|
area.x2 = x + GRID_RANGE + HIT_RANGE - 1;
|
|||
|
area.y2 = y + GRID_RANGE + HIT_RANGE - 1;
|
|||
|
ClearBitmap(LV_COLOR_BLACK, &area, (lv_color_t*)ark_lcd_get_virt_addr());
|
|||
|
CP15_clean_dcache_for_dma((uint32_t)(lv_color_t*)ark_lcd_get_virt_addr(),
|
|||
|
(uint32_t)(lv_color_t*)ark_lcd_get_virt_addr() + FB_SIZE);
|
|||
|
}
|
|||
|
|
|||
|
static int compare_data(calibration *cal)
|
|||
|
{
|
|||
|
int ret=0;
|
|||
|
int diff_x;
|
|||
|
int diff_y;
|
|||
|
|
|||
|
diff_x = (int)fabs(cal->x[0] - cal->x[1]);
|
|||
|
diff_y = (int)fabs(cal->y[0] - cal->y[1]);
|
|||
|
|
|||
|
if(diff_x > diff_y)
|
|||
|
lg_direction = 0;
|
|||
|
else
|
|||
|
lg_direction = 1;
|
|||
|
|
|||
|
TOUCH_DEBUG_MSG("lg_direction = %d\r\n", lg_direction);
|
|||
|
|
|||
|
if(lg_direction == 0)
|
|||
|
{
|
|||
|
if((cal->x [0]<cal->x [1])&&(cal->x [3]<cal->x [2]))
|
|||
|
ret=1;
|
|||
|
if((cal->x [0]>cal->x [1])&&(cal->x [3]>cal->x [2]))
|
|||
|
ret=1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if((cal->y[0]<cal->y[1])&&(cal->y[3]<cal->y[2]))
|
|||
|
ret=1;
|
|||
|
if((cal->y[0]>cal->y[1])&&(cal->y[3]>cal->y[2]))
|
|||
|
ret=1;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
static int square_judge(calibration *cal)
|
|||
|
{
|
|||
|
int ret=0;
|
|||
|
|
|||
|
if(lg_direction == 0)
|
|||
|
{
|
|||
|
abs_ax=fabs(cal->x [0] - cal->x [1]);
|
|||
|
abs_dx=fabs(cal->x [2]-cal->x [3]);
|
|||
|
abs_err1=fabs(abs_ax -abs_dx);
|
|||
|
TOUCH_DEBUG_MSG("***abs_ax=%d, abs_dx=%d, abs_err1=%d, SYSTEM_ERROR1=%d*******\n", (int)abs_ax, (int)abs_dx, (int)abs_err1, (int)SYSTEM_ERROR1);
|
|||
|
|
|||
|
|
|||
|
abs_lx=fabs(cal->x [0]-cal->x [4]);
|
|||
|
abs_rx=fabs(cal->x[3]-cal->x [4]);
|
|||
|
abs_err2=fabs(abs_lx -abs_rx);
|
|||
|
TOUCH_DEBUG_MSG("***abs_lx=%d,abs_rx=%d,abs_err2=%d****2\n", (int)abs_lx, (int)abs_rx, (int)abs_err2);
|
|||
|
|
|||
|
|
|||
|
abs_ly=fabs(cal->y [0]-cal->y [3]);
|
|||
|
abs_ry=fabs(cal->y [1]-cal->y [2]);
|
|||
|
abs_err3=fabs(abs_ly -abs_ry);
|
|||
|
TOUCH_DEBUG_MSG("***abs_ly=%d, abs_ry=%d, abs_err3=%d****2\n", (int)abs_ly, (int)abs_ry, (int)abs_err3);
|
|||
|
|
|||
|
|
|||
|
if(abs_err1<SYSTEM_ERROR1&&abs_err2<SYSTEM_ERROR1&&abs_err3<SYSTEM_ERROR1)
|
|||
|
ret=1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
abs_ax=fabs(cal->y[0] - cal->y[1]);
|
|||
|
abs_dx=fabs(cal->y[2]-cal->y[3]);
|
|||
|
abs_err1=fabs(abs_ax -abs_dx);
|
|||
|
TOUCH_DEBUG_MSG("***abs_ax=%d, abs_dx=%d, abs_err1=%d, SYSTEM_ERROR1=%d*******\n", (int)abs_ax, (int)abs_dx, (int)abs_err1, (int)SYSTEM_ERROR1);
|
|||
|
|
|||
|
|
|||
|
abs_lx=fabs(cal->y[0]-cal->y[4]);
|
|||
|
abs_rx=fabs(cal->y[3]-cal->y[4]);
|
|||
|
abs_err2=fabs(abs_lx -abs_rx);
|
|||
|
TOUCH_DEBUG_MSG("***abs_lx=%d, abs_rx=%d, abs_err2=%d****2\n", (int)abs_lx, (int)abs_rx, (int)abs_err2);
|
|||
|
|
|||
|
|
|||
|
abs_ly=fabs(cal->x[0]-cal->x[3]);
|
|||
|
abs_ry=fabs(cal->x[1]-cal->x[2]);
|
|||
|
abs_err3=fabs(abs_ly -abs_ry);
|
|||
|
TOUCH_DEBUG_MSG("***abs_ly=%d, abs_ry=%d, abs_err3=%d****2\n", (int)abs_ly, (int)abs_ry, (int)abs_err3);
|
|||
|
|
|||
|
|
|||
|
if(abs_err1<SYSTEM_ERROR1&&abs_err2<SYSTEM_ERROR1&&abs_err3<SYSTEM_ERROR1)
|
|||
|
ret=1;
|
|||
|
}
|
|||
|
|
|||
|
TOUCH_DEBUG_MSG("***ret=%d****4\n",ret);
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
static int judge_center(calibration *cal)
|
|||
|
{
|
|||
|
int ret=0;
|
|||
|
|
|||
|
if(lg_direction == 0)
|
|||
|
{
|
|||
|
abs_cx=fabs(cal->x [4]-cal->x [0])*2;
|
|||
|
abs_cy=fabs(cal->y [4]-cal->y [0])*2;
|
|||
|
abs_err4=fabs(abs_cx -abs_ax);
|
|||
|
abs_err5=fabs(abs_cy -abs_ly);
|
|||
|
TOUCH_DEBUG_MSG("***abs_cx=%d, abs_cy=%d, abs_err4=%d, abs_err5=%d****2\n", (int)abs_cx, (int)abs_cy, (int)abs_err4, (int)abs_err5);
|
|||
|
|
|||
|
if(abs_err4<SYSTEM_ERROR1&&abs_err5<SYSTEM_ERROR1)
|
|||
|
ret=1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
abs_cx=fabs(cal->y[4]-cal->y[0])*2;
|
|||
|
abs_cy=fabs(cal->x[4]-cal->x[0])*2;
|
|||
|
abs_err4=fabs(abs_cx -abs_ax);
|
|||
|
abs_err5=fabs(abs_cy -abs_ly);
|
|||
|
TOUCH_DEBUG_MSG("***abs_cx=%d, abs_cy=%d, abs_err4=%d, abs_err5=%d****2\n", (int)abs_cx, (int)abs_cy, (int)abs_err4, (int)abs_err5);
|
|||
|
|
|||
|
if(abs_err4<SYSTEM_ERROR1&&abs_err5<SYSTEM_ERROR1)
|
|||
|
ret=1;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
static int filter_data(calibration *cal)
|
|||
|
{
|
|||
|
int ret=0;
|
|||
|
float abs_lcd;
|
|||
|
int scale;
|
|||
|
int i;
|
|||
|
|
|||
|
TOUCH_DEBUG_MSG("***filter_data****1\n");
|
|||
|
for(i=0;i<5;i++)
|
|||
|
{
|
|||
|
TOUCH_DEBUG_MSG("cal->x[%d] = %d, cal->y[%d] = %d\r\n", i, (int)cal->x[i], i, (int)cal->y[i]);
|
|||
|
}
|
|||
|
|
|||
|
if(compare_data( cal))
|
|||
|
{
|
|||
|
TOUCH_DEBUG_MSG("*** Pass compare_data ****\n");
|
|||
|
|
|||
|
if(square_judge(cal))
|
|||
|
{
|
|||
|
TOUCH_DEBUG_MSG("*** Pass square_judge ****\n");
|
|||
|
|
|||
|
abs_lcd=fabs(cal->xfb[1] -cal->xfb[0]);
|
|||
|
TOUCH_DEBUG_MSG("***abs_ax=%d, abs_lcd=%d****\n", (int)abs_ax, (int)abs_lcd);
|
|||
|
scale=(int)(abs_ax/abs_lcd);
|
|||
|
TOUCH_DEBUG_MSG("***scale=%d****4\n",scale);
|
|||
|
if(SCALE_AERROR<scale&&SCALE_DERROR>scale)
|
|||
|
{
|
|||
|
TOUCH_DEBUG_MSG("*** Scale check ok ****\n");
|
|||
|
if(judge_center(cal))
|
|||
|
{
|
|||
|
ret=1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
TOUCH_DEBUG_MSG("*** Failed at judge_center****\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
TOUCH_DEBUG_MSG("*** filter_data ret=%d****\n",ret);
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
static void get_sample (calibration *cal,
|
|||
|
int index, int x, int y, char *name)
|
|||
|
{
|
|||
|
PAN_DATA ts_cord;
|
|||
|
|
|||
|
PutHitCursor(x, y);
|
|||
|
// getxy (ts, &cal->x [index], &cal->y [index]);
|
|||
|
GetTouchHit(&ts_cord);
|
|||
|
cal->x [index] = ts_cord.adcX;
|
|||
|
cal->y [index] = ts_cord.adcY;
|
|||
|
|
|||
|
ClrHitCursor(x, y);
|
|||
|
|
|||
|
cal->xfb [index] = x;
|
|||
|
cal->yfb [index] = y;
|
|||
|
|
|||
|
TOUCH_DEBUG_MSG("get_sample %s : X = %4d Y = %4d\n", name, cal->x [index], cal->y [index]);
|
|||
|
}
|
|||
|
|
|||
|
unsigned int AdjustTouch(void)
|
|||
|
{
|
|||
|
unsigned int i;
|
|||
|
|
|||
|
|
|||
|
#if 0
|
|||
|
cal.a[0]=56822272;
|
|||
|
cal.a[1]=-14948;
|
|||
|
cal.a[2]=36;
|
|||
|
cal.a[3]=38820672;
|
|||
|
cal.a[4]=-59;
|
|||
|
cal.a[5]=-11704;
|
|||
|
cal.a[6]=65536;
|
|||
|
|
|||
|
lg_bTouchAdjusted = 1;
|
|||
|
#else
|
|||
|
while(1)
|
|||
|
{
|
|||
|
get_sample (&cal, 0, 50, 50, "Top left");
|
|||
|
get_sample (&cal, 1, LCD_WIDTH - 50, 50, "Top right");
|
|||
|
get_sample (&cal, 2, LCD_WIDTH - 50, LCD_HEIGHT - 50, "Bot right");
|
|||
|
get_sample (&cal, 3, 50, LCD_HEIGHT - 50, "Bot left");
|
|||
|
get_sample (&cal, 4, LCD_WIDTH / 2, LCD_HEIGHT / 2, "Center");
|
|||
|
|
|||
|
if(filter_data(&cal))
|
|||
|
{
|
|||
|
perform_calibration (&cal);
|
|||
|
for(i=0;i<7;i++)
|
|||
|
{
|
|||
|
printf("the result cal->a[%d]=%d\n", i, cal.a[i]);
|
|||
|
}
|
|||
|
SaveCalibration(&cal);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
lg_bTouchAdjusted = 1;
|
|||
|
|
|||
|
return 0; // 5次均无效, 取默认值
|
|||
|
}
|
|||
|
|
|||
|
int LoadTouchConfigure(void)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|