全部博文(218)
分类: LINUX
2008-03-01 20:16:23
/*
这段代码完成对刚才得到的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 s
{
#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)
s
#ifdef HOOK_FOR_DRAG
else
s
#endif
spin_unlock_irq(&(tsdev.lock));
/*
释放这把锁。
*/
}
static void s
{
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 s
{
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 s
{
#ifdef HOOK_FOR_DRAG
del_timer(&ts_timer);
//删除定时器
#endif
MOD_DEC_USE_COUNT;
//模块引用数减1
return 0;
}
static struct file_operations s
owner: THIS_MODULE,
open: s
read:s
release: s
#ifdef USE_ASYNC
fasync: s
#endif
poll: s
};
void tsEvent_dummy(void) {}
#ifdef CONFIG_PM
static int s
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 s
{
int ret;
tsEvent = tsEvent_dummy;
/*
tsEvent 为函数指针,指向函数tsEvent_dummy(),不过该函数为空函数,相关定义如
下:
static void (*tsEvent)(void);
……
void tsEvent_dummy(void) {}
*/
ret = register_chrdev(0, DEVICE_NAME, &s
if (ret < 0) {
printk(DEVICE_NAME " can't get major number\n");
return ret;
}
tsMajor = ret;
/*
首先调用register_chrdev()函数来进行设备的注册。
宏DEVICE_NEME 定义为:
#define DEVICE_NAME "s
即该设备的节点名为/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, s
DEVICE_NAME, s
/*
注册ADC 中断,其中:
中断号为IRQ_ADC_DONE(即62,这个值的确定由处理器的硬件决定,不可更
改为其他值。
对应的中断处理函数为s
中断类型为快速中断(即参数SA_INTERRUPT 指定值)。
DEVICE_NAME 参数用来显示中断的拥有者,在/proc/interrupts 中可以看到
*/
if (ret) goto adc_failed;
ret = request_irq(IRQ_TC, s
DEVICE_NAME, s
if (ret) goto tc_failed;
/*
注册触摸屏中断,其中:
中断号为IRQ_TC(即61,这个值的确定由处理器的硬件决定,不可更改为其他值。
对应的中断处理函数为s
中断类型为快速中断(即参数SA_INTERRUPT 指定值)。
DEVICE_NAME 参数用来显示中断的拥有者,在/proc/interrupts 中可以看到
*/
/* Wait for touch screen interrupts */
wait_down_int();
/*
设置等待模式
*/
#ifdef CONFIG_DEVFS_FS
devfs_ts_dir = devfs_mk_dir(NULL, "touchscreen", NULL);
devfs_tsraw = devfs_register(devfs_ts_dir, "0raw", DEVFS_FL_DEFAULT,
tsMajor, TSRAW_MINOR, S_IFCHR | S_IRUSR | S_IWUSR,
&s
#endif
/*
首先调用devfs_mk_dir()函数来创建目录touchscreen,然后调用devfs_register()来进行
注册,这样设备被加载后,其设备节点为/dev/touchscreen/0raw
*/
#ifdef CONFIG_PM
#if 0
tsdev.pm_dev = pm_register(PM_GP_DEV, PM_USER_INPUT,
s
#endif
tsdev.pm_dev = pm_register(PM_DEBUG_DEV, PM_USER_INPUT,
s
#endif
printk(DEVICE_NAME " initialized\n");
return 0;
tc_failed:
free_irq(IRQ_ADC_DONE, s
adc_failed:
return ret;
}
static void __exit s
{
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_tsraw);
devfs_unregister(devfs_ts_dir);
#endif
unregister_chrdev(tsMajor, DEVICE_NAME);
#ifdef CONFIG_PM
pm_unregister(tsdev.pm_dev);
#endif
free_irq(IRQ_ADC_DONE, s
free_irq(IRQ_TC, s
}
module_init(s
module_exit(s