1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author         Notes
8  * 2020-11-08     bigmagic       first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 
14 #include "drv_xpt2046.h"
15 //http://www.lcdwiki.com/MHS-3.5inch_RPi_Display
16 
17 #define DBG_TAG "xpt2046"
18 #define DBG_LVL DBG_INFO
19 #include <rtdbg.h>
20 
21 //XPT2046
22 #define     READ_X                (0xD0)
23 #define     READ_Y                (0x90)
24 
25 #define     TFT_WIDTH             (320)
26 #define     TFT_HEIGHT            (480)
27 //freq
28 #define     TOUCH_SPI_MAX_FREQ    (10*1000)
29 
30 #define     TP_IRQ_PIN            (17)
31 #define     TOUCH_DEVICE_NAME     ("spi0.1")
32 
33 static struct rt_semaphore touch_ack;
34 static rt_touch_t touch_device = RT_NULL;
35 
36 static rt_thread_t touch_tid = RT_NULL;
37 #define TOUCH_THREAD_STACK_SIZE     (1024)
38 #define TOUCH_THREAD_PRIORITY       (30)
39 #define TOUCH_THREAD_TIMESLICE      (10)
40 
41 rt_uint8_t touch_flag = 0;
42 rt_uint16_t touch_x_val = 0;
43 rt_uint16_t touch_y_val = 0;
44 
45 extern struct rt_semaphore lcd_spi_lock;
touch_read_x_y(void * dev,rt_uint16_t * x,rt_uint16_t * y)46 static void touch_read_x_y(void *dev, rt_uint16_t *x, rt_uint16_t *y)
47 {
48     struct rt_spi_device *touch_dev = (struct rt_spi_device *)dev;
49     struct rt_spi_message msg1,msg2,msg3,msg4;
50     rt_uint16_t readx_val = 0,ready_val = 0;
51     rt_uint8_t readx[2];
52     rt_uint8_t ready[2];
53     rt_sem_take(&lcd_spi_lock, RT_WAITING_FOREVER);
54 
55     int read_x_id = READ_X;
56     int read_y_id = READ_Y;
57 
58     msg1.send_buf   = &read_x_id;
59     msg1.recv_buf   = RT_NULL;
60     msg1.length     = 1;
61     msg1.cs_take    = 1;
62     msg1.cs_release = 0;
63     msg1.next       = &msg2;
64 
65     msg2.send_buf   = RT_NULL;
66     msg2.recv_buf   = &readx[0];
67     msg2.length     = 2;
68     msg2.cs_take    = 0;
69     msg2.cs_release = 0;
70     msg2.next       = &msg3;
71 
72     msg3.send_buf   = &read_y_id;
73     msg3.recv_buf   = RT_NULL;
74     msg3.length     = 1;
75     msg3.cs_take    = 0;
76     msg3.cs_release = 0;
77     msg3.next       = &msg4;
78 
79     msg4.send_buf   = RT_NULL;
80     msg4.recv_buf   = &ready[0];
81     msg4.length     = 2;
82     msg4.cs_take    = 0;
83     msg4.cs_release = 1;
84     msg4.next       = RT_NULL;
85 
86     rt_spi_transfer_message(touch_dev, &msg1);
87 
88     readx_val = ((readx[0] << 8) | readx[1]) >> 4;
89     ready_val = ((ready[0] << 8) | ready[1]) >> 4;
90 
91     rt_sem_release(&lcd_spi_lock);
92     *x = readx_val;
93     *y = ready_val;
94 }
95 
96 /*
97 XPT2046:Width:320 High:480
98 no pressed:(0x800,0xfff)
99 ---ETH----USB-----------------------
100 | (0x800,0x800)      (0xfff,0x800) |
101 |                                  |
102 | (0x800,0xFFF)      (0xfff,0xfff) |
103 ------------------------------------
104 */
105 #define XMIN 0x800
106 #define YMAX 0xfff
read_tp(void * dev,rt_uint16_t * x,rt_uint16_t * y)107 void read_tp(void *dev, rt_uint16_t *x, rt_uint16_t *y)
108 {
109     struct rt_spi_device *touch_dev = (struct rt_spi_device *)dev;
110     rt_uint8_t try = 0;
111     uint16_t _y[5] = {0,0,0,0,0};
112     uint16_t _x[5] = {0,0,0,0,0};
113     uint16_t x_val = 0;
114     uint16_t y_val = 0;
115     uint16_t cur_x = 0;
116     uint16_t cur_y = 0;
117     int index = 0;
118 
119     while(1)
120     {
121         try = try + 1;
122         touch_read_x_y(touch_dev, x, y);
123         if((*x > XMIN) && (*y < YMAX))
124         {
125             _x[index] = *x;
126             _y[index] = *y;
127             index = index + 1;
128         }
129         if(index == 5)
130         {
131             break;
132         }
133 
134         if(try > 10)
135         {
136             break;
137         }
138     }
139 
140     x_val = (_x[0] + _x[1] + _x[2] + _x[3]+ _x[4]) / index;
141     y_val = (_y[0] + _y[1] + _y[2] + _y[3]+ _y[4]) / index;
142 
143     cur_x = (x_val - 0x800) * TFT_WIDTH / 0x800;
144     cur_y = (y_val - 0x800) * TFT_HEIGHT / 0x800;
145 
146     if((cur_x < TFT_WIDTH) && (cur_y < TFT_HEIGHT))
147     {
148         *x = TFT_WIDTH - cur_x;
149         *y = TFT_HEIGHT - cur_y;
150     }
151     else
152     {
153         *x = 0;
154         *y = 0;
155     }
156 }
157 
touch_thread_entry(void * param)158 static void touch_thread_entry(void *param)
159 {
160     rt_uint16_t x,y;
161     struct rt_spi_device *touch_dev;
162     touch_dev = (struct rt_spi_device *)rt_device_find(TOUCH_DEVICE_NAME);
163     touch_dev->config.max_hz = TOUCH_SPI_MAX_FREQ;
164     if (!touch_dev)
165     {
166         rt_kprintf("no %s!\n", TOUCH_DEVICE_NAME);
167     }
168 
169     while (1)
170     {
171         rt_sem_take(&touch_ack, RT_WAITING_FOREVER);
172         read_tp(touch_dev, &x, &y);
173         if((x!= 0) && (y !=0))
174         {
175             touch_x_val = x;
176             touch_y_val = y;
177             touch_flag = 1;
178         }
179         rt_pin_mode(TP_IRQ_PIN, PIN_MODE_INPUT_PULLUP);
180     }
181 }
182 
touch_readly(void * args)183 static void touch_readly(void *args)
184 {
185     if(rt_pin_read(TP_IRQ_PIN) == PIN_LOW)
186     {
187         rt_pin_mode(TP_IRQ_PIN, PIN_MODE_OUTPUT);
188         rt_pin_write(TP_IRQ_PIN,PIN_HIGH);
189         rt_sem_release(&touch_ack);
190     }
191 }
192 
xpt2046_read_point(struct rt_touch_device * touch,void * buf,rt_size_t read_num)193 static rt_ssize_t xpt2046_read_point(struct rt_touch_device *touch, void *buf, rt_size_t read_num)
194 {
195     rt_uint16_t* touchxy = (rt_uint16_t *)buf;
196     if((read_num != 0) && (touch_flag == 1))
197     {
198         touchxy[0] = touch_x_val;
199         touchxy[1] = touch_y_val;
200         touch_flag = 0;
201         return read_num;
202     }
203     else
204     {
205         return 0;
206     }
207 }
208 
xpt2046_control(struct rt_touch_device * device,int cmd,void * data)209 static rt_err_t xpt2046_control(struct rt_touch_device *device, int cmd, void *data)
210 {
211     return RT_EOK;
212 }
213 
214 static struct rt_touch_ops touch_ops =
215 {
216     .touch_readpoint = xpt2046_read_point,
217     .touch_control = xpt2046_control,
218 };
219 
hw_xpt2046_touch_init(void)220 static int hw_xpt2046_touch_init(void)
221 {
222     //touch sem
223     rt_sem_init(&touch_ack, "touch_ack", 0, RT_IPC_FLAG_FIFO);
224 
225     touch_tid = rt_thread_create("touch",
226                             touch_thread_entry, RT_NULL,
227                             TOUCH_THREAD_STACK_SIZE,
228                             TOUCH_THREAD_PRIORITY, TOUCH_THREAD_TIMESLICE);
229     if (touch_tid != RT_NULL)
230         rt_thread_startup(touch_tid);
231 
232     rt_pin_mode(TP_IRQ_PIN, PIN_MODE_INPUT_PULLUP);
233     rt_pin_attach_irq(TP_IRQ_PIN, PIN_IRQ_MODE_LOW_LEVEL, touch_readly, RT_NULL);
234     rt_pin_irq_enable(TP_IRQ_PIN, PIN_IRQ_ENABLE);
235 
236     touch_device = (rt_touch_t)rt_calloc(1, sizeof(struct rt_touch_device));
237 
238     if (touch_device == RT_NULL)
239         return -RT_ERROR;
240 
241     /* register touch device */
242     touch_device->info.type = RT_TOUCH_TYPE_RESISTANCE;
243     touch_device->info.vendor = RT_TOUCH_VENDOR_UNKNOWN;
244     //rt_memcpy(&touch_device->config, cfg, sizeof(struct rt_touch_config));
245     touch_device->ops = &touch_ops;
246 
247     rt_hw_touch_register(touch_device, "xpt2046", RT_DEVICE_FLAG_INT_RX, RT_NULL);
248 
249     return 0;
250 }
251 INIT_DEVICE_EXPORT(hw_xpt2046_touch_init);
252