zoukankan      html  css  js  c++  java
  • 2440 5.0BSP触摸屏驱动学习(作者:wogoyixikexie@gliet)

    2440 5.0BSP触摸屏驱动学习(作者:wogoyixikexie@gliet)

    //-----------------------------------------------------------------------------------------------------------

    // 日期:2009年3月14日11:49:48

    // 作者:wogoyixikexie@gliet

    // 版权:桂林电子科技大学一系科协wogoyixikexie@gliet

    // 最后修改:2009年3月17日10:20:39

    //-----------------------------------------------------------------------------------------------------------     

         以前曾经看过一下子触摸屏驱动,但是那时候火候不到,现在老大叫我看,并且写一篇博客,现在我就边看边写吧。

         曾经在nasiry看到touch.dll是这样生成的。

    touch.dll生成过程
    有意思的是tchmdd.lib则比较特殊,在OAK的lib文件夹中居然找不到这个文件,而在项目文件的OAK目录下该文件确是存在的,也就是说该文件在CESYSGEN的过程中产生。根据该链接库提供的接口来看,可以猜测该lib应当由另外几个零散的lib组成,这些链接库的source文件夹在OAK\COMMON\Drivers\Touch目录下。后来在PUBLIC\COMMON\CESYSGEN下的makefile文件内找到如下内容

    tchmdd::

            @set TARGETTYPE=LIBRARY

            @set TARGETNAME=$@

            @set RELEASETYPE=OAK

            @set TARGETLIBS=

    !IFDEF SYSGEN_TRANSCRIBER

            @set SOURCELIBS=$(SG_INPUT_LIB)\tchmain.lib $(SG_INPUT_LIB)\tch_trns.lib

            echo touch includes transcriber hooks

    !ELSE

            @set SOURCELIBS=$(SG_INPUT_LIB)\tchmain.lib $(SG_INPUT_LIB)\tchbasic.lib

            echo touch is minimal

    !ENDIF

    确定了Tchmdd.lib的内容就是tchmain.lib+ tch_trns.lib或tchbasic.lib.因为tchmdd需要通过专门的Nmake指令完成生成的动作,所以在Touch驱动目录下都会有一个bat文件用于产生tchmdd.lib文件用于后面的链接库。

    之所以需要将tchmdd.lib设定为这种方式生成,而不直接产生可以猜测为不同的编译条件下DDI的接口不同(见第一部分),所以通过这里来选择不同的DDI接口实现。

    这样一来Touch驱动就分成两种不同的类型了:

    1.       不使用扩展DDI接口的Touch驱动

    2.       在TRANSCRIBER编译条件下产生的带扩展的Touch驱动。

         哈哈,现在看看我的2440 touch到底用了什么代码,首先找到TOUCH.def文件,内容如下:

    LIBRARY  TOUCH

    EXPORTS
     STDAPI(TouchPanelGetDeviceCaps, 8);
     STDAPI(TouchPanelEnable,4);
     STDAPI(TouchPanelDisable,0);
     STDAPI(TouchPanelSetMode, 8);
     STDAPI(TouchPanelReadCalibrationPoint, 8);
     STDAPI(TouchPanelReadCalibrationAbort, 0);
     STDAPI(TouchPanelSetCalibration, 20);
     STDAPI(TouchPanelCalibrateAPoint, 16);
     STDAPI(TouchPanelPowerHandler, 4);
    ; @CESYSGEN IF WCESHELLFE_MODULES_MSTRANSCRIBER || SHELLW_MODULES_TRANSCRIBER
     TouchReset
     TouchRegisterWindow
     TouchUnregisterWindow
     TouchSetValue
     TouchGetValue
     TouchCreateEvent
     TouchGetFocusWnd
     TouchGetLastTouchFocusWnd
     TouchGetQueuePtr
    ; @CESYSGEN ENDIF 

         很明显,这个DEF文件也受控制了,现在使用dumbin看看touch.dll到底导出了什么函数就可以知道用了什么库了。

         由此可以看出,触摸屏驱动使用了非扩展方案。现在开始分析代码。

         MDD层:

         1.TouchPanelEnable

         该函数首先调用TouchPanelpAttach函数,(在TouchPanelpAttach里面又调用和坐标校正相关的TouchPanelSetCalibration函数);DdsiTouchPanelEnable(在PDD中实现)以及初始化触摸屏驱动的按下弹起、滑动两个线程。

         2.TouchPanelDisable

         该函数调用DdsiTouchPanelDisable(PDD实现——释放触摸屏驱动占用的队内存以及禁止pen up/down中断)以及SetEvent一些事件。

         3.TouchPanelGetDeviceCaps

         该函数为DDI接口函数。用于查询触摸屏设备支持的具体功能。

    调用到的DDSI函数为

    DdsiTouchPanelGetDeviceCaps

    该函数动作为

    (1).       通过DDSI函数查询相应的信息

    (2).       当查询屏幕坐标信息时保存屏幕信息,供后面程序映射屏幕坐标

    4.TouchPanelSetMode

    该函数根据switch语句设置一些优先级采样相关的东西

     5.TouchPanelReadCalibrationPoint

    该函数主要是读入Common.reg的注册表,但是我对这个注册表的作用还不是很明白。——了解的告知小弟一声。

    [HKEY_LOCAL_MACHINE\SYSTEM\GWE]
        "ActivityEvent"="PowerManager/ActivityTimer/UserActivity"

    dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"System\\GWE", 0, 0, &hk);

    dwStatus = RegQueryValueEx(hk, L"ActivityEvent", NULL, &dwType, (LPBYTE) szEventPath, &dwSize);

    hevActivity = OpenEvent(EVENT_ALL_ACCESS, FALSE, szEventPath);——不理解的是这里了。

     6.TouchPanelReadCalibrationAbort

       该函数在效验取消的时候被调用。仅仅设置状态位和事件后返回。

       

       7.  TouchPanelSetCalibration

       该函数是校准相关的东西,我的数学太烂了,看了代码不知道怎么回事。现在暂时放弃,以后有空再研究了。

       8.TouchPanelCalibrateAPoint

       该函数用于校正坐标,使用的公式貌似是最小二乘法,数学忘记了,真是后悔以前没有学好。就贴个代码吧。

         最后一个MDD函数 TouchPanelPowerHandler

         该函数调用PDD的DdsiTouchPanelPowerHandler函数实现功能。

         PDD层:

         一、TSP_VirtualFree(VOID); TSP_VirtualAlloc(VOID);

         上面两个函数分别是释放和获得wince系统的堆内存

         二、TSP_SampleStart

         采样开始,利用PWM定时器3

         三、TSP_SampleStop

         停止采样,关闭定时器

         四、TSP_PowerOn

         该函数初始化AD、定时器,以及消除INT_TC Touch screen interrupt屏蔽

         五、TSP_PowerOff

         屏蔽INT_TC Touch screen interrupt

         六、TSP_CalibrationPointGet

         该函数是用来计算五个点的校正坐标的,我们在校正笔针的时候会调用到这个函数

         七、TSP_TransXY

         该函数为作比较转换函数,被DdsiTouchPanelGetPoint函数调用。对于里面的写法我不懂,TSP_MINXTSP_MINy的值到底是根据什么来取的?我记得触摸屏驱动和LCD大小是无关的,以前我修改屏幕不同的LCD驱动的时候并没有修改触摸屏就可以用了,这个值到底是怎么搞的呢?也没有相关资料说明真是难以理解的。

         八、TSP_GetXY

         该函数是读入的X、Y坐标AD值,这个值是连续采样四次(如果要精准,估计加大采样次数即可);被DdsiTouchPanelGetPoint调用

         九、DdsiTouchPanelGetDeviceCaps

         该函数是一些触摸屏参数设置,采样率等;还有就是点号,校正点的坐标计算等。

         十、DdsiTouchPanelSetMode

         参数设置

         十一、DdsiTouchPanelEnable

         该函数用来申请触摸屏用到相关两个中断,不过它的一些写法让人有点费解Irq[0]=-1;Irq[1]=OAL_INTR_FORCE_STATIC;Irq[2]=IRQ_ADC;不知道它为何要这样写。

         十二、DdsiTouchPanelDisable

         该函数释放对内存等资源。

         十三、DdsiTouchPanelAttachDdsiTouchPanelDetach

         两函数没有任何动作。

         十四、DdsiTouchPanelPowerHandler

         根绝条件是执行TSP_PowerOffTSP_PowerOn

         十五、DdsiTouchPanelGetPoint

         两个中断的线程函数,被TouchPanelpISR函数调用——TouchPanelpISR是在TouchPanelEnable函数创建的线程

    补充:

         (1)触摸屏中断申请

         我感觉触摸屏的中断有点奇怪,首次看到这样的写法。(触摸屏的两个中断是绑定同一个线程的,是个经典例子)

          // Obtain sysintr values from the OAL for the touch and touch changed interrupts.
        //
     RETAILMSG(0, (TEXT("enable touch sysintr.\r\n")));
        Irq[0]=-1;Irq[1]=OAL_INTR_FORCE_STATIC;Irq[2]=IRQ_ADC;
        if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof(Irq), &gIntrTouch, sizeof(UINT32), NULL))
        {
            RETAILMSG(1, (TEXT("ERROR: Failed to request the touch sysintr.\r\n")));
            gIntrTouch = SYSINTR_UNDEFINED;
            return(FALSE);
        }
        Irq[0]=-1;Irq[1]=OAL_INTR_FORCE_STATIC;Irq[2]=IRQ_TIMER3;
        if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &Irq, sizeof(Irq), &gIntrTouchChanged, sizeof(UINT32), NULL))
        {
            RETAILMSG(1, (TEXT("ERROR: Failed to request the touch changed sysintr.\r\n")));
            gIntrTouchChanged = SYSINTR_UNDEFINED;
            return(FALSE);
        }

         KernelIoControl的第二个参数是指向一个buf的指针,IRQ数组是如何得到处理的呢?在OALIntrRequestSysIntr函数中有

    if (
            g_oalIrq2SysIntr[irq] == SYSINTR_UNDEFINED ||
            (flags & OAL_INTR_FORCE_STATIC) != 0
        ) {
            g_oalIrq2SysIntr[irq] = sysIntr;
        }

         以前看OALIntrRequestSysIntr都只是看函数名称,没有看它带的参数,现在要好好看看

    UINT32 OALIntrRequestSysIntr(UINT32 count, const UINT32 *pIrqs, UINT32 flags)
    count *pIrqs  flags都有它的作用。

         后来在CSDN请教LinHanLao前辈,得到了满意的回复:

    aIrqs[0] = -1;

    // Using -1 indicates we are not using the legacy calling convention. 

         关于OAL_INTR_FORCE_STATIC的详细解释在PB帮助文档有说明。

         (2)触摸屏中断线程

         触摸屏涉及两个中断,一个是按下,弹起笔针,另外一个是笔针滑动中断;他们分别是由INT_TC和Timer3实现的。非常有趣的是这两个中断绑定同一个线程(在CSDN有人问过,现在终于亲自看到了(*^__^*) 嘻嘻……),任何一个中断产生都能启动线程。

         弹起、按下笔针中断很容易理解,但是这个滑动却是比较牛,在产生按下动作之后,是通过定时器采样,然后计算亮点的差值来做的,不过我对笔针的框选动作始终不理解,还有触摸屏驱动是如何被应用程序调用的呢?我们如何自己写校验算法呢?毕竟他不是流驱动。以后到CSDN发帖求助吧,这篇博客完之前贴一下它的中断的关键代码。

      

    /* :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */
    /* :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */

    PUBLIC VOID
    DdsiTouchPanelGetPoint(TOUCH_PANEL_SAMPLE_FLAGS * pTipStateFlags,
            INT * pUncalX,
            INT * pUncalY)
    {
     static INT x, y;
     //INT_TC Touch screen interrupt (pen up/down) INT_ADC
     if (v_pINTregs->SUBSRCPND & (1<<IRQ_SUB_TC))  /* SYSINTR_TOUCH Interrupt Case*/
     {
      *pTipStateFlags = TouchSampleValidFlag;

      if ( (v_pADCregs->ADCDAT0 & (1 << 15)) |
        (v_pADCregs->ADCDAT1 & (1 << 15)) )
      {
       bTSP_DownFlag = FALSE;

       DEBUGMSG(ZONE_TIPSTATE, (TEXT("up\r\n")));

       v_pADCregs->ADCTSC &= 0xff;

       *pUncalX = x;
       *pUncalY = y;

       TSP_SampleStop();
      }
      else
      {
       bTSP_DownFlag = TRUE;

       if (!TSP_GetXY(&x, &y))
        *pTipStateFlags = TouchSampleIgnore;

       TSP_TransXY(&x, &y);

       *pUncalX = x;
       *pUncalY = y;

       *pTipStateFlags |= TouchSampleDownFlag;

       //DEBUGMSG(ZONE_TIPSTATE, (TEXT("down %x %x\r\n"), x, y));

       TSP_SampleStart();
      }

      v_pINTregs->SUBSRCPND  =  (1<<IRQ_SUB_TC);
      v_pINTregs->INTSUBMSK &= ~(1<<IRQ_SUB_TC);

      InterruptDone(gIntrTouch);
     }
     else  /* SYSINTR_TOUCH_CHANGED Interrupt Case  */
     {
    //  TSP_SampleStart();
      
      if (bTSP_DownFlag)
      {
       INT  tx, ty;
       INT  dx, dy;

       if (!TSP_GetXY(&tx, &ty))
        *pTipStateFlags = TouchSampleIgnore;
       else
       {
        TSP_TransXY(&tx, &ty);
    // insert by mostek@dstcorp.com
    #define X_ERRV 0x3bf
    #define Y_ERRV 0x4ff

        if ((tx == X_ERRV) && (ty == Y_ERRV))//差值界定
        {
         tx = x;
         ty = y;
        }
    // ========求两点间的差值=========== mostek
        dx = (tx > x) ? (tx - x) : (x - tx);
        dy = (ty > y) ? (ty - y) : (y - ty);

        if (dx > TSP_CHANGE || dy > TSP_CHANGE)
        {
         *pUncalX = x = tx;
         *pUncalY = y = ty;

         //DEBUGMSG(ZONE_TIPSTATE, (TEXT("down-c-v %x %x\r\n"), x, y));
         *pTipStateFlags = TouchSampleValidFlag | TouchSampleDownFlag;
        }
        else
        {
         *pUncalX = x;
         *pUncalY = y;

         DEBUGMSG(ZONE_TIPSTATE, (TEXT("down-c %x %x\r\n"), x, y));

         *pTipStateFlags = TouchSampleIgnore;
        }
       }
      }
      else
      {
       *pTipStateFlags = TouchSampleIgnore;

       TSP_SampleStop();
      }

      InterruptDone(gIntrTouchChanged);
     }
    }


     


     

    相关文章参考:http://topic.csdn.net/u/20081215/16/3ae65482-c8ea-4e09-a725-89a9255eb60f.html

                        http://blog.csdn.net/gooogleman/archive/2009/03/14/3990238.aspx


    /*++

    Routine Description:

        Convert uncalibrated points to calibrated points.


    Autodoc Information:

        @doc INTERNAL DRIVERS MDD TOUCH_DRIVER
        @func VOID | TouchPanelCalibrateAPoint |
        Convert uncalibrated points to calibrated points.

        @comm
        The transform coefficients are already in vCalcParam.<nl>


        @devnote
        Note that there is a *4 hiding in the calculations of X and
        Y.  This is a means of providing sub-pixel accuracy to GWE,
        which will theoretically help improve accuracy in inking. It
        would be nice if this multiplier were defined in a .h file
        by gwe, but it isn't.  So make very sure that this value
        agrees with the divisor used by gwe in touch.cpp.
    --*/


    void
    TouchPanelCalibrateAPoint(
        INT32   UncalX,     //@PARM The uncalibrated X coordinate
        INT32   UncalY,     //@PARM The uncalibrated Y coordinate
        INT32   *pCalX,     //@PARM The calibrated X coordinate
        INT32   *pCalY      //@PARM The calibrated Y coordinate
        )
    {
        INT32   x, y;

        if ( !v_Calibrated ){
            *pCalX = UncalX;
            *pCalY = UncalY;
            return;
        }
         //
         // Note the *4 in the expression below.  This is a kludge
         // perpetrated on behalf of gwe.  It provides a form of
         // sub-pixel accuracy desirable for inking
         //
        x = (v_CalcParam.a1 * UncalX + v_CalcParam.b1 * UncalY +
             v_CalcParam.c1) * 4 / v_CalcParam.delta;
        y = (v_CalcParam.a2 * UncalX + v_CalcParam.b2 * UncalY +
             v_CalcParam.c2) * 4 / v_CalcParam.delta;
        if ( x < 0 ){
            x = 0;
        }

        if ( y < 0 ){
            y = 0;
        }

        *pCalX = x;
        *pCalY = y;
    }

  • 相关阅读:
    import cv2出现“ImportError: DLL load failed: 找不到指定的模块”
    Ubuntu 18.04 安装MySQL
    在Pycharm中自动添加时间日期作者等信息
    Ubuntu18.04安装Python虚拟环境
    Windows10远程报错:由于CredSSP加密Oracle修正
    Ubuntu 18.04LTS 更新镜像配置
    jetbrains的JetBrains PyCharm 2018.3.1破解激活到2100年(最新亲测可用)
    解决爬虫中遇到的js加密问题之有道登录js逆向解析
    利用远程服务器在docker容器搭建pyspider运行时出错的问题
    linux服务器安装pyspide关于rgnutls.h: No such file or directory 的解决方案
  • 原文地址:https://www.cnblogs.com/gooogleman/p/1869701.html
Copyright © 2011-2022 走看看