From 9d2a32d07e6e07b9bddf685cbbebeb9a521ce05b Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 30 Dec 2021 21:49:52 -0500 Subject: [PATCH] countio: add selectable rise and fall detection, pulls --- locale/circuitpython.pot | 16 +++-- ports/atmel-samd/common-hal/countio/Counter.c | 64 +++++++++++------- ports/atmel-samd/common-hal/countio/Counter.h | 4 +- ports/espressif/common-hal/countio/Counter.c | 22 +++--- ports/nrf/common-hal/countio/Counter.c | 61 +++++++++++------ ports/nrf/common-hal/countio/Counter.h | 2 +- .../raspberrypi/common-hal/countio/Counter.c | 34 +++++----- .../raspberrypi/common-hal/countio/Counter.h | 2 +- py/circuitpy_defns.mk | 5 +- shared-bindings/countio/Counter.c | 54 ++++++++------- shared-bindings/countio/Counter.h | 5 +- shared-bindings/countio/Edge.c | 67 +++++++++++++++++++ shared-bindings/countio/Edge.h | 44 ++++++++++++ shared-bindings/countio/__init__.c | 9 +-- shared-bindings/digitalio/DigitalInOut.c | 25 ++----- shared-bindings/digitalio/Pull.c | 13 ++++ shared-bindings/digitalio/Pull.h | 2 + tests/pyboard.py | 2 +- 18 files changed, 300 insertions(+), 131 deletions(-) create mode 100644 shared-bindings/countio/Edge.c create mode 100644 shared-bindings/countio/Edge.h diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 7ca30dc063..4a90a1437d 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -144,6 +144,10 @@ msgstr "" msgid "%q must be of type %q" msgstr "" +#: shared-bindings/digitalio/Pull.c +msgid "%q must be of type %q or None" +msgstr "" + #: ports/atmel-samd/common-hal/busio/UART.c msgid "%q must be power of 2" msgstr "" @@ -1596,7 +1600,7 @@ msgstr "" msgid "No DMA pacing timer found" msgstr "" -#: shared-module/adafruit_bus_device/I2CDevice.c +#: shared-module/adafruit_bus_device/i2c_device/I2CDevice.c #, c-format msgid "No I2C device at address: %x" msgstr "" @@ -1896,7 +1900,7 @@ msgstr "" msgid "Pin interrupt already in use" msgstr "" -#: shared-bindings/adafruit_bus_device/SPIDevice.c +#: shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c #: shared-bindings/digitalio/DigitalInOut.c msgid "Pin is input only" msgstr "" @@ -1978,6 +1982,10 @@ msgstr "" msgid "RAISE mode is not implemented" msgstr "" +#: ports/raspberrypi/common-hal/countio/Counter.c +msgid "RISE_AND_FALL not available on this chip" +msgstr "" + #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" msgstr "" @@ -2447,10 +2455,6 @@ msgstr "" msgid "Unsupported operation" msgstr "" -#: shared-bindings/digitalio/DigitalInOut.c -msgid "Unsupported pull value." -msgstr "" - #: ports/espressif/common-hal/dualbank/__init__.c msgid "Update Failed" msgstr "" diff --git a/ports/atmel-samd/common-hal/countio/Counter.c b/ports/atmel-samd/common-hal/countio/Counter.c index e4df55eba6..c68b9e18ef 100644 --- a/ports/atmel-samd/common-hal/countio/Counter.c +++ b/ports/atmel-samd/common-hal/countio/Counter.c @@ -10,14 +10,14 @@ #include "supervisor/shared/translate.h" void common_hal_countio_counter_construct(countio_counter_obj_t *self, - const mcu_pin_obj_t *pin_a) { - if (!pin_a->has_extint) { + const mcu_pin_obj_t *pin, countio_edge_t edge, digitalio_pull_t pull) { + if (!pin->has_extint) { mp_raise_RuntimeError(translate("Pin must support hardware interrupts")); } if (eic_get_enable()) { - if (!eic_channel_free(pin_a->extint_channel)) { + if (!eic_channel_free(pin->extint_channel)) { mp_raise_RuntimeError(translate("A hardware interrupt channel is already in use")); } } else { @@ -25,28 +25,50 @@ void common_hal_countio_counter_construct(countio_counter_obj_t *self, } // These default settings apply when the EIC isn't yet enabled. - self->eic_channel_a = pin_a->extint_channel; + self->eic_channel = pin->extint_channel; - self->pin_a = pin_a->number; + self->pin = pin->number; - gpio_set_pin_function(self->pin_a, GPIO_PIN_FUNCTION_A); - gpio_set_pin_pull_mode(self->pin_a, GPIO_PULL_UP); + gpio_set_pin_function(self->pin, GPIO_PIN_FUNCTION_A); - set_eic_channel_data(self->eic_channel_a, (void *)self); + enum gpio_pull_mode asf_pull = GPIO_PULL_OFF; + switch (pull) { + case PULL_UP: + asf_pull = GPIO_PULL_UP; + break; + case PULL_DOWN: + asf_pull = GPIO_PULL_DOWN; + break; + case PULL_NONE: + default: + break; + } + gpio_set_pin_pull_mode(self->pin, asf_pull); + + set_eic_channel_data(self->eic_channel, (void *)self); self->count = 0; + claim_pin(pin); + set_eic_handler(self->eic_channel, EIC_HANDLER_COUNTER); - claim_pin(pin_a); - - - set_eic_handler(self->eic_channel_a, EIC_HANDLER_COUNTER); - turn_on_eic_channel(self->eic_channel_a, EIC_CONFIG_SENSE0_FALL_Val); - + uint32_t sense_setting = EIC_CONFIG_SENSE0_BOTH_Val; + switch (edge) { + case EDGE_RISE: + sense_setting = EIC_CONFIG_SENSE0_RISE_Val; + break; + case EDGE_FALL: + sense_setting = EIC_CONFIG_SENSE0_FALL_Val; + break; + case EDGE_RISE_AND_FALL: + default: + break; + } + turn_on_eic_channel(self->eic_channel, sense_setting); } bool common_hal_countio_counter_deinited(countio_counter_obj_t *self) { - return self->pin_a == NO_PIN; + return self->pin == NO_PIN; } void common_hal_countio_counter_deinit(countio_counter_obj_t *self) { @@ -54,12 +76,12 @@ void common_hal_countio_counter_deinit(countio_counter_obj_t *self) { return; } - set_eic_handler(self->eic_channel_a, EIC_HANDLER_NO_INTERRUPT); - turn_off_eic_channel(self->eic_channel_a); + set_eic_handler(self->eic_channel, EIC_HANDLER_NO_INTERRUPT); + turn_off_eic_channel(self->eic_channel); - reset_pin_number(self->pin_a); - self->pin_a = NO_PIN; + reset_pin_number(self->pin); + self->pin = NO_PIN; } @@ -72,10 +94,6 @@ void common_hal_countio_counter_set_count(countio_counter_obj_t *self, self->count = new_count; } -void common_hal_countio_counter_reset(countio_counter_obj_t *self) { - self->count = 0; -} - void counter_interrupt_handler(uint8_t channel) { countio_counter_obj_t *self = get_eic_channel_data(channel); diff --git a/ports/atmel-samd/common-hal/countio/Counter.h b/ports/atmel-samd/common-hal/countio/Counter.h index 8af22253f9..a57df9a777 100644 --- a/ports/atmel-samd/common-hal/countio/Counter.h +++ b/ports/atmel-samd/common-hal/countio/Counter.h @@ -8,8 +8,8 @@ typedef struct { mp_obj_base_t base; - uint8_t pin_a; - uint8_t eic_channel_a : 4; + uint8_t pin; + uint8_t eic_channel : 4; mp_int_t count; } countio_counter_obj_t; diff --git a/ports/espressif/common-hal/countio/Counter.c b/ports/espressif/common-hal/countio/Counter.c index 418a8ae4d4..d18196051f 100644 --- a/ports/espressif/common-hal/countio/Counter.c +++ b/ports/espressif/common-hal/countio/Counter.c @@ -32,7 +32,7 @@ #include "supervisor/shared/translate.h" void common_hal_countio_counter_construct(countio_counter_obj_t *self, - const mcu_pin_obj_t *pin) { + const mcu_pin_obj_t *pin, countio_edge_t edge, digitalio_pull_t pull) { claim_pin(pin); // Prepare configuration for the PCNT unit @@ -41,9 +41,10 @@ void common_hal_countio_counter_construct(countio_counter_obj_t *self, .pulse_gpio_num = pin->number, .ctrl_gpio_num = PCNT_PIN_NOT_USED, .channel = PCNT_CHANNEL_0, - // What to do on the positive / negative edge of pulse input? - .pos_mode = PCNT_COUNT_INC, // Count up on the positive edge - .neg_mode = PCNT_COUNT_DIS, // Keep the counter value on the negative edge + // What to do on the rising / falling edge of pulse input? + // If EDGE_RISE_AND_FALL, both modeswill do PCNT_COUNT_INC. + .pos_mode = (edge == EDGE_FALL) ? PCNT_COUNT_DIS : PCNT_COUNT_INC, // Count up unless only fall + .neg_mode = (edge == EDGE_RISE) ? PCNT_COUNT_DIS : PCNT_COUNT_INC, // Count up unless only rise }; // Initialize PCNT unit @@ -53,6 +54,15 @@ void common_hal_countio_counter_construct(countio_counter_obj_t *self, } self->pin = pin->number; + + gpio_pullup_dis(pin->number); + gpio_pulldown_dis(pin->number); + if (pull == PULL_UP) { + gpio_pullup_en(pin->number); + } else if (pull == PULL_DOWN) { + gpio_pulldown_en(pin->number); + } + self->unit = (pcnt_unit_t)unit; } @@ -79,7 +89,3 @@ void common_hal_countio_counter_set_count(countio_counter_obj_t *self, self->count = new_count; pcnt_counter_clear(self->unit); } - -void common_hal_countio_counter_reset(countio_counter_obj_t *self) { - common_hal_countio_counter_set_count(self, 0); -} diff --git a/ports/nrf/common-hal/countio/Counter.c b/ports/nrf/common-hal/countio/Counter.c index b2296a7dcc..32dc6af74b 100644 --- a/ports/nrf/common-hal/countio/Counter.c +++ b/ports/nrf/common-hal/countio/Counter.c @@ -18,45 +18,70 @@ static void _intr_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { } void common_hal_countio_counter_construct(countio_counter_obj_t *self, - const mcu_pin_obj_t *pin_a) { + const mcu_pin_obj_t *pin, countio_edge_t edge, digitalio_pull_t pull) { - self->pin_a = pin_a->number; - _countio_objs[self->pin_a] = self; + self->pin = pin->number; + _countio_objs[self->pin] = self; self->count = 0; + nrf_gpiote_polarity_t polarity = NRF_GPIOTE_POLARITY_TOGGLE; + switch (edge) { + case EDGE_RISE: + polarity = NRF_GPIOTE_POLARITY_LOTOHI; + break; + case EDGE_FALL: + polarity = NRF_GPIOTE_POLARITY_HITOLO; + break; + case EDGE_RISE_AND_FALL: + default: + break; + } + + nrf_gpio_pin_pull_t hal_pull = NRF_GPIO_PIN_NOPULL; + switch (pull) { + case PULL_UP: + hal_pull = NRF_GPIO_PIN_PULLUP; + break; + case PULL_DOWN: + hal_pull = NRF_GPIO_PIN_PULLDOWN; + break; + case PULL_NONE: + default: + break; + } + nrfx_gpiote_in_config_t cfg = { - .sense = NRF_GPIOTE_POLARITY_HITOLO, - .pull = NRF_GPIO_PIN_PULLUP, + .sense = polarity, + .pull = hal_pull, .is_watcher = false, .hi_accuracy = true, - .skip_gpio_setup = false + .skip_gpio_setup = false, }; - - nrfx_err_t err = nrfx_gpiote_in_init(self->pin_a, &cfg, _intr_handler); + nrfx_err_t err = nrfx_gpiote_in_init(self->pin, &cfg, _intr_handler); if (err != NRFX_SUCCESS) { mp_raise_RuntimeError(translate("All channels in use")); } - nrfx_gpiote_in_event_enable(self->pin_a, true); + nrfx_gpiote_in_event_enable(self->pin, true); - claim_pin(pin_a); + claim_pin(pin); } bool common_hal_countio_counter_deinited(countio_counter_obj_t *self) { - return self->pin_a == NO_PIN; + return self->pin == NO_PIN; } void common_hal_countio_counter_deinit(countio_counter_obj_t *self) { if (common_hal_countio_counter_deinited(self)) { return; } - _countio_objs[self->pin_a] = NULL; + _countio_objs[self->pin] = NULL; - nrfx_gpiote_in_event_disable(self->pin_a); - nrfx_gpiote_in_uninit(self->pin_a); - reset_pin_number(self->pin_a); - self->pin_a = NO_PIN; + nrfx_gpiote_in_event_disable(self->pin); + nrfx_gpiote_in_uninit(self->pin); + reset_pin_number(self->pin); + self->pin = NO_PIN; } mp_int_t common_hal_countio_counter_get_count(countio_counter_obj_t *self) { @@ -67,7 +92,3 @@ void common_hal_countio_counter_set_count(countio_counter_obj_t *self, mp_int_t new_count) { self->count = new_count; } - -void common_hal_countio_counter_reset(countio_counter_obj_t *self) { - self->count = 0; -} diff --git a/ports/nrf/common-hal/countio/Counter.h b/ports/nrf/common-hal/countio/Counter.h index cf40a63a02..a90bea70d6 100644 --- a/ports/nrf/common-hal/countio/Counter.h +++ b/ports/nrf/common-hal/countio/Counter.h @@ -8,7 +8,7 @@ typedef struct { mp_obj_base_t base; - uint8_t pin_a; + uint8_t pin; mp_int_t count; } countio_counter_obj_t; diff --git a/ports/raspberrypi/common-hal/countio/Counter.c b/ports/raspberrypi/common-hal/countio/Counter.c index fe7dd545f8..0ae773bdf3 100644 --- a/ports/raspberrypi/common-hal/countio/Counter.c +++ b/ports/raspberrypi/common-hal/countio/Counter.c @@ -4,6 +4,8 @@ #include "py/mpstate.h" #include "supervisor/shared/translate.h" +#include "shared-bindings/countio/Edge.h" +#include "shared-bindings/digitalio/Pull.h" #include "common-hal/pwmio/PWMOut.h" #include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" @@ -12,20 +14,24 @@ void common_hal_countio_counter_construct(countio_counter_obj_t *self, - const mcu_pin_obj_t *pin_a) { + const mcu_pin_obj_t *pin, countio_edge_t edge, digitalio_pull_t pull) { - if (pwm_gpio_to_channel(pin_a->number) != PWM_CHAN_B) { + if (pwm_gpio_to_channel(pin->number) != PWM_CHAN_B) { mp_raise_RuntimeError(translate("Pin must be on PWM Channel B")); } - self->pin_a = pin_a->number; - self->slice_num = pwm_gpio_to_slice_num(self->pin_a); + if (edge == EDGE_RISE_AND_FALL) { + mp_raise_NotImplementedError(translate("RISE_AND_FALL not available on this chip")); + } + + self->pin = pin->number; + self->slice_num = pwm_gpio_to_slice_num(self->pin); if (MP_STATE_PORT(counting)[self->slice_num] != NULL) { mp_raise_RuntimeError(translate("PWM slice already in use")); } - uint8_t ab_channel = pwm_gpio_to_channel(self->pin_a); + uint8_t ab_channel = pwm_gpio_to_channel(self->pin); if (!pwmio_claim_slice_ab_channels(self->slice_num)) { mp_raise_RuntimeError(translate("PWM slice channel A already in use")); } @@ -36,11 +42,12 @@ void common_hal_countio_counter_construct(countio_counter_obj_t *self, irq_set_enabled(PWM_IRQ_WRAP, true); pwm_config cfg = pwm_get_default_config(); - pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_B_RISING); + pwm_config_set_clkdiv_mode(&cfg, edge == EDGE_RISE ? PWM_DIV_B_RISING : PWM_DIV_B_FALLING); pwm_init(self->slice_num, &cfg, false); - gpio_set_function(self->pin_a, GPIO_FUNC_PWM); + gpio_set_function(self->pin, GPIO_FUNC_PWM); + gpio_set_pulls(self->pin, pull == PULL_UP, pull == PULL_DOWN); - claim_pin(pin_a); + claim_pin(pin); MP_STATE_PORT(counting)[self->slice_num] = self; @@ -58,7 +65,7 @@ void reset_countio(void) { } bool common_hal_countio_counter_deinited(countio_counter_obj_t *self) { - return self->pin_a == 0; + return self->pin == 0; } void common_hal_countio_counter_deinit(countio_counter_obj_t *self) { @@ -71,10 +78,10 @@ void common_hal_countio_counter_deinit(countio_counter_obj_t *self) { pwmio_release_slice_ab_channels(self->slice_num); - reset_pin_number(self->pin_a); + reset_pin_number(self->pin); MP_STATE_PORT(counting)[self->slice_num] = NULL; - self->pin_a = 0; + self->pin = 0; self->slice_num = 0; } @@ -90,11 +97,6 @@ void common_hal_countio_counter_set_count(countio_counter_obj_t *self, self->count = new_count; } -void common_hal_countio_counter_reset(countio_counter_obj_t *self) { - pwm_set_counter(self->slice_num, 0); - self->count = 0; -} - void counter_interrupt_handler(void) { uint32_t mask = pwm_get_irq_status_mask(); diff --git a/ports/raspberrypi/common-hal/countio/Counter.h b/ports/raspberrypi/common-hal/countio/Counter.h index 7469dd2d00..3355036eed 100644 --- a/ports/raspberrypi/common-hal/countio/Counter.h +++ b/ports/raspberrypi/common-hal/countio/Counter.h @@ -8,7 +8,7 @@ typedef struct { mp_obj_base_t base; - uint8_t pin_a; + uint8_t pin; uint8_t slice_num; mp_int_t count; } countio_counter_obj_t; diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index b7aae4d114..48a37be499 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -453,8 +453,7 @@ $(filter $(SRC_PATTERNS), \ _eve/__init__.c \ camera/ImageFormat.c \ canio/Match.c \ - qrio/PixelPolicy.c \ - qrio/QRInfo.c \ + countio/Edge.c \ digitalio/Direction.c \ digitalio/DriveMode.c \ digitalio/Pull.c \ @@ -468,6 +467,8 @@ $(filter $(SRC_PATTERNS), \ msgpack/ExtType.c \ paralleldisplay/__init__.c \ paralleldisplay/ParallelBus.c \ + qrio/PixelPolicy.c \ + qrio/QRInfo.c \ supervisor/RunReason.c \ wifi/AuthMode.c \ wifi/Packet.c \ diff --git a/shared-bindings/countio/Counter.c b/shared-bindings/countio/Counter.c index 873da912a6..8582f4497e 100644 --- a/shared-bindings/countio/Counter.c +++ b/shared-bindings/countio/Counter.c @@ -7,47 +7,56 @@ #include "py/runtime0.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/countio/Counter.h" +#include "shared-bindings/countio/Edge.h" #include "shared-bindings/util.h" //| class Counter: -//| """Counter will keep track of the number of falling edge transistions (pulses) on a -//| given pin""" +//| """Count the number of rising- and/or falling-edge transitions on a given pin. +//| """ //| -//| def __init__(self, pin_a: microcontroller.Pin) -> None: -//| """Create a Counter object associated with the given pin. It tracks the number of -//| falling pulses relative when the object is constructed. +//| def __init__(self, pin: microcontroller.Pin, *, edge: Edge = Edge.FALL, pull: Optional[digitalio.Pull]) -> None: +//| """Create a Counter object associated with the given pin that counts +//| rising- and/or falling-edge transitions. At least one of ``rise`` and ``fall`` must be True. +//| The default is to count only falling edges, and is for historical backward compatibility. //| -//| :param ~microcontroller.Pin pin_a: Pin to read pulses from. +//| :param ~microcontroller.Pin pin: pin to monitor +//| :param Edge: which edge transitions to count +//| :param digitalio.Pull: enable a pull-up or pull-down if not None //| //| -//| For example:: +//| For example:: //| -//| import board -//| import countio +//| import board +//| import countio //| -//| pin_counter = countio.Counter(board.D1) -//| #reset the count after 100 counts -//| while True: -//| if pin_counter.count == 100: -//| pin_counter.reset() -//| print(pin_counter.count)""" +//| # Count rising edges only. +//| pin_counter = countio.Counter(board.D1, edge=Edge.RISE) +//| # Reset the count after 100 counts. +//| while True: +//| if pin_counter.count >= 100: +//| pin_counter.reset() +//| print(pin_counter.count) +//| """ +//| ... //| STATIC mp_obj_t countio_counter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { ARG_pin_a }; + enum { ARG_pin, ARG_edge, ARG_pull }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_pin_a, MP_ARG_REQUIRED | MP_ARG_OBJ } - + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_edge, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_FROM_PTR(&edge_FALL_obj) } }, + { MP_QSTR_pull, MP_ARG_KW_ONLY | 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_a = validate_obj_is_free_pin(args[ARG_pin_a].u_obj); - + const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj); + const countio_edge_t edge = validate_edge(args[ARG_edge].u_obj, MP_QSTR_edge); + const digitalio_pull_t pull = validate_pull(args[ARG_pull].u_obj, MP_QSTR_pull); countio_counter_obj_t *self = m_new_obj(countio_counter_obj_t); self->base.type = &countio_counter_type; - common_hal_countio_counter_construct(self, pin_a); + common_hal_countio_counter_construct(self, pin, edge, pull); return MP_OBJ_FROM_PTR(self); } @@ -118,8 +127,7 @@ const mp_obj_property_t countio_counter_count_obj = { STATIC mp_obj_t countio_counter_reset(mp_obj_t self_in) { countio_counter_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); - // set the position to zero for reset - common_hal_countio_counter_reset(self); + common_hal_countio_counter_set_count(self, 0); return mp_const_none; } diff --git a/shared-bindings/countio/Counter.h b/shared-bindings/countio/Counter.h index a9eced41a3..d660cc8f49 100644 --- a/shared-bindings/countio/Counter.h +++ b/shared-bindings/countio/Counter.h @@ -3,16 +3,17 @@ #include "common-hal/microcontroller/Pin.h" #include "common-hal/countio/Counter.h" +#include "shared-bindings/countio/Edge.h" +#include "shared-bindings/digitalio/Pull.h" extern const mp_obj_type_t countio_counter_type; extern void common_hal_countio_counter_construct(countio_counter_obj_t *self, - const mcu_pin_obj_t *pin_a); + const mcu_pin_obj_t *pin, countio_edge_t edge, digitalio_pull_t pull); extern void common_hal_countio_counter_deinit(countio_counter_obj_t *self); extern bool common_hal_countio_counter_deinited(countio_counter_obj_t *self); extern mp_int_t common_hal_countio_counter_get_count(countio_counter_obj_t *self); extern void common_hal_countio_counter_set_count(countio_counter_obj_t *self, mp_int_t new_count); -extern void common_hal_countio_counter_reset(countio_counter_obj_t *self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO_COUNTER_H diff --git a/shared-bindings/countio/Edge.c b/shared-bindings/countio/Edge.c new file mode 100644 index 0000000000..980b3a3705 --- /dev/null +++ b/shared-bindings/countio/Edge.c @@ -0,0 +1,67 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Dan Halbert for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/obj.h" +#include "py/enum.h" +#include "py/runtime.h" + +#include "shared-bindings/countio/Edge.h" + +MAKE_ENUM_VALUE(countio_edge_type, edge, RISE, EDGE_RISE); +MAKE_ENUM_VALUE(countio_edge_type, edge, FALL, EDGE_FALL); +MAKE_ENUM_VALUE(countio_edge_type, edge, RISE_AND_FALL, EDGE_RISE_AND_FALL); + +//| class Edge: +//| """Enumerates which signal transitions can be counted.""" +//| +//| def __init__(self) -> None: +//| """Enum-like class to define which signal transitions to count.""" +//| ... +//| +//| RISE: Edge +//| """Count the rising edges.""" +//| +//| FALL: Edge +//| """Count the falling edges.""" +//| +//| RISE_AND_FALL: Edge +//| """Count the rising and falling edges.""" +//| +MAKE_ENUM_MAP(countio_edge) { + MAKE_ENUM_MAP_ENTRY(edge, RISE), + MAKE_ENUM_MAP_ENTRY(edge, FALL), + MAKE_ENUM_MAP_ENTRY(edge, RISE_AND_FALL), +}; + +STATIC MP_DEFINE_CONST_DICT(countio_edge_locals_dict, countio_edge_locals_table); + +MAKE_PRINTER(countio, countio_edge); + +MAKE_ENUM_TYPE(countio, Edge, countio_edge); + +countio_edge_t validate_edge(mp_obj_t obj, qstr arg_name) { + return cp_enum_value(&countio_edge_type, mp_arg_validate_type(obj, &countio_edge_type, arg_name)); +} diff --git a/shared-bindings/countio/Edge.h b/shared-bindings/countio/Edge.h new file mode 100644 index 0000000000..ca4cddbef3 --- /dev/null +++ b/shared-bindings/countio/Edge.h @@ -0,0 +1,44 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 an Halbertfor Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO_EDGE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO_EDGE_H + +#include "py/enum.h" +#include "py/obj.h" + +typedef enum _countio_edge_t { + EDGE_RISE, + EDGE_FALL, + EDGE_RISE_AND_FALL, +} countio_edge_t; + +extern const mp_obj_type_t countio_edge_type; +extern const cp_enum_obj_t edge_FALL_obj; + +countio_edge_t validate_edge(mp_obj_t obj, qstr arg_name); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO_EDGE_H diff --git a/shared-bindings/countio/__init__.c b/shared-bindings/countio/__init__.c index faa23da9b0..d72ed9fd25 100644 --- a/shared-bindings/countio/__init__.c +++ b/shared-bindings/countio/__init__.c @@ -7,16 +7,12 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/countio/__init__.h" #include "shared-bindings/countio/Counter.h" +#include "shared-bindings/countio/Edge.h" //| """Support for edge counting //| //| The `countio` module contains logic to read and count edge transistions //| - -//| .. warning:: This module is not available in some SAMD21 (aka M0) builds. See the -//| :ref:`module-support-matrix` for more info. -//| - //| All classes change hardware state and should be deinitialized when they //| are no longer needed if the program continues after use. To do so, either //| call :py:meth:`!deinit` or use a context manager. See @@ -25,7 +21,8 @@ STATIC const mp_rom_map_elem_t countio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_countio) }, - { MP_ROM_QSTR(MP_QSTR_Counter), MP_ROM_PTR(&countio_counter_type) }, + { MP_ROM_QSTR(MP_QSTR_Counter), MP_ROM_PTR(&countio_counter_type) }, + { MP_ROM_QSTR(MP_QSTR_Edge), MP_ROM_PTR(&countio_edge_type) }, }; STATIC MP_DEFINE_CONST_DICT(countio_module_globals, countio_module_globals_table); diff --git a/shared-bindings/digitalio/DigitalInOut.c b/shared-bindings/digitalio/DigitalInOut.c index cabf500d53..af7defd911 100644 --- a/shared-bindings/digitalio/DigitalInOut.c +++ b/shared-bindings/digitalio/DigitalInOut.c @@ -166,15 +166,7 @@ STATIC mp_obj_t digitalio_digitalinout_switch_to_input(size_t n_args, const mp_o mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - digitalio_pull_t pull = PULL_NONE; - if (args[ARG_pull].u_rom_obj == MP_ROM_PTR(&digitalio_pull_up_obj)) { - pull = PULL_UP; - } else if (args[ARG_pull].u_rom_obj == MP_ROM_PTR(&digitalio_pull_down_obj)) { - pull = PULL_DOWN; - } - // do the transfer - common_hal_digitalio_digitalinout_switch_to_input(self, pull); + common_hal_digitalio_digitalinout_switch_to_input(self, validate_pull(args[ARG_pull].u_rom_obj, MP_QSTR_pull)); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_KW(digitalio_digitalinout_switch_to_input_obj, 1, digitalio_digitalinout_switch_to_input); @@ -320,9 +312,9 @@ STATIC mp_obj_t digitalio_digitalinout_obj_get_pull(mp_obj_t self_in) { } digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(self); if (pull == PULL_UP) { - return (mp_obj_t)&digitalio_pull_up_obj; + return MP_OBJ_FROM_PTR(&digitalio_pull_up_obj); } else if (pull == PULL_DOWN) { - return (mp_obj_t)&digitalio_pull_down_obj; + return MP_OBJ_FROM_PTR(&digitalio_pull_down_obj); } return mp_const_none; } @@ -335,15 +327,8 @@ STATIC mp_obj_t digitalio_digitalinout_obj_set_pull(mp_obj_t self_in, mp_obj_t p mp_raise_AttributeError(translate("Pull not used when direction is output.")); return mp_const_none; } - digitalio_pull_t pull = PULL_NONE; - if (pull_obj == MP_ROM_PTR(&digitalio_pull_up_obj)) { - pull = PULL_UP; - } else if (pull_obj == MP_ROM_PTR(&digitalio_pull_down_obj)) { - pull = PULL_DOWN; - } else if (pull_obj != mp_const_none) { - mp_raise_ValueError(translate("Unsupported pull value.")); - } - common_hal_digitalio_digitalinout_set_pull(self, pull); + + common_hal_digitalio_digitalinout_set_pull(self, validate_pull(pull_obj, MP_QSTR_pull)); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(digitalio_digitalinout_set_pull_obj, digitalio_digitalinout_obj_set_pull); diff --git a/shared-bindings/digitalio/Pull.c b/shared-bindings/digitalio/Pull.c index 8ded64fb47..4db68dda10 100644 --- a/shared-bindings/digitalio/Pull.c +++ b/shared-bindings/digitalio/Pull.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include "py/runtime.h" #include "shared-bindings/digitalio/Pull.h" //| class Pull: @@ -72,3 +73,15 @@ const mp_obj_type_t digitalio_pull_type = { .print = digitalio_pull_print, .locals_dict = (mp_obj_dict_t *)&digitalio_pull_locals_dict, }; + +digitalio_pull_t validate_pull(mp_rom_obj_t obj, qstr arg_name) { + if (obj == MP_ROM_PTR(&digitalio_pull_up_obj)) { + return PULL_UP; + } else if (obj == MP_ROM_PTR(&digitalio_pull_down_obj)) { + return PULL_DOWN; + } + if (obj == MP_ROM_NONE) { + return PULL_NONE; + } + mp_raise_TypeError_varg(translate("%q must be of type %q or None"), arg_name, MP_QSTR_Pull); +} diff --git a/shared-bindings/digitalio/Pull.h b/shared-bindings/digitalio/Pull.h index b97e8fb255..f4f6c42690 100644 --- a/shared-bindings/digitalio/Pull.h +++ b/shared-bindings/digitalio/Pull.h @@ -43,4 +43,6 @@ typedef struct { extern const digitalio_pull_obj_t digitalio_pull_up_obj; extern const digitalio_pull_obj_t digitalio_pull_down_obj; +digitalio_pull_t validate_pull(mp_rom_obj_t obj, qstr arg_name); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_DIGITALIO_PULL_H diff --git a/tests/pyboard.py b/tests/pyboard.py index 582a1f894f..616773a313 120000 --- a/tests/pyboard.py +++ b/tests/pyboard.py @@ -1 +1 @@ -../tools/cpboard.py +../tools/cpboard.py \ No newline at end of file