📄 wmtouch.c
字号:
/*-----------------------------------------------------------------------------
* Copyright (c) Wolfson Microelectronics plc. All rights reserved.
*
* This software as well as any related documentation is furnished under
* license and may only be used or copied in accordance with the terms of the
* license. The information in this file is furnished for informational use
* only, is subject to change without notice, and should not be construed as
* a commitment by Wolfson Microelectronics plc. Wolfson Microelectronics plc
* assumes no responsibility or liability for any errors or inaccuracies that
* may appear in this document or any software that may be provided in
* association with this document.
*
* Except as permitted by such license, no part of this document may be
* reproduced, stored in a retrieval system, or transmitted in any form or by
* any means without the express written consent of Wolfson Microelectronics plc.
*
* $Id: WMTouch.c 3497 2006-07-28 16:25:36Z marthur $
*
* This file contains platform-independent routines for controlling the touch
* screen operation on Wolfson codecs.
*
* Warning:
* This driver is specifically written for Wolfson Codecs. It is not a
* general CODEC device driver.
*
* -----------------------------------------------------------------------------*/
/*
* IMPORTANT
*
* The functions in this file must obey two rules:
*
* 1. They do not use any memory other than stack space and parameters passed in.
* 2. They do not make system calls, unless WMSystemCallsAllowed returns TRUE.
*
* All functions take a context parameter, which passes in pointers to the virtual
* addresses of memory-mapped registers, and stores what type of device is being
* accessed.
*
* Some client functions provide shared memory via the v_pWMData member of the
* context structure. This cannot be relied on. However, the v_pADCData member
* can be relied on by functions in this file.
*/
/*
* This file offers both raw and averaged touch points. The averaged touch
* points are calculated as follows.
*
* We keep a buffer of the last WM_NUM_SAMPLES_PER_POINT points. For each of
* these points we maintain a matches field which is a bitfield indicating
* which of the other points are within range. If any points are in range
* this bitfield will be non-zero and we will use the point in the average.
* If no points are in range, the bitfield will be zero and we will ignore
* that point.
*
* For example, given p1(142,731), p2(151,729), p3(334,734), p4(148,750) and a
* threshold of 20, the matches flags will be:
*
* p1.x p1.y p1 p2.x p2.y p2 p3.x p3.y p3 p4.x p4.y p4 matches (binary)
* p1: - - no 9=y 2=y yes 192=n 3=y no 6=y 19=y yes 1010 yes
* p2: 9=y 2=y yes - - no 183=n 5=y no 3=y 21=n no 0001 yes
* p3:192=n 3=y no 183=n 5=y no - - no 186=n 16=y no 0000 no
* p4: 6=y 19=y yes 3=y 21=n no 186=n 16=y no - - no 1000 yes
*
* So points p1, p2 and p4 are valid because they're in range of at least one
* other point. We then take the average:
*
* p.x = (p1.x + p2.x + p4.x ) / 3 = 147
* p.y = (p1.y + p2.y + p4.y ) / 3 = 736
*
* When we take the next reading, we replace p1 with the new reading (it's a
* circular buffer, remember) and recompare all points against p1. If p1 is
* (162,761) we get:
* [new]
* p1.x p1.y p1 p2.x p2.y p2 p3.x p3.y p3 p4.x p4.y p4 matches (binary)
* p1: - - no 11=y 32=n no 172=n 27=n no 14=y 11=y yes 1000 yes
* p2: 11=y 32=n no - - no 183=n 5=y no 3=y 21=n no 0000 yes
* p3:172=n 27=n no 183=n 5=y no - - no 186=n 16=y no 0000 no
* p4: 14=y 11=y yes 3=y 21=n no 186=n 16=y no - - no 0001 yes
*
* So points p1 and p4 are valid because they're in range of at least one
* other point. We then take the average:
*
* p.x = (p1.x + p4.x ) / 2 = 155
* p.y = (p1.y + p4.y ) / 2 = 755
*
* And so it continues.
*/
/*
* Include files
*/
#include "WMCommon.h"
#include "WMGlobals.h"
#include "WMControlLink.h"
#include "WMTouch.h"
#include "WMAuxADC.h"
#include "WMPlatformACLink.h"
#include "WMInterrupts.h"
#include "WMDevice.h"
#include "WMPower.h"
#include "WMGPIO.h"
/*
* Only build this if we're doing Touch support.
*/
#if WM_TOUCH
/*
* Global definitions
*/
/*
* Private data
*/
/*
* Function prototypes
*/
static void private_ResetHistory( WM_DEVICE_HANDLE hDevice );
static WMSTATUS private_FillHistoryBuffer( WM_DEVICE_HANDLE hDevice );
static void private_AddHistoryPoint( WM_DEVICE_HANDLE hDevice,
const WM_TOUCH_POINT *pPoint
);
static WMSTATUS private_GetAveragedCoordinates( WM_DEVICE_HANDLE hDevice,
WM_REGVAL *pXCoord,
WM_REGVAL *pYCoord
);
static WM_BOOL private_IsPenDebouncing( WM_DEVICE_HANDLE hDevice );
/*-----------------------------------------------------------------------------
* Function: WMTouchInit
*
* Initialises the touch functionality.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMTouchInit( WM_DEVICE_HANDLE hDevice )
{
WMSTATUS status = WMS_UNSUPPORTED;
WM_DEVICE_CONTEXT *pDeviceContext = WMHANDLE_TO_DEVICE( hDevice );
WM_ASSERT( hDevice, NULL != pDeviceContext );
if ( pDeviceContext->fnTouchInit )
{
status = pDeviceContext->fnTouchInit( hDevice );
}
return status;
}
/*-----------------------------------------------------------------------------
* Function: WM97TouchInit
*
* Initialises the touch functionality.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WM97TouchInit( WM_DEVICE_HANDLE hDevice )
{
WMSTATUS status;
WM_REGVAL digitiserSetup = 0;
/* Initialise the ADC layer */
status = WMAuxADCInit( hDevice );
if ( WM_ERROR( status ) )
{
goto error0;
}
/* Make sure the device is powered up enough for us */
status = WMTouchPowerUp( hDevice, WM_POWER_PEN_DETECT );
if ( WM_ERROR( status ) )
{
goto error1;
}
/* Only 9705, 9712 & 9713 have touch functionality */
if ( !WM_IS_TOUCH_SUPPORTED( hDevice ) )
{
WM_TRACE( hDevice,
("WM97TouchInit: There is no Touch "
"Screen Support for this Wolfson Device! 0x%X",
WM_DEVICE_TYPE( hDevice )
));
goto error2;
}
/*
* Read the current value in DIGITISER_SETUP.
*/
status = WMRead( hDevice, WM97_DIGITISER_SETUP, &digitiserSetup );
if ( WM_ERROR( status ) )
{
goto error2;
}
/* Set up the Pendown GPIO on WM9712 and WM9713 */
if ( IS_WM9712_FAMILY( hDevice ) || IS_WM9713_FAMILY( hDevice ) )
{
/* 4- or 5-wire */
#if WM97_TOUCH_5WIRE
digitiserSetup |= WM9712_13_TOUCHSETUP_5WIRE;
#else
digitiserSetup &= ~WM9712_13_TOUCHSETUP_5WIRE;
#endif
#if !WM_USE_VIRTUAL_PENDOWN
#if WM_PENIRQ_INVERTED
/* We also need to invert the pendown signal so it is active low */
digitiserSetup |= WM9713_PENDOWN_INVERT;
#endif /* WM_PENIRQ_INVERTED */
/*
* Configure alternate function for GPIO as pen down.
*/
status = WMGPIOEnableAlternateFunction( hDevice,
WM_PENDOWN_GPIO( hDevice ),
TRUE
);
if ( WM_ERROR( status ) )
{
WM_TRACE( hDevice, (
"WM97TouchInit : WMGPIOEnableAlternateFunction failed: 0%s",
WMStatusText( status ) ) );
goto error2;
}
#endif /* !WM_USE_VIRTUAL_PENDOWN */
}
/*
* Set the pen-detect sensitivity.
*/
if ( !IS_WM9705_FAMILY( hDevice ) )
{
WM_ASSERT( hDevice, 0 < WM_TOUCH_PEN_SENSITIVITY );
WM_ASSERT( hDevice,
WM_TOUCH_PEN_SENSITIVITY ==
(WM_TOUCH_PEN_SENSITIVITY & WM9712_13_TOUCHSETUP_RPU_MASK)
);
digitiserSetup &= ~WM9712_13_TOUCHSETUP_RPU_MASK;
digitiserSetup |= WM_TOUCH_PEN_SENSITIVITY;
}
#if WM_TOUCH_CAPS
if ( IS_WM9705_FAMILY( hDevice ) )
{
digitiserSetup |= WM97_TOUCHSETUP_PDD_7;
}
#endif /* WM_TOUCH_CAPS */
/*
* Now write the values we've built up.
* Note we set up DIGITISER_SETUP when we start reading from
* an ADC so we don't need to do it here.
*/
status = WMWrite( hDevice,
WM97_DIGITISER_SETUP,
digitiserSetup
);
if ( WM_ERROR( status ) )
{
WM_TRACE( hDevice, (
"WM97TouchInit : WMWrite failed: %s",
WMStatusText( status ) ) );
goto error2;
}
return WMS_SUCCESS;
error2:
WMTouchPowerDown( hDevice, WM_POWER_TOUCH );
error1:
WMAuxADCShutdown( hDevice );
error0:
return status;
}
/*-----------------------------------------------------------------------------
* Function: WMTouchShutdown
*
* Shuts down the touch functionality.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: void
*---------------------------------------------------------------------------*/
void WMTouchShutdown( WM_DEVICE_HANDLE hDevice )
{
WMTouchPowerDown( hDevice, WM_POWER_TOUCH );
WMAuxADCShutdown( hDevice );
WMLinkShutdown( hDevice, WM_DRIVER_TOUCH );
}
/*-----------------------------------------------------------------------------
* Function: WMTouchPowerUp
*
* Called to power up the touch-specific sections of the chip.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* powerSections The sections to power up.
*
* Returns: WMSTATUS
* See WMStatus.h.
*---------------------------------------------------------------------------*/
WMSTATUS WMTouchPowerUp( WM_DEVICE_HANDLE hDevice,
WM_POWERFLAG powerSections
)
{
WMSTATUS status;
/* Check we've got AUX ADC */
if ( !WM_IS_AUXADC_SUPPORTED( hDevice ) )
{
status = WMS_UNSUPPORTED;
goto error;
}
/* Power up the relevant sections of the chip */
status = WMPowerUp( hDevice,
WM_DRIVER_TOUCH,
powerSections
);
if ( WM_ERROR( status ) )
{
goto error;
}
/* Set up the GPIOs */
status = WMPlatformConfigureTouchGPIO( hDevice );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -