基於FT5x06嵌入式Linux電容觸控螢幕驅動

來源:互聯網
上載者:User

***************************************************************************************************************************
作者:EasyWave                                                                                 時間:2013.02.06

類別:Linux 核心驅動源碼分析                                                      聲明:轉載,請保留連結

注意:如有錯誤,歡迎指正。這些是我學習的日誌文章......

***************************************************************************************************************************

一:FT5X06電容觸摸IC簡介

     FT5x06系列ICs是單晶片電容式觸控螢幕控制器IC,帶有一個內建的8位微控制器單元(MCU)。採用互電容的方法,在配合的相互的電容式觸摸面板,它支援真正的多點觸摸功能。FT5x06具有方便使用的輸入的功能,這可以應用在許多攜帶型裝置,例如蜂窩式電話,移動互連網裝置,迷你筆記型電腦和筆記本個人電腦。FT5x06系列IC包括FT5206/FT5306/FT5406。具體的功能如所示:

 

二:硬體介面設計

從FT5X06的datasheet中,我們可以看到,FT5X06既可以工作的SPI的介面方式,也可以工作在I2C的介面方式,不管工作在SPI,還是工作在I2C,從硬體的介面設計上來說,這下面的幾個控制口,都是需要要接的。如所示:

1):INT引腳,這個腳是一個中端訊號,它用來通知HOST端FT5X06已經準備好,可以進行讀操作了。

2):WAKE引腳:這個功能主要的作用是將FT5X06從睡眠狀態轉換到工作狀態。

3):/RST引腳:FT5X06的晶片複位訊號。

如何來設計硬體介面呢,這個我們可以從FT5X06的datasheet看出來,首先我們來看下FT5X06的上電時序,如所示:

FT5X06的上電時序

FT5X06的RESET時序

FT5X06的wakeup時序

各自的最小的時間限制如下所所示:

因此,從上面的圖片和表格中,我們可以看出,在poweron中,必須確保在上電後,wakeup的電平為高電平,至於INT訊號,只要確保無INT訊號時,這個INT為高即可,這個可以從poweron的時序可以看出,它是一個低電平的動作,這個是驅動中來做的事情了。

接下來就是確定I2C的從地址,如所示:[以下引用自網路]

從地址高位必須為:3,低位必鬚根據i2ccon設定的值來確定。

根據FT5406資料手冊上的指令,我們先瞭解下驅動如何?電容屏的多點觸摸,其實很簡單,主要需要觸控螢幕IC FT5406 能夠捕獲多點資料,這點電容屏基本多能支援到捕獲2點以上,而FT5406 可以捕獲5個觸摸點,編寫驅動時,只要去擷取這幾個點的資料,然後上報就可以了。如所示:[以下引用自網路]

02H :捕獲的觸摸點個數              03H- 1EH :對應每個點的x,y座標數值。

 

三:Linux驅動源碼

        I2C的驅動需要根據具體的ARM晶片,一般來說,IC原廠,一般會將在linux的bsp中都會有I2C的驅動,這個部分不需要我們去寫的,我們只需要將FT5X06和BSP包中的I2C驅動匹配起來就好了。而整個FT5X06也是這樣做的。在linu核心中關於i2c的一般會有這個函數:i2c_board_info()i2c_board_info用於構建資訊表來列出存在的I2C裝置。這一資訊用於增長新型I2C驅動的驅動模型樹。對於主板,它使用i2c_register_board_info()來靜態建立。對於子板,利用已知的適配器使用i2c_new_device()動態建立。

struct i2c_board_info {    char type[I2C_NAME_SIZE];      unsigned short flags;      unsigned short addr;      void *platform_data;      struct dev_archdata *archdata;      int irq;  };static struct i2c_board_info i2c_devs0[] __initdata = {#ifdef CONFIG_TOUCHSCREEN_CDTLCD{I2C_BOARD_INFO("ft5x0x_ts", 0x3x),.irq = IRQ_EINT1,},#endif };


最後在核心初始化的部分調用int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len);函數即可。如下詳細的解釋:
@busnum: 指定這些裝置屬於哪個匯流排
@info: I2C裝置描述符向量
@len: 向量中描述符的數量;為了預留特定的匯流排號,可以是0。
i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));


下面貼出部分代碼:[下面的代碼是Android下的Linux驅動,如果要修改到通用的Linux核心中,需要修改代碼的]

static int ft5x0x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id){struct ft5x0x_ts_data *ft5x0x_ts;struct input_dev *input_dev;int err = 0;unsigned char uc_reg_value; #if CFG_SUPPORT_TOUCH_KEY    int i;#endifprintk("[FTS] ft5x0x_ts_probe, driver version is %s.\n", CFG_FTS_CTP_DRIVER_VERSION);if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {err = -ENODEV;goto exit_check_functionality_failed;}ft5x0x_ts = kzalloc(sizeof(struct ft5x0x_ts_data), GFP_KERNEL);//ft5x0x_ts = kmalloc(sizeof(struct ft5x0x_ts_data), GFP_KERNEL);if (!ft5x0x_ts){err = -ENOMEM;goto exit_alloc_data_failed;}//memset(ft5x0x_ts, 0, sizeof(struct ft5x0x_ts_data));this_client = client;i2c_set_clientdata(client, ft5x0x_ts);mutex_init(&ft5x0x_ts->device_mode_mutex);INIT_WORK(&ft5x0x_ts->pen_event_work, ft5x0x_ts_pen_irq_work);ft5x0x_ts->ts_workqueue = create_singlethread_workqueue(dev_name(&client->dev));if (!ft5x0x_ts->ts_workqueue) {err = -ESRCH;goto exit_create_singlethread;}err = request_irq(IRQ_EINT(6), ft5x0x_ts_interrupt, IRQF_TRIGGER_FALLING, "ft5x0x_ts", ft5x0x_ts);if (err < 0) {dev_err(&client->dev, "ft5x0x_probe: request irq failed\n");goto exit_irq_request_failed;}disable_irq(IRQ_EINT(6));input_dev = input_allocate_device();if (!input_dev) {err = -ENOMEM;dev_err(&client->dev, "failed to allocate input device\n");goto exit_input_dev_alloc_failed;}ft5x0x_ts->input_dev = input_dev;set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);set_bit(ABS_MT_POSITION_X, input_dev->absbit);set_bit(ABS_MT_POSITION_Y, input_dev->absbit);set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);input_set_abs_params(input_dev,     ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0);input_set_abs_params(input_dev,     ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);input_set_abs_params(input_dev,     ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0);input_set_abs_params(input_dev,     ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);    input_set_abs_params(input_dev,     ABS_MT_TRACKING_ID, 0, 5, 0, 0);    set_bit(EV_KEY, input_dev->evbit);    set_bit(EV_ABS, input_dev->evbit);#if CFG_SUPPORT_TOUCH_KEY    //setup key code area    set_bit(EV_SYN, input_dev->evbit);    set_bit(BTN_TOUCH, input_dev->keybit);    input_dev->keycode = tsp_keycodes;    for(i = 0; i < CFG_NUMOFKEYS; i++)    {        input_set_capability(input_dev, EV_KEY, ((int*)input_dev->keycode)[i]);        tsp_keystatus[i] = KEY_RELEASE;    }#endifinput_dev->name= FT5X0X_NAME;//dev_name(&client->dev)err = input_register_device(input_dev);if (err) {dev_err(&client->dev,"ft5x0x_ts_probe: failed to register input device: %s\n",dev_name(&client->dev));goto exit_input_register_device_failed;}#ifdef CONFIG_HAS_EARLYSUSPENDprintk("==register_early_suspend =\n");ft5x0x_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;ft5x0x_ts->early_suspend.suspend = ft5x0x_ts_suspend;ft5x0x_ts->early_suspend.resume= ft5x0x_ts_resume;register_early_suspend(&ft5x0x_ts->early_suspend);#endif    msleep(150);  //make sure CTP already finish startup process        //get some register information    uc_reg_value = ft5x0x_read_fw_ver();    printk("[FTS] Firmware version = 0x%x\n", uc_reg_value);    ft5x0x_read_reg(FT5X0X_REG_PERIODACTIVE, &uc_reg_value);    printk("[FTS] report rate is %dHz.\n", uc_reg_value * 10);    ft5x0x_read_reg(FT5X0X_REG_THGROUP, &uc_reg_value);    printk("[FTS] touch threshold is %d.\n", uc_reg_value * 4);#if CFG_SUPPORT_AUTO_UPG    fts_ctpm_auto_upg();#endif    #if CFG_SUPPORT_UPDATE_PROJECT_SETTING    fts_ctpm_update_project_setting();#endif    enable_irq(IRQ_EINT(6));   //create sysfs   err = sysfs_create_group(&client->dev.kobj, &ft5x0x_attribute_group);   if (0 != err)  {dev_err(&client->dev, "%s() - ERROR: sysfs_create_group() failed: %d\n", __FUNCTION__, err);sysfs_remove_group(&client->dev.kobj, &ft5x0x_attribute_group);  }   else    {        printk("ft5x0x:%s() - sysfs_create_group() succeeded.\n", __FUNCTION__);    }printk("[FTS] ==probe over =\n");    return 0;exit_input_register_device_failed:input_free_device(input_dev);exit_input_dev_alloc_failed://free_irq(client->irq, ft5x0x_ts);free_irq(IRQ_EINT(6), ft5x0x_ts);exit_irq_request_failed://exit_platform_data_null:cancel_work_sync(&ft5x0x_ts->pen_event_work);destroy_workqueue(ft5x0x_ts->ts_workqueue);exit_create_singlethread:printk("==singlethread error =\n");i2c_set_clientdata(client, NULL);kfree(ft5x0x_ts);exit_alloc_data_failed:exit_check_functionality_failed:return err;}static int __devexit ft5x0x_ts_remove(struct i2c_client *client){struct ft5x0x_ts_data *ft5x0x_ts;printk("==ft5x0x_ts_remove=\n");ft5x0x_ts = i2c_get_clientdata(client);unregister_early_suspend(&ft5x0x_ts->early_suspend);//free_irq(client->irq, ft5x0x_ts);mutex_destroy(&ft5x0x_ts->device_mode_mutex);free_irq(IRQ_EINT(6), ft5x0x_ts);input_unregister_device(ft5x0x_ts->input_dev);kfree(ft5x0x_ts);cancel_work_sync(&ft5x0x_ts->pen_event_work);destroy_workqueue(ft5x0x_ts->ts_workqueue);i2c_set_clientdata(client, NULL); del_timer(&test_timer);return 0;}static const struct i2c_device_id ft5x0x_ts_id[] = {{ FT5X0X_NAME, 0x3x },{ }};MODULE_DEVICE_TABLE(i2c, ft5x0x_ts_id);static struct i2c_driver ft5x0x_ts_driver = {.probe= ft5x0x_ts_probe,.remove= __devexit_p(ft5x0x_ts_remove),.id_table= ft5x0x_ts_id,.driver= {.name= FT5X0X_NAME,.owner= THIS_MODULE,},};static int __init ft5x0x_ts_init(void){int ret;printk("==ft5x0x_ts_init==\n");ret = i2c_add_driver(&ft5x0x_ts_driver);printk("ret=%d\n",ret);return ret;}static void __exit ft5x0x_ts_exit(void){printk("==ft5x0x_ts_exit==\n");i2c_del_driver(&ft5x0x_ts_driver);}module_init(ft5x0x_ts_init);module_exit(ft5x0x_ts_exit);MODULE_AUTHOR("<wenfs@Focaltech-systems.com>");MODULE_DESCRIPTION("FocalTech ft5x0x TouchScreen driver");MODULE_LICENSE("GPL");


移植到通用的Linux的核心中,就不寫出來了,自己去研究吧。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.