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  * 2018-10-03     xuzhuoyi     first implementation.
9  */
10 
11 #include "drv_touch.h"
12 #include "drivers/dev_i2c.h"
13 
14 #ifdef PKG_USING_LITTLEVGL2RTT
15 #include "littlevgl2rtt.h"
16 #endif
17 
18 
19 #define TSC_I2C_ADDR    0x41            /* 7-bit I2C address                  */
20 
21 static struct rt_i2c_bus_device *stmpe811_i2c_bus;
22 
23 
24 /**
25   \fn          int32_t touch_readRegister (uint8_t reg, uint8_t *val)
26   \brief       Read register value from Touchscreen controller
27   \param[in]   reg    Register address
28   \param[out]  val    Pointer where data will be read from register
29   \returns
30    - \b  0: function succeeded
31    - \b -1: function failed
32 */
touch_read(uint8_t reg,uint8_t * val)33 static int32_t touch_read (uint8_t reg, uint8_t *val)
34 {
35     struct rt_i2c_msg msgs[2];
36 
37     msgs[0].addr  = TSC_I2C_ADDR;
38     msgs[0].flags = RT_I2C_WR;
39     msgs[0].buf   = ®
40     msgs[0].len   = 1;
41 
42     msgs[1].addr  = TSC_I2C_ADDR;
43     msgs[1].flags = RT_I2C_RD;
44     msgs[1].buf   = val;
45     msgs[1].len   = 1;
46 
47     if (rt_i2c_transfer(stmpe811_i2c_bus, msgs, 2) == 2)
48     {
49         return RT_EOK;
50     }
51     else
52     {
53         return -RT_ERROR;
54     }
55 
56 }
57 
58 /**
59   \fn          int32_t touch_writeData (uint8_t reg, const uint8_t *val)
60   \brief       Write value to Touchscreen controller register
61   \param[in]   reg    Register address
62   \param[in]   val    Pointer with data to write to register
63   \returns
64    - \b  0: function succeeded
65    - \b -1: function failed
66 */
touch_write(uint8_t reg,uint8_t val)67 static int32_t touch_write(uint8_t reg, uint8_t val)
68 {
69     struct rt_i2c_msg msgs;
70     rt_uint8_t buf[2];
71 
72     buf[0] = reg;
73     buf[1] = val;
74 
75     msgs.addr  = TSC_I2C_ADDR;
76     msgs.flags = RT_I2C_WR;
77     msgs.buf   = buf;
78     msgs.len   = 2;
79 
80     if (rt_i2c_transfer(stmpe811_i2c_bus, &msgs, 1) == 1)
81     {
82     return RT_EOK;
83     }
84     else
85     {
86     return -RT_ERROR;
87     }
88 
89 }
90 
91 
92 /**
93   \fn          int32_t Touch_Initialize (void)
94   \brief       Initialize touchscreen
95   \returns
96    - \b  0: function succeeded
97    - \b -1: function failed
98 */
stmpe811_touch_init(rt_device_t dev)99 static rt_err_t stmpe811_touch_init(rt_device_t dev)
100 {
101     stmpe811_i2c_bus = rt_i2c_bus_device_find("i2c3");
102 
103     touch_write(STMPE811_SYS_CTRL1,      0x02); /* Reset Touch-screen controller */
104     rt_thread_mdelay(10);                              /* Wait 10ms                     */
105 
106 
107     touch_write(STMPE811_SYS_CTRL2,      0x0C); /* Enable TSC and ADC            */
108     touch_write(STMPE811_ADC_CTRL1,      0x68); /* Set sample time , 12-bit mode */
109     rt_thread_mdelay(1);                               /* Wait 1ms                      */
110 
111     touch_write(STMPE811_ADC_CTRL2,      0x01); /* ADC frequency 3.25 MHz        */
112     touch_write(STMPE811_TSC_CFG,        0xC2); /* Detect delay 10us,
113                                                  Settle time 500us             */
114     touch_write(STMPE811_FIFO_TH,        0x01); /* Threshold for FIFO            */
115     touch_write(STMPE811_FIFO_STA,       0x01); /* FIFO reset                    */
116     touch_write(STMPE811_FIFO_STA,       0x00); /* FIFO not reset                */
117     touch_write(STMPE811_TSC_FRACTION_Z, 0x07); /* Fraction z                    */
118     touch_write(STMPE811_TSC_I_DRIVE,    0x01); /* Drive 50 mA typical           */
119     touch_write(STMPE811_GPIO_AF,        0x00); /* Pins are used for touchscreen */
120     touch_write(STMPE811_TSC_CTRL,       0x01); /* Enable TSC                    */
121 
122     return 0;
123 }
124 
125 /**
126   \fn          int32_t Touch_Uninitialize (void)
127   \brief       De-initialize touchscreen
128   \returns
129    - \b  0: function succeeded
130    - \b -1: function failed
131 */
touch_uninitialize(void)132 int32_t touch_uninitialize (void) {
133   touch_write(STMPE811_SYS_CTRL1, 0x02);  /* Reset Touch-screen controller    */
134   return 0;
135 }
136 
137 /**
138   \fn          int32_t Touch_GetState (TOUCH_STATE *pState)
139   \brief       Get touchscreen state
140   \param[out]  pState  pointer to TOUCH_STATE structure
141   \returns
142    - \b  0: function succeeded
143    - \b -1: function failed
144 */
touch_get_state(struct touch_state * state)145 int32_t touch_get_state(struct touch_state *state)
146 {
147     uint8_t val;
148     uint8_t num;
149     uint8_t xyz[4];
150     int32_t res;
151     struct rt_i2c_msg msgs[2];
152 
153     /* Read touch status */
154     res = touch_read(STMPE811_TSC_CTRL, &val);
155     if (res < 0) return -1;
156     state->pressed = (val & (1 << 7)) ? 1 : 0;
157 
158     if (state->pressed)
159     {
160         val = STMPE811_TSC_DATA;
161 
162         /* If FIFO overflow, discard all samples except the last one */
163         res = touch_read(STMPE811_FIFO_SIZE, &num);
164         if (res < 0 || num == 0) return -1;
165 
166         while (num--)
167         {
168             msgs[0].addr  = TSC_I2C_ADDR;
169             msgs[0].flags = RT_I2C_WR;
170             msgs[0].buf   = &val;
171             msgs[0].len   = 1;
172 
173             //rt_i2c_transfer(stmpe811_i2c_bus, &msgs, 1);
174           //ptrI2C->MasterTransmit (TSC_I2C_ADDR, &val, 1, true);
175           //while (ptrI2C->GetStatus().busy);
176             msgs[1].addr  = TSC_I2C_ADDR;
177             msgs[1].flags = RT_I2C_RD;
178             msgs[1].buf   = xyz;
179             msgs[1].len   = 4;
180             rt_i2c_transfer(stmpe811_i2c_bus, msgs, 2);
181           //ptrI2C->MasterReceive (TSC_I2C_ADDR, xyz, 4, false);
182           //while (ptrI2C->GetStatus().busy);
183         }
184         state->x =  (int16_t)((xyz[0] << 4) | ((xyz[1] & 0xF0) >> 4));
185         state->y =  (int16_t) (xyz[2]       | ((xyz[1] & 0x0F) << 8));
186     }
187     else
188     {
189         /* Clear all data in FIFO */
190         touch_write(STMPE811_FIFO_STA, 0x1);
191         touch_write(STMPE811_FIFO_STA, 0x0);
192     }
193 
194     return 0;
195 }
196 
touch_show_state()197 void touch_show_state()
198 {
199     int16_t x;
200     int16_t y;
201     struct touch_state ts;
202     touch_get_state(&ts);
203     x = (3706 - ts.x) / 14;
204     y = (-461 + ts.y) / 10.5;
205     rt_kprintf("[drv_touch] touch_show_state, x: %d, y: %d, pressed: %d, padding: %d\n", ts.x , ts.y, ts.pressed, ts.padding);
206     rt_kprintf("[drv_touch] touch_show_state, phy x: %d, phy y: %d\n", x , y);
207 }
208 MSH_CMD_EXPORT(touch_show_state, show screen coordinate in touching);
209 
rt_hw_touch_init(void)210 static int rt_hw_touch_init(void)
211 {
212     static struct rt_device touch;
213 
214     /* init device structure */
215     touch.type = RT_Device_Class_Unknown;
216     touch.init = stmpe811_touch_init;
217     touch.user_data = RT_NULL;
218 
219     /* register touch device to RT-Thread */
220     rt_device_register(&touch, "touch", RT_DEVICE_FLAG_RDWR);
221 
222     return RT_EOK;
223 }
224 INIT_BOARD_EXPORT(rt_hw_touch_init);
225