⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 touch.c

📁 触摸屏驱动实验 基于TEB-44B0实验平台的触摸屏驱动 包括触摸屏驱动程序与测试程序
💻 C
字号:
/* * s3c44b0-ts.c * * touchScreen driver for SAMSUNG S3C44B0 * * Author: vencent <zlg@qhkj.com> * Date  : $Date: 2003/12/17 07:11:00 $  * * * Based on s3c44b0-ts.c * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file COPYING in the main directory of this archive * for more details. * * History: * *  */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>//#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/wait.h>#include <linux/interrupt.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/semaphore.h>#include <asm/segment.h>#include <asm/system.h>#include <asm/byteorder.h>#include <asm/unaligned.h>#include <asm/arch/irqs.h>#include <asm/arch/hardware.h>//#include "sio.h"#define PEN_UP	        0		#define PEN_DOWN	1#define PEN_FLEETING	2#define MAX_TS_BUF	2	/* how many do we want to buffer */#define DEVICE_NAME	"ts"#define TSRAW_MINOR	1typedef struct {  unsigned short pressure;  unsigned short x;  unsigned short y;  unsigned short pad;} TS_RET;typedef struct {	unsigned int penStatus;		/* PEN_UP, PEN_DOWN, PEN_FLEETING */	TS_RET buf[MAX_TS_BUF];		/* protect against overrun */	//unsigned int head = 0, tail = 1;	/* head and tail for queued events */	wait_queue_head_t wq;	spinlock_t lock;} TS_DEV;static TS_DEV tsdev;static unsigned short EDGE_X_MIN=0;static unsigned short EDGE_Y_MIN=0;static unsigned short EDGE_X_MAX=4096;static unsigned short EDGE_Y_MAX=4096;static unsigned short SCREEN_X=320;static unsigned short SCREEN_Y=240;#define IRQ_TC	S3C44B0X_INTERRUPT_EINT2#define ADS7843_PIN_CS		(1<<6)	//GPF6#define ADS7843_PIN_CLK         (1<<8)    //GPF8#define ADS7843_PIN_DIN         (1<<5)    //GPF5#define ADS7843_PIN_DOUT         (1<<7)    //GPF7#define ADS7843_PIN_PEN	        (1<<2)	// GPG2/EXINT2//控制字各位定义#define ADS7843_START_BIT       (1<<0) #define ADS7843_A2              (1<<1) #define ADS7843_A1              (1<<2) #define ADS7843_A0              (1<<3) #define ADS7843_MODE           (1<<4) #define ADS7843_SER_DFR         (1<<5)  #define ADS7843_PD1             (1<<6) #define ADS7843_PD0             (1<<7)   /* Ask for X conversion enable PENIRQ */#define ADS7843_ASKX (ADS7843_START_BIT |      \                 ADS7843_A2 |                    \                 ADS7843_A1 *0|                  \                 ADS7843_A0 |                    \                 ADS7843_MODE *0|                \                 ADS7843_SER_DFR *0|             \                 ADS7843_PD1 *0|                 \                 ADS7843_PD0 *0) /* Ask for Y conversion enable PENIRQ */#define ADS7843_ASKY (ADS7843_START_BIT |      \                         ADS7843_A2 *0 |         \                         ADS7843_A1 *0|          \                         ADS7843_A0 |            \                         ADS7843_MODE *0|        \                         ADS7843_SER_DFR*0 |     \                         ADS7843_PD1 *0|         \                         ADS7843_PD0 *0)/*Enable PENIRQ*/#define ADS7843_NOP (ADS7843_START_BIT |       \                         ADS7843_A2 *0 |        \                         ADS7843_A1 *0|          \                         ADS7843_A0 *0|          \                         ADS7843_MODE *0|        \                         ADS7843_SER_DFR *0|     \                         ADS7843_PD1 *0|         \                         ADS7843_PD0 *0)//#define BUF_HEAD  	(tsdev.buf[tsdev.head])//#define BUF_TAIL		(tsdev.buf[tsdev.tail])#define BUF_HEAD  	(tsdev.buf[0])#define BUF_TAIL		(tsdev.buf[1])//#define INCBUF(x,mod) 	((++(x)) & ((mod) - 1))static int tsMajor = 10;static void (*tsEvent)(void);#define HOOK_FOR_DRAG#ifdef HOOK_FOR_DRAG#define TS_TIMER_DELAY  (HZ/10) /* 100 ms */#define TS_TIMER_DELAY1  (HZ/20) /* 5 ms */static struct timer_list ts_timer;#endif#define HOLDING_TIME	50   // 50us// Write ads7843 control command  void ads7843_din(char command){         int i;	          for(i = 0; i < 8; i++,command>>=1)         {                 outl(inl(S3C44B0X_PDATF)|(ADS7843_PIN_CLK), S3C44B0X_PDATF); // CLK->1                 if( command & 0x01 )                         outl(inl(S3C44B0X_PDATF)|(ADS7843_PIN_DIN), S3C44B0X_PDATF); //DIN->1                 else                         outl(inl(S3C44B0X_PDATF)&~(ADS7843_PIN_DIN), S3C44B0X_PDATF); //DIN->0                  udelay(HOLDING_TIME);                 outl(inl(S3C44B0X_PDATF)&~(ADS7843_PIN_CLK), S3C44B0X_PDATF); // CLK->0                 udelay(HOLDING_TIME);         }}//测量X static int s3c44b0_ts_measure_x(void){	char i;     	int touch_data = 0;        outl(inl(S3C44B0X_PDATF)&~(ADS7843_PIN_CS|ADS7843_PIN_CLK), S3C44B0X_PDATF);  // CS,CLK->0	ads7843_din( ADS7843_ASKX );	        outl(inl(S3C44B0X_PDATF)&~(ADS7843_PIN_CLK|ADS7843_PIN_DIN), S3C44B0X_PDATF);  // CLK,DIN->0        udelay(HOLDING_TIME);	outl(inl(S3C44B0X_PDATF)|(ADS7843_PIN_CLK), S3C44B0X_PDATF); // CLK->1 //         while(!(inl(S3C44B0X_PDATF) & ADS7843_BUSY));        udelay(HOLDING_TIME);	outl(inl(S3C44B0X_PDATF)&~(ADS7843_PIN_CLK), S3C44B0X_PDATF); // CLK->0        udelay(HOLDING_TIME);          for(i = 0; i < 15; i++,touch_data <<= 1)         {                 outl(inl(S3C44B0X_PDATF)|(ADS7843_PIN_CLK), S3C44B0X_PDATF); // CLK->1                 if(inl(S3C44B0X_PDATF) & ADS7843_PIN_DOUT)                         touch_data |= 0x01;                 else                         touch_data &= ~(0x01);                 udelay(HOLDING_TIME);                 outl(inl(S3C44B0X_PDATF)&~(ADS7843_PIN_CLK), S3C44B0X_PDATF); // CLK->0                 udelay(HOLDING_TIME);         }         outl(inl(S3C44B0X_PDATF)|(ADS7843_PIN_CS), S3C44B0X_PDATF);  // CS->1         touch_data >>= 3;         return (touch_data & 0xfff);  }  //测量Y static int s3c44b0_ts_measure_y(void){	char i;     	int touch_data = 0;        outl(inl(S3C44B0X_PDATF)&~(ADS7843_PIN_CS|ADS7843_PIN_CLK), S3C44B0X_PDATF);  // CS,CLK->0	ads7843_din( ADS7843_ASKY );	        outl(inl(S3C44B0X_PDATF)&~(ADS7843_PIN_CLK|ADS7843_PIN_DIN), S3C44B0X_PDATF);  // CLK,DIN->0        udelay(HOLDING_TIME);	outl(inl(S3C44B0X_PDATF)|(ADS7843_PIN_CLK), S3C44B0X_PDATF); // CLK->1 //         while(!(inl(S3C44B0X_PDATF) & ADS7843_BUSY));        udelay(HOLDING_TIME);	outl(inl(S3C44B0X_PDATF)&~(ADS7843_PIN_CLK), S3C44B0X_PDATF); // CLK->0        udelay(HOLDING_TIME);          for(i = 0; i < 15; i++,touch_data <<= 1)         {                 outl(inl(S3C44B0X_PDATF)|(ADS7843_PIN_CLK), S3C44B0X_PDATF); // CLK->1                 if(inl(S3C44B0X_PDATF) & ADS7843_PIN_DOUT)                         touch_data |= 0x01;                 else                         touch_data &= ~(0x01);                 udelay(HOLDING_TIME);                 outl(inl(S3C44B0X_PDATF)&~(ADS7843_PIN_CLK), S3C44B0X_PDATF); // CLK->0                 udelay(HOLDING_TIME);         }         outl(inl(S3C44B0X_PDATF)|(ADS7843_PIN_CS), S3C44B0X_PDATF);  // CS->1         touch_data >>= 3;         return (touch_data & 0xfff);  }static int x, y;	/* touch screen coorinates */static void tsEvent_raw(void){	if (tsdev.penStatus == PEN_DOWN || tsdev.penStatus == PEN_FLEETING) {		BUF_HEAD.x = BUF_TAIL.x;		BUF_HEAD.y = BUF_TAIL.y;		BUF_HEAD.pressure = tsdev.penStatus;	} 	else {		BUF_HEAD.x = 0;		BUF_HEAD.y = 0;		BUF_HEAD.pressure = PEN_UP;	}	//tsdev.head = INCBUF(tsdev.head, MAX_TS_BUF);	wake_up_interruptible(&(tsdev.wq));}static int tsRead(TS_RET * ts_ret){	//spin_lock_irq(&(tsdev.lock));	ts_ret->x = BUF_TAIL.x;	ts_ret->y = BUF_TAIL.y;	ts_ret->pressure = BUF_TAIL.pressure;	//tsdev.tail = INCBUF(tsdev.tail, MAX_TS_BUF);	//spin_unlock_irq(&(tsdev.lock));       // printk("BUF_TAIL.x = %d, BUF_TAIL.y = %d\n",ts_ret->x,ts_ret->y);	return sizeof(TS_RET);}/*static ssize_t s3c44b0_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){	TS_RET ts_ret;retry: 	if (tsdev.head != tsdev.tail) {		int count;		count = tsRead(&ts_ret);		if (count) copy_to_user(buffer, (char *)&ts_ret, count);		return count;	} else {		if (filp->f_flags & O_NONBLOCK)			return -EAGAIN;		interruptible_sleep_on(&(tsdev.wq));		if (signal_pending(current))			return -ERESTARTSYS;		goto retry;	}	return sizeof(TS_RET);}*/static ssize_t s3c44b0_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){	int count;	TS_RET ts_ret;		//if (tsdev.head == tsdev.tail)	//if ((BUF_HEAD.x != BUF_TAIL.x) && (BUF_HEAD.y != BUF_TAIL.y)) 	if ((BUF_TAIL.x == 0) && (BUF_TAIL.y == 0)) 	{	 if (filp->f_flags & O_NONBLOCK)			return -EAGAIN;		interruptible_sleep_on(&(tsdev.wq));		if (signal_pending(current))			return -ERESTARTSYS;	}		count = tsRead(&ts_ret);	if (count) copy_to_user(buffer, (char *)&ts_ret, count);	return count;	}	static unsigned int s3c44b0_ts_poll(struct file *filp, struct poll_table_struct *wait){	poll_wait(filp, &(tsdev.wq), wait);	//if (tsdev.head != tsdev.tail)	//if ((BUF_HEAD.x != BUF_TAIL.x) && (BUF_HEAD.y != BUF_TAIL.y))	if ((BUF_TAIL.x == 0) && (BUF_TAIL.y == 0)) 	  return (POLLIN | POLLRDNORM);	return  0;}static void s3c44b0_isr_tc(int irq, void *dev_id, struct pt_regs *reg){	//spin_lock_irq(&(tsdev.lock));	//DPRINTK("Occured Touch Screen Interrupt\n");	if ((tsdev.penStatus == PEN_UP)) {		int i;		//PCONG &= ~(3<<10);	//into input mode		//TS_CLOSE_INT();		//disable_irq(IRQ_TC); 		//udelay(1);		if ((inl(S3C44B0X_PDATG) & ADS7843_PIN_PEN)==0) {			tsdev.penStatus = PEN_DOWN;#ifdef HOOK_FOR_DRAG 			//ts_timer.expires = jiffies + TS_TIMER_DELAY1;			ts_timer.expires = jiffies + TS_TIMER_DELAY;			add_timer(&ts_timer);#endif		}		else{			//PCONG |= (3<<10);	//into EXINT mode			//enable_irq(IRQ_TC); 			//outl((0x01)<<23, S3C44B0X_I_ISPC); 		}	}	//spin_unlock_irq(&(tsdev.lock));	outl((0x01)<<23, S3C44B0X_I_ISPC); }#ifdef HOOK_FOR_DRAGstatic void ts_timer_handler(unsigned long data){	//spin_lock_irq(&(tsdev.lock));	if ((inl(S3C44B0X_PDATG)&ADS7843_PIN_PEN)==0) {		//s3c44b0_get_XY();		//if(tsdev.penStatus == PEN_DOWN)		BUF_TAIL.x = s3c44b0_ts_measure_x();		BUF_TAIL.y = s3c44b0_ts_measure_y();		tsdev.penStatus = PEN_FLEETING;#ifdef HOOK_FOR_DRAG 			ts_timer.expires = jiffies + TS_TIMER_DELAY;			add_timer(&ts_timer);#endif	}	else{		tsdev.penStatus = PEN_UP;		del_timer(&ts_timer);		tsEvent();		//enable_irq(IRQ_TC); 	}	//spin_unlock_irq(&(tsdev.lock));	//outl((0x01)<<23, S3C44B0X_I_ISPC);  }#endifstatic int s3c44b0_ts_open(struct inode *inode, struct file *filp){               int ret;		ret = request_irq(IRQ_TC, s3c44b0_isr_tc, 0, 			  DEVICE_NAME, NULL);	if(ret < 0)  	{   	 printk("TouchPanel Driver: Error while installing IRQ_TC handler.\n");   	return -ENODEV;  	}  	else  	{   	// printk("The TouchPanel is registered successfully!\n");   	 //printk("ret = %d \n", ret);  	}	        outl(inl(S3C44B0X_PCONG)|((0x03)<<4), S3C44B0X_PCONG);   	outl(inl(S3C44B0X_INTMOD)&(~(0x1<<23)), S3C44B0X_INTMOD);  	outl(inl(S3C44B0X_EXTINT)&(~((0x7)<<8)), S3C44B0X_EXTINT);  	outl(inl(S3C44B0X_EXTINT)|(0x2<<8), S3C44B0X_EXTINT);			outl(inl(S3C44B0X_PCONE)&(0x3cfff), S3C44B0X_PCONE);  	outl(inl(S3C44B0X_PCONE)|(0x1000), S3C44B0X_PCONE);    //PE6 as output   	outl(inl(S3C44B0X_PUPE)&(0x1bf), S3C44B0X_PUPE);   	outl(inl(S3C44B0X_PDATE)|(0x40), S3C44B0X_PDATE);      /*     PE6->1   Disable I/O expand in CPLD     */	disable_irq(IRQ_TC); 		//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));	enable_irq(IRQ_TC); 	MOD_INC_USE_COUNT;	return 0;}static int s3c44b0_ts_release(struct inode *inode, struct file *filp){#ifdef HOOK_FOR_DRAG	del_timer(&ts_timer);#endif	disable_irq(IRQ_TC); 	free_irq(IRQ_TC, NULL);	MOD_DEC_USE_COUNT;	return 0;}static struct file_operations s3c44b0ts_fops = {	owner:	THIS_MODULE,	open:	s3c44b0_ts_open,	read:	s3c44b0_ts_read,		release:	s3c44b0_ts_release,	poll:	s3c44b0_ts_poll,};void tsEvent_dummy(void) {}void s3c44b0_ts_init(void){	int ret;	int flags;	tsEvent = tsEvent_dummy;		outl(inl(S3C44B0X_PCONF)&(~((0x0fff)<<10)), S3C44B0X_PCONF);   	outl(inl(S3C44B0X_PCONF)|((0x209)<<10), S3C44B0X_PCONF);     	outl(inl(S3C44B0X_PUPF)&(0x01f), S3C44B0X_PUPF);  	outl(inl(S3C44B0X_PUPF)|(0x080), S3C44B0X_PUPF);    	outl(inl(S3C44B0X_PDATF)&(0x0df), S3C44B0X_PDATF);   //PF8,PF5->0  	outl(inl(S3C44B0X_PDATF)|(0x040), S3C44B0X_PDATF);   //CS/PF6->1        	//local_irq_save(flags);  /*	outl(inl(S3C44B0X_PCONG)|((0x03)<<4), S3C44B0X_PCONG);   	outl(inl(S3C44B0X_INTMOD)&(0x0<<23), S3C44B0X_INTMOD);  	outl(inl(S3C44B0X_EXTINT)&(~((0x7)<<8)), S3C44B0X_EXTINT);  	outl(inl(S3C44B0X_EXTINT)|(0x2<<8), S3C44B0X_EXTINT);  */            // local_irq_restore(flags);	ret = register_chrdev(tsMajor, DEVICE_NAME, &s3c44b0ts_fops);	if (ret < 0) {	  printk("Panic! Could not register TouchPanel Driver.\n");	  //return ret;	}	printk("The TouchPanel is registered successfully!\n");		//local_irq_save(flags);	/* Enable touch interrupt *//*	ret = request_irq(IRQ_TC, s3c44b0_isr_tc, 0, 			  DEVICE_NAME, NULL);	if(ret < 0)  	{   	 printk("TouchPanel Driver: Error while installing IRQ_TC handler.\n");   	//return -ENODEV;  	}  	else  	{   	 printk("The TouchPanel is registered successfully!\n");   	 //printk("ret = %d \n", ret);  	}	disable_irq(IRQ_TC); 	//udelay(10);	//local_irq_restore(flags);*/ 	return;}static void s3c44b0_ts_exit(void){	unregister_chrdev(tsMajor, DEVICE_NAME);	//free_irq(IRQ_TC, NULL);}//module_init(s3c44b0_ts_init);//module_exit(s3c44b0_ts_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -