📄 s3c6410_touch.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 2005. Samsung Electronics, co. ltd All rights reserved.
Module Name:
Abstract:
Platform dependent TOUCH initialization functions
rev:
2004.4.27 : S3C2440 port
2005.05.23 : Magneto porting revision
2006.06.29 : S3C2443 port
2007.02.21 : S3C6410 port
Notes:
--*/
#include <bsp.h>
#include <tchddsi.h>
#include "s3c6410_adc_touch_macro.h"
#ifndef DEBUG
DBGPARAM dpCurSettings = {
TEXT("Touch"), {
TEXT("Samples"),TEXT("Calibrate"),TEXT("Stats"),TEXT("Thread"),
TEXT("TipState"),TEXT("Init"),TEXT(""),TEXT(""),
TEXT(""),TEXT("Misc"),TEXT("Delays"),TEXT("Timing"),
TEXT("Alloc"),TEXT("Function"),TEXT("Warning"),TEXT("Error") },
0x8000 // error
};
#endif
//------------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------------
DWORD gIntrTouch = SYSINTR_NOP;
DWORD gIntrTouchChanged = SYSINTR_NOP;
//------------------------------------------------------------------------------
// Local Variables
//------------------------------------------------------------------------------
static volatile S3C6410_GPIO_REG * g_pGPIOReg = NULL;
static volatile S3C6410_ADC_REG * g_pADCReg = NULL;
static volatile S3C6410_VIC_REG * g_pVIC0Reg = NULL;
static volatile S3C6410_VIC_REG * g_pVIC1Reg = NULL;
static volatile S3C6410_PWM_REG * g_pPWMReg = NULL;
static BOOL g_bTSP_Initialized = FALSE;
static BOOL g_bTSP_DownFlag = FALSE;
static int g_TSP_CurRate = 0;
static unsigned int g_SampleTick_High;
static unsigned int g_SampleTick_Low;
static CRITICAL_SECTION g_csTouchADC; // Critical Section for ADC Done
//------------------------------------------------------------------------------
// External Variables
//------------------------------------------------------------------------------
extern "C" const int MIN_CAL_COUNT = 1;
static VOID TSP_VirtualFree(VOID);
static BOOL Touch_Pen_Filtering(int *px, int *py);
static VOID TSP_SampleStop(VOID);
static BOOL
TSP_VirtualAlloc(VOID)
{
BOOL bRet = TRUE;
PHYSICAL_ADDRESS ioPhysicalBase = {0,0};
DEBUGMSG(TSP_ZONE_FUNCTION,(_T("[TSP] ++TSP_VirtualAlloc()\r\n")));
ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_GPIO;
g_pGPIOReg = (S3C6410_GPIO_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_GPIO_REG), FALSE);
if (g_pGPIOReg == NULL)
{
RETAILMSG(TSP_ZONE_ERROR,(_T("[TSP:ERR] TSP_VirtualAlloc() : g_pGPIOReg Allocation Fail\r\n")));
bRet = FALSE;
goto CleanUp;
}
ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_ADC;
g_pADCReg = (S3C6410_ADC_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_ADC_REG), FALSE);
if (g_pADCReg == NULL)
{
RETAILMSG(TSP_ZONE_ERROR,(_T("[TSP:ERR] TSP_VirtualAlloc() : g_pADCReg Allocation Fail\r\n")));
bRet = FALSE;
goto CleanUp;
}
ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_VIC0;
g_pVIC0Reg = (S3C6410_VIC_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_VIC_REG), FALSE);
if (g_pVIC0Reg == NULL)
{
RETAILMSG(TSP_ZONE_ERROR,(_T("[TSP:ERR] TSP_VirtualAlloc() : g_pVIC0Reg Allocation Fail\r\n")));
bRet = FALSE;
goto CleanUp;
}
ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_VIC1;
g_pVIC1Reg = (S3C6410_VIC_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_VIC_REG), FALSE);
if (g_pVIC1Reg == NULL)
{
RETAILMSG(TSP_ZONE_ERROR,(_T("[TSP:ERR] TSP_VirtualAlloc() : g_pVIC1Reg Allocation Fail\r\n")));
bRet = FALSE;
goto CleanUp;
}
ioPhysicalBase.LowPart = S3C6410_BASE_REG_PA_PWM;
g_pPWMReg = (S3C6410_PWM_REG *)MmMapIoSpace(ioPhysicalBase, sizeof(S3C6410_PWM_REG), FALSE);
if (g_pPWMReg == NULL)
{
RETAILMSG(TSP_ZONE_ERROR,(_T("[TSP:ERR] TSP_VirtualAlloc() : g_pPWMReg Allocation Fail\r\n")));
bRet = FALSE;
goto CleanUp;
}
CleanUp:
if (bRet == FALSE)
{
RETAILMSG(TSP_ZONE_ERROR,(_T("[TSP:ERR] TSP_VirtualAlloc() : Failed\r\n")));
TSP_VirtualFree();
}
TSPMSG((_T("[TSP] --TSP_VirtualAlloc() = %d\r\n"), bRet));
return bRet;
}
static VOID
TSP_VirtualFree(VOID)
{
TSPMSG((_T("[TSP] ++TSP_VirtualFree()\r\n")));
if (g_pGPIOReg)
{
MmUnmapIoSpace((PVOID)g_pGPIOReg, sizeof(S3C6410_SYSCON_REG));
g_pGPIOReg = NULL;
}
if (g_pADCReg)
{
MmUnmapIoSpace((PVOID)g_pADCReg, sizeof(S3C6410_ADC_REG));
g_pADCReg = NULL;
}
if (g_pVIC0Reg)
{
MmUnmapIoSpace((PVOID)g_pVIC0Reg, sizeof(S3C6410_VIC_REG));
g_pVIC0Reg = NULL;
}
if (g_pVIC1Reg)
{
MmUnmapIoSpace((PVOID)g_pVIC1Reg, sizeof(S3C6410_VIC_REG));
g_pVIC1Reg = NULL;
}
if (g_pPWMReg)
{
MmUnmapIoSpace((PVOID)g_pPWMReg, sizeof(S3C6410_PWM_REG));
g_pPWMReg = NULL;
}
TSPMSG((_T("[TSP] --TSP_VirtualFree()\r\n")));
}
static VOID
TSP_PowerOn(VOID)
{
TSPMSG((_T("[TSP] ++TSP_PowerOn()\r\n")));
g_pADCReg->ADCDLY = ADC_DELAY(TSP_ADC_DELAY);
g_pADCReg->ADCCON = RESSEL_12BIT | PRESCALER_EN | PRESCALER_VAL(TSP_ADC_PRESCALER) | STDBM_NORMAL;
g_pADCReg->ADCTSC = ADCTSC_WAIT_PENDOWN;
g_pADCReg->ADCCLRINT = CLEAR_ADC_INT;
g_pADCReg->ADCCLRWK = CLEAR_ADCWK_INT;
g_SampleTick_Low = TSP_TIMER_CNT_LOW;
g_SampleTick_High = TSP_TIMER_CNT_HIGH;
// Set Divider MUX for Timer3
SET_TIMER3_DIVIDER_MUX(g_pPWMReg, TSP_TIMER_DIVIDER);
g_pPWMReg->TCNTB3 = g_SampleTick_Low;
// timer3 interrupt disable
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) & ~TIMER3_INTERRUPT_ENABLE;
// timer3 interrupt status clear
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) | TIMER3_PENDING_CLEAR;
TSPMSG((_T("[TSP] --TSP_PowerOn()\r\n")));
}
static VOID
TSP_PowerOff(VOID)
{
TSPMSG((_T("[TSP] ++TSP_PowerOff()\r\n")));
TSP_SampleStop();
// To prevent touch locked after wake up,
// Wait for ADC Done
// Do not turn off ADC before its A/D conversion finished
EnterCriticalSection(&g_csTouchADC);
// ADC Done in TSP_GETXy()..
LeaveCriticalSection(&g_csTouchADC);
g_pADCReg->ADCTSC = UD_SEN_DOWN | YM_SEN_EN | YP_SEN_DIS | XM_SEN_DIS | XP_SEN_DIS | PULL_UP_DIS | AUTO_PST_DIS | XY_PST_NOP;
// ADC Standby Mode, conversion data will be preserved.
g_pADCReg->ADCCON |= STDBM_STANDBY;
TSPMSG((_T("[TSP] --TSP_PowerOff()\r\n")));
}
static VOID
TSP_SampleStart(VOID)
{
// timer3 interrupt status clear, Do not use OR/AND operation on TINTC_CSTAT directly
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) | TIMER3_PENDING_CLEAR;
// timer3 interrupt enable, Do not use OR/AND operation on TINTC_CSTAT directly
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) | TIMER3_INTERRUPT_ENABLE;
STOP_TIMER3(g_pPWMReg);
UPDATE_TCNTB3(g_pPWMReg);
NOUPDATE_TCNTB3(g_pPWMReg);
SET_TIMER3_AUTORELOAD(g_pPWMReg);
START_TIMER3(g_pPWMReg);
}
static VOID
TSP_SampleStop(VOID)
{
STOP_TIMER3(g_pPWMReg);
// timer3 interrupt disable, Do not use OR/AND operation on TINTC_CSTAT directly
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) & ~TIMER3_INTERRUPT_ENABLE;
// timer3 interrupt status clear, Do not use OR/AND operation on TINTC_CSTAT directly
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) | TIMER3_PENDING_CLEAR;
}
static BOOL
TSP_CalibrationPointGet(TPDC_CALIBRATION_POINT *pTCP)
{
int cDisplayWidth, cDisplayHeight;
int CalibrationRadiusX, CalibrationRadiusY;
TSPMSG((_T("[TSP] ++TSP_CalibrationPointGet()\r\n")));
cDisplayWidth = pTCP->cDisplayWidth;
cDisplayHeight = pTCP->cDisplayHeight;
CalibrationRadiusX = cDisplayWidth / 20;
CalibrationRadiusY = cDisplayHeight / 20;
switch (pTCP->PointNumber)
{
case 0:
pTCP->CalibrationX = cDisplayWidth / 2;
pTCP->CalibrationY = cDisplayHeight / 2;
break;
case 1:
pTCP->CalibrationX = CalibrationRadiusX * 2;
pTCP->CalibrationY = CalibrationRadiusY * 2;
break;
case 2:
pTCP->CalibrationX = CalibrationRadiusX * 2;
pTCP->CalibrationY = cDisplayHeight - CalibrationRadiusY * 2;
break;
case 3:
pTCP->CalibrationX = cDisplayWidth - CalibrationRadiusX * 2;
pTCP->CalibrationY = cDisplayHeight - CalibrationRadiusY * 2;
break;
case 4:
pTCP->CalibrationX = cDisplayWidth - CalibrationRadiusX * 2;
pTCP->CalibrationY = CalibrationRadiusY * 2;
break;
default:
pTCP->CalibrationX = cDisplayWidth / 2;
pTCP->CalibrationY = cDisplayHeight / 2;
SetLastError(ERROR_INVALID_PARAMETER);
RETAILMSG(TSP_ZONE_ERROR,(_T("[TSP:ERR] TSP_CalibrationPointGet() : ERROR_INVALID_PARAMETER\r\n")));
return FALSE;
}
TSPMSG((_T("[TSP] --TSP_CalibrationPointGet()\r\n")));
return TRUE;
}
static BOOL
TSP_GetXY(int *px, int *py)
{
int i,j,k;
int temp;
int x[TSP_SAMPLE_NUM], y[TSP_SAMPLE_NUM];
int dx, dy;
int TimeOut = 100; // about 100ms
EnterCriticalSection(&g_csTouchADC);
for (i = 0; i < TSP_SAMPLE_NUM; i++)
{
g_pADCReg->ADCTSC = ADCTSC_AUTO_ADC; // Auto Conversion
g_pADCReg->ADCCON |= ENABLE_START_EN; // ADC Conversion Start
while (g_pADCReg->ADCCON & ENABLE_START_EN)
{ // Wait for Start Bit Cleared
if(TimeOut-- < 0)
{
RETAILMSG(ZONE_ERROR,(TEXT("ADC cannot start\n")));
goto ADCfails;
}
Sleep(1);
}
TimeOut = 100; // about 100ms
while (!(g_pADCReg->ADCCON & ECFLG_END))
{ // Wait for ADC Conversion Ended
if(TimeOut-- < 0)
{
RETAILMSG(ZONE_ERROR,(TEXT("ADC Conversion cannot be done\n")));
goto ADCfails;
}
Sleep(1);
}
x[i] = D_XPDATA_MASK(g_pADCReg->ADCDAT0);
y[i] = D_YPDATA_MASK(g_pADCReg->ADCDAT1);
}
ADCfails:
LeaveCriticalSection(&g_csTouchADC);
for (j = 0; j < TSP_SAMPLE_NUM -1; ++j)
{
for (k = j+1; k < TSP_SAMPLE_NUM; ++k)
{
if(x[j]>x[k])
{
temp = x[j];
x[j]=x[k];
x[k]=temp;
}
if(y[j]>y[k])
{
temp = y[j];
y[j]=y[k];
y[k]=temp;
}
}
}
#ifdef DETAIL_SAMPLING
// 8 samples Interpolation (weighted 4 samples)
*px = (x[2] + ((x[3]+x[4])<<1) + (x[3]+x[4]) + x[5]);
*py = (y[2] + ((y[3]+y[4])<<1) + (y[3]+y[4]) + y[5]);
if ((*px & 0x7) > 3) *px = (*px>>3) + 1;
else *px = *px>>3;
if ((*py & 0x7) > 3) *py = (*py>>3) + 1;
else *py = *py>>3;
dx = x[5] - x[2];
dy = y[5] - y[2];
#else
// 2 samples average
*px = (x[1] + x[2] + 1)>>1;
*py = (y[1] + y[2] + 1)>>1;
dx = x[2] - x[1];
dy = y[2] - y[1];
#endif
if ((dx > TSP_INVALIDLIMIT) || (dy > TSP_INVALIDLIMIT))
{
return FALSE;
}
else
{
return TRUE;
}
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -