@@ -89,9 +89,9 @@ freq_hop_sel_t selfcap_freq_hops[3u] = {DEF_SELFCAP_HOP_FREQS};
8989 * the elements of this structure. DO NOT modify any of the input values
9090 * directly in this structure.
9191 */
92- static touch_selfcap_config_t selfcap_config = {
93- DEF_SELFCAP_NUM_CHANNELS , /* Self Cap number of channels. */
94- DEF_SELFCAP_NUM_SENSORS , /* Self Cap number of sensors. */
92+ touch_selfcap_config_t selfcap_config = {
93+ 0 , /* Self Cap number of channels. */
94+ 0 , /* Self Cap number of sensors. */
9595 DEF_SELFCAP_NUM_ROTORS_SLIDERS , /* Self Cap number of rotors and
9696 * sliders. */
9797
@@ -181,58 +181,87 @@ touch_config_t touch_config = {
181181 DEF_TOUCH_PTC_ISR_LVL , /* PTC interrupt level. */
182182};
183183
184- bool ptc_initialized = false;
184+ nativeio_touchin_obj_t * active_touchin_obj [DEF_SELFCAP_NUM_CHANNELS ];
185+
185186void common_hal_nativeio_touchin_construct (nativeio_touchin_obj_t * self ,
186187 const mcu_pin_obj_t * pin ) {
187188 if (!pin -> has_touch ) {
188189 // No ADC function on that pin
189190 nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "pin %q does not have touch capabilities" , pin -> name ));
190191 }
191192
192- touch_ret_t status ;
193- if (!ptc_initialized ) {
194- /* Setup and enable generic clock source for PTC module. */
195- struct system_gclk_chan_config gclk_chan_conf ;
196- system_gclk_chan_get_config_defaults (& gclk_chan_conf );
197- gclk_chan_conf .source_generator = GCLK_GENERATOR_1 ;
198- system_gclk_chan_set_config (PTC_GCLK_ID , & gclk_chan_conf );
199- system_gclk_chan_enable (PTC_GCLK_ID );
200- system_apb_clock_set_mask (SYSTEM_CLOCK_APB_APBC , PM_APBCMASK_PTC );
201-
202- /* Initialize touch library for Self Cap operation. */
203- status = touch_selfcap_sensors_init_with_rs_table (& touch_config ,
204- PRIV_SELFCAP_RS_TABLE_INIT , PRIV_NM_TABLE_INIT ,
205- PRIV_FREQ_AUTO_TUNE_CHK , PRIV_MOIS_TOLERANCE_CHK );
206- if (status != TOUCH_SUCCESS ) {
207- nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "Touch init failed (%d)" , status ));
193+ if (selfcap_config .num_channels > 0 ) {
194+ // Deinit the touch sensor, we're going to reinitialize it.
195+ touch_selfcap_sensors_deinit ();
196+
197+ // Remove holes in the active list from sensors that may have been
198+ // disabled.
199+ int first_hole = -1 ;
200+ for (int i = 0 ; i < selfcap_config .num_channels ; i ++ ) {
201+ if (active_touchin_obj [i ] == NULL && first_hole == -1 ) {
202+ first_hole = i ;
203+ } else if (active_touchin_obj [i ] != NULL && first_hole != -1 ) {
204+ active_touchin_obj [first_hole ] = active_touchin_obj [i ];
205+ first_hole = i ;
206+ }
208207 }
209- ptc_initialized = true;
210- }
211- // Map Y line to channel. Boards can switch the order.
212- int channel ;
213- for (channel = 0 ; channel < DEF_SELFCAP_NUM_CHANNELS ; channel ++ ) {
214- if (selfcap_y_nodes [channel ] == Y (pin -> touch_y_line )) {
215- break ;
208+ if (first_hole > -1 ) {
209+ selfcap_config .num_channels = first_hole ;
210+ selfcap_config .num_sensors = first_hole ;
216211 }
217212 }
218- if (channel == DEF_SELFCAP_NUM_CHANNELS ) {
219- nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "Pin %q on this board does not have touch capabilities" , pin -> name ));
220- }
221- status = touch_selfcap_sensor_config (SENSOR_TYPE_KEY , channel , channel ,
222- NO_AKS_GROUP , 10u , HYST_25 , RES_8_BIT , & self -> sensor_id );
213+
214+ // Add our sensor to the end of the list.
215+ self -> pin = pin ;
216+ selfcap_y_nodes [selfcap_config .num_channels ++ ] = Y (pin -> touch_y_line );
217+ active_touchin_obj [selfcap_config .num_sensors ++ ] = self ;
218+
219+ /* Setup and enable generic clock source for PTC module. */
220+ struct system_gclk_chan_config gclk_chan_conf ;
221+ system_gclk_chan_get_config_defaults (& gclk_chan_conf );
222+ gclk_chan_conf .source_generator = GCLK_GENERATOR_1 ;
223+ system_gclk_chan_set_config (PTC_GCLK_ID , & gclk_chan_conf );
224+ system_gclk_chan_enable (PTC_GCLK_ID );
225+ system_apb_clock_set_mask (SYSTEM_CLOCK_APB_APBC , PM_APBCMASK_PTC );
226+
227+ touch_ret_t status ;
228+ /* Initialize touch library for Self Cap operation. */
229+ status = touch_selfcap_sensors_init_with_rs_table (& touch_config ,
230+ PRIV_SELFCAP_RS_TABLE_INIT , PRIV_NM_TABLE_INIT ,
231+ PRIV_FREQ_AUTO_TUNE_CHK , PRIV_MOIS_TOLERANCE_CHK );
223232 if (status != TOUCH_SUCCESS ) {
224- nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "Touch pad config failed (%d)" , status ));
233+ nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "Touch init failed (%d)" , status ));
234+ }
235+ for (int i = 0 ; i < selfcap_config .num_channels ; i ++ ) {
236+ status = touch_selfcap_sensor_config (SENSOR_TYPE_KEY , i , i ,
237+ NO_AKS_GROUP , 10u , HYST_25 , RES_8_BIT , & active_touchin_obj [i ]-> sensor_id );
238+ if (status != TOUCH_SUCCESS ) {
239+ nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "Touch pad config failed (%d)" , status ));
240+ }
225241 }
226242 status = touch_selfcap_sensors_calibrate (AUTO_TUNE_RSEL );
227243 if (status != TOUCH_SUCCESS ) {
228244 nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "Touch pad calibration failed (%d)" , status ));
229245 }
230246
231- self -> pin = pin ;
247+ // Run a measurement to get calibrated.
248+ common_hal_nativeio_touchin_get_value (self );
232249}
233250
251+ // This may get called twice, once on exit or deinit and once from the finaliser
252+ // (__del__). We need the finaliser to reduce the chance of us writing to memory
253+ // we no longer own because we keep track of Python pointers in active_touchin_obj.
234254void common_hal_nativeio_touchin_deinit (nativeio_touchin_obj_t * self ) {
235255 touch_selfcap_sensor_disable (self -> sensor_id );
256+ // Remove ourselves from the list of active objects. We don't change the
257+ // selfcap settings at all because we don't want to reinit now. Instead,
258+ // we'll collect blank spots later on reinit.
259+ for (int i = 0 ; i < DEF_SELFCAP_NUM_CHANNELS ; i ++ ) {
260+ if (active_touchin_obj [i ] == self ) {
261+ active_touchin_obj [i ] = NULL ;
262+ break ;
263+ }
264+ }
236265}
237266
238267volatile bool touch_read_ready = false;
@@ -263,12 +292,15 @@ bool common_hal_nativeio_touchin_get_value(nativeio_touchin_obj_t *self) {
263292
264293 while (!touch_read_ready && ticks_ms - start_ticks < 1000 ) {
265294 // wait
295+ #ifdef MICROPY_VM_HOOK_LOOP
296+ MICROPY_VM_HOOK_LOOP
297+ #endif
266298 }
267299 }
268300
269301 if (touch_acq_status & TOUCH_BURST_AGAIN ) {
270302 nlr_raise (mp_obj_new_exception_msg (& mp_type_OSError , "Touch read failed" ));
271303 }
272304
273- return (p_selfcap_measure_data -> p_sensor_states [self -> sensor_id / 8 ] & (1 << (self -> sensor_id % 8 ))) == 1 ;
305+ return (p_selfcap_measure_data -> p_sensor_states [self -> sensor_id / 8 ] & (1 << (self -> sensor_id % 8 ))) != 0 ;
274306}
0 commit comments