⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmtouch.c

📁 WM9713 audio codec driver for WinCE 5.0
💻 C
📖 第 1 页 / 共 3 页
字号:
 /*-----------------------------------------------------------------------------
 * 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 2468 2005-11-29 13:03:53Z fb $
 *
 * 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;
    }

    if ( IS_WM9713_FAMILY( hDevice ) )
    {
        /* We need touch => hit extended powerdown register */
        status = WMClearField( hDevice,
                               WM9713_EXT_POWERDOWN_1,
                               WM9713_EXTPWR_AUXADC
                             );
        if ( WM_ERROR( status ) )
        {
            goto error2;
        }
    }

    /* 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,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -