@@ -45,13 +45,40 @@ bool touch_enabled = false;
4545
4646#define CHANNEL_NO 0
4747#define N_SAMPLES 10
48+ #define K_FACTOR 100000000L
49+
50+ static uint16_t process_samples (nrf_saadc_value_t samples [], int n_samples ) {
51+ // XXX sort of like a least squares fit here, with the assumption
52+ // that the timing ('x') is stable (thus we suspend interrupts while
53+ // taking these measurements)
54+
55+ int32_t sumy = 0 ;
56+ int32_t sumxy = 0 ;
57+
58+ for (int i = 0 ; i < N_SAMPLES ; i ++ ) {
59+ sumy += samples [i ];
60+ sumxy += i * samples [i ];
61+ }
62+
63+ // we don't really care about the units, and so we can cut out a
64+ // whole bunch of stuff which is based only on N_SAMPLES, eg:
65+ // n, sum(x), sum(x^2) and sum(x)^2 terms. This leaves only:
66+
67+ int16_t m = (N_SAMPLES - 1 ) * sumy / 2 - sumxy ;
68+
69+ // m is proportional to the charge rate of the capacitor which is
70+ // in reciprocal proportion to the actual capacitance.
71+ return (uint16_t )(K_FACTOR / m );
72+ }
4873
4974static uint16_t get_raw_reading (touchio_touchin_obj_t * self ) {
5075
5176 nrf_saadc_value_t samples [N_SAMPLES ];
5277
5378 // Configure analog input.
54- // XXX cloned from AnalogIn and probably overkill
79+ // XXX analogio.AnalogIn and this class both use SAADC channel 0
80+ // all the time and never any other channel. This seems a bit
81+ // silly.
5582
5683 const nrf_saadc_channel_config_t config = {
5784 .resistor_p = NRF_SAADC_RESISTOR_DISABLED ,
@@ -75,14 +102,15 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
75102 nrf_saadc_channel_init (CHANNEL_NO , & config );
76103 nrf_saadc_buffer_init (samples , N_SAMPLES );
77104
78- // set pad to digital output high for 20us to charge it
105+ // set pad to digital output high for 10us to charge it
79106
80107 nrf_gpio_cfg_output (self -> pin -> number );
81108 nrf_gpio_pin_set (self -> pin -> number );
82109
83- mp_hal_delay_us (20 );
110+ mp_hal_delay_us (10 );
84111
85112 // set pad back to an input and take some samples
113+ // IRQs are suspended to make sure our samples are at fixed times.
86114
87115 __disable_irq ();
88116
@@ -92,7 +120,7 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
92120 while (nrf_saadc_event_check (NRF_SAADC_EVENT_STARTED ) == 0 );
93121 nrf_saadc_event_clear (NRF_SAADC_EVENT_STARTED );
94122
95- // XXX surely there's a better way
123+ // XXX surely there's a better way? PPI?
96124 for (uint32_t i = 0 ; i < N_SAMPLES ; i ++ ) {
97125 nrf_saadc_task_trigger (NRF_SAADC_TASK_SAMPLE );
98126 while (nrf_saadc_event_check (NRF_SAADC_EVENT_DONE ) == 0 );
@@ -105,7 +133,7 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
105133 while (nrf_saadc_event_check (NRF_SAADC_EVENT_STOPPED ) == 0 );
106134 nrf_saadc_event_clear (NRF_SAADC_EVENT_STOPPED );
107135
108- // turn off SAADC & set output pin low
136+ // turn off SAADC & set output pin low (to minimize leakage currents)
109137
110138 nrf_gpio_pin_clear (self -> pin -> number );
111139
@@ -114,23 +142,8 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) {
114142
115143 nrf_gpio_cfg_output (self -> pin -> number );
116144
117- int32_t sumy = 0 ;
118- int32_t sumxy = 0 ;
119-
120- //mp_printf(MP_PYTHON_PRINTER, "touch");
121-
122- // XXX sort of like a least squares fit here
123-
124- for (int i = 0 ; i < N_SAMPLES ; i ++ ) {
125- //mp_printf(MP_PYTHON_PRINTER, " %d", samples[i]);
126- sumy += samples [i ];
127- sumxy += i * samples [i ];
128- }
129- int32_t r = (N_SAMPLES - 1 ) * sumy / 2 - sumxy ;
130-
131- //mp_printf(MP_PYTHON_PRINTER, " -> %d %d -> %d\n", sumy, sumxy, r);
145+ return process_samples (samples , N_SAMPLES );
132146
133- return (uint16_t )r ;
134147}
135148
136149void common_hal_touchio_touchin_construct (touchio_touchin_obj_t * self ,
0 commit comments