微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 触摸屏驱动程序(输入子系统)

触摸屏驱动程序(输入子系统)

时间:11-21 来源:互联网 点击:
#include "linux/errno.h"

#include"linux/kernel.h"

#include"linux/module.h"

#include"linux/slab.h"

#include"linux/input.h"

#include"linux/init.h"

#include"linux/serio.h"

#include"linux/delay.h"

#include"linux/platform_device.h"

#include"linux/clk.h"

#include"asm/io.h"

#include"asm/irq.h"

#include"asm/plat-s3c24xx/ts.h"

#include"asm/arch/regs-adc.h"

#include"asm/arch/regs-gpio.h"

struct s3c_ts_regs {

unsigned long adccon;

unsigned long adctsc;

unsigned long adcdly;

unsigned long adcdat0;

unsigned long adcdat1;

unsigned long adcupdn;

};

static struct input_dev *s3c_ts_dev;

static volatile struct s3c_ts_regs *s3c_ts_regs;

static struct timer_list ts_timer;

//等到触控笔按下模式

static void enter_wait_pen_down_mode(void)

{

s3c_ts_regs->adctsc = 0xd3;

}

//等到触控笔松开模式

static void enter_wait_pen_up_mode(void)

{

s3c_ts_regs->adctsc = 0x1d3;

}

//进入X/Y方向ADC同时转换模式

static void enter_measure_xy_mode(void)

{

s3c_ts_regs->adctsc = (1<3)|(1<2);

}

//启动ADC转换

static void start_adc(void)

{

s3c_ts_regs->adccon |= (1<0);

}

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;

}

static void s3c_ts_timer_function(unsigned long data)

{

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

{

// 测量X/Y坐标

enter_measure_xy_mode();

start_adc();

}

}

//触控笔按下、抬起中断服务函数

static irqreturn_t pen_down_up_irq(int irq, void *dev_id)

{

if (s3c_ts_regs->adcdat0 & (1<15))

{

//printk("pen up\n");

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

{

//printk("pen down\n");

//enter_wait_pen_up_mode();

enter_measure_xy_mode();

start_adc();

}

return IRQ_HANDLED;

}

static irqreturn_t adc_irq(int irq, void *dev_id)

{

static int cnt = 0;

static int x[4], y[4];

int adcdat0, adcdat1;

// 优化措施2: 如果ADC完成时, 发现触摸笔已经松开, 则丢弃此次结果

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

{

// printk("adc_irq cnt = %d, x = %d, y = %d\n", ++cnt, adcdat0 & 0x3ff, adcdat1 & 0x3ff);

// 优化措施3: 多次测量求平均值

x[cnt] = adcdat0 & 0x3ff;

y[cnt] = adcdat1 & 0x3ff;

++cnt;

if (cnt == 4)

{

// 优化措施4: 软件过滤

if (s3c_filter_ts(x, y))

{

//printk("x = %d, y = %d\n", (x[0]+x[1]+x[2]+x[3])/4, (y[0]+y[1]+y[2]+y[3])/4);

input_report_abs(s3c_ts_dev, ABS_X, (x[0]+x[1]+x[2]+x[3])/4);

input_report_abs(s3c_ts_dev, ABS_Y, (y[0]+y[1]+y[2]+y[3])/4);

input_report_abs(s3c_ts_dev, ABS_PRESSURE, 1);

input_report_key(s3c_ts_dev, BTN_TOUCH, 1);

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top