diff options
| author | Nick Moore <nick@zoic.org> | 2018-12-11 14:33:03 +1100 |
|---|---|---|
| committer | Nick Moore <nick@zoic.org> | 2018-12-11 14:33:35 +1100 |
| commit | 1dc4c4757e2eb476fec6ae9e49f1136c1c7ea86b (patch) | |
| tree | 7bcf2d070116378637676793abb9f39991c31689 | |
| parent | 901db4797ed99e1c70692d9d1e261d7da9d10cfb (diff) | |
touchio.TouchIn sensing working on a single pin! adafruit/circuitpython#1048
| -rw-r--r-- | ports/nrf/common-hal/touchio/TouchIn.c | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/ports/nrf/common-hal/touchio/TouchIn.c b/ports/nrf/common-hal/touchio/TouchIn.c index db20e42d1..b2d61f548 100644 --- a/ports/nrf/common-hal/touchio/TouchIn.c +++ b/ports/nrf/common-hal/touchio/TouchIn.c @@ -45,13 +45,40 @@ bool touch_enabled = false; #define CHANNEL_NO 0 #define N_SAMPLES 10 +#define K_FACTOR 100000000L + +static uint16_t process_samples(nrf_saadc_value_t samples[], int n_samples) { + // XXX sort of like a least squares fit here, with the assumption + // that the timing ('x') is stable (thus we suspend interrupts while + // taking these measurements) + + int32_t sumy = 0; + int32_t sumxy = 0; + + for (int i = 0; i < N_SAMPLES; i++) { + sumy += samples[i]; + sumxy += i*samples[i]; + } + + // we don't really care about the units, and so we can cut out a + // whole bunch of stuff which is based only on N_SAMPLES, eg: + // n, sum(x), sum(x^2) and sum(x)^2 terms. This leaves only: + + int16_t m = (N_SAMPLES - 1) * sumy / 2 - sumxy; + + // m is proportional to the charge rate of the capacitor which is + // in reciprocal proportion to the actual capacitance. + return (uint16_t)(K_FACTOR / m); +} static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { nrf_saadc_value_t samples[N_SAMPLES]; // Configure analog input. - // XXX cloned from AnalogIn and probably overkill + // XXX analogio.AnalogIn and this class both use SAADC channel 0 + // all the time and never any other channel. This seems a bit + // silly. const nrf_saadc_channel_config_t config = { .resistor_p = NRF_SAADC_RESISTOR_DISABLED, @@ -75,14 +102,15 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { nrf_saadc_channel_init(CHANNEL_NO, &config); nrf_saadc_buffer_init(samples, N_SAMPLES); - // set pad to digital output high for 20us to charge it + // set pad to digital output high for 10us to charge it nrf_gpio_cfg_output(self->pin->number); nrf_gpio_pin_set(self->pin->number); - mp_hal_delay_us(20); + mp_hal_delay_us(10); // set pad back to an input and take some samples + // IRQs are suspended to make sure our samples are at fixed times. __disable_irq(); @@ -92,7 +120,7 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { while (nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED) == 0); nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); - // XXX surely there's a better way + // XXX surely there's a better way? PPI? for (uint32_t i = 0; i < N_SAMPLES; i++) { nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); 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) { while (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED) == 0); nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); - // turn off SAADC & set output pin low + // turn off SAADC & set output pin low (to minimize leakage currents) nrf_gpio_pin_clear(self->pin->number); @@ -114,23 +142,8 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { nrf_gpio_cfg_output(self->pin->number); - int32_t sumy = 0; - int32_t sumxy = 0; - - //mp_printf(MP_PYTHON_PRINTER, "touch"); - - // XXX sort of like a least squares fit here - - for (int i = 0; i < N_SAMPLES; i++) { - //mp_printf(MP_PYTHON_PRINTER, " %d", samples[i]); - sumy += samples[i]; - sumxy += i*samples[i]; - } - int32_t r = (N_SAMPLES - 1) * sumy / 2 - sumxy; - - //mp_printf(MP_PYTHON_PRINTER, " -> %d %d -> %d\n", sumy, sumxy, r); + return process_samples(samples, N_SAMPLES); - return (uint16_t)r; } void common_hal_touchio_touchin_construct(touchio_touchin_obj_t* self, |
