史上最详细的触摸屏驱动分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/*触摸屏驱动程序及分析*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* For ts.dev.id.version */
#define S3C2410TSVERSION 0x0101
#define WAIT4INT(x) (((x)<<8) | \
S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_XY_PST(3))
#define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))
static char *s3c2410ts_name = "s3c2410 TouchScreen";
static struct input_dev *dev;
static long xp;
static long yp;
static int count;
extern struct semaphore ADC_LOCK;
static int OwnADC = 0;
static void __iomem *base_addr;
/*把GPG12~15 设置为保留模式*/
static inline void s3c2410_ts_connect(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);
s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);
s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);
s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
}
/*求坐标的平均值,报告坐标,当还是按下状态时,再次调用ADC转换,如果抬起则让触摸屏设置为等待中断模式*/
static void touch_timer_fire(unsigned long data)
{
unsigned long data0;
unsigned long data1;
int updown;
/*用于读取ADCDA T数据*/
data0 = ioread32(base_addr+S3C2410_ADCDA T0);
data1 = ioread32(base_addr+S3C2410_ADCDA T1);
/*判断是按下还是送开*/
updown = (!(data0 & S3C2410_ADCDA T0_UPDOWN)) && (!(data1 & S3C2410_ADCDA T0_UPDOWN));
/*如果按下*/
if (updown) {
if (count != 0) {/*转换四次后进行事件汇报*/
long tmp;
tmp = xp;
xp = yp;
yp = tmp;
/* 求平均值*/
xp >>= 2;
yp >>= 2;
/* 报告x、y的绝对坐标值*/
input_report_abs(dev, ABS_X, xp);
input_report_abs(dev, ABS_Y, yp);
/* 报告按键事件,键值为1(代表触摸屏对应的按键被按下) */
input_report_key(dev, BTN_TOUCH, 1);
/* 报告触摸屏的状态,1表明触摸屏被按下*/
input_report_abs(dev, ABS_PRESSURE, 1);
/* 同步*/
input_sync(dev);
}
xp = 0;
yp = 0;
count = 0;
/*自动X/Y轴坐标转换模式的设置,自动地进行X轴和Y轴的转换操作,随后产生相应的INT_ADC中断通知转换完毕*/
iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
/*如果还没有启动ADC或者ADC转换四次完毕后则启动ADC*/
iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else {
count = 0;
/* 如果触摸笔是弹起状态,则提出报告,并让触摸屏处于等待触摸的阶段*/
/* 报告按键事件,键值为0(代表触摸屏对应的按键被释放) */
input_report_key(dev, BTN_TOUCH, 0);
/* 报告触摸屏的状态,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);
}
}
}
static struct timer_list touch_timer =
TIMER_INITIALIZER(touch_timer_fire, 0, 0);
/*当触摸按下时,产生INT_TC中断,会进入到stylus_updown中断处理函数
当有中断产生时,会使OwnADC=1,然后读取数据,并判断是抬起还是按下,按下则调用touch_timer_fire()函数,
抬起则释放锁,并使OwnADC=0
*/