S3C2410触摸屏驱动代码分析3 阳光穿透心脏的1/2处 2022-03-26 13:16 221阅读 0赞 /\* 这段代码完成对刚才得到的y 值进行修正,将结果保存在cheat\_diff\_y 变 量中 \*/ //y = y - (max + min); //y = y / (TIMES - 2); adc\_state = 1; mode\_y\_axis(); start\_adc\_y(); /\* 开始进行y 坐标的转换,注意此处由start\_adc\_y()函数引发一次AD 中 断,开始进行Y 坐标的转换,特别需要注意的是此处adc\_state 的值变为1,表示转换的第 二阶段(即Y 坐标转换阶段的开始)。 Y坐标转换的代码是下面的由鲜绿颜色标注的代码。 \*/ \} \} else if (adc\_state == 1) \{ //进行Y 坐标转换,原理同上,自己 分析 if (time == 0) \{ x = 0; //max = 0; //min = 0xffffffff; \} if (time < TIMES) \{ disable\_ts\_adc(); data\[time\] = (ADCDAT1 & 0x3ff); //if (tmp > max) max = tmp; //if (tmp < min) min = tmp; //x += tmp; start\_adc\_y(); time ++; \} else \{ for (i = 0; i < TIMES; i++) \{ for (j = 0; j < TIMES - i; j++) \{ if (data\[j\] > data\[j+1\]) \{ tmp = data\[j\]; data\[j\] = data\[j+1\]; data\[j+1\] = tmp; \} \} \} time = 0; x = 0; for (i = TIMES / 6; i < TIMES\*5/6; i++) \{ x += data\[i\]; \} x /= (TIMES\*2/3); x &= 0x3ff; if (cheat < 400) \{ for (i = 0; i < CHEAT\_NUMBER; i++) \{ if (x > cheat\_x\[i\]) \{ cheat\_diff\_x = x - cheat\_x\[i\]; \} else \{ cheat\_diff\_x = cheat\_x\[i\] - x; \} if (cheat\_diff\_x < 5) \{ x = cheat\_x\[i\]; break; \} else if (cheat\_x\[i\] == 0) \{ cheat\_x\[i\] = x; break; \} \} \} adc\_state = 0; /\* 再次将adc\_state 清为0,表示一次转换的结束(包括X 坐标和Y 坐标)。 \*/ tsdev.penStatus = PEN\_DOWN; /\* 将笔的状态设定为按下 \*/ x=1024-x;//only for 240\*320! y=1024-y;//only for 240\*320! /\* 将刚才得到的坐标进行转换成LCD 屏上的坐标。 \*/ DPRINTK("PEN DOWN: x: %08d, y: %08d\\n", y, x); //printk("PEN DOWN: x: %08d, y: %08d\\n", y, x); wait\_up\_int(); /\* 等待笔从屏上拿起。如果笔从屏上拿起将再次触发触摸屏中断。 \*/ tsEvent(); /\* 将刚才的结果写入到环形缓冲区中。注意tsEvent 为函数指针,该函数指 针在ts\_open()中被定义为: tsEvent = tsEvent\_raw; 所以此处应调用tsEvent\_raw()函数。 \*/ \} \} \} static void s3c2410\_isr\_adc(int irq, void \*dev\_id, struct pt\_regs \*reg) \{ \#if 0 DPRINTK("Occured Touch Screen Interrupt\\n"); DPRINTK("SUBSRCPND = 0x%08lx\\n", SUBSRCPND); \#endif spin\_lock\_irq(&(tsdev.lock)); /\* 首先获得触摸屏设备的自旋锁。在一次转换过程中,不允许多个转换的请求发生。 \*/ if (tsdev.penStatus == PEN\_UP) s3c2410\_get\_XY();//进行一次x/y 坐标的转换 \#ifdef HOOK\_FOR\_DRAG else s3c2410\_get\_XY(); \#endif spin\_unlock\_irq(&(tsdev.lock)); /\* 释放这把锁。 \*/ \} static void s3c2410\_isr\_tc(int irq, void \*dev\_id, struct pt\_regs \*reg) \{ volatile int i; \#if 0 DPRINTK("Occured Touch Screen Interrupt\\n"); DPRINTK("SUBSRCPND = 0x%08lx\\n", SUBSRCPND); \#endif spin\_lock\_irq(&(tsdev.lock)); /\* 首先获得触摸屏设备的锁 \*/ /\* 由于在ts\_open()函数中有如下代码: tsdev.penStatus = PEN\_UP 所以发生中断时执行红颜色相关的代码 \*/ if (tsdev.penStatus == PEN\_UP) \{//处理一次A/D 转换 //for (i = 0; i < 8000; i++) start\_ts\_adc(); /\* 开始进行第一次触摸屏转换 \*/ \} else \{//处理在同一段时间内多次按下触摸屏 tsdev.penStatus = PEN\_UP; //DPRINTK("PEN UP: x: %08d, y: %08d\\n", x, y); DPRINTK("PEN UP: x: %08d, y: %08d\\n", y, x); wait\_down\_int(); cheat ++; tsEvent(); \} spin\_unlock\_irq(&(tsdev.lock)); \} \#ifdef HOOK\_FOR\_DRAG static void ts\_timer\_handler(unsigned long data) \{ spin\_lock\_irq(&(tsdev.lock)); if (tsdev.penStatus == PEN\_DOWN) \{ start\_ts\_adc(); \} spin\_unlock\_irq(&(tsdev.lock)); \} \#endif static int s3c2410\_ts\_open(struct inode \*inode, struct file \*filp) \{ tsdev.head = tsdev.tail = 0; /\* 环形缓冲区的头部和尾部指针分别指向缓冲区队列的头。 \*/ tsdev.penStatus = PEN\_UP; /\* 笔的状态设定为抬起状态。 \*/ \#ifdef HOOK\_FOR\_DRAG init\_timer(&ts\_timer); ts\_timer.function = ts\_timer\_handler; /\* 初始化定时器 \*/ \#endif tsEvent = tsEvent\_raw; /\* 设置读取环形缓冲区内数据的函数 \*/ init\_waitqueue\_head(&(tsdev.wq)); /\* 初始化等待队列 \*/ MOD\_INC\_USE\_COUNT; /\* 模块引用数增加1 \*/ return 0; \} static int s3c2410\_ts\_release(struct inode \*inode, struct file \*filp) \{ \#ifdef HOOK\_FOR\_DRAG del\_timer(&ts\_timer); //删除定时器 \#endif MOD\_DEC\_USE\_COUNT; //模块引用数减1 return 0; \} static struct file\_operations s3c2410\_fops = \{ owner: THIS\_MODULE, open: s3c2410\_ts\_open, read:s3c2410\_ts\_read, release: s3c2410\_ts\_release, \#ifdef USE\_ASYNC fasync: s3c2410\_ts\_fasync, \#endif poll: s3c2410\_ts\_poll, \}; void tsEvent\_dummy(void) \{\} \#ifdef CONFIG\_PM static int s3c2410\_ts\_pm\_callback(struct pm\_dev \*pm\_dev, pm\_request\_t req, void \*data) \{ switch (req) \{ case PM\_SUSPEND: tsEvent = tsEvent\_dummy; break; case PM\_RESUME: tsEvent = tsEvent\_raw; wait\_down\_int(); break; \} return 0; \} \#endif \#ifdef CONFIG\_DEVFS\_FS static devfs\_handle\_t devfs\_ts\_dir, devfs\_tsraw; \#endif static int \_\_init s3c2410\_ts\_init(void) \{ int ret; tsEvent = tsEvent\_dummy; /\* tsEvent 为函数指针,指向函数tsEvent\_dummy(),不过该函数为空函数,相关定义如 下: static void (\*tsEvent)(void); …… void tsEvent\_dummy(void) \{\} \*/ ret = register\_chrdev(0, DEVICE\_NAME, &s3c2410\_fops); if (ret < 0) \{ printk(DEVICE\_NAME " can't get major number\\n"); return ret; \} tsMajor = ret; /\* 首先调用register\_chrdev()函数来进行设备的注册。 宏DEVICE\_NEME 定义为: \#define DEVICE\_NAME "s3c2410-ts" 即该设备的节点名为/dev/s3c2410-ts register\_chrdev 函数的第一个实参0,表明该设备的主设备号由系统动态分配,其具体 分配的主设备号可以在文件/proc/devices 文件中查到,然后才可以利用该主设备号用mknod 来创建设备节点。 \*/ /\* set gpio to XP, YM, YP and YM \*/ \#if 0 set\_GPIO\_mode(GPIO106\_nYPON\_MD); set\_GPIO\_mode(GPIO105\_YMON\_MD); set\_GPIO\_mode(GPIO104\_nXPON\_MD); set\_GPIO\_mode(GPIO103\_XMON\_MD); GPUP(GPIO106\_nYPON) |= GPIO\_bit(GPIO106\_nYPON); GPUP(GPIO105\_YMON) &= GPIO\_bit(GPIO105\_YMON); GPUP(GPIO104\_nXPON) |= GPIO\_bit(GPIO104\_nXPON); GPUP(GPIO103\_XMON) &= GPIO\_bit(GPIO103\_XMON); \#else set\_gpio\_ctrl(GPIO\_YPON); set\_gpio\_ctrl(GPIO\_YMON); set\_gpio\_ctrl(GPIO\_XPON); set\_gpio\_ctrl(GPIO\_XMON); /\* 设置处理器上GPIO 引脚(触摸屏相关)为触摸屏引脚。set\_gpio\_ctrl 宏完成相关引脚 的设置,一般完成引脚功能的设置和PULLUP 寄存器的设置。 \*/ \#endif /\* Enable touch interrupt \*/ ret = request\_irq(IRQ\_ADC\_DONE, s3c2410\_isr\_adc, SA\_INTERRUPT, DEVICE\_NAME, s3c2410\_isr\_adc); /\* 注册ADC 中断,其中:
还没有评论,来说两句吧...