ts.c源码:
#include "linux/module.h"
#include "linux/init.h"
#include "linux/fs.h"
#include "linux/interrupt.h"
#include "linux/irq.h"
#include "linux/sched.h"
#include "linux/pm.h"
#include "linux/sysctl.h"
#include "linux/proc_fs.h"
#include "linux/delay.h"
#include "linux/platform_device.h"
#include "linux/input.h"
#include "linux/io.h"
#include "linux/clk.h"
#include "linux/delay.h"
static struct timer_list ts_timer;
static struct input_dev *ts_dev;
struct adc_regs {
unsigned long adccon;
unsigned long adctsc;
unsigned long adcdly;
unsigned long adcdat0;
unsigned long adcdat1;
unsigned long adcupdn;
unsigned long adcclrint;
unsigned long reserved;
unsigned long adcclrintpndnup;
};
static struct adc_regs *adc_regs;
static void enter_wait_for_pen_down(void)
{
adc_regs->adctsc = 0xd3;
}
static void enter_wait_for_pen_up(void)
{
adc_regs->adctsc = 0x1d3;
}
static void enter_measure_xy_mode(void)
{
adc_regs->adctsc = ((1<<7) | (1<<6) | (1<<4) | (1<<3) | (1<<2));
}
static void start_adc(void)
{
adc_regs->adccon |= (1<<0);
}
static irqreturn_t ts_pen_down_up_isr(int irq, void *dev_id)
{
unsigned long data0, data1;
int down;
data0 = adc_regs->adcdat0;
data1 = adc_regs->adcdat1;
down = (!(data0 & (1<<15))) && (!(data1 & (1<<15)));
if (!down)
{
//printk("pen up\n");
enter_wait_for_pen_down();
// 调用evdev_event: 保存,唤醒
input_event(ts_dev, EV_ABS, ABS_PRESSURE, 0);
input_event(ts_dev, EV_KEY, BTN_TOUCH, 0);
input_sync(ts_dev);
}
else
{
//printk("pen down\n");
//enter_wait_for_pen_up();
// 进入"自动测量x/y座标模式"
enter_measure_xy_mode();
// 启动ADC
start_adc();
}
adc_regs->adcupdn = 0;
adc_regs->adcclrint = 0;
adc_regs->adcclrintpndnup = 0;
return IRQ_HANDLED;
}
static irqreturn_t adc_isr(int irq, void *dev_id)
{
// 为何不在这里立刻处理ADC到结果?
// 因为6410的ADC有个缺点:
// 当ADC刚完成时, 必须等待若干ms,
// 才能读取adcdat0,adcdata1来判断
// 当前的触摸屏是被按下还是松开
// 启动定时器, 是为了不在中断处理函数里等待
mod_timer(&ts_timer, jiffies + HZ/100);
enter_wait_for_pen_up();
adc_regs->adcupdn = 0;
adc_regs->adcclrint = 0;
adc_regs->adcclrintpndnup = 0;
return IRQ_HANDLED;
}
static irqreturn_t adc_isr_ok_old(int irq, void *dev_id)
{
int x,y;
int adcdat0,adcdat1;
int down;
#if 1 // in auto xy mode, after adc interrupt, have to wait several ms to test up/down
udelay(1000);
udelay(1000);
udelay(1000);
udelay(1000);
#endif
adcdat0 = adc_regs->adcdat0;
adcdat1 = adc_regs->adcdat1;
x = adcdat0 & 0xfff;
y = adcdat1 & 0xfff;
down = (!(adcdat0 & (1<<15))) && (!(adcdat1 & (1<<15)));
//printk("adcdat0 = 0x%x, adc_dat1 = 0x%x\n", adcdat0, adcdat1);
if (down)
{
//printk("enter_wait_for_pen_up\n");
enter_wait_for_pen_up();
//printk("x = %d, y = %d\n", x, y);
input_event(ts_dev, EV_ABS, ABS_X, x);
input_event(ts_dev, EV_ABS, ABS_Y, y);
input_event(ts_dev, EV_ABS, ABS_PRESSURE, 1);
input_event(ts_dev, EV_KEY, BTN_TOUCH, 1);
input_sync(ts_dev);
// 启动定时器
mod_timer(&ts_timer, jiffies + HZ/100);
}
else
{
//printk("enter_wait_for_pen_down\n");
enter_wait_for_pen_down();
input_event(ts_dev, EV_ABS, ABS_PRESSURE, 0);
input_event(ts_dev, EV_KEY, BTN_TOUCH, 0);
input_sync(ts_dev);
}
adc_regs->adcupdn = 0;
adc_regs->adcclrint = 0;
adc_regs->adcclrintpndnup = 0;
return IRQ_HANDLED;
}
static void ts_timer_function_ok_old(unsigned long data)
{
// 如果触摸笔已经松开, 就没必要再次启动ADC
// 否则, 启动ADC
unsigned long data0, data1;
int down;
data0 = adc_regs->adcdat0;
data1 = adc_regs->adcdat1;
down = (!(data0 & (1<<15))) && (!(data1 & (1<<15)));
if (down)
{
enter_measure_xy_mode();
start_adc();
}
else
{
enter_wait_for_pen_down();
input_event(ts_dev, EV_ABS, ABS_PRESSURE, 0);
input_event(ts_dev, EV_KEY, BTN_TOUCH, 0);
input_sync(ts_dev);
}
}
static void ts_timer_function(unsigned long data)
{
// 如果触摸笔已经松开, 就没必要再次启动ADC
// 否则, 启动ADC
unsigned long data0, data1;
int down;
int x, y;
data0 = adc_regs->adcdat0;
data1 = adc_regs->adcdat1;
down = (!(data0 & (1<<15))) && (!(data1 & (1<<15)));
if (down)
{
x = data0 & 0xfff;
y = data1 & 0xfff;
input_event(ts_dev, EV_ABS, ABS_X, x);
input_event(ts_dev, EV_ABS, ABS_Y, y);
input_event(ts_dev, EV_ABS, ABS_PRESSURE, 1);
input_event(ts_dev, EV_KEY, BTN_TOUCH, 1);
input_sync(ts_dev);
enter_measure_xy_mode();
start_adc();
}
else
{
enter_wait_for_pen_down();
input_event(ts_dev, EV_ABS, ABS_PRESSURE, 0);
input_event(ts_dev, EV_KEY, BTN_TOUCH, 0);
input_sync(ts_dev);
}
}
static int ts_init(void)
{
struct clk *clk;
// 1. 分配input_dev
ts_dev = input_allocate_device();
// 2. 设置
// 2.1 能产生哪类事件
set_bit(EV_KEY, ts_dev->evbit);
set_bit(EV_ABS, ts_dev->evbit);
// 2.2 能产生这类事件里的哪些事件
set_bit(BTN_TOUCH, ts_dev->keybit);
input_set_abs_params(ts_dev, ABS_X, 0, 0xfff, 0, 0);
input_set_abs_params(ts_dev, ABS_Y, 0, 0xfff, 0, 0);
input_set_abs_params(ts_dev, ABS_PRESSURE, 0, 1, 0, 0);
// 3. 注册
input_register_device(ts_dev);
// 4. 硬件相关
adc_regs = ioremap(0x7E00B000, sizeof(struct adc_regs));
clk = clk_get(NULL, "adc");
clk_enable(clk); // PCLK_GATE[12]设为1
// bit[16] : 1 = 12-bit A/D conversion
// bit[14] : 1 - enable A/D converter prescaler enable
// bit[13:6] : A/D converter prescaler value,
// PCLK=66500000, adcclk=pclk/(n+1)
// 取值13, adclk=66.5MHz/14=4.75
adc_regs->adccon = (1<<16) | (1<<14) | (65<<6);
adc_regs->adcdly = 0xffff;
adc_regs->adcclrintpndnup = 0;
request_irq(IRQ_TC, ts_pen_down_up_isr, IRQF_SHARED, "pen_down_up", 1);
request_irq(IRQ_ADC, adc_isr, IRQF_SHARED, "adc", 1);
init_timer(&ts_timer);
ts_timer.expires = 0;
ts_timer.function = ts_timer_function;
add_timer(&ts_timer);
// 进入"wait for interrupt mode", 等待触摸笔按下或松开的模式
enter_wait_for_pen_down();
return 0;
}
static void ts_exit(void)
{
del_timer(&ts_timer);
free_irq(IRQ_TC, 1);
free_irq(IRQ_ADC, 1);
iounmap(adc_regs);
input_unregister_device(ts_dev);
input_free_device(ts_dev);
}
module_init(ts_init);
module_exit(ts_exit);
MODULE_LICENSE("GPL");
====================================================================
Mekefile文件:
KERN_DIR = /home/linux/linux-3.0.1
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += ts.o
=====================================================================
测试:
一、配置内核make menuconfig ARCH=arm 去掉第三张图片中touchscreens选项前的*
若只做这一步,编译内核会提示如下错误:
arch/arm/mach-s3c64xx/built-in.o: In function `smdk6410_machine_init':
/xh/work/linux-3.0.1/arch/arm/mach-s3c64xx/mach-smdk6410.c:1096: undefined reference to `s3c_ts_set_platdata'
arch/arm/mach-s3c64xx/built-in.o:(.init.data+0x26c): undefined reference to `s3c_device_ts'
make: *** [.tmp_vmlinux1] Error 1
[root@IVAN linux-3.0.1]#
二、打开/arch/arm/mach-s3c64xx/mach-smdk6410.c
搜索 “s3c_ts_set_platdata”和“s3c_device_ts”,并注释掉这两行。
成功……
三、使用新内核启动:
1、编译内核:
make zImage //生成内核镜像文件
cp arch/arm/boot/zImage ../../zImage_no_ts
2、把开发板设置为SD卡启动,使用SD卡启动后按空格进入SD卡的u-boot;
3、用SD卡里面的u-boot烧写内核到0x000000200000-0x000000700000 : "Kernel"分区:
tftp 50008000 zImage_no_ts
nand erase 200000 500000
nand write 50008000 200000 500000
4、烧写完成后设置开发版为nand flash启动,使用新内核启动。
四、编译测试(详细可以参考JZ2440触摸屏驱动程序(输入子系统)):
insmod ts.ko
insmod lcd.ko
编译:
tar xzf tslib-1.4.tar.gz
cd tslib
./autogen.sh
mkdir tmp
echo "ac_cv_func_malloc_0_nonnull=yes" >arm-linux.cache
./configure --host=arm-linux --cache-file=arm-linux.cache --prefix=$(pwd)/tmp
make
make install
set bootargs root=/dev/nfs nfsroot=10.1.0.124:/rootfs ip=10.1.0.126 console=ttySAC0
安装:
cd tmp
cp * -rf 开发板的/
使用:
1.
修改 /etc/ts.conf第1行(去掉#号):
# module_raw input
改为:
module_raw input
2.
export TSLIB_FBDEVICE=/dev/fb0 # LCD
export TSLIB_TSDEVICE=/dev/event2 # 触摸屏
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_PLUGINDIR=/lib/ts
export TSLIB_CONSOLEDEVICE=none
测试:
ts_calibrate
ts_test
hexdump /dev/event2
上一篇:OK6410分层分离(总线-驱动-设备模型)
下一篇:OK6410之LCD驱动
推荐阅读
史海拾趣
在电子行业中,台湾双羽公司凭借其卓越的技术实力与不懈的创新精神,逐步发展成为行业内的佼佼者。以下是五个关于台湾双羽公司发展起来的相关故事,每个故事均基于事实描述,且字数达到要求。
1. 技术合作的起点
故事概述:台湾双羽公司的发展历程可以追溯到1973年,这一年,公司与日本福岛双羽电机公司建立了技术合作关系。这一合作不仅为双羽带来了先进的电阻器制造技术,还为其后续的产品开发和品质提升奠定了坚实基础。通过引进日本的高品质电阻器生产工艺和管理经验,双羽迅速在电阻器市场上站稳了脚跟,并逐渐发展成为业界的佼佼者。
细节补充:在技术合作的初期,双羽公司派遣了多名技术人员前往日本学习,他们不仅掌握了电阻器的核心制造技术,还带回了严谨的生产流程和质量控制标准。这些宝贵的经验和技术积累,为双羽公司后续的创新发展提供了有力支持。
2. 多元化产品线的拓展
故事概述:随着技术的不断积累和市场的逐步扩大,台湾双羽公司开始积极拓展多元化产品线。公司不仅继续深耕电阻器领域,还逐步涉足电容器、电感器等电子元器件的研发和生产。通过多元化产品线的拓展,双羽公司进一步巩固了其在电子行业的地位,并为客户提供了一站式电子元器件解决方案。
细节补充:在多元化产品线的拓展过程中,双羽公司始终坚持技术创新和品质至上的原则。公司不断投入研发资金,引进先进生产设备和技术人才,确保每一款产品的性能和质量都能达到行业领先水平。同时,双羽公司还建立了完善的质量管理体系和售后服务体系,为客户提供全方位的支持和服务。
3. 全球化布局的实现
故事概述:为了更好地服务全球客户并拓展国际市场,台湾双羽公司开始实施全球化布局战略。公司先后在苏州、深圳等地设立生产基地和销售中心,并逐步将产品和服务推向海外市场。通过全球化布局的实现,双羽公司的品牌影响力和市场份额得到了显著提升。
细节补充:在全球化布局的过程中,双羽公司充分考虑了不同地区的市场需求和文化差异。公司针对不同地区的客户需求制定了个性化的产品方案和服务策略,并加强与当地经销商和合作伙伴的合作与交流。这些措施不仅提升了双羽公司的市场竞争力,还为其在全球范围内的快速发展奠定了坚实基础。
4. 创新驱动的发展模式
故事概述:台湾双羽公司始终将创新作为企业发展的核心驱动力。公司不断投入研发资源和技术力量,推动新产品、新技术和新工艺的研发与应用。通过创新驱动的发展模式,双羽公司在电阻器及其他电子元器件领域取得了多项重大技术突破和专利成果。
细节补充:在创新驱动的发展模式下,双羽公司建立了完善的创新体系和激励机制。公司鼓励员工积极参与创新活动并提出合理化建议和意见;同时与高校、科研机构等外部合作伙伴建立紧密的合作关系;共同开展技术研发和人才培养工作。这些措施不仅激发了员工的创新热情和工作积极性;还为公司带来了源源不断的创新动力和发展活力。
5. 社会责任的践行
故事概述:台湾双羽公司在追求经济效益的同时,始终不忘履行社会责任。公司积极参与公益事业和社会活动;为当地经济发展和社会进步做出了积极贡献。通过践行社会责任;双羽公司不仅赢得了社会各界的广泛赞誉和尊重;还进一步提升了企业的品牌形象和知名度。
细节补充:在社会责任的践行过程中;双羽公司注重环保和可持续发展。公司采用先进的生产工艺和设备;减少能源消耗和废弃物排放;实现绿色生产和循环发展。同时;双羽公司还积极参与环保公益活动;倡导绿色消费和低碳生活理念;为构建美好家园贡献自己的力量。
随着市场的不断变化和客户需求的日益多样化,茂达电子开始积极扩展产品线。除了原有的电源转换及电源管理IC外,公司还成功研发了放大器及驱动IC、离散式功率元件等系列产品。这些新产品的推出,不仅丰富了茂达电子的产品线,也为客户提供了更多样化的选择。
随着市场的不断变化和客户需求的日益多样化,茂达电子开始积极扩展产品线。除了原有的电源转换及电源管理IC外,公司还成功研发了放大器及驱动IC、离散式功率元件等系列产品。这些新产品的推出,不仅丰富了茂达电子的产品线,也为客户提供了更多样化的选择。
Hongfa宏发公司,全称厦门宏发电声股份有限公司,由郭满金先生于1984年创立。公司初创时,仅有简陋的厂房和设备,投资不过360万元,员工仅数十人。但宏发从一开始就明确了产品定位与市场定位,专注于继电器研发及制造领域。1987年,宏发成功以中国厂家商标及型号取得UL认证,进一步奠定了其在国际市场上的基础。通过不断的技术积累和市场开拓,宏发逐渐在国内继电器行业中崭露头角。
近年来,随着全球对环保和可持续发展的重视,Hei Inc Optoelectronic Division积极响应国家号召,将绿色可持续发展理念融入到企业的生产经营中。公司投入巨资研发环保型光电子器件,并不断优化生产工艺流程以降低能耗和排放。同时,公司还积极参与各类环保公益活动,提升公众对绿色光电子技术的认知度。这些举措不仅赢得了社会各界的广泛赞誉,还为公司树立了良好的企业形象和品牌形象。在绿色可持续发展的道路上,Hei Inc Optoelectronic Division正稳步前行,不断开创光电子领域的新篇章。
进入2015年后,随着物联网、5G等新兴技术的兴起,光电子器件的市场需求呈现出爆发式增长。Hei Inc Optoelectronic Division敏锐地捕捉到了这一市场趋势,及时调整产品策略,加大了对低功耗、小型化光电子模块的研发力度。公司推出的新一代光电子模块不仅满足了市场对于高效能、低能耗的需求,还凭借其优异的性价比迅速占领了市场份额。这一举措不仅推动了公司的快速增长,还进一步巩固了其在光电子领域的市场地位。
知道1/4波长射频个公式:波长(天线)=(300/f)*0.25*0.96 这个F是指一个固定频率么,现在我的频率是925MHZ to 2175MHZ ,天线长度该如何设置呢?… 查看全部问答∨ |
以太网 Lite MAC(媒体访问控制器)设计用来整合 IEEE 标准内介绍的可用特性。802.3 媒体独立接口(MII)规范。 The Ethernet Lite MAC (Media Access Controller) is designed to incorporate the applicable features described in the IEEE Std ...… 查看全部问答∨ |
CodeWarrior+USB-TAP怎么调试PowerPC(VxWorks系统)下的bootrom 请教高手,一个问题 现在我手上有一个CodeWarrior IDE(Windows版)和USB-TAP 我就是想问:怎么用它们调试基于Freescale’ PowerPC的MPC8270下面的bootrom,我用的是VxWorks系统,可以跟踪romInit、bootInit跑到什么地方的那种,而不是调试Linux下 ...… 查看全部问答∨ |
我使用的QQ2440V3 开发板,按照说明书的介绍,安装好了USB驱动,在DNW中显示为“OK”,但是ActiveSync一直连接不上pc,哪位知道怎么解决?是什么问题造成的?… 查看全部问答∨ |
本来不好意思问这些代码问题。但是钻进了死胡同,看了差不多一天了也还是没有头绪;以前学得都比较顺畅,今天开始不停郁闷。 问题如下: 1、startup.s其中一个功能是把eboot的代码搬到RAM中运行,根据注释,我找到 startup.s中相应的代码: ;&n ...… 查看全部问答∨ |
|
设计资源 培训 开发板 精华推荐
- TE Connectivity利用传感和连接解决方案,赋能电动汽车发展 参与有好礼!
- 【EEWORLD第三十五届】2012年02月社区明星人物揭晓!
- Microchip有奖直播:VectorBlox™ SDK 报名中
- 【EEWORLD第三十三届】2011年12月社区明星人物揭晓!
- 月度原创精选评选2018年7月(总第6期)
- 恩智浦跨界处理器能玩出多少应用
- 有奖直播:英飞凌针对电动工具的高功率、高效率以及高可靠性解决方案
- 免费申请|基于STM32H7处理器的机器视觉微控制器板OpenMV4 Cam H7
- 是德科技有奖直播:湾区圆桌派-穿越频谱壁垒:毫米波技术的创新之路
- 4小时实战+剖析:TI工程师教你快速上手 各种无线产品开发 (限量$14售CC1352R1无线开发板,助你参与动手实验)