Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2294925
  • 博文数量: 218
  • 博客积分: 5767
  • 博客等级: 大校
  • 技术积分: 5883
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-01 14:44
文章存档

2012年(53)

2011年(131)

2009年(1)

2008年(33)

分类: 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 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 中断,其中:

􀁺 中断号为IRQ_ADC_DONE(即62,这个值的确定由处理器的硬件决定,不可更

改为其他值。

􀁺 对应的中断处理函数为s3c2410_isr_adc()

􀁺 中断类型为快速中断(即参数SA_INTERRUPT 指定值)。

􀁺 DEVICE_NAME 参数用来显示中断的拥有者,在/proc/interrupts 中可以看到

*/

if (ret) goto adc_failed;

ret = request_irq(IRQ_TC, s3c2410_isr_tc, SA_INTERRUPT,

DEVICE_NAME, s3c2410_isr_tc);

if (ret) goto tc_failed;

/*

注册触摸屏中断,其中:

􀁺 中断号为IRQ_TC(即61,这个值的确定由处理器的硬件决定,不可更改为其他值。

􀁺 对应的中断处理函数为s3c2410_isr_tc()

􀁺 中断类型为快速中断(即参数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,

&s3c2410_fops, NULL);

#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,

s3c2410_ts_pm_callback);

#endif

tsdev.pm_dev = pm_register(PM_DEBUG_DEV, PM_USER_INPUT,

s3c2410_ts_pm_callback);

#endif

printk(DEVICE_NAME " initialized\n");

return 0;

tc_failed:

free_irq(IRQ_ADC_DONE, s3c2410_isr_adc);

adc_failed:

return ret;

}

static void __exit s3c2410_ts_exit(void)

{

#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, s3c2410_isr_adc);

free_irq(IRQ_TC, s3c2410_isr_tc);

}

module_init(s3c2410_ts_init);

module_exit(s3c2410_ts_exit);

阅读(2212) | 评论(0) | 转发(0) |
0

上一篇:S3C2410触摸屏驱动代码分析2

下一篇:声明

给主人留下些什么吧!~~