One-touch chip analysis
First, remove the four screws of the touch screen and turn over the touch screen to observe. You can see the touch chip on the touch screen cable. Observe the chip model carefully (if you can't see clearly, you can use a magnifying glass and a flashlight to view it). We can see that the touch screen control chip of TQ210 is GT811. Then I found the chip manual of GT811 (these materials have been uploaded to my CSDN resources, please support me). With the manual, it is not difficult to write the driver.
GT811 leads to 6 pins, namely VCC, GND, I2CSDA, I2CSCL, INT and RESET. Although the INT pin is not necessary, the development of efficient and resource-saving touch screen drivers often uses interrupt mode. The following is the pin diagram of GT811:
I used a multimeter to measure the pins of the touch module. The actual line sequence is GND, SDA, SDL, INT, RESET and VDD. The initialization sequence of GT811 is as follows:
- (1) Initialize the INT pin to a floating input state and initialize the RESET pin to an output state and output a low level
- (2) Delay 1ms
- (3) Initialize the RESET pin to a floating input state and enable the pull-up
- (4) Write the GT811 register configuration table
- (5) Configure the INT pin as needed
2. I2C driver writing
The I2C driver is also based on the bus structure, but it is divided into two types, one is the Legacy method and the other is the New Style method. The Legacy method is no longer supported in the new kernel, but Teacher Wei Dongshan’s video still analyzes the Legacy method. You can use Source Insight to track and analyze the New Style method yourself. I will not go into details here. You can refer to the following code for details.
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- const static unsigned short normal_address[] = {0x5d, I2C_CLIENT_END};
- static unsigned gt811_rst;
- static unsigned gt811_int;
- static struct input_dev *ts_input;
- static struct workqueue_struct *wq;
- static struct work_struct work;
- static struct i2c_client * this_client = NULL;
- static unsigned int status = 0;
- static int i2c_read_bytes(struct i2c_client *client, uint8_t *buf, int len)
- {
- struct i2c_msg msgs[2];
- int ret=-1;
- msgs[0].flags=!I2C_M_RD;
- msgs[0].addr=client->addr;
- msgs[0].len=2;
- msgs[0].buf=&buf[0];
- msgs[1].flags=I2C_M_RD;
- msgs[1].addr=client->addr;
- msgs[1].len=len-2;
- msgs[1].buf=&buf[2];
- ret=i2c_transfer(client->adapter,msgs, 2);
- return ret;
- }
- static int i2c_write_bytes(struct i2c_client *client,uint8_t *data,int len)
- {
- struct i2c_msg msg;
- int ret=-1;
- msg.flags=!I2C_M_RD;
- msg.addr=client->addr;
- msg.len=len;
- msg.buf=data;
- ret=i2c_transfer(client->adapter,&msg, 1);
- return ret;
- }
- static const struct i2c_device_id ts_id[] = {
- { "tq210-ts", 0 },
- { }
- };
- static int ts_init_panel(struct i2c_client *client){
- short ret=-1;
- uint8_t config_info[] = {
- 0x06,0xA2,
- 0x12,0x10,0x0E,0x0C,0x0A,0x08,0x06,0x04,0x02,0x00,0xE2,0x53,0xD2,0x53,0xC2,0x53,
- 0xB2,0x53,0xA2,0x53,0x92,0x53,0x82,0x53,0x72,0x53,0x62,0x53,0x52,0x53,0x42,0x53,
- 0x32,0x53,0x22,0x53,0x12,0x53,0x02,0x53,0xF2,0x53,0x0F,0x13,0x40,0x40,0x40,0x10,
- 0x10,0x10,0x0F,0x0F,0x0A,0x35,0x25,0x0C,0x03,0x00,0x05,0x20,0x03,0xE0,0x01,0x00,
- 0x00,0x34,0x2C,0x36,0x2E,0x00,0x00,0x03,0x19,0x03,0x08,0x00,0x00,0x00,0x00,0x00,
- 0x14,0x10,0xEC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x40,
- 0x30,0x3C,0x28,0x00,0x00,0x00,0x00,0xC0,0x12,0x01
- }; [page]
- config_info[62] = 480 >> 8;
- config_info[61] = 480 & 0xff;
- config_info[64] = 800 >> 8;
- config_info[63] = 800 & 0xff;
- ret = i2c_write_bytes(client, config_info, sizeof(config_info)/sizeof(config_info[0]));
- if(ret < 0) {
- printk(KERN_ERR "GT811 Send config failed! ");
- return ret;
- }
- return 0;
- }
- static irqreturn_t gt811_int_handler(int irq, void *devid){
- disable_irq_nosync(this_client->irq);
- queue_work(wq, &work);
- return IRQ_RETVAL(IRQ_HANDLED);
- }
- static void ts_work_func(struct work_struct* work){
- int ret;
- unsigned char point_data[19] = {0x07, 0x21, 0};
- unsigned short input_x = 0;
- unsigned short input_y = 0;
- unsigned short input_p = 0;
- ret=i2c_read_bytes(this_client, point_data, sizeof(point_data)/sizeof(point_data[0]));
- if(ret <= 0){
- printk("Failed ");
- return;
- }
- if(point_data[2]&0x1){
- status = 1;
- input_y = 479-((point_data[4]<<8)|point_data[5]);
- input_x = 799-((point_data[6]<<8)|point_data[7]);
- input_p = point_data[8];
- printk("stat: %d, x: %d, y: %d, p: %d ", point_data[2], input_x, input_y,
- input_p);
- }
- else if(status){
- status = 0;
- printk("up ");
- }
- enable_irq(this_client->irq);
- }
- static int ts_probe(struct i2c_client *client, const struct i2c_device_id *id){
- int retry, ret;
- char test_data;
- printk("ts_probe ");
- test_data = 0;
- gt811_rst = S5PV210_GPD0(3);
- gt811_int = S5PV210_GPH1(6);
- gpio_request(gt811_rst, "reset");
- gpio_request(gt811_rst, "tsint");
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
- {
- dev_err(&client->dev, "Must have I2C_FUNC_I2C. ");
- return -ENODEV;
- }
- s3c_gpio_setpull(gt811_rst, S3C_GPIO_PULL_UP);
- for(retry=0;retry < 5; retry++)
- {
- gpio_direction_output(gt811_rst, 0);
- msleep(1);
- gpio_direction_input(gt811_rst);
- msleep(100);
- ret =i2c_write_bytes(client, &test_data, 1);
- if (ret > 0)
- break;
- dev_info(&client->dev, "GT811 I2C TEST FAILED! Please check the HARDWARE connect ");
- }
- if(ret <= 0)
- {
- dev_err(&client->dev, "Warning: I2C communication might be ERROR! ");
- return -ENODEV;
- }
- for(retry = 0; retry != 5; ++ retry){
- ret = ts_init_panel(client);
- if(ret != 0){
- continue;
- }
- else{
- break;
- }
- }
- if(ret != 0){
- printk("GT811 Configue failed! ");
- return -ENODEV;
- }
- this_client = client;
- ts_input = input_allocate_device();
- if (IS_ERR(ts_input)) {
- printk("GT811 allocate ts input device failed! ");
- return -ENOMEM;
- }
- ts_input->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- ts_input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- ts_input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
- input_set_abs_params(ts_input, ABS_Y, 0, 799, 0, 0);
- input_set_abs_params(ts_input, ABS_X, 0, 479, 0, 0);
- input_set_abs_params(ts_input, ABS_PRESSURE, 0, 255, 0, 0);
- ts_input->name = "tq210-ts";
- ts_input->phys = "input/ts";
- ts_input->id.bustype = BUS_I2C;
- ts_input->id.product = 0xBEEF;
- ts_input->id.vendor =0xDEAD;
- ret = input_register_device(ts_input);
- if(ret < 0){
- printk("Unable register %s input device! ", ts_input->name);
- input_free_device(ts_input);
- return -ENOMEM;
- }
- client->irq = IRQ_EINT(14);
- s3c_gpio_setpull(gt811_int, S3C_GPIO_PULL_UP);
- if(request_irq(IRQ_EINT(14), gt811_int_handler, IRQF_TRIGGER_FALLING, "gt811-int", NULL) < 0){
- printk("Request irq for gt811 failed! ");
- input_unregister_device(ts_input);
- input_free_device(ts_input);
- return -ENOMEM;
- }
- wq = create_workqueue("ts_handle_thread");
- if(wq == NULL){
- printk(KERN_ALERT "crete workqueue failed! ");
- input_unregister_device(ts_input);
- input_free_device(ts_input);
- free_irq(IRQ_EINT(14), NULL);
- return -ENOMEM;
- }
- INIT_WORK(&work, ts_work_func);
- return 0;
- }
- static int ts_remove(struct i2c_client *client){
- free_irq(IRQ_EINT(14), NULL);
- enable_irq(client->irq);
- flush_workqueue(wq);
- destroy_workqueue(wq);
- input_unregister_device(ts_input);
- input_free_device(ts_input);
- gpio_free(gt811_rst);
- gpio_free(gt811_int);
- return 0;
- } [page]
- static struct i2c_driver ts_driver = {
- .driver = {
- .name = "tq210-ts",
- .owner = THIS_MODULE,
- },
- .probe = ts_probe,
- .remove = ts_remove,
- .id_table = ts_id,
- .address_list = normal_address,
- };
- static int ts_init(void){
- printk("init ");
- i2c_add_driver(&ts_driver);
- return 0;
- }
- static void ts_exit(void){
- i2c_del_driver(&ts_driver);
- printk("exit ");
- }
- module_init(ts_init);
- module_exit(ts_exit);
- MODULE_LICENSE("GPL");
Three registered TS I2C module devices
- static struct i2c_board_info smdkv210_i2c_devs2[] __initdata = {
- /* To Be Updated */
- { I2C_BOARD_INFO("tq210-ts", 0x5d), },
- ;
Four tslib test tutorials (ubuntu)
- sudo apt-get install git
2. Download the latest tslib
- git clone https://github.com/kergoth/tslib
3. Install auto
- sudo apt-get install autoconf automake libtool
4. Compile 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
5. Install tslib
- cd tmp
- cp * /nfsroot/rootfs -rfd
6. Configure tslib
- Modify /etc/ts.conf
- Will go
- # module_raw input
- to:
- module_raw input
- (Actually, it removes the # sign and the first space in the high line)
7. Configure tslib running environment variables
- export TSLIB_TSDEVICE=/dev/input/event1 //This needs to be modified according to your own event location. The new kernel is in /dev/input/event*
- export TSLIB_CALIBFILE=/etc/pointercal
- export TSLIB_CONFFILE=/etc/ts.conf
- export TSLIB_PLUGINDIR=/lib/ts
- export TSLIB_CONSOLEDEVICE=none
- export TSLIB_FBDEVICE=/dev/fb0
8. Calibration (capacitive screen does not actually need calibration, it is only for testing the touch screen driver)
- Run ts_calibrate and perform calibration according to the prompts
9. Free drawing
- Run ts_test and click the draw button to draw freely. The effect is as shown below.
Five conclusions
Previous article:S5PV210 (TQ210) study notes - USB HOST transplantation
Next article:S5PV210 (TQ210) study notes - LCD driver writing
Recommended ReadingLatest update time:2024-11-16 14:49
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Today at 14:00, live broadcast with prizes: [In-depth and easy-to-understand wearable health monitoring]
- MSP430 capture device is simple and practical
- I want to learn stm32, please recommend a tutorial
- [NXP Rapid IoT Review] + Use of Bluetooth (1 Preliminary Exploration)
- 500 yuan for infrared counting microcontroller
- Why can the serial port receive 9600 but lose bytes at 115200?
- What is the chip with 4BMN silk screen? It has 5 pins.
- I encountered a problem when testing the CAN communication isolation chip a few days ago. I hope you can give me some advice.
- Reminiscing about the past! A brief discussion on the century-long history of radio development
- Network port debugging issues