1+ /*
2+ * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
3+ * SPDX-FileCopyrightText: 2025 Waveshare
4+ *
5+ * SPDX-License-Identifier: Apache-2.0
6+ */
7+
8+ #include <stdio.h>
9+ #include <string.h>
10+ #include "freertos/FreeRTOS.h"
11+ #include "freertos/task.h"
12+ #include "esp_system.h"
13+ #include "esp_err.h"
14+ #include "esp_log.h"
15+ #include "esp_check.h"
16+ #include "driver/gpio.h"
17+ #include "esp_lcd_panel_io.h"
18+ #include "esp_lcd_touch.h"
19+ #include "esp_lcd_touch_cst328.h"
20+
21+ static const char * TAG = "CST328" ;
22+
23+ //workmode
24+ #define CST328_REG_DEBUG_INFO_MODE 0xD101
25+ #define CST328_REG_RESET_MODE 0xD102
26+ #define CST328_REG_DEBUG_RECALIBRATION_MODE 0xD104
27+ #define CST328_REG_DEEP_SLEEP_MODE 0xD105
28+ #define CST328_REG_DEBUG_POINT_MODE 0xD108
29+ #define CST328_REG_NORMAL_MODE 0xD109
30+
31+ #define CST328_REG_DEBUG_RAWDATA_MODE 0xD10A
32+ #define CST328_REG_DEBUG_DIFF_MODE 0xD10D
33+ #define CST328_REG_DEBUG_FACTORY_MODE 0xD119
34+ #define CST328_REG_DEBUG_FACTORY_MODE_2 0xD120
35+ //debug info
36+ /****************CST328_REG_DEBUG_INFO_MODE address start***********/
37+ #define CST328_REG_DEBUG_INFO_BOOT_TIME 0xD1FC
38+ #define CST328_REG_DEBUG_INFO_RES_Y 0xD1FA
39+ #define CST328_REG_DEBUG_INFO_RES_X 0xD1F8
40+ #define CST328_REG_DEBUG_INFO_KEY_NUM 0xD1F7
41+ #define CST328_REG_DEBUG_INFO_TP_NRX 0xD1F6
42+ #define CST328_REG_DEBUG_INFO_TP_NTX 0xD1F4
43+
44+ /* CST328 registers */
45+ #define ESP_LCD_TOUCH_CST328_READ_Number_REG (0xD005)
46+ #define ESP_LCD_TOUCH_CST328_READ_XY_REG (0xD000)
47+ #define ESP_LCD_TOUCH_CST328_READ_Checksum_REG (0x80FF)
48+ #define ESP_LCD_TOUCH_CST328_CONFIG_REG (0x8047)
49+
50+
51+ /*******************************************************************************
52+ * Function definitions
53+ *******************************************************************************/
54+ static esp_err_t esp_lcd_touch_cst328_read_data (esp_lcd_touch_handle_t tp );
55+ static bool esp_lcd_touch_cst328_get_xy (esp_lcd_touch_handle_t tp , uint16_t * x , uint16_t * y , uint16_t * strength , uint8_t * point_num , uint8_t max_point_num );
56+ static esp_err_t esp_lcd_touch_cst328_del (esp_lcd_touch_handle_t tp );
57+ static esp_err_t touch_cst328_i2c_read (esp_lcd_touch_handle_t tp , uint16_t reg , uint8_t * data , uint8_t len );
58+ static esp_err_t touch_cst328_i2c_write (esp_lcd_touch_handle_t tp , uint16_t reg , uint8_t * data , uint8_t len );
59+ static esp_err_t touch_cst328_reset (esp_lcd_touch_handle_t tp );
60+ static void touch_cst328_read_cfg (esp_lcd_touch_handle_t tp );
61+
62+
63+ /*******************************************************************************
64+ * Public API functions
65+ *******************************************************************************/
66+
67+ esp_err_t esp_lcd_touch_new_i2c_cst328 (const esp_lcd_panel_io_handle_t io , const esp_lcd_touch_config_t * config , esp_lcd_touch_handle_t * out_touch )
68+ {
69+ esp_err_t ret = ESP_OK ;
70+
71+ assert (io != NULL );
72+ assert (config != NULL );
73+ assert (out_touch != NULL );
74+
75+ /* Prepare main structure */
76+ esp_lcd_touch_handle_t esp_lcd_touch_cst328 = heap_caps_calloc (1 , sizeof (esp_lcd_touch_t ), MALLOC_CAP_DEFAULT );
77+ ESP_GOTO_ON_FALSE (esp_lcd_touch_cst328 , ESP_ERR_NO_MEM , err , TAG , "no mem for CST328 controller" );
78+ /* Communication interface */
79+ esp_lcd_touch_cst328 -> io = io ;
80+
81+ /* Only supported callbacks are set */
82+ esp_lcd_touch_cst328 -> read_data = esp_lcd_touch_cst328_read_data ;
83+ esp_lcd_touch_cst328 -> get_xy = esp_lcd_touch_cst328_get_xy ;
84+ esp_lcd_touch_cst328 -> del = esp_lcd_touch_cst328_del ;
85+
86+ /* Mutex */
87+ esp_lcd_touch_cst328 -> data .lock .owner = portMUX_FREE_VAL ;
88+
89+ /* Save config */
90+ memcpy (& esp_lcd_touch_cst328 -> config , config , sizeof (esp_lcd_touch_config_t ));
91+
92+ /* Prepare pin for touch interrupt */
93+ if (esp_lcd_touch_cst328 -> config .int_gpio_num != GPIO_NUM_NC ) {
94+ const gpio_config_t int_gpio_config = {
95+ .mode = GPIO_MODE_INPUT ,
96+ .intr_type = GPIO_INTR_NEGEDGE ,
97+ .pin_bit_mask = BIT64 (esp_lcd_touch_cst328 -> config .int_gpio_num )
98+ };
99+ ret = gpio_config (& int_gpio_config );
100+ ESP_GOTO_ON_ERROR (ret , err , TAG , "GPIO config failed" );
101+
102+ }
103+
104+ /* Reset controller */
105+ ret = touch_cst328_reset (esp_lcd_touch_cst328 );
106+ ESP_GOTO_ON_ERROR (ret , err , TAG , "CST328 reset failed" );
107+ touch_cst328_read_cfg (esp_lcd_touch_cst328 );
108+
109+ err :
110+ if (ret != ESP_OK ) {
111+ ESP_LOGE (TAG , "Error (0x%x)! Touch controller CST328 initialization failed!" , ret );
112+ if (esp_lcd_touch_cst328 ) {
113+ esp_lcd_touch_cst328_del (esp_lcd_touch_cst328 );
114+ }
115+ }
116+
117+ * out_touch = esp_lcd_touch_cst328 ;
118+
119+ return ret ;
120+ }
121+
122+ /*******************************************************************************
123+ * Private functions
124+ *******************************************************************************/
125+
126+ static esp_err_t esp_lcd_touch_cst328_read_data (esp_lcd_touch_handle_t tp )
127+ {
128+ esp_err_t err ;
129+ uint8_t buf [41 ];
130+ uint8_t touch_cnt = 0 ;
131+ uint8_t clear = 0 ;
132+ size_t i = 0 ,num = 0 ;
133+
134+ assert (tp != NULL );
135+
136+ err = touch_cst328_i2c_read (tp , ESP_LCD_TOUCH_CST328_READ_Number_REG , buf , 1 );
137+ ESP_RETURN_ON_ERROR (err , TAG , "I2C read error!" );
138+ /* Any touch data? */
139+ if ((buf [0 ] & 0x0F ) == 0x00 ) {
140+ touch_cst328_i2c_write (tp , ESP_LCD_TOUCH_CST328_READ_Number_REG , & clear , 1 ); // No touch data
141+ } else {
142+ /* Count of touched points */
143+ touch_cnt = buf [0 ] & 0x0F ;
144+ if (touch_cnt > 5 || touch_cnt == 0 ) {
145+ touch_cst328_i2c_write (tp , ESP_LCD_TOUCH_CST328_READ_Number_REG , & clear , 1 );
146+ return ESP_OK ;
147+ }
148+
149+ /* Read all points */
150+ err = touch_cst328_i2c_read (tp , ESP_LCD_TOUCH_CST328_READ_XY_REG , & buf [1 ], 27 );
151+ ESP_RETURN_ON_ERROR (err , TAG , "I2C read error!" );
152+
153+ /* Clear all */
154+ err = touch_cst328_i2c_write (tp , ESP_LCD_TOUCH_CST328_READ_Number_REG , & clear , 1 );
155+ ESP_RETURN_ON_ERROR (err , TAG , "I2C read error!" );
156+
157+ taskENTER_CRITICAL (& tp -> data .lock );
158+
159+ /* Number of touched points */
160+ if (touch_cnt > CONFIG_ESP_LCD_TOUCH_MAX_POINTS )
161+ touch_cnt = CONFIG_ESP_LCD_TOUCH_MAX_POINTS ;
162+ tp -> data .points = (uint8_t )touch_cnt ;
163+
164+ /* Fill all coordinates */
165+ for (i = 0 ; i < touch_cnt ; i ++ ) {
166+ if (i > 0 ) num = 2 ;
167+ tp -> data .coords [i ].x = (uint16_t )(((uint16_t )buf [(i * 5 ) + 2 + num ] << 4 ) + ((buf [(i * 5 ) + 4 + num ] & 0xF0 )>> 4 ));
168+ tp -> data .coords [i ].y = (uint16_t )(((uint16_t )buf [(i * 5 ) + 3 + num ] << 4 ) + ( buf [(i * 5 ) + 4 + num ] & 0x0F ));
169+ tp -> data .coords [i ].strength = ((uint16_t )buf [(i * 5 ) + 5 + num ]);
170+ }
171+
172+ taskEXIT_CRITICAL (& tp -> data .lock );
173+ }
174+
175+ return ESP_OK ;
176+ }
177+
178+
179+
180+ static bool esp_lcd_touch_cst328_get_xy (esp_lcd_touch_handle_t tp , uint16_t * x , uint16_t * y , uint16_t * strength , uint8_t * point_num , uint8_t max_point_num )
181+ {
182+ assert (tp != NULL );
183+ assert (x != NULL );
184+ assert (y != NULL );
185+ assert (point_num != NULL );
186+ assert (max_point_num > 0 );
187+
188+ taskENTER_CRITICAL (& tp -> data .lock );
189+
190+ /* Count of points */
191+ if (tp -> data .points > max_point_num )
192+ tp -> data .points = max_point_num ;
193+
194+ for (size_t i = 0 ; i < tp -> data .points ; i ++ ) {
195+ x [i ] = tp -> data .coords [i ].x ;
196+ y [i ] = tp -> data .coords [i ].y ;
197+
198+ if (strength ) {
199+ strength [i ] = tp -> data .coords [i ].strength ;
200+ }
201+ }
202+ * point_num = tp -> data .points ;
203+ /* Invalidate */
204+ tp -> data .points = 0 ;
205+
206+
207+ taskEXIT_CRITICAL (& tp -> data .lock );
208+ return (* point_num > 0 );
209+ }
210+
211+
212+ static esp_err_t esp_lcd_touch_cst328_del (esp_lcd_touch_handle_t tp )
213+ {
214+ assert (tp != NULL );
215+
216+ /* Reset GPIO pin settings */
217+ if (tp -> config .int_gpio_num != GPIO_NUM_NC ) {
218+ gpio_reset_pin (tp -> config .int_gpio_num );
219+ }
220+
221+ /* Reset GPIO pin settings */
222+ if (tp -> config .rst_gpio_num != GPIO_NUM_NC ) {
223+ gpio_reset_pin (tp -> config .rst_gpio_num );
224+ }
225+
226+ free (tp );
227+
228+ return ESP_OK ;
229+ }
230+
231+
232+
233+ static esp_err_t touch_cst328_reset (esp_lcd_touch_handle_t tp )
234+ {
235+ assert (tp != NULL );
236+
237+ ESP_RETURN_ON_ERROR (gpio_set_level (tp -> config .rst_gpio_num , !tp -> config .levels .reset ), TAG , "GPIO set level error!" );
238+ vTaskDelay (pdMS_TO_TICKS (10 ));
239+ ESP_RETURN_ON_ERROR (gpio_set_level (tp -> config .rst_gpio_num , tp -> config .levels .reset ), TAG , "GPIO set level error!" );
240+ vTaskDelay (pdMS_TO_TICKS (10 ));
241+
242+ return ESP_OK ;
243+ }
244+
245+ static void touch_cst328_read_cfg (esp_lcd_touch_handle_t tp )
246+ {
247+ uint8_t buf [24 ];
248+
249+ assert (tp != NULL );
250+ touch_cst328_i2c_write (tp , CST328_REG_DEBUG_INFO_MODE , buf , 0 );
251+ touch_cst328_i2c_read (tp , CST328_REG_DEBUG_INFO_BOOT_TIME , (uint8_t * )& buf [0 ], 4 );
252+ ESP_LOGI (TAG , "TouchPad_ID:0x%02x,0x%02x,0x%02x,0x%02x" , buf [0 ], buf [1 ], buf [2 ], buf [3 ]);
253+
254+ touch_cst328_i2c_read (tp , CST328_REG_DEBUG_INFO_RES_X , (uint8_t * )& buf [0 ], 1 );
255+ touch_cst328_i2c_read (tp , CST328_REG_DEBUG_INFO_RES_X + 1 , (uint8_t * )& buf [1 ], 1 );
256+ ESP_LOGI (TAG , "TouchPad_X_MAX:%d" , buf [1 ]* 256 + buf [0 ]);
257+ touch_cst328_i2c_read (tp , CST328_REG_DEBUG_INFO_RES_Y , (uint8_t * )& buf [2 ], 1 );
258+ touch_cst328_i2c_read (tp , CST328_REG_DEBUG_INFO_RES_Y + 1 , (uint8_t * )& buf [3 ], 1 );
259+ ESP_LOGI (TAG , "TouchPad_Y_MAX:%d" , buf [3 ]* 256 + buf [2 ]);
260+
261+ touch_cst328_i2c_read (tp , CST328_REG_DEBUG_INFO_TP_NTX , buf , 24 );
262+ ESP_LOGI (TAG , "D1F4:0x%02x,0x%02x,0x%02x,0x%02x" , buf [0 ], buf [1 ], buf [2 ], buf [3 ]);
263+ ESP_LOGI (TAG , "D1F8:0x%02x,0x%02x,0x%02x,0x%02x" , buf [4 ], buf [5 ], buf [6 ], buf [7 ]);
264+ ESP_LOGI (TAG , "D1FC:0x%02x,0x%02x,0x%02x,0x%02x" , buf [8 ], buf [9 ], buf [10 ], buf [11 ]);
265+ ESP_LOGI (TAG , "D200:0x%02x,0x%02x,0x%02x,0x%02x" , buf [12 ], buf [13 ], buf [14 ], buf [15 ]);
266+ ESP_LOGI (TAG , "D204:0x%02x,0x%02x,0x%02x,0x%02x" , buf [16 ], buf [17 ], buf [18 ], buf [19 ]);
267+ ESP_LOGI (TAG , "D208:0x%02x,0x%02x,0x%02x,0x%02x" , buf [20 ], buf [21 ], buf [22 ], buf [23 ]);
268+
269+ touch_cst328_i2c_write (tp , CST328_REG_NORMAL_MODE , buf , 0 );
270+ }
271+
272+
273+ static esp_err_t touch_cst328_i2c_read (esp_lcd_touch_handle_t tp , uint16_t reg , uint8_t * data , uint8_t len )
274+ {
275+ assert (tp != NULL );
276+ assert (data != NULL );
277+
278+ /* Read data */
279+ return esp_lcd_panel_io_rx_param (tp -> io , reg , data , len );
280+ }
281+
282+ static esp_err_t touch_cst328_i2c_write (esp_lcd_touch_handle_t tp , uint16_t reg , uint8_t * data , uint8_t len )
283+ {
284+ assert (tp != NULL );
285+ /* Write data */
286+ return esp_lcd_panel_io_tx_param (tp -> io , reg , data , len );
287+ }
0 commit comments