From a11217a5ef0bf1bdc487015155c3d7ce1f7af5dd Mon Sep 17 00:00:00 2001 From: Tod Kurt Date: Sun, 6 Apr 2025 14:55:13 -0700 Subject: [PATCH 1/5] added touchio pullup for RP2350 --- locale/circuitpython.pot | 7 +- .../raspberrypi/common-hal/touchio/TouchIn.c | 103 ++++++++++++++++++ .../raspberrypi/common-hal/touchio/TouchIn.h | 26 +++++ .../raspberrypi/common-hal/touchio/__init__.c | 5 + ports/raspberrypi/mpconfigport.mk | 3 +- 5 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 ports/raspberrypi/common-hal/touchio/TouchIn.c create mode 100644 ports/raspberrypi/common-hal/touchio/TouchIn.h create mode 100644 ports/raspberrypi/common-hal/touchio/__init__.c diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 687cf5f071524..e09bdb7b4d7f1 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1555,6 +1555,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "" +#: ports/raspberrypi/common-hal/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "" @@ -2577,7 +2581,8 @@ msgstr "" msgid "bits must be 32 or less" msgstr "" -#: shared-bindings/audiodelays/Echo.c shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/PitchShift.c #: shared-bindings/audiofilters/Distortion.c #: shared-bindings/audiofilters/Filter.c shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" diff --git a/ports/raspberrypi/common-hal/touchio/TouchIn.c b/ports/raspberrypi/common-hal/touchio/TouchIn.c new file mode 100644 index 0000000000000..35341a8156724 --- /dev/null +++ b/ports/raspberrypi/common-hal/touchio/TouchIn.c @@ -0,0 +1,103 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2018 Nick Moore for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include +#include + +#include "py/runtime.h" +#include "py/mphal.h" +#include "shared-bindings/touchio/TouchIn.h" +#include "shared-bindings/microcontroller/Pin.h" + +// Native touchio only for RP2350, which cannot do shared-module touchio +#ifdef PICO_RP2350 + +// This is a capacitive touch sensing routine using a single digital +// pin. The pin should be connected to the sensing pad, and to ground +// via a 1Mohm or thereabout drain resistor. When a reading is taken, +// the pin's capacitance is charged by setting it to a digital output +// 'high' for a few microseconds, and then it is changed to a high +// impedance input. We measure how long it takes to discharge through +// the resistor (around 50us), using a busy-waiting loop, and average +// over N_SAMPLES cycles to reduce the effects of noise. + +#define N_SAMPLES 10 +#define TIMEOUT_TICKS 10000 + +static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { + + uint16_t ticks = 0; + + for (uint16_t i = 0; i < N_SAMPLES; i++) { + // set pad to digital output LOW for 10us to charge it + + common_hal_digitalio_digitalinout_switch_to_output(self->digitalinout, false, DRIVE_MODE_PUSH_PULL); + mp_hal_delay_us(10); + + // set pad back to an input and take some samples, waiting for it to go HIGH + + common_hal_digitalio_digitalinout_switch_to_input(self->digitalinout, PULL_NONE); + + while (!common_hal_digitalio_digitalinout_get_value(self->digitalinout)) { + if (ticks >= TIMEOUT_TICKS) { + return TIMEOUT_TICKS; + } + ticks++; + } + } + return ticks; +} + +void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, const mcu_pin_obj_t *pin) { + common_hal_mcu_pin_claim(pin); + self->digitalinout = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); + + common_hal_digitalio_digitalinout_construct(self->digitalinout, pin); + + uint16_t raw_reading = get_raw_reading(self); + if (raw_reading == TIMEOUT_TICKS) { + common_hal_touchio_touchin_deinit(self); + mp_raise_ValueError(MP_ERROR_TEXT("No pullup on pin; 1Mohm recommended")); + } + self->threshold = raw_reading * 1.05 + 100; +} + +bool common_hal_touchio_touchin_deinited(touchio_touchin_obj_t *self) { + return self->digitalinout == MP_OBJ_NULL; +} + +void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t *self) { + if (common_hal_touchio_touchin_deinited(self)) { + return; + } + + common_hal_digitalio_digitalinout_deinit(self->digitalinout); + self->digitalinout = MP_OBJ_NULL; +} + +void touchin_reset() { +} + +bool common_hal_touchio_touchin_get_value(touchio_touchin_obj_t *self) { + uint16_t reading = get_raw_reading(self); + return reading > self->threshold; +} + +uint16_t common_hal_touchio_touchin_get_raw_value(touchio_touchin_obj_t *self) { + return get_raw_reading(self); +} + +uint16_t common_hal_touchio_touchin_get_threshold(touchio_touchin_obj_t *self) { + return self->threshold; +} + +void common_hal_touchio_touchin_set_threshold(touchio_touchin_obj_t *self, + uint16_t new_threshold) { + self->threshold = new_threshold; +} + +#endif diff --git a/ports/raspberrypi/common-hal/touchio/TouchIn.h b/ports/raspberrypi/common-hal/touchio/TouchIn.h new file mode 100644 index 0000000000000..2d7faa32fff24 --- /dev/null +++ b/ports/raspberrypi/common-hal/touchio/TouchIn.h @@ -0,0 +1,26 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft +// SPDX-FileCopyrightText: Copyright (c) 2018 Nick Moore for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +#include "py/obj.h" + +// Native touchio only for RP2350, which cannot do shared-module touchio +#ifdef PICO_RP2350 + +typedef struct { + mp_obj_base_t base; + digitalio_digitalinout_obj_t *digitalinout; + uint16_t threshold; +} touchio_touchin_obj_t; + +void touchin_reset(void); + +#endif diff --git a/ports/raspberrypi/common-hal/touchio/__init__.c b/ports/raspberrypi/common-hal/touchio/__init__.c new file mode 100644 index 0000000000000..72d32ef2b2c5d --- /dev/null +++ b/ports/raspberrypi/common-hal/touchio/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index bb4e183461bec..f689653fb2197 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -66,7 +66,8 @@ CIRCUITPY_PICODVI ?= 1 # Our generic touchio uses a pull down and RP2350 A2 hardware doesn't work correctly. # So, turn touchio off because it doesn't work. -CIRCUITPY_TOUCHIO = 0 +CIRCUITPY_TOUCHIO = 1 +CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 # delay in ms before calling cyw43_arch_init_with_country CIRCUITPY_CYW43_INIT_DELAY ?= 0 From 6c1b6a4b59000abbef69346d3ac493450ac7fc5f Mon Sep 17 00:00:00 2001 From: Tod Kurt Date: Mon, 7 Apr 2025 12:32:00 -0700 Subject: [PATCH 2/5] add small note in port makefile about pull-up touchio for RP2350 --- ports/raspberrypi/mpconfigport.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index f689653fb2197..2a2693fb1fc4d 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -65,7 +65,8 @@ CIRCUITPY_ALARM = 0 CIRCUITPY_PICODVI ?= 1 # Our generic touchio uses a pull down and RP2350 A2 hardware doesn't work correctly. -# So, turn touchio off because it doesn't work. +# So, turn generic touchio off because it doesn't work. +# And use a "native" touchio that expects 1M pull-up resistor instead of pull-down CIRCUITPY_TOUCHIO = 1 CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 From 232b69929083bd5bcfea9539ddd923874f30ffee Mon Sep 17 00:00:00 2001 From: Tod Kurt Date: Mon, 7 Apr 2025 18:53:05 -0700 Subject: [PATCH 3/5] Add "pull" parameter to TouchIn ports --- locale/circuitpython.pot | 2 +- ports/atmel-samd/common-hal/touchio/TouchIn.c | 3 +- ports/espressif/common-hal/touchio/TouchIn.c | 3 +- .../raspberrypi/common-hal/touchio/TouchIn.c | 103 ------------------ .../raspberrypi/common-hal/touchio/TouchIn.h | 26 ----- .../raspberrypi/common-hal/touchio/__init__.c | 5 - ports/raspberrypi/mpconfigport.mk | 6 - shared-bindings/touchio/TouchIn.c | 21 ++-- shared-bindings/touchio/TouchIn.h | 3 +- shared-bindings/touchio/__init__.c | 5 +- shared-module/touchio/TouchIn.c | 26 +++-- shared-module/touchio/TouchIn.h | 1 + 12 files changed, 43 insertions(+), 161 deletions(-) delete mode 100644 ports/raspberrypi/common-hal/touchio/TouchIn.c delete mode 100644 ports/raspberrypi/common-hal/touchio/TouchIn.h delete mode 100644 ports/raspberrypi/common-hal/touchio/__init__.c diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index e09bdb7b4d7f1..8e169a7f7a655 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1555,7 +1555,7 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "" -#: ports/raspberrypi/common-hal/touchio/TouchIn.c +#: shared-module/touchio/TouchIn.c msgid "No pullup on pin; 1Mohm recommended" msgstr "" diff --git a/ports/atmel-samd/common-hal/touchio/TouchIn.c b/ports/atmel-samd/common-hal/touchio/TouchIn.c index 05c3f3ee923d9..dc31bfe634be5 100644 --- a/ports/atmel-samd/common-hal/touchio/TouchIn.c +++ b/ports/atmel-samd/common-hal/touchio/TouchIn.c @@ -12,6 +12,7 @@ #include "py/binary.h" #include "py/mphal.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/Pull.h" #include "shared-bindings/touchio/TouchIn.h" // Native touchio only exists for SAMD21 @@ -38,7 +39,7 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { } void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, - const mcu_pin_obj_t *pin) { + const mcu_pin_obj_t *pin, const digitalio_pull_t pull) { if (!pin->has_touch) { raise_ValueError_invalid_pin(); } diff --git a/ports/espressif/common-hal/touchio/TouchIn.c b/ports/espressif/common-hal/touchio/TouchIn.c index 2a37e6e526fb8..147acb2cfbf19 100644 --- a/ports/espressif/common-hal/touchio/TouchIn.c +++ b/ports/espressif/common-hal/touchio/TouchIn.c @@ -9,9 +9,10 @@ #include "py/runtime.h" #include "peripherals/touch.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/Pull.h" void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, - const mcu_pin_obj_t *pin) { + const mcu_pin_obj_t *pin, const digitalio_pull_t pull) { if (pin->touch_channel == NO_TOUCH_CHANNEL) { raise_ValueError_invalid_pin(); } diff --git a/ports/raspberrypi/common-hal/touchio/TouchIn.c b/ports/raspberrypi/common-hal/touchio/TouchIn.c deleted file mode 100644 index 35341a8156724..0000000000000 --- a/ports/raspberrypi/common-hal/touchio/TouchIn.c +++ /dev/null @@ -1,103 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries -// SPDX-FileCopyrightText: Copyright (c) 2018 Nick Moore for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#include -#include - -#include "py/runtime.h" -#include "py/mphal.h" -#include "shared-bindings/touchio/TouchIn.h" -#include "shared-bindings/microcontroller/Pin.h" - -// Native touchio only for RP2350, which cannot do shared-module touchio -#ifdef PICO_RP2350 - -// This is a capacitive touch sensing routine using a single digital -// pin. The pin should be connected to the sensing pad, and to ground -// via a 1Mohm or thereabout drain resistor. When a reading is taken, -// the pin's capacitance is charged by setting it to a digital output -// 'high' for a few microseconds, and then it is changed to a high -// impedance input. We measure how long it takes to discharge through -// the resistor (around 50us), using a busy-waiting loop, and average -// over N_SAMPLES cycles to reduce the effects of noise. - -#define N_SAMPLES 10 -#define TIMEOUT_TICKS 10000 - -static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { - - uint16_t ticks = 0; - - for (uint16_t i = 0; i < N_SAMPLES; i++) { - // set pad to digital output LOW for 10us to charge it - - common_hal_digitalio_digitalinout_switch_to_output(self->digitalinout, false, DRIVE_MODE_PUSH_PULL); - mp_hal_delay_us(10); - - // set pad back to an input and take some samples, waiting for it to go HIGH - - common_hal_digitalio_digitalinout_switch_to_input(self->digitalinout, PULL_NONE); - - while (!common_hal_digitalio_digitalinout_get_value(self->digitalinout)) { - if (ticks >= TIMEOUT_TICKS) { - return TIMEOUT_TICKS; - } - ticks++; - } - } - return ticks; -} - -void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, const mcu_pin_obj_t *pin) { - common_hal_mcu_pin_claim(pin); - self->digitalinout = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); - - common_hal_digitalio_digitalinout_construct(self->digitalinout, pin); - - uint16_t raw_reading = get_raw_reading(self); - if (raw_reading == TIMEOUT_TICKS) { - common_hal_touchio_touchin_deinit(self); - mp_raise_ValueError(MP_ERROR_TEXT("No pullup on pin; 1Mohm recommended")); - } - self->threshold = raw_reading * 1.05 + 100; -} - -bool common_hal_touchio_touchin_deinited(touchio_touchin_obj_t *self) { - return self->digitalinout == MP_OBJ_NULL; -} - -void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t *self) { - if (common_hal_touchio_touchin_deinited(self)) { - return; - } - - common_hal_digitalio_digitalinout_deinit(self->digitalinout); - self->digitalinout = MP_OBJ_NULL; -} - -void touchin_reset() { -} - -bool common_hal_touchio_touchin_get_value(touchio_touchin_obj_t *self) { - uint16_t reading = get_raw_reading(self); - return reading > self->threshold; -} - -uint16_t common_hal_touchio_touchin_get_raw_value(touchio_touchin_obj_t *self) { - return get_raw_reading(self); -} - -uint16_t common_hal_touchio_touchin_get_threshold(touchio_touchin_obj_t *self) { - return self->threshold; -} - -void common_hal_touchio_touchin_set_threshold(touchio_touchin_obj_t *self, - uint16_t new_threshold) { - self->threshold = new_threshold; -} - -#endif diff --git a/ports/raspberrypi/common-hal/touchio/TouchIn.h b/ports/raspberrypi/common-hal/touchio/TouchIn.h deleted file mode 100644 index 2d7faa32fff24..0000000000000 --- a/ports/raspberrypi/common-hal/touchio/TouchIn.h +++ /dev/null @@ -1,26 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft -// SPDX-FileCopyrightText: Copyright (c) 2018 Nick Moore for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include "common-hal/microcontroller/Pin.h" -#include "shared-bindings/digitalio/DigitalInOut.h" - -#include "py/obj.h" - -// Native touchio only for RP2350, which cannot do shared-module touchio -#ifdef PICO_RP2350 - -typedef struct { - mp_obj_base_t base; - digitalio_digitalinout_obj_t *digitalinout; - uint16_t threshold; -} touchio_touchin_obj_t; - -void touchin_reset(void); - -#endif diff --git a/ports/raspberrypi/common-hal/touchio/__init__.c b/ports/raspberrypi/common-hal/touchio/__init__.c deleted file mode 100644 index 72d32ef2b2c5d..0000000000000 --- a/ports/raspberrypi/common-hal/touchio/__init__.c +++ /dev/null @@ -1,5 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC -// -// SPDX-License-Identifier: MIT diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index 2a2693fb1fc4d..1404b2b06777c 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -64,12 +64,6 @@ CIRCUITPY_ALARM = 0 # Default PICODVI on because it doesn't require much code in RAM to talk to HSTX. CIRCUITPY_PICODVI ?= 1 -# Our generic touchio uses a pull down and RP2350 A2 hardware doesn't work correctly. -# So, turn generic touchio off because it doesn't work. -# And use a "native" touchio that expects 1M pull-up resistor instead of pull-down -CIRCUITPY_TOUCHIO = 1 -CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 - # delay in ms before calling cyw43_arch_init_with_country CIRCUITPY_CYW43_INIT_DELAY ?= 0 diff --git a/shared-bindings/touchio/TouchIn.c b/shared-bindings/touchio/TouchIn.c index e0d0479858842..6be15cc86361a 100644 --- a/shared-bindings/touchio/TouchIn.c +++ b/shared-bindings/touchio/TouchIn.c @@ -31,22 +31,29 @@ //| print("touched!")""" //| -//| def __init__(self, pin: microcontroller.Pin) -> None: +//| def __init__(self, pin: microcontroller.Pin, pull: Optional[digitalio.Pull] = None) -> None: //| """Use the TouchIn on the given pin. //| //| :param ~microcontroller.Pin pin: the pin to read from""" +//| :param Optional[digitalio.Pull] pull: specify external pull resistor type. If None, assume pull-down or chip-specific implementation //| ... //| static mp_obj_t touchio_touchin_make_new(const mp_obj_type_t *type, - size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check number of arguments - mp_arg_check_num(n_args, n_kw, 1, 1, false); + size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - // 1st argument is the pin - const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[0], MP_QSTR_pin); + enum { ARG_pin, ARG_pull }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); + const digitalio_pull_t pull = validate_pull(args[ARG_pull].u_obj, MP_QSTR_pull); touchio_touchin_obj_t *self = mp_obj_malloc(touchio_touchin_obj_t, &touchio_touchin_type); - common_hal_touchio_touchin_construct(self, pin); + common_hal_touchio_touchin_construct(self, pin, pull); return (mp_obj_t)self; } diff --git a/shared-bindings/touchio/TouchIn.h b/shared-bindings/touchio/TouchIn.h index 0ab510394792f..d9b34aa74e51e 100644 --- a/shared-bindings/touchio/TouchIn.h +++ b/shared-bindings/touchio/TouchIn.h @@ -7,6 +7,7 @@ #pragma once #include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/digitalio/Pull.h" #if CIRCUITPY_TOUCHIO_USE_NATIVE #include "common-hal/touchio/TouchIn.h" @@ -16,7 +17,7 @@ extern const mp_obj_type_t touchio_touchin_type; -void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, const mcu_pin_obj_t *pin); +void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, const mcu_pin_obj_t *pin, digitalio_pull_t pull); void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t *self); bool common_hal_touchio_touchin_deinited(touchio_touchin_obj_t *self); bool common_hal_touchio_touchin_get_value(touchio_touchin_obj_t *self); diff --git a/shared-bindings/touchio/__init__.c b/shared-bindings/touchio/__init__.c index 82e855b81d3ea..1abad056fa950 100644 --- a/shared-bindings/touchio/__init__.c +++ b/shared-bindings/touchio/__init__.c @@ -28,8 +28,9 @@ //| For more information about working with the `touchio` module in CircuitPython, //| see `this Learn guide page `_. //| -//| **Limitations**: `touchio` is available on Raspberry Pi RP2040 builds, -//| but not on RP2350, due to GPIO hardware limitations. +//| **Limitations**: `touchio` on RP2350 must have a pull-up resistor to 3.3V +//| instead of ground and set the `pull=Pull.UP` parameter when constructing +//| a `TouchIn` object, due to GPIO hardware limitations. //| //| Example:: //| diff --git a/shared-module/touchio/TouchIn.c b/shared-module/touchio/TouchIn.c index 9334b369f6579..b81b52b44415f 100644 --- a/shared-module/touchio/TouchIn.c +++ b/shared-module/touchio/TouchIn.c @@ -12,15 +12,18 @@ #include "py/mphal.h" #include "shared-bindings/touchio/TouchIn.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/Pull.h" -// This is a capacitive touch sensing routine using a single digital -// pin. The pin should be connected to the sensing pad, and to ground +// This is a capacitive touch sensing routine using a single digital pin. +// For pull==PULL_DOWN, the pin should be connected to the sensing pad and to ground // via a 1Mohm or thereabout drain resistor. When a reading is taken, // the pin's capacitance is charged by setting it to a digital output // 'high' for a few microseconds, and then it is changed to a high // impedance input. We measure how long it takes to discharge through // the resistor (around 50us), using a busy-waiting loop, and average // over N_SAMPLES cycles to reduce the effects of noise. +// For the pull=PULL_UP case, the 1M resistor is connected to 3v3, the pin is +// driven 'low' then measure how long it takes to go 'high'. #define N_SAMPLES 10 #define TIMEOUT_TICKS 10000 @@ -28,18 +31,19 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { uint16_t ticks = 0; - + // state to charge pin to: if pull-down or None, pull HIGH, if pull-up, pull LOW + bool pincharge = !(self->pull == PULL_UP); for (uint16_t i = 0; i < N_SAMPLES; i++) { - // set pad to digital output high for 10us to charge it + // set pad to digital output 'pincharge' for 10us to charge it - common_hal_digitalio_digitalinout_switch_to_output(self->digitalinout, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_switch_to_output(self->digitalinout, pincharge, DRIVE_MODE_PUSH_PULL); mp_hal_delay_us(10); // set pad back to an input and take some samples common_hal_digitalio_digitalinout_switch_to_input(self->digitalinout, PULL_NONE); - while (common_hal_digitalio_digitalinout_get_value(self->digitalinout)) { + while (common_hal_digitalio_digitalinout_get_value(self->digitalinout) == pincharge) { if (ticks >= TIMEOUT_TICKS) { return TIMEOUT_TICKS; } @@ -49,16 +53,22 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { return ticks; } -void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, const mcu_pin_obj_t *pin) { +void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, const mcu_pin_obj_t *pin, const digitalio_pull_t pull) { common_hal_mcu_pin_claim(pin); self->digitalinout = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(self->digitalinout, pin); + self->pull = pull; + uint16_t raw_reading = get_raw_reading(self); if (raw_reading == TIMEOUT_TICKS) { common_hal_touchio_touchin_deinit(self); - mp_raise_ValueError(MP_ERROR_TEXT("No pulldown on pin; 1Mohm recommended")); + if (self->pull == PULL_UP) { + mp_raise_ValueError(MP_ERROR_TEXT("No pullup on pin; 1Mohm recommended")); + } else { + mp_raise_ValueError(MP_ERROR_TEXT("No pulldown on pin; 1Mohm recommended")); + } } self->threshold = raw_reading * 1.05 + 100; } diff --git a/shared-module/touchio/TouchIn.h b/shared-module/touchio/TouchIn.h index a03811a1823d4..1d35b904f35d8 100644 --- a/shared-module/touchio/TouchIn.h +++ b/shared-module/touchio/TouchIn.h @@ -15,6 +15,7 @@ typedef struct { mp_obj_base_t base; digitalio_digitalinout_obj_t *digitalinout; + digitalio_pull_t pull; uint16_t threshold; } touchio_touchin_obj_t; From 0bd7d7e265acf12e7271ec6ea6c2c9805a904d84 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Mon, 7 Apr 2025 22:12:28 -0400 Subject: [PATCH 4/5] Update shared-bindings/touchio/TouchIn.c --- shared-bindings/touchio/TouchIn.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shared-bindings/touchio/TouchIn.c b/shared-bindings/touchio/TouchIn.c index 6be15cc86361a..19d97bd9d7c56 100644 --- a/shared-bindings/touchio/TouchIn.c +++ b/shared-bindings/touchio/TouchIn.c @@ -34,8 +34,9 @@ //| def __init__(self, pin: microcontroller.Pin, pull: Optional[digitalio.Pull] = None) -> None: //| """Use the TouchIn on the given pin. //| -//| :param ~microcontroller.Pin pin: the pin to read from""" -//| :param Optional[digitalio.Pull] pull: specify external pull resistor type. If None, assume pull-down or chip-specific implementation +//| :param ~microcontroller.Pin pin: the pin to read from +//| :param Optional[digitalio.Pull] pull: specify external pull resistor type. If None, assume pull-down or chip-specific implementation that does not require a pull. +//| """ //| ... //| static mp_obj_t touchio_touchin_make_new(const mp_obj_type_t *type, From b689d74ee0109b3f96a614d0296c22fceeddb82a Mon Sep 17 00:00:00 2001 From: Tod Kurt Date: Mon, 7 Apr 2025 22:06:45 -0700 Subject: [PATCH 5/5] fix docstring --- shared-bindings/touchio/__init__.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shared-bindings/touchio/__init__.c b/shared-bindings/touchio/__init__.c index 1abad056fa950..8f9e56d4bdb58 100644 --- a/shared-bindings/touchio/__init__.c +++ b/shared-bindings/touchio/__init__.c @@ -29,7 +29,7 @@ //| see `this Learn guide page `_. //| //| **Limitations**: `touchio` on RP2350 must have a pull-up resistor to 3.3V -//| instead of ground and set the `pull=Pull.UP` parameter when constructing +//| instead of ground and set the ``pull=Pull.UP`` parameter when constructing //| a `TouchIn` object, due to GPIO hardware limitations. //| //| Example:: @@ -41,7 +41,8 @@ //| print(touch_pin.value) //| //| This example will initialize the the device, and print the -//| :py:data:`~touchio.TouchIn.value`.""" +//| :py:data:`~touchio.TouchIn.value`. +//| """ static const mp_rom_map_elem_t touchio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_touchio) },