第二种情况,如果触摸屏被按下,首先触发触摸中断,执行stylus_updown函数


static irqreturn_t stylus_updown(int irq, void *dev_id)
{
       unsigned long data0;
       unsigned long data1;
       int updown;
       if (down_trylock(&ADC_LOCK) == 0) {  //获取一把锁
              OwnADC = 1;       //表示获得锁
              data0 = ioread32(base_addr+S3C2410_ADCDAT0); //读取X轴数据
              data1 = ioread32(base_addr+S3C2410_ADCDAT1); //读取Y轴数据
              updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); //触摸屏是否被按下,按下updowm=1
              if (updown) {
                     touch_timer_fire(0);  // 如果触摸屏被按下,执行touch_timer_fire
              } else {  //去抖动操作,释放锁
                     OwnADC = 0;
                     up(&ADC_LOCK);
              }
       }
       return IRQ_HANDLED;
}


  下面我们第二次分析touch_timer_fire,而这次主要是因为触摸中断中调用了这个函数,假设当前触摸屏被按下后,坐标值还没进行AD转换


static void touch_timer_fire(unsigned long data)
{
     unsigned long data0;
     unsigned long data1;
       int updown;
     data0 = ioread32(base_addr+S3C2410_ADCDAT0);
     data1 = ioread32(base_addr+S3C2410_ADCDAT1);
      updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
      if (updown) {  //触摸屏被按下
             if (count != 0) { //count是全局变量,统计AD转换次数,目前未AD转换
                     long tmp;                                                                                        
                     tmp = xp;
                     xp = yp;
                     yp = tmp;                                                                                        
           xp >>= 2;
           yp >>= 2;
                    input_report_abs(dev, ABS_X, xp);
                    input_report_abs(dev, ABS_Y, yp);
                    input_report_key(dev, BTN_TOUCH, 1);
                    input_report_abs(dev, ABS_PRESSURE, 1);
                    input_sync(dev);
             }
             xp = 0;      //虽然触摸屏被按下,但是未完成AD转换
             yp = 0;
             count = 0;
             //自动连续测量X和Y坐标
iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
//AD转换开始且该位在开始后清零
             iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
      } else {
             count = 0;
             input_report_key(dev, BTN_TOUCH, 0);
             input_report_abs(dev, ABS_PRESSURE, 0);
             input_sync(dev);
             iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
              if (OwnADC) {
                     OwnADC = 0;
                     up(&ADC_LOCK);
              }
      }
}


  现在我们知道,如果触摸屏被按下,但是AD还没转换完毕,那么我们会开启AD转换,自动测量X和Y坐标,这样会触发AD转换中断,执行AD转换的中断处理程序。其实当我们的触摸屏被按下,当X和Y轴获取电压值,然后会进行AD转换,执行AD转换的中断处理程序。好了,我们该看看AD转换的中断代码了。


static irqreturn_t stylus_action(int irq, void *dev_id)
{
       unsigned long data0;
       unsigned long data1;
       if (OwnADC) { //只有触摸屏被按下,相应了触摸中断该标志才为1
              data0 = ioread32(base_addr+S3C2410_ADCDAT0); //读取X坐标
              data1 = ioread32(base_addr+S3C2410_ADCDAT1);  //读取Y坐标
              xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;//叠加X坐标
              yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;//叠加Y坐标
              count++;  //统计AD转换次数
           if (count < (1<<2)) { //如果AD转换次数不足4次
                     //自动连续测量X和Y坐标
 iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
//AD转换开始且该位在开始后清零
iowrite32(ioread32(base_addr+S3C2410_ADCCON) |S3C2410_ADCCON_ENABLE_START,base_addr+S3C2410_ADCCON);
              } else {
                     mod_timer(&touch_timer, jiffies+1); //四次AD转换后,修改定时时间
                     iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC);//等待释放
              }
       }
       return IRQ_HANDLED;
}