TP自适应
最近又要求职了,梳理了下这两年折腾的东西,发现有个产品很可惜,都开发完了,但是废掉了没上市。中兴的一款手表,我很喜欢那个金属壳子,结实,拿在手里沉甸甸,可以用来砸核桃。
当时调TP的时候,换了几个厂家,程序里要做自适应,还好TP控制器里都有唯一的特征值,所以可以识别出设备类型。这里都是i2c接口的TP,如果接口不一样还得调整。高通也提供了linux/android下的驱动程序,用的上报机制,框架太庞大,没办法用在小CPU上。在前同事的基础上改造了下,还不够通用,如果今后再有机会用到TP,再优化吧。
TP驱动程序
tp_driver.c
#include "tp_driver.h" #include "em_gpio.h" #include "i2c_driver.h" static void tp_init(void) { GPIO_PinModeSet(TP_REST_PORT, TP_REST_PIN, gpioModePushPull, 1); GPIO_PinOutSet(TP_REST_PORT, TP_REST_PIN); GPIO_PinModeSet(TP_INT_PORT,TP_INT_PIN, gpioModeInput,0); //GPIO_PinModeSet(TP_INT_PORT,TP_INT_PIN, gpioModeInputPullFilter,0); GPIO_IntConfig(TP_INT_PORT, TP_INT_PIN, false, true, true); GPIO_PinModeSet(TP_PW_PORT,TP_PW_PIN, gpioModeWiredAnd,0); GPIO_PinOutClear(TP_PW_PORT, TP_PW_PIN); } static void tp_rest(void) { GPIO_PinOutClear(TP_PW_PORT, TP_PW_PIN); GPIO_PinOutSet(TP_REST_PORT, TP_REST_PIN); uint32_t i =1000; while(--i); GPIO_PinOutClear(TP_REST_PORT, TP_REST_PIN); i =1000; while(--i); GPIO_PinOutSet(TP_REST_PORT, TP_REST_PIN); } static uint8_t search_device(void) { uint8_t reset_data[4]={0}; uint8_t tp_data[4]={0}; tp_rest(); uint32_t i= 6000000; while(--i); I2C->ReadBytesWithoutReg(0x15<<1,reset_data,4); if( (reset_data[0]==0x55) && (reset_data[1]==0x55) && (reset_data[2]==0x55) && (reset_data[3]==0x55) ) { uint8_t fireware_id_cmd[4]= {0x53, 0xf0, 0x00, 0x01}; uint8_t fireware_id_major; uint8_t fireware_id_minor; uint16_t fireware_id; I2C->WriteBytesWithoutReg(0x15<<1,fireware_id_cmd,4); i=5000; while(--i); I2C->ReadBytesWithoutReg(0x15<<1,tp_data,4); fireware_id_major = ((tp_data[1]&0x0f)<<4) | ((tp_data[2]&0xf0)>>4) ; fireware_id_minor = ((tp_data[2]&0x0f)<<4) | ((tp_data[3]&0xf0)>>4) ; fireware_id = fireware_id_major<<8 | fireware_id_minor; if(fireware_id == 0x1AB0) { return TP_eWD1000; } } else { uint8_t vendor_id; I2C->readbyte(I2C0, 0x7c, 0xA8, &vendor_id); if(vendor_id == 0x5f) { return TP_FT3X07; } else { GPIO_PinOutSet(TP_PW_PORT, TP_PW_PIN); //tp power down I2C->init(); return 0; } } } static void ReadXY(uint16_t *tp_x,uint16_t *tp_y) { uint8_t tp_type = search_device(); if (tp_type == TP_eWD1000) { uint16_t *tp_x1=0; uint16_t *tp_y2=0; uint8_t tp_data[4]={0}; uint8_t fireware_id_cmd[4]= {0x53, 0xf0, 0x00, 0x01}; uint8_t fireware_version_cmd[4]={0x53, 0x00, 0x00, 0x01}; uint8_t boot_code_cmd[4]= {0x53, 0x10, 0x00, 0x01}; uint8_t x_resolution_cmd[4]= {0x53, 0x60, 0x00, 0x00}; uint8_t y_resolution_cmd[4]= {0x53, 0x63, 0x00, 0x00}; uint8_t tp_sleep_cmd[4]= {0x54, 0x50, 0x00, 0x01}; // 可以不用写信息 /* I2C->WriteBytesWithoutReg(0x15<<1,x_resolution_cmd,4); int i = 2000; while(--i); I2C->ReadBytesWithoutReg(0x15<<1,tp_data,8); *tp_x = (tp_data[2]) | ((tp_data[3]&0xf0)<<4); I2C->WriteBytesWithoutReg(0x15<<1,y_resolution_cmd,4); i = 2000; while(--i); I2C->ReadBytesWithoutReg(0x15<<1,tp_data,8); *tp_y = (tp_data[2]) | ((tp_data[3]&0xf0)<<4); */ I2C->ReadBytesWithoutReg(0x15<<1,tp_data,8); *tp_x = ((uint16_t)((tp_data[1]&0xf0)<<4) | tp_data[2]) ; *tp_y = ((uint16_t)((tp_data[1]&0x0f)<<8) | tp_data[3]) ; //支持两点触碰 //*tp_x1 = ((uint16_t)((tp_data[4]&0xf0)<<4) | tp_data[5]) ; //*tp_y2 = ((uint16_t)((tp_data[4]&0x0f)<<8) | tp_data[6]) ; } else if(tp_type == TP_FT3X07) { uint8_t tp_data[4]; uint8_t x_h=0, x_l=0, y_h=0, y_l=0; I2C->readbyte(I2C0, 0x7c, 0x03, &tp_data[0]); I2C->readbyte(I2C0, 0x7c, 0x04, &tp_data[1]); I2C->readbyte(I2C0, 0x7c, 0x05, &tp_data[2]); I2C->readbyte(I2C0, 0x7c, 0x06, &tp_data[3]); x_h= tp_data[0]; x_l= tp_data[1]; *tp_x = ((x_h <<8)&0xff)| x_l; y_h= tp_data[2]; y_l= tp_data[3]; *tp_y = ((y_h <<8)&0xff)| y_l; } else { } } static void tp_int_enable(void) { GPIO_IntConfig(TP_INT_PORT, TP_INT_PIN, true, true, true); } static void tp_int_disable(void) { GPIO_IntConfig(TP_INT_PORT, TP_INT_PIN, true, true, false); } static void tp_sleep(void){ //I2C->writebyte(I2C0, 0x7c, 0xa5, 0x03); GPIO_PinOutSet(TP_PW_PORT, TP_PW_PIN); } TP_T TP_D= { tp_init, tp_rest, search_device, ReadXY, tp_int_enable, tp_int_disable, tp_sleep, }; TP_T *TP=&TP_D;
tp_driver.h
#ifndef __TOUCH_DRIVER_H #define __TOUCH_DRIVER_H #include <stdint.h> #include <stdlib.h> #include <stdbool.h> enum tp_type_t{ TP_FT3X07=1, TP_eWD1000 }; #define TOUCH_PANNEL_ADDR (0x7C) #define TP_INT_PORT (gpioPortA) #define TP_INT_PIN (3) #define TP_PIN_IS_HI() ( ( GPIO->P[TP_INT_PORT].DIN & (0x1<<TP_INT_PIN)) == (0x1<<TP_INT_PIN)) #define TP_PIN_IS_LO() ( ( GPIO->P[TP_INT_PORT].DIN & (0x1<<TP_INT_PIN)) == 0x0 ) #define TP_REST_PORT (gpioPortA) #define TP_REST_PIN (4) #define TP_PW_PORT (gpioPortE) #define TP_PW_PIN (15) typedef struct { void (*init)(void); void (*rest)(void); void (*search_device)(void); void (*ReadXY)(uint16_t *tp_x,uint16_t *tp_y); void (*int_enable)(void); void (*int_disable)(void); void (*sleep)(void); }TP_T; extern TP_T *TP; #endif
GUI导入,这里用的emWin,其他GUI也类似。
tp_driver_bsp.c
#include "GUI.h" #include "touch_bsp.h" #include <stdint.h> #include <stdlib.h> #include <stdbool.h> #include "tp_driver.h" #define TP_X_OFFSET (18) #define TP_Y_OFFSET (18) #define TP_MAPTO_LCD_LENGHT (94) void GetTouchXY(int16_t *Xmotion,int16_t *Ymotion) { TP->ReadXY(&x,&y); if(tp_type == TP_eWD1000) { if(x==0||y==0) return; if(x==1024||y==1024) return; else { x=((TP_eWD1000_MAX_X-x)*LCD_MAX_X)/TP_eWD1000_MAX_X; y=((TP_eWD1000_MAX_Y-y)*LCD_MAX_Y)/TP_eWD1000_MAX_Y; } } else { if(x==0||y==0) return; if(x==0x00ff||y==0x00ff) return; else { #if 1 //触摸区域为内切矩形 x=((x)*TP_MAPTO_LCD_LENGHT)/TP_FT3X07_MAX_X+TP_X_OFFSET; y=((y)*TP_MAPTO_LCD_LENGHT)/TP_FT3X07_MAX_Y+TP_Y_OFFSET; #else //触摸区域为全屏 x=((x)*LCD_MAX_X)/TP_FT3X07_MAX_X; y=((y)*LCD_MAX_Y)/TP_FT3X07_MAX_Y; #endif } } GUI_TOUCH_StoreState(x, y); *Xmotion=x; *Ymotion=y; }
tp_driver_bsp.h
#ifndef __TOUCH_BSP_H #define __TOUCH_BSP_H #include <stdint.h> #include <stdlib.h> #include <stdbool.h> #include "tp_driver.h" #define TP_eWD1000_MAX_X (1024) #define TP_eWD1000_MAX_Y (1024) #define TP_FT3X07_MAX_X (127) #define TP_FT3X07_MAX_Y (127) #define LCD_MAX_X (127) #define LCD_MAX_Y (127) #define TP_SCAN_INTERVAL (25) extern void GetTouchXY(int16_t *Xmotion,int16_t *Ymotion); #endif