首页 > 其他 > 详细

触摸屏驱动程序

时间:2014-07-02 21:54:36      阅读:476      评论:0      收藏:0      [点我收藏+]

触摸屏驱动程序框架与上一片文章的输入子系统类似,只是底层驱动由按键变成了触摸屏。

S3C2440的ADC相关寄存器:

struct s3c_ts_regs {
  unsigned long adccon;
  unsigned long adctsc;
  unsigned long adcdly;
  unsigned long adcdat0;
  unsigned long adcdat1;
  unsigned long adcupdn;
};

1.分配input_dev结构体

struct input_dev *s3c_ts_dev = input_allocate_device();
2.设置
2.1设置产生哪类事件
set_bit(EV_KEY, s3c_ts_dev->evbit);
set_bit(EV_ABS, s3c_ts_dev->evbit);
2.2能产生这类事件中的哪些事件
set_bit(BTN_TOUCH, s3c_ts_dev->keybit);
//表示支持绝对值x坐标,并设置它在坐标系中的最大值和最小值,以及干扰值和平焊位置等
input_set_abs_params(s3c_ts_dev, ABS_X,              0, 0x3FF, 0, 0);
input_set_abs_params(s3c_ts_dev, ABS_Y,              0, 0x3FF, 0, 0);
input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);
3.注册
inpute_register_device(s3c_ts_dev);
4.硬件相关操作
4.1使能ADC时钟
struct clk *clk = clk_get(NULL, "adc");
clk_enable(clk);
4.2设置ADC相应寄存器
s3c_ts_regs = ioremap((0x58000000, sizeof(struct s3c_ts_regs));
/* converter prescaler enable , ADCCLK=PCLK/(49+1)=50MHz/(49+1)=1MHz */
s3c_ts_regs->adccon = (1<<14)|(49<<6);
s3c_ts_regs->adcdly = 0xffff;//为了确保ADC转换的精度,将这个寄存器设置成最大值
4.3申请中断,ADC转换完成中断和触摸屏按下或抬起中断
request_irq(IRQ_TC, pen_down_up_irq, IRQF_SAMPLE_RANDOM, "ts_pen", NULL);
request_irq(IRQ_ADC, adc_irq, IRQF_SAMPLE_RANDOM, "adc", NULL);
4.4初始化定时器,用来处理在触摸屏上滑动的情况
init_timer(&ts_timer);
ts_timer.function = s3c_ts_timer_function;
add_timer(&ts_timer);
4.5让触摸屏进入等待笔尖按下状态
enter_wait_pen_dowm_mode();
5.触摸屏模式设置
void enter_wait_pen_down_mode(void)
{
     s3c_ts_regs->adctsc = 0xd3;
}
void enter_wait_pen_up_mode(void)
{
     s3c_ts_regs->adctsc = 0x1d3;
}
void enter_measure_xy_mode(void)
{
     s3c_ts_regs->adctsc = (1<<3) | (1<<2);
}
void start_adc(void)
{
     s3c_ts_regs->adccon |= (1<<0);
}
6.定时器处理函数,上报事件
void s3c_ts_timer_function(void)
{
     if (s3c_ts_regs->adcdat0 & (1<<15))
     {
          /* 松开 */
          input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);
          input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
          input_sync(s3c_ts_dev);
          enter_wait_pen_down_mode();
     } else {
          /* 按下 */
          enter_measure_xy_mode();
          start_adc();
     }
}
7.中断处理函数
irqreturn_t pen_down_up_irq(int irq, void *dev_id)
{
     if (s3c_ts_regs->adcdat0 & (1<<15)) {
          /* 松开 */
          input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);
          input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
          input_sync(s3c_ts_dev);
          enter_wait_pen_down_mode();
     } else {
          /* 按下 */
          enter_measure_xy_mode();
          start_adc();
     }
     return IRQ_HANDLED;
}
irqreturn_t adc_irq(int irq, void *dev_id)
{
     static int cnt = 0;
     static int x[4], y[4];
     int adcdat0, adcdat1;
     
    adcdat0 = s3c_ts_regs->adcdat0;
    adcdat1 = s3c_ts_regs->adcdat1;
    if (s3c_ts_regs->adcdat0 & (1<<15)) {
          /* 松开 */
         cnt = 0;
         input_report_abs(s3c_ts_dev, ABS_PRESSURE, 0);
         input_report_key(s3c_ts_dev, BTN_TOUCH, 0);
          input_sync(s3c_ts_dev);
         enter_wait_pen_down_mode();
     } else {
         x[cnt] = adcdat0 & 0x3FFF;
         y[cnt] = adcdat1 & 0x3FFF;
         ++cnt;
         if (cnt == 4) {
               if (s3c_filter_ts(x, y)) {
                   input_report_abs(s3c_ts_dev, ABS_X, (x[1]+x[2]+x[3]+x[4])/4);
                   input_report_abs(s3c_ts_dev, ABS_Y, (y[1]+y[2]+y[3]+y[4])/4);
                   input_report_abs(s3c_ts_dev, ABS_PRESSURE, 1);
                   input_report_key(s3c_ts_dev, BTN_TOUCH, 1);
                   input_sync(s3c_ts_dev);
               }
              cnt = 0;
              enter_wait_pen_up_mode();
              mod_timer(&ts_timer, jiffies + HZ / 100);
          } else {
              enter_measure_xy_mode();
              start_adc();
          }
     }
    return IRQ_HANDLED;
}
8.过滤ADC转化的数据
static int s3c_filter_ts(int x[], int y[])
{
#define ERR_LIMIT 10

     int avr_x, avr_y;
     int det_x, det_y;

     avr_x = (x[0] + x[1])/2;
     avr_y = (y[0] + y[1])/2;

     det_x = (x[2] > avr_x) ? (x[2] - avr_x) : (avr_x - x[2]);
     det_y = (y[2] > avr_y) ? (y[2] - avr_y) : (avr_y - y[2]);

     if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))
          return 0;

     avr_x = (x[1] + x[2])/2;
     avr_y = (y[1] + y[2])/2;

     det_x = (x[3] > avr_x) ? (x[3] - avr_x) : (avr_x - x[3]);
     det_y = (y[3] > avr_y) ? (y[3] - avr_y) : (avr_y - y[3]);

     if ((det_x > ERR_LIMIT) || (det_y > ERR_LIMIT))
          return 0;

     return 1;
}
 

触摸屏驱动程序,布布扣,bubuko.com

触摸屏驱动程序

原文:http://www.cnblogs.com/zpehome/p/3819051.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!