Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion locale/circuitpython.pot
Original file line number Diff line number Diff line change
Expand Up @@ -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 ""
Expand Down Expand Up @@ -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"
Expand Down
103 changes: 103 additions & 0 deletions ports/raspberrypi/common-hal/touchio/TouchIn.c
Original file line number Diff line number Diff line change
@@ -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 <string.h>
#include <stdio.h>

#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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the old comment, but your implementation works the opposite way.

Copy link
Author

@todbot todbot Apr 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just listened now, after having seen the github notes. doh!

Having an optional argument to TouchIn() is what I originally did (you may've seen my opened-and-quickly closed PR ##10223) as I realized this would impact all other ports, increase their code footprint, and require me to touch many more files to adjust the touchio API for all ports.

As I listen to the meeting audio, I'm conflicted. I like the simplicity of this change, but dislike the confusion it can cause for users. I like adding a pull_dir argument but I'm worried about busting available space on SAMD21. Sigh.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that PR. I was going to comment that I think it's OK, and preferred, to use digitalio.Pull, because we use that consistently elsewhere. The argument will need to be validated to be of type Pull or None. Yes, it will grow the SAMD21 port slightly. We could #if out the validation on SAMD21 (or anything not TOUCH_NATIVE) to save space if we needed to.

SAMD21 and Espressif are the only two ports with native touchio. So there aren't that many other places to change to add the extra argument to common-hal.

Then you could add CIRCUITPY_TOUCHIO_PULL_DIRECTION to determine, at compile time, the two alternatives for the shared-module code. This would be a bool internally, since that's the easiest thing for the preprocessor. It would default to the DOWN value (false) in circuitpy_mpconfig.h, and be set to UP (true) only for RP2350.

The documentation in shared-bindings will need to be updated.

I think users will be confused a bit either way, but the extra arg makes the assumed pull more explicit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing all ports is the nature of changing a CircuitPython API. It ensures consistency. The reason is to make the up or down choice explicit so folks know to change their setup.

The benefit of adding an additional parameter would be that you can use the common touchio code still. It can support both up and down and only raise an exception on RP2350 with down.

Do we want to split out generic touchio into a new module? That wouldn't change touchio on SAMD and allow both to coexist in the future. We could do the hybrid model in CP10.


#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
26 changes: 26 additions & 0 deletions ports/raspberrypi/common-hal/touchio/TouchIn.h
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions ports/raspberrypi/common-hal/touchio/__init__.c
Original file line number Diff line number Diff line change
@@ -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
6 changes: 4 additions & 2 deletions ports/raspberrypi/mpconfigport.mk
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ 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.
CIRCUITPY_TOUCHIO = 0
# 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
Expand Down