ADC和s3c2440 触摸屏驱动
10 位 CMOS 的 ADC(模数转换器)是有 8 通道模拟输入的循环类型设备。其转换模拟输入
信号到 10 位的数字编码,最大的转换率是在 2.5MHz 转换时钟下达到 500KSPS。AD 转换
器支持片上采样和保持功能及掉电模式。
触摸屏接口可以控制或选择触摸屏触点用于 XY 坐标的转换。触摸屏接口包括触摸触点控
制逻辑和有中断产生逻辑的 ADC 接口逻辑。
触摸屏接口模式
(1) 正常转换模式
单个转换模式可能多数是使用在通用目的的ADC转换。该模式可以通过设置
ADCCON(ADC控制寄存器)来初始化并且完成对ADCDAT0 的读写操作(ADC数据寄存
器 0)。
(2) 分离XY坐标转换模式
触摸屏控制器可以在两种转换模式中的一种模式下操作。分离的XY坐标转换模式由以下方
法操作。X坐标模式写X坐标转换数据到ADCDAT0,触摸屏接口产生中断源到中断控制
器。Y坐标模式写Y坐标转换数据到ADCDAT1,触摸屏接口产生中断源到中断控制器
(3) 自动(连续)XY坐标转换模式
自动(连续)XY坐标转换模式是如下操作,触摸屏控制器连续的转换触摸X坐标和Y坐
标。在触摸控制器写X测量数据到ADCDAT0 且写Y测量数据到ADCDAT1 后,触摸屏接口
产生中断源到自动坐标转换模式下的中断控制器。
(4) 等待中断模式
当光标按下,触摸屏控制器产生中断信号(INT_TC)。触摸屏控制器的等待中断模式必须
设定为触摸屏接口中触点的状态(XP、XM、YP、YM)。
在触摸屏控制器产生中断信号(INT_TC),等待中断模式必须被清除。(XY_PST设置到
无操作模式)
首先就是要初始化了。
//configure TS
ADCCON = (1 << 14) | (25 << 6);
ADCDLY = 10000;
我们设的就是等待中断模式。说明要求设置的位
Touch Screen Controller generates interrupt (INT_TC) signal when the Stylus is down. Waiting for Interrupt Mode
setting value is rADCTSC=0xd3; // XP_PU, XP_Dis, XM_Dis, YP_Dis, YM_En.
// wait for down YM en YP dis XM dis XP dis XP PU en wait
ADCTSC = (0 << 8) | (1 << 7) | ( 1 << 6) | (0 << 5) | (1 << 4) | (0 << 3) | 0x3;
// wait for up YM en YP dis XM dis XP dis XP PU en wait
ADCTSC = (1 << 8) | (1 << 7) | ( 1 << 6) | (0 << 5) | (1 << 4) | (0 << 3) | 0x3;
基本的中断和转换过程是这样的。
ts中断进入-》ADC中断,
down中断 等ADC中断。
ADC中断等up中断
up中断等down中断
在ADC中断的时候就是自动处理X,Y坐标的时候
由于涉及到始终频率。所以函数在PROBE的时候要设好时钟!
在内核也要申请相关的中断源。由于中断不能处理太长的问题。所以这次用了工作队列来完成转换和打印的工作
有些地方是多余的。是自己加上去的。作用并不大
代码如下。只列出了重要的函数。由于采集到的坐标还没作相对的校验。你可以用ts_lib校验。或者3点成一个面写个算法校验一下
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("KK");
struct lcd {
struct cdev dev;
struct work_struct work;
struct work_struct work1;
dev_t no;
int irq;
int irq1;
unsigned char *lcd_base;
unsigned long adccon;
unsigned long adctsc;
unsigned long adcdly;
unsigned long adcdat0;
unsigned long adcdat1;
unsigned long adcupnd;
void (*on) (struct lcd * lcd);
void (*off) (struct lcd * lcd);
};
struct lcd my_lcd;
void lcd_on(struct lcd *lcd)
{
unsigned int value;
value = ioread32(lcd->adccon);
value = (1 << 14) | (25 << 6);
iowrite32(value, lcd->adccon);
value = ioread32(lcd->adcdly);
value = 10000;
iowrite32(value, lcd->adcdly);
value = ioread32(lcd->adctsc);
value =
(0 << 8) | (1 << 7) | (1 << 6) | (0 << 5) | (1 << 4) | (0 << 3) |
0x3;
iowrite32(value, lcd->adctsc);
}
struct file_operations my_lcd_ops = {
.open = lcd_open,
.release = my_release,
};
int my_remove(struct device *dev);
int my_probe(struct device *dev);
struct device_driver my_driver = {
.name = "s3c2410-ts",
.probe = my_probe,
.remove = my_remove,
.bus = &platform_bus_type,
};
irqreturn_t irq1_handler(int irq, void *dev_id, struct pt_regs *regs)
{
struct lcd *tmp = dev_id;
schedule_work(&tmp->work1);
return IRQ_HANDLED;
}
irqreturn_t irq0_handler(int irq, void *dev_id, struct pt_regs * regs)
{
struct lcd *tmp = dev_id;
schedule_work(&tmp->work);
return IRQ_HANDLED;
}
void work_handler1(void *data)
{
struct lcd *tmp = data;
unsigned int val;
unsigned int val1;
unsigned int val2;
val = ioread32(tmp->adcdat0);
val1 = ioread32(tmp->adcdat1);
printk("x = %d ,y = %d \n", val & 0x3ff, val1 & 0x3ff);
input_report_abs(&tmp->dev, ABS_X, val & 0x3ff);
input_report_abs(&tmp->dev, ABS_Y, val1 & 0x3ff);
input_report_key(&tmp->dev, ABS_PRESSURE, 1);
input_sync(&tmp->dev);
val2 = ioread32(tmp->adctsc);
val2 =
(0 << 8) | (1 << 7) | (1 << 6) | (0 << 5) | (1 << 4) | (0 << 3) |
0x3;
iowrite32(val2, tmp->adctsc);
}
void work_handler(void *data)
{
struct lcd *tmp = data;
unsigned int val;
val = ioread32(tmp->adcdat0);
if (val & (1 << 15)) {
printk("up\n");
val = ioread32(tmp->adctsc);
val =
(0 << 8) | (1 << 7) | (1 << 6) | (0 << 5) | (1 << 4) | (0 << 3)
| 0x3;
iowrite32(val, tmp->adctsc);
} else {
printk("down\n");
val = ioread32(tmp->adctsc);
val = (1 << 2) | 0x0;
iowrite32(val, tmp->adctsc);
val = ioread32(tmp->adccon);
val |= 1;
iowrite32(val, tmp->adccon);
}
}
struct class *test_class = NULL;
struct class_device *test_class_device = NULL;
struct clk *cl = 0;
int my_probe(struct device *dev)
{
int ret;
printk("test_xxx\n");
cl = clk_get(NULL, "adc");
clk_use(cl);
clk_enable(cl);
#if 1
test_class = class_create(THIS_MODULE, "KK");
if (IS_ERR(test_class)) {
return PTR_ERR(test_class);
}
test_class_device =
class_device_create(test_class, my_lcd.no, NULL, "test");
if (IS_ERR(test_class_device)) {
return PTR_ERR(test_class_device);
}
my_lcd.no = MKDEV(27, 0);
#endif
ret = register_chrdev_region(my_lcd.no, 1, "led");
if (ret) {
printk("register char device number failed.\n");
return ret;
}
my_lcd.on = lcd_on;
my_lcd.off = lcd_off;
cdev_init(&my_lcd.dev, &my_lcd_ops);
cdev_add(&my_lcd.dev, my_lcd.no, 1);
char *p;
p = request_mem_region(0x58000000, SZ_1M, "lcd");
if (IS_ERR(p)) {
printk("request io mem failed.\n");
unregister_chrdev_region(my_lcd.no, 1);
return PTR_ERR(p);
}
my_lcd.irq = IRQ_TC;
my_lcd.irq1 = IRQ_ADC;
my_lcd.lcd_base = ioremap_nocache(0x58000000, SZ_1M);
/* ioremap_cahced */
my_lcd.adccon = my_lcd.lcd_base;
my_lcd.adctsc = my_lcd.lcd_base + 0x04;
my_lcd.adcdly = my_lcd.lcd_base + 0x08;
my_lcd.adcdat0 = my_lcd.lcd_base + 0x0c;
my_lcd.adcdat1 = my_lcd.lcd_base + 0x10;
my_lcd.adcupnd = my_lcd.lcd_base + 0x14;
INIT_WORK(&my_lcd.work, work_handler, &my_lcd);
INIT_WORK(&my_lcd.work1, work_handler1, &my_lcd);
request_irq(my_lcd.irq, irq0_handler, SA_SAMPLE_RANDOM, "irq0",
&my_lcd);
request_irq(my_lcd.irq1, irq1_handler, SA_SAMPLE_RANDOM, "irq1",
&my_lcd);
ts.evbit[0] = BIT(EV_ABS) | BIT(EV_SYN);
set_bit(EV_ABS, ts.evbit);
set_bit(EV_SYN, ts.evbit);
input_set_abs_params(&ts, ABS_X, 0, 0x3ff, 0, 0);
input_set_abs_params(&ts, ABS_Y, 0, 0x3ff, 0, 0);
input_set_abs_params(&ts, ABS_PRESSURE, 0, 1, 0, 0);
input_register_device(&ts);
return 0;
}
int my_remove(struct device *dev)
{
printk("remove .... \n");
cdev_del(&my_lcd);
unregister_chrdev_region(my_lcd.no, 1);
class_device_destroy(test_class, my_lcd.no);
class_destroy(test_class);
clk_disable(cl);
clk_unuse(cl);
clk_put(cl);
return 0;
}
int test_init(void)
{
driver_register(&my_driver);
return 0;
}
module_init(test_init);
module_exit(test_exit);
阅读(667) | 评论(0) | 转发(0) |