📄 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 (Hoyjoon Kim)
2005.05.23 : Magneto porting revision (junkim)
2006.06.29 : S3C2443 port(JJG)
2007.02.21 : S3C6410 port (dodan2)
Notes:
--*/
#include <bsp.h>
#include <DrvLib.h>
#include <tchddsi.h>
#include "s3c6410_adc_touch_macro.h"
#ifdef REMOVE_BEFORE_RELEASE
#define TSPMSG(x)
#define TSPINF(x)
#define TSPERR(x) RETAILMSG(TRUE, x)
#else
//#define TSPMSG(x) RETAILMSG(TRUE, x)
#define TSPMSG(x)
#define TSPINF(x) RETAILMSG(TRUE, x)
//#define TSPINF(...)
#define TSPERR(x) RETAILMSG(TRUE, x)
//#define TSPERR(...)
#endif
#define DETAIL_SAMPLING
#define NEW_FILTER_SCHEME
#define TSP_ADC_DELAY (10000) // 40000
#define TSP_ADC_PRESCALER (24) // 49 // 200
#define TSP_SAMPLE_RATE_LOW (50) // 50 Samples per Sec
#define TSP_SAMPLE_RATE_HIGH (100) // 100 Samples per Sec
#define TSP_TIMER_DIVIDER (1)
#define TSP_TIMER_CNT_LOW (S3C6410_PCLK/SYS_TIMER_PRESCALER/TSP_TIMER_DIVIDER/TSP_SAMPLE_RATE_LOW-1)
#define TSP_TIMER_CNT_HIGH (S3C6410_PCLK/SYS_TIMER_PRESCALER/TSP_TIMER_DIVIDER/TSP_SAMPLE_RATE_HIGH-1)
#define TSP_INVALIDLIMIT (40)
#ifdef NEW_FILTER_SCHEME
#define TSP_FILTER_LIMIT (3)
#else
#define TSP_FILTER_LIMIT (25)
#endif
#ifdef DETAIL_SAMPLING
#define TSP_SAMPLE_NUM (8)
#else
#define TSP_SAMPLE_NUM (4)
#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;
TSPMSG((_T("[TSP] ++TSP_VirtualAlloc()\r\n")));
g_pGPIOReg = (S3C6410_GPIO_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_GPIO, sizeof(S3C6410_GPIO_REG), FALSE);
if (g_pGPIOReg == NULL)
{
TSPERR((_T("[TSP:ERR] TSP_VirtualAlloc() : g_pGPIOReg Allocation Fail\r\n")));
bRet = FALSE;
goto CleanUp;
}
g_pADCReg = (S3C6410_ADC_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_ADC, sizeof(S3C6410_ADC_REG), FALSE);
if (g_pADCReg == NULL)
{
TSPERR((_T("[TSP:ERR] TSP_VirtualAlloc() : g_pADCReg Allocation Fail\r\n")));
bRet = FALSE;
goto CleanUp;
}
g_pVIC0Reg = (S3C6410_VIC_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_VIC0, sizeof(S3C6410_VIC_REG), FALSE);
if (g_pVIC0Reg == NULL)
{
TSPERR((_T("[TSP:ERR] TSP_VirtualAlloc() : g_pVIC0Reg Allocation Fail\r\n")));
bRet = FALSE;
goto CleanUp;
}
g_pVIC1Reg = (S3C6410_VIC_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_VIC1, sizeof(S3C6410_VIC_REG), FALSE);
if (g_pVIC1Reg == NULL)
{
TSPERR((_T("[TSP:ERR] TSP_VirtualAlloc() : g_pVIC1Reg Allocation Fail\r\n")));
bRet = FALSE;
goto CleanUp;
}
g_pPWMReg = (S3C6410_PWM_REG *)DrvLib_MapIoSpace(S3C6410_BASE_REG_PA_PWM, sizeof(S3C6410_PWM_REG), FALSE);
if (g_pPWMReg == NULL)
{
TSPERR((_T("[TSP:ERR] TSP_VirtualAlloc() : g_pPWMReg Allocation Fail\r\n")));
bRet = FALSE;
goto CleanUp;
}
CleanUp:
if (bRet == FALSE)
{
TSPERR((_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)
{
DrvLib_UnmapIoSpace((PVOID)g_pGPIOReg);
g_pGPIOReg = NULL;
}
if (g_pADCReg)
{
DrvLib_UnmapIoSpace((PVOID)g_pADCReg);
g_pADCReg = NULL;
}
if (g_pVIC0Reg)
{
DrvLib_UnmapIoSpace((PVOID)g_pVIC0Reg);
g_pVIC0Reg = NULL;
}
if (g_pVIC1Reg)
{
DrvLib_UnmapIoSpace((PVOID)g_pVIC1Reg);
g_pVIC1Reg = NULL;
}
if (g_pPWMReg)
{
DrvLib_UnmapIoSpace((PVOID)g_pPWMReg);
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);
#if (CPU_NAME == S3C6410)
g_pADCReg->ADCCON = RESSEL_12BIT | PRESCALER_EN | PRESCALER_VAL(TSP_ADC_PRESCALER);
#elif (CPU_NAME == S3C6400)
g_pADCReg->ADCCON = PRESCALER_EN | PRESCALER_VAL(TSP_ADC_PRESCALER);
#endif // add by shin.0322
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
switch(TSP_TIMER_DIVIDER)
{
case 1:
g_pPWMReg->TCFG1 = (g_pPWMReg->TCFG1 & ~(0xf<<12)) | (0<<12);
break;
case 2:
g_pPWMReg->TCFG1 = (g_pPWMReg->TCFG1 & ~(0xf<<12)) | (1<<12);
break;
case 4:
g_pPWMReg->TCFG1 = (g_pPWMReg->TCFG1 & ~(0xf<<12)) | (2<<12);
break;
case 8:
g_pPWMReg->TCFG1 = (g_pPWMReg->TCFG1 & ~(0xf<<12)) | (3<<12);
break;
case 16:
g_pPWMReg->TCFG1 = (g_pPWMReg->TCFG1 & ~(0xf<<12)) | (4<<12);
break;
default:
g_pPWMReg->TCFG1 = (g_pPWMReg->TCFG1 & ~(0xf<<12)) | (0<<12);
break;
}
g_pPWMReg->TCNTB3 = g_SampleTick_Low;
// timer3 interrupt disable
//g_pPWMReg->TINT_CSTAT &= ~(1<<3); // Do not use OR/AND operation on TINTC_CSTAT
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) & ~TIMER3_INTERRUPT_ENABLE;
// timer3 interrupt status clear
//g_pPWMReg->TINT_CSTAT |= (1<<8); // Do not use OR/AND operation on TINTC_CSTAT
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..
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;
TSPMSG((_T("[TSP] --TSP_PowerOff()\r\n")));
}
static VOID
TSP_SampleStart(VOID)
{
//TSPMSG((_T("[TSP] ++TSP_SampleStart()\r\n")));
// timer3 interrupt status clear
//g_pPWMReg->TINT_CSTAT |= (1<<8); // Do not use OR/AND operation on TINTC_CSTAT
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) | TIMER3_PENDING_CLEAR;
// timer3 interrupt enable
//g_pPWMReg->TINT_CSTAT |= (1<<3); // Do not use OR/AND operation on TINTC_CSTAT
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) | TIMER3_INTERRUPT_ENABLE;
g_pPWMReg->TCON &= ~(0xf<<16); // Timer3 Stop
g_pPWMReg->TCON |= (1<<17); // update TCNTB3
g_pPWMReg->TCON &= ~(1<<17);
g_pPWMReg->TCON |= ((1<<19)|(1<<16)); // AutoReload mode, Timer3 Start
//TSPMSG((_T("[TSP] --TSP_SampleStart()\r\n")));
}
static VOID
TSP_SampleStop(VOID)
{
//TSPMSG((_T("[TSP] ++TSP_SampleStop()\r\n")));
g_pPWMReg->TCON &= ~(0xf<<16); // Timer3 stop
// timer3 interrupt disable
//g_pPWMReg->TINT_CSTAT &= ~(1<<3); // Do not use OR/AND operation on TINTC_CSTAT
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) & ~TIMER3_INTERRUPT_ENABLE;
// timer3 interrupt status clear
//g_pPWMReg->TINT_CSTAT |= (1<<8); // Do not use OR/AND operation on TINTC_CSTAT
g_pPWMReg->TINT_CSTAT = TINT_CSTAT_INTMASK(g_pPWMReg->TINT_CSTAT) | TIMER3_PENDING_CLEAR;
//TSPMSG((_T("[TSP] --TSP_SampleStop()\r\n")));
}
static BOOL
TSP_CalibrationPointGet(TPDC_CALIBRATION_POINT *pTCP)
{
int cDisplayWidth, cDisplayHeight;
int CalibrationRadiusX, CalibrationRadiusY;
TSPMSG((_T("[TSP] ++TSP_CalibrationPointGet()\r\n")));
#if(LCD_TYPE==LCD_TYPE_LANDSCAPE)
cDisplayWidth = pTCP->cDisplayHeight;
cDisplayHeight = pTCP->cDisplayWidth;
#elif (LCD_TYPE==LCD_TYPE_PORTRAIT)
cDisplayWidth = pTCP->cDisplayWidth;
cDisplayHeight = pTCP->cDisplayHeight;
#else
#error LCD_TYPE_UNDEFINED_ERROR
#endif
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);
TSPERR((_T("[TSP:ERR] TSP_CalibrationPointGet() : ERROR_INVALID_PARAMETER\r\n")));
return FALSE;
}
#if(LCD_TYPE==LCD_TYPE_LANDSCAPE)
int orig_x = pTCP->CalibrationX;
int orig_y = pTCP->CalibrationY;
pTCP->CalibrationX = orig_y;
pTCP->CalibrationY = cDisplayWidth - orig_x - 1;
#endif
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;
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
Sleep(1);
}
while (!(g_pADCReg->ADCCON & ECFLG_END))
{ // Wait for ADC Conversion Ended
Sleep(1);
}
x[i] = D_XPDATA_MASK(g_pADCReg->ADCDAT0);
y[i] = D_YPDATA_MASK(g_pADCReg->ADCDAT1);
}
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -