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

📄 ads7843_ts.c

📁 基于linux操作系统的触摸屏驱动程序
💻 C
字号:
/******************************************************************************** File name :  ads7843.c**     ** Description :**     ADS7843(Touch Screen Controller)**      ** Compile environment and method of compile & link**      gcc version 2.95.2 20000313 (Debian GNU/Linux)**** Usage :**      Touch screen controller Device Driver for X-Hyper25X Board **  ** License : **      This program is free software; you can redistribute it and/or modify**      it under the terms of the GNU General Public License version 2 as**      published by the Free Software Foundation**** Modification history :**      Date        Version  Programmer & Tester   Modify issue**      2002.5.1    0.1      Heo young Wook        Create**      2003.8.1    0.2      Heo young Wook        interrupt modify*********************************************************************************/#include <linux/config.h>#include <linux/types.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/delay.h>#include <linux/fs.h>#include <linux/poll.h>#include <linux/string.h>#include <linux/devfs_fs_kernel.h>#include <asm/uaccess.h>#include <asm/hardware.h>#include <asm/irq.h>#include "ads7843_ts.h"#define PRINTK printk#define DELAY 30static int head, tail;static TS_EVENT cur_data, samples[3], buf[BUFSIZE];static struct fasync_struct *fasync;static unsigned long in_timehandle = 0;unsigned int count =0;static void ts_clear(void);static void print_par(void);static void read_xy(void);void ads7843_din(char command){        int i;		XHYPER255_ClearBit(0, ADS7843_CS);        udelay(DELAY);        for(i = 0; i < 8; i++)        {		        XHYPER255_ClearBit(0, ADS7843_CLK);                        if((command >> i)&0x1){		                XHYPER255_SetBit(0, ADS7843_DIN);				} else {		                XHYPER255_ClearBit(0, ADS7843_DIN);				}                udelay(DELAY);                XHYPER255_SetBit(0, ADS7843_CLK);        }}void ads7843_askx(void){        ads7843_din(SPIMDATA_ASKX);}void ads7843_asky(void){        ads7843_din(SPIMDATA_ASKY);}void ads7843_nop(void){        ads7843_din(SPIMDATA_NOP);}int sa1100_ts_measure_x(void){    char i;    int touch_data = 0;	        XHYPER255_ClearBit(0, ADS7843_CS);        udelay(DELAY);         for(i = 0; i < 8; i++)        {                XHYPER255_ClearBit(0, ADS7843_CLK);                udelay(DELAY);                if((  SPIMDATA_ASKX >> i) & 0x01){                        XHYPER255_SetBit(0, ADS7843_DIN);				} else {                        XHYPER255_ClearBit(0, ADS7843_DIN);				}                udelay(DELAY);                XHYPER255_SetBit(0, ADS7843_CLK);        }        XHYPER255_ClearBit(0, ADS7843_CLK);        udelay(DELAY);        while(!(GPLR0 & GPIO_bit(ADS7843_BUSY)))				printk("BUSY1\n");        XHYPER255_ClearBit(0, ADS7843_CLK);        for(i = 0; i < 15; i++)        {                touch_data <<= 1;                if(GPLR0 & GPIO_bit(ADS7843_DOUT)){                        touch_data |= 0x01;				} else {                        touch_data &= 0xffffe;				}		        XHYPER255_SetBit(0, ADS7843_CLK);                udelay(DELAY);		        XHYPER255_ClearBit(0, ADS7843_CLK);        }        touch_data >>= 3;        return (touch_data & 0xfff);}int sa1100_ts_measure_y(void){    char i;    int touch_data = 0;        XHYPER255_ClearBit(0, ADS7843_CS);      udelay(DELAY);        for(i = 0; i < 8; i++)        {                XHYPER255_ClearBit(0, ADS7843_CLK);                udelay(DELAY);                if((  SPIMDATA_ASKY >> i) & 0x01){                        XHYPER255_SetBit(0, ADS7843_DIN);				} else {                        XHYPER255_ClearBit(0, ADS7843_DIN);				}                udelay(DELAY);                XHYPER255_SetBit(0, ADS7843_CLK);        }        XHYPER255_ClearBit(0, ADS7843_CLK);        udelay(DELAY);        while(!(GPLR0 & GPIO_bit(ADS7843_BUSY)))				printk("BUSY2\n");	        XHYPER255_ClearBit(0, ADS7843_CLK);        for(i = 0; i < 15; i++)        {                touch_data <<= 1;                if(GPLR0 & GPIO_bit(ADS7843_DOUT)){                        touch_data |= 0x01;				} else {                        touch_data &= 0xffffe;				}                XHYPER255_SetBit(0, ADS7843_CLK);                udelay(DELAY);                XHYPER255_ClearBit(0, ADS7843_CLK);        }        touch_data >>= 3;        return (touch_data & 0xfff);}void Ads7843_Enable_IRQ(void){	ADS7843_CS_LOW								// CS Low	udelay(DELAY);	ads7843_din(SPIMDATA_NOP);	udelay(DELAY);	ADS7843_CS_HIGH								// CS High - Conversion END}static int ads7843_ts_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){/* Microwindows style (should change to TS_CAL when the specification is ready) */   switch (cmd)   {      case 3:	 raw_max_x = arg;	 break;      case 4:	 raw_max_y = arg;	 break;      case 5:	 res_x = arg;	 break;      case 6:	 res_y = arg;	 break;      case 10:	 raw_min_x = arg;	 break;      case 11:	 raw_min_y = arg;	 break;      case 12:/* New attribute for portrait modes */	 xyswap = arg;/* Allen Add */      case 13:	       /* 0 = Enable calibration ; 1 = Calibration OK */	 cal_ok = arg;      case 14:	       /* Clear all buffer data */	 ts_clear();	 break;      case 15:	       /* X axis reversed setting */	 x_rev = arg;	 break;      case 16:	       /* Y axis reversed setting */	 y_rev = arg;	 break;      case 17:	       /* Clear all buffer data */	 print_par();	 break;/* Allen */   }   return 0;}static void ts_clear(void){   int i;   for (i=0; i < BUFSIZE; i++)   {       buf[i].pressure=(short)NULL;       buf[i].x=(int)NULL;       buf[i].y=(int)NULL;       buf[i].millisecs=(int)NULL;   }   head = 0;   tail = 0;}static void print_par(void){   printk(" Kernel ==> cal_ok = %d\n",cal_ok);   printk(" Kernel ==> raw_max_x = %d\n",raw_max_x);   printk(" Kernel ==> raw_max_y = %d\n",raw_max_y);   printk(" Kernel ==> res_x = %d\n",res_x);   printk(" Kernel ==> res_y = %d\n",res_y);   printk(" Kernel ==> raw_min_x = %d\n",raw_min_x);   printk(" Kernel ==> raw_min_y = %d\n",raw_min_y);   printk(" Kernel ==> xyswap = %d\n",xyswap);   printk(" Kernel ==> x_rev = %d\n",x_rev);   printk(" Kernel ==> y_rev = %d\n",y_rev);}static void new_data(void){   static TS_EVENT last_data = { 0, 0, 0, 0 };   static TS_EVENT temp_data[2];   int diff0, diff1, diff2, diff3=0;   if (cur_data.pressure)   {      diff0 = abs(samples[0].x - samples[1].x);      diff1 = abs(samples[1].x - samples[2].x);      diff2 = abs(samples[2].x - samples[0].x);      if (diff0 > XLIMIT || diff1 > XLIMIT || diff2 > XLIMIT) 	 return;      if (diff0 < diff1)      {	 if (diff2 < diff0)	    temp_data[0].x = (samples[0].x + samples[2].x) / 2;	 else	    temp_data[0].x = (samples[0].x + samples[1].x) / 2;      }      else      {	 if (diff2 < diff3)	    temp_data[0].x = (samples[2].x + samples[0].x) / 2;	 else	    temp_data[0].x = (samples[2].x + samples[1].x) / 2;      }      diff0 = abs(samples[0].y - samples[1].y);      diff1 = abs(samples[1].y - samples[2].y);      diff2 = abs(samples[2].y - samples[0].y);      if (diff0 > YLIMIT || diff1 > YLIMIT || diff2 > YLIMIT || diff3 > YLIMIT)	 return;      if (diff0 < diff2)      {	 if (diff2 < diff3)	    temp_data[0].y = (samples[0].y + samples[2].y) / 2;	 else	    temp_data[0].y = (samples[0].y + samples[1].y) / 2;      }      else      {	 if (diff2 < diff3)	    temp_data[0].y = (samples[2].y + samples[0].y) / 2;	 else	    temp_data[0].y = (samples[2].y + samples[1].y) / 2;      }      if(!last_data.x && !last_data.y)      {	  last_data = temp_data[0];	  temp_data[1] = temp_data[0];	  return;      }      cur_data.x = last_data.x;      cur_data.y = last_data.y;      last_data = temp_data[1];      temp_data[1] = temp_data[0];   }   else   {/* Reset jitter detection on pen release */      last_data.x = 0;      last_data.y = 0;   }   cur_data.millisecs = jiffies;   if (head != tail)   {      int last = head--;      if (last < 0)	 last = BUFSIZE - 1;   }   buf[head] = cur_data;   if (++head == BUFSIZE)      head = 0;   if (head == tail && tail++ == BUFSIZE)      tail = 0;   if (fasync)      kill_fasync(&fasync, SIGIO, POLL_IN);//   printk("X = %d, Y = %d \n",cur_data.x, cur_data.y);   wake_up_interruptible(&queue);}static TS_EVENT get_data(void){   int last = tail;   if (++tail == BUFSIZE)      tail = 0;   return buf[last];}static void wait_for_action(void){	set_GPIO_IRQ_edge(IRQ_GPIO_ADS7843, GPIO_FALLING_EDGE);	enable_irq(IRQ_GPIO_ADS7843);}static unsigned int ads7843_ts_poll(struct file *filp, poll_table *wait){	poll_wait(filp, &queue, wait);	if (head != tail)		return POLLIN | POLLRDNORM;	return 0;}static ssize_t ads7843_ts_read(struct file *filp, char *buf, size_t count, loff_t *l){   DECLARE_WAITQUEUE(wait, current);   int i;   TS_EVENT t;   short out_buf[4];   short tmp;   if (head == tail)   {      if (filp->f_flags & O_NONBLOCK)	 return -EAGAIN;      add_wait_queue(&queue, &wait);      current->state = TASK_INTERRUPTIBLE;      while ((head == tail) && !signal_pending(current))      {	 schedule();	 current->state = TASK_INTERRUPTIBLE;      }      current->state = TASK_RUNNING;      remove_wait_queue(&queue, &wait);   }   for (i = count; i >= sizeof(out_buf); i -= sizeof(out_buf), buf += sizeof(out_buf))	         {      if (head == tail)	 break;      t = get_data();       out_buf[0] = t.pressure;       if(xyswap) {	  tmp = t.y;	  t.y = t.x;	  t.x = tmp;      }	      if (cal_ok)      {	      out_buf[1] = (x_rev) ? ((raw_max_x - t.x) * res_x) / (raw_max_x - raw_min_x) :		      ((t.x - raw_min_x) * res_x) / (raw_max_x - raw_min_x);	      out_buf[2] = (y_rev) ? ((raw_max_y - t.y) * res_y) / (raw_max_y - raw_min_y) :		      ((t.y - raw_min_y) * res_y) / (raw_max_y - raw_min_y);	      	      out_buf[1] = out_buf[1] < res_x ? out_buf[1] : res_x - 1;	      out_buf[2] = out_buf[2] < res_y ? out_buf[2] : res_y - 1;	      	      out_buf[1] = out_buf[1] >= 0 ? out_buf[1] : 0;	      out_buf[2] = out_buf[2] >= 0 ? out_buf[2] : 0;      }      else      {	      out_buf[1] =  t.y;	      out_buf[2] =  t.x;      }	out_buf[3] = t.millisecs;	copy_to_user(buf, &out_buf, sizeof(out_buf));		       }   return count - i;}static void ads7843_ts_timer(unsigned long);static int ads7843_ts_starttimer(void){   in_timehandle++;   init_timer(&timer);   timer.function = ads7843_ts_timer;   timer.expires = jiffies + HZ / 100;   add_timer(&timer);   return 0;}static void ads7843_ts_timer(unsigned long data){   in_timehandle--;   if (GPLR0 & GPIO_bit(ADS7843_PENIRQ)){      cur_data.pressure = 0;      new_data();      wait_for_action();   }   else   if(samples[0].x!=0 ||  samples[1].x!=0 || samples[2].x!=0)      read_xy();}static void read_xy(void){    disable_irq(IRQ_GPIO_ADS7843);	ads7843_askx();	udelay(200);	ads7843_asky();				    samples[0].x = sa1100_ts_measure_x();    samples[0].y = sa1100_ts_measure_y();      samples[1].x = sa1100_ts_measure_x();    samples[1].y = sa1100_ts_measure_y();    samples[2].x = sa1100_ts_measure_x();    samples[2].y = sa1100_ts_measure_y();   cur_data.pressure = 1;   new_data();   ads7843_ts_starttimer();}static int ads7843_ts_fasync(int fd, struct file *filp, int on){	int retval;	retval = fasync_helper(fd, filp, on, &fasync);	if (retval < 0)		return retval;	return 0;}static int ads7843_ts_open(struct inode *inode, struct file *filp){	ts_clear();	MOD_INC_USE_COUNT;	return 0;}static int ads7843_ts_release(struct inode *inode, struct file *filp){	ts_clear();	ads7843_ts_fasync(-1, filp, 0);	MOD_DEC_USE_COUNT;	return 0;}static void ads7843_ts_interrupt(int irq, void *dev_id, struct pt_regs *regs){	if (in_timehandle > 0)		return;	read_xy();}static struct file_operations ads7843_ts_fops = {	read:	ads7843_ts_read,	poll:	ads7843_ts_poll,	ioctl:	ads7843_ts_ioctl,	fasync:	ads7843_ts_fasync,	open:	ads7843_ts_open,	release:ads7843_ts_release,};int sa1100_ts_init(void){	    raw_max_x = 965;	raw_max_y = 970;		    	raw_min_x = 23;	raw_min_y = 45;					res_x =640;	res_y =480;	xyswap = 0;	head = 0;	tail = 0;	cal_ok = 1;	x_rev = 0;	y_rev = 1;	init_waitqueue_head(&queue);	wait_for_action();	return 0;}static devfs_handle_t devfs_handle, devfs_ts_dir;int __init ads7843_ts_init(void){	int ret;	if ((ret=devfs_register_chrdev(TS_MAJOR, TS_NAME, &ads7843_ts_fops))!=0)	{		printk("registering of " TS_NAME " is failed\n");		return ret;	}	devfs_ts_dir = devfs_mk_dir(NULL, "touchscreen", NULL);	devfs_handle = devfs_register(devfs_ts_dir, "0raw",			DEVFS_FL_DEFAULT,			TS_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR,			&ads7843_ts_fops, NULL);			if ((ret = request_irq(IRQ_GPIO_ADS7843, ads7843_ts_interrupt,				       SA_SHIRQ|SA_INTERRUPT, TS_NAME, dev_id)))	{		printk("ads7843_ts_init: failed to register IRQ\n");		free_irq(IRQ_GPIO_ADS7843, dev_id);		return ret;	}	if ((ret = sa1100_ts_init()) != 0)	{		free_irq(IRQ_GPIO_ADS7843, dev_id);		return ret;	}		GPDR0 &= ~GPIO_bit(ADS7843_BUSY);	GPDR0 &= ~GPIO_bit(ADS7843_DOUT);	Ads7843_Enable_IRQ();	printk("ads7843 touch screen driver initialized\n");	return 0;}void __exit ads7843_ts_cleanup(void){	if (in_timehandle)		del_timer(&timer);	free_irq(IRQ_GPIO_ADS7843, dev_id);	devfs_unregister_chrdev(TS_MAJOR, TS_NAME);	printk("ads7843 touch screen driver removed\n");}module_init(ads7843_ts_init);module_exit(ads7843_ts_cleanup);

⌨️ 快捷键说明

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