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