📄 ucb1400_ts_tinyx.c
字号:
}
buf[head] = cur_data;
if (++head == BUFSIZE)
head = 0;
if (head == tail && tail++ == BUFSIZE)
tail = 0;
copy_right = 1;
}
unsigned int ucb1400_adc_read( char channel )
{
unsigned short flag=0;
unsigned short val=0;
flag = AE;
pxa_ac97_write(&pxa_ac97_codec, 0x66, flag);
flag |= AS;
pxa_ac97_write(&pxa_ac97_codec, 0x66, flag);
flag |= channel;
pxa_ac97_write(&pxa_ac97_codec, 0x66, flag);
for(;;)
{
val = pxa_ac97_read(&pxa_ac97_codec, 0x68);
if ( val & (1<<15) )
break;
set_current_state(TASK_INTERRUPTIBLE );
schedule_timeout(1);
}
/* if (channel == AI_TSPY)
printk(KERN_EMERG" X POSITION IS 0x%08x\n", val);
else
printk(KERN_EMERG" Y POSITION IS 0x%08x\n", val);
*/
return (val & 0x3ff);
}
static unsigned short read_x_position(void )
{
pxa_ac97_write(&pxa_ac97_codec, 0x64, (1<<4) | (1<<1) | (1<<8) | (1<<11));
pxa_ac97_write(&pxa_ac97_codec, 0x64, (1<<4) | (1<<1) | (1<<8) | (1<<11));
pxa_ac97_write(&pxa_ac97_codec, 0x64, (1<<4) | (1<<1) | (2<<8) | (1<<11));
udelay(55);
return ucb1400_adc_read( AI_TSPY );
}
static unsigned short read_y_position(void )
{
pxa_ac97_write(&pxa_ac97_codec, 0x64, (1<<6) | (1<<3) | (1<<8) | (1<<11));
pxa_ac97_write(&pxa_ac97_codec, 0x64, (1<<6) | (1<<3) | (1<<8) | (1<<11));
pxa_ac97_write(&pxa_ac97_codec, 0x64, (1<<6) | (1<<3) | (2<<8) | (1<<11));
udelay(55);
return ucb1400_adc_read( AI_TSPX );
}
static void read_xy(void )
{
samples[0].x = read_x_position( );
samples[0].y = read_y_position( );
samples[1].x = read_x_position( );
samples[1].y = read_y_position( );
new_data( );
}
static void wait_for_action(void)
{
set_GPIO_IRQ_edge(13, GPIO_RISING_EDGE);
enable_irq(UCB1400_IRQ);
}
/*IRQ interrupt handle function*/
void ucb1400_IRQ_handle( void)
{
disable_irq( UCB1400_IRQ );
pxa_ac97_write(&pxa_ac97_codec, 0x60, 0x0);
cur_data.pressure = 1;
if_pressure = 1;
read_xy( );
if(fasync)
kill_fasync(&fasync, SIGIO, POLL_IN);
wake_up_interruptible(&ts_wait);
ts_occur = 1;
return ;
}
void task_queue_timer_func(void * parm )
{
timer_handle( );
}
static void ucb1400_ts_timer(unsigned long data)
{
static struct tq_struct task_one=
{
routine : task_queue_timer_func,
data: NULL,
sync:0,
};
schedule_task(&task_one);
}
static int ucb1400_ts_starttimer(void)
{
//modify here can effect other running application
unsigned long time_long=jiffies + 2;
if(!in_timehandle)
{
in_timehandle++;
init_timer(&timer);
timer.function = ucb1400_ts_timer;
timer.expires = time_long ;
add_timer(&timer);
}
return 0;
}
static TS_EVENT get_data(void)
{
int last = tail;
if (++tail == BUFSIZE)
tail = 0;
return buf[last];
}
/*Read operation*/
static ssize_t ucb1400_ts_read(struct file *filp, char *buf, size_t count, loff_t *l)
{
TS_EVENT t;
short out_buf[4];
int scale;
pxa_ac97_write(&pxa_ac97_codec, 0x60, 0x0);
ts_occur = 0;
short tail=0;//add by bruce
short head=0;//add by bruce
read_xy( );
pxa_ac97_write(&pxa_ac97_codec, 0x64, MX| PX | PXP | MXP | PYG | MYG | TM_INTERRUPT );
if (copy_right)
{
t = get_data();
out_buf[0] = t.pressure;
if(t.pressure==0)
{
tch_queue.head=0;
tch_queue.tail=0;
tch_queue.num=0;
//tch_queueSumX=0;
//tch_queueSumY=0;
}
else
{
if(tch_queue.num<QUE_LENTH)
{
tch_queue.tch_queue[tch_queue.tail].x=t.x;
tch_queue.tch_queue[tch_queue.tail].y=t.y;
tch_queue.tch_queue[tch_queue.tail].millisecs=t.millisecs;
tch_queue.num++;
tch_queue.tail++;
}
else
{
tch_queue.tch_queue[tch_queue.tail].x=t.x;
tch_queue.tch_queue[tch_queue.tail].y=t.y;
tch_queue.tch_queue[tch_queue.tail].millisecs=t.millisecs;
tch_queue.head=(++tch_queue.head)%(QUE_LENTH+1);
tch_queue.tail=(++tch_queue.tail)%(QUE_LENTH+1);
}
}
if(tch_queue.num>8)
{
int difX=0;
int difY=0;
int n=0;
int k=0;
int sum4Hx=0;
int sum4Hy=0;
int sum4Tx=0;
int sum4Ty=0;
for(n=0;n<4;n++)
{
sum4Hx+=tch_queue.tch_queue[(tch_queue.head+n)%(QUE_LENTH+1)].x;
sum4Tx+=tch_queue.tch_queue[(tch_queue.tail+QUE_LENTH-n)%(QUE_LENTH+1)].x;
sum4Ty+=tch_queue.tch_queue[(tch_queue.tail+QUE_LENTH-n)%(QUE_LENTH+1)].y;
sum4Hy+=tch_queue.tch_queue[(tch_queue.head+n)%(QUE_LENTH+1)].y;
}
difX=(sum4Tx-sum4Hx)/4;
difY=(sum4Ty-sum4Hy)/4;
//printk(KERN_EMERG "head:%d ,head.x:%d head.y:%d ,tail:%d ,tail.x:%d tail.y:%d ,difX:%d ,difY:%d ,difM:%d \n",tch_queue.head,tch_queue.tch_queue[tch_queue.head].x,tch_queue.tch_queue[tch_queue.head].y,tch_queue.tail,tch_queue.tch_queue[tch_queue.tail].x,tch_queue.tch_queue[tch_queue.tail].y,difX,difY,difM);
if((difX<50&&difX>-50)&&(difY<50&&difY>-50))
{
//printk(KERN_EMERG "single point mode\n");
tch_queueSumX=0;
tch_queueSumY=0;
//tail=tch_queue.tail;
head=tch_queue.head;
for(k=0;k<tch_queue.num;k++)
{
tch_queueSumX+=(int)(tch_queue.tch_queue[head].x);
tch_queueSumY+=(int)(tch_queue.tch_queue[head].y);
head++;
head=head%(QUE_LENTH+1);
}
//printk(KERN_EMERG "tch_queueSumX: %d,tch_queueSumY: %d, tch_queue.num: %d\n",tch_queueSumX,tch_queueSumY,tch_queue.num);
t.x=tch_queueSumX/tch_queue.num;
t.y=tch_queueSumY/tch_queue.num;
}
else
{
//printk(KERN_EMERG "pressMove mode\n");
tch_queueSumX=0;
tch_queueSumY=0;
for(n=0;n<8;n++)
{
tch_queueSumX+=tch_queue.tch_queue[(tch_queue.tail+QUE_LENTH-n)%(QUE_LENTH+1)].x;
tch_queueSumY+=tch_queue.tch_queue[(tch_queue.tail+QUE_LENTH-n)%(QUE_LENTH+1)].y;
//printk(KERN_EMERG "%d ,%d\n",tch_queue.tch_queue[(tch_queue.tail+QUE_LENTH-n)%(QUE_LENTH+1)].x,tch_queue.tch_queue[(tch_queue.tail+QUE_LENTH-n)%(QUE_LENTH+1)].y);
}
//printk(KERN_EMERG "Move mode: tch_queueSumX: %d,tch_queueSumY: %d\n",tch_queueSumX,tch_queueSumY);
t.x=tch_queueSumX/8;
t.y=tch_queueSumY/8;
}
}
else
{
/*
int k=0;
//printk(KERN_EMERG "single point mode\n");
tch_queueSumX=0;
tch_queueSumY=0;
//tail=tch_queue.tail;
head=tch_queue.head;
for(k=0;k<tch_queue.num;k++)
{
tch_queueSumX+=(int)(tch_queue.tch_queue[head].x);
tch_queueSumY+=(int)(tch_queue.tch_queue[head].y);
head++;
head=head%(QUE_LENTH+1);
}
//printk(KERN_EMERG "tch_queueSumX: %d,tch_queueSumY: %d, tch_queue.num: %d\n",tch_queueSumX,tch_queueSumY,tch_queue.num);
t.x=tch_queueSumX/tch_queue.num;
t.y=tch_queueSumY/tch_queue.num;
*/
}
/*these codes for test by bruce begin*/
//out_buf[1] = (res_x*(t.x-raw_min_x))/(raw_max_x-raw_min_x+35)-15+t.y*10/200;
//out_buf[2] = (res_y*(raw_max_y-t.y))/(raw_max_y-raw_min_y+30)-16+t.x*15/200;
/*these codes for test by bruce end*/
out_buf[1] = (res_x*(t.x-raw_min_x))/(raw_max_x-raw_min_x)+2;
out_buf[2] = (res_y*(raw_max_y-t.y))/(raw_max_y-raw_min_y)-1;
int tempx=0;
int tempy=0;
tempx = (int)(out_buf[1]);
tempy = (int)(out_buf[2]);
out_buf[1]=(short)(tempx-(xConDif+x2xScaDif*tempx+y2xScaDif*tempy)/mulNum);
out_buf[2]=(short)(tempy-(yConDif+y2yScaDif*tempy+x2yScaDif*tempx)/mulNum);
//printk(KERN_EMERG "%d,%d,%d,%d %d,%d,%d, %d, %d,%d,%d ,%d,%d\n",tempx,tempy,out_buf[0],t.millisecs,xConDif,x2xScaDif,y2xScaDif,mulNum,yConDif,y2yScaDif,x2yScaDif,out_buf[1],out_buf[2]);
out_buf[3] = t.millisecs;
/*adjust the touch screen*/
//scale = 5-out_buf[2]/100;
//out_buf[1] = out_buf[1] + 3*scale;
//out_buf[2] = out_buf[2] + 2;
//printk(KERN_EMERG "X:%d,Y:%d,Pressure:%d\n",out_buf[1],out_buf[2],out_buf[0]);
copy_to_user(buf, &out_buf, sizeof(out_buf));
copy_right = 0;
}
if (if_pressure)
{
ucb1400_ts_starttimer();
}
else
{
wait_for_action( );
restore_interrupt();
pxa_ac97_write(&pxa_ac97_codec, 0x60, 0x2000);
}
return count;
}
/*POLL Function*/
static unsigned int ucb1400_ts_poll(struct file *filp, poll_table *wait)
{
poll_wait(filp, &ts_wait, wait);
if (ts_occur)
return POLLIN | POLLRDNORM;
return 0;
}
/*fasync Function */
static int ucb1400_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 void calibrate_init(void)
{
raw_max_x = 955;
raw_max_y = 954;
raw_min_x = 45;
raw_min_y = 80;
res_x = 640;
res_y = 480;
xyswap = 1;
head = 0;
tail = 0;
cal_ok = 1;
x_rev = 0;
y_rev = 1;
/* --bruce-- */
tch_queue.head=0;
tch_queue.tail=0;
tch_queue.num=0;
tch_queueSumX=0;
tch_queueSumY=0;
sumM=0;
xConDif=i2c_read_long(0);//add by bruce
x2xScaDif=i2c_read_long(1);//add by bruce
y2xScaDif=i2c_read_long(2);//add by bruce
yConDif=i2c_read_long(3);//add by bruce
y2yScaDif=i2c_read_long(4);//add by bruce
x2yScaDif=i2c_read_long(5);//add by bruce
mulNum=i2c_read_long(6);//add by bruce
init_waitqueue_head(&queue);
wait_for_action();
return ;
}
void bl_timer_func(unsigned long data)
{
XSBASE270_BCR_CLEARBIT(XSB_BCR_LCD_PWR_ENB);
}
void bl_thread(void * data)
{
struct task_struct *tsk = current;
daemonize();
reparent_to_init();
tsk->tty = NULL;
tsk->policy = SCHED_FIFO;
tsk->rt_priority = 1;
strcpy(tsk->comm, "bl_thread");
init_timer(&bl_timer);
bl_timer.function = bl_timer_func;
bl_timer.expires = jiffies + bright_time*HZ;
add_timer(&bl_timer);
}
static int ucb1400_ts_open(struct inode *inode, struct file *filp)
{
// init_waitqueue_head(&ts_wait);
ts_occur = 0;
ts_clear( );
//calibrate_init( );
/*init_completion(&kthread_completion);
ret=kernel_thread(ucb1400_thread, 0, CLONE_FS | CLONE_FILES);
if ( ret>=0 )
{
wait_for_completion(&kthread_completion);
}
*/
ucb1400_enable_irq( );
return 0;
}
static struct file_operations ucb1400_ts_fops=
{
open: ucb1400_ts_open,
poll: ucb1400_ts_poll,
fasync: ucb1400_ts_fasync,
read: ucb1400_ts_read,
ioctl: ucb1400_ts_ioctl,
};
int __init ucb1400_ts_init(void)
{
int res;
res = register_chrdev(11, "UCB1400 TouchScreen Controller", &ucb1400_ts_fops);
kernel_thread(bl_thread, NULL, CLONE_FS | CLONE_FILES);//add by bruce
init_waitqueue_head(&ts_wait);
calibrate_init( );/* --bruce-- */
return res;
}
void __exit ucb1400_ts_cleanup(void)
{
}
module_init(ucb1400_ts_init);
module_exit(ucb1400_ts_cleanup);
EXPORT_SYMBOL(ucb1400_IRQ_handle);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -