diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 12a6fed68c9a1..695f3bf8cc4d1 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -1560,6 +1560,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "" @@ -2582,7 +2586,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/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/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index bb4e183461bec..1404b2b06777c 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -64,10 +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 touchio off because it doesn't work. -CIRCUITPY_TOUCHIO = 0 - # 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..19d97bd9d7c56 100644 --- a/shared-bindings/touchio/TouchIn.c +++ b/shared-bindings/touchio/TouchIn.c @@ -31,22 +31,30 @@ //| 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 ~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, - 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..8f9e56d4bdb58 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:: //| @@ -40,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) }, 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;