countio: add selectable rise and fall detection, pulls

This commit is contained in:
Dan Halbert 2021-12-30 21:49:52 -05:00
parent cd7e879f30
commit 9d2a32d07e
18 changed files with 300 additions and 131 deletions

View File

@ -144,6 +144,10 @@ msgstr ""
msgid "%q must be of type %q" msgid "%q must be of type %q"
msgstr "" msgstr ""
#: shared-bindings/digitalio/Pull.c
msgid "%q must be of type %q or None"
msgstr ""
#: ports/atmel-samd/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c
msgid "%q must be power of 2" msgid "%q must be power of 2"
msgstr "" msgstr ""
@ -1596,7 +1600,7 @@ msgstr ""
msgid "No DMA pacing timer found" msgid "No DMA pacing timer found"
msgstr "" msgstr ""
#: shared-module/adafruit_bus_device/I2CDevice.c #: shared-module/adafruit_bus_device/i2c_device/I2CDevice.c
#, c-format #, c-format
msgid "No I2C device at address: %x" msgid "No I2C device at address: %x"
msgstr "" msgstr ""
@ -1896,7 +1900,7 @@ msgstr ""
msgid "Pin interrupt already in use" msgid "Pin interrupt already in use"
msgstr "" msgstr ""
#: shared-bindings/adafruit_bus_device/SPIDevice.c #: shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c
#: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/digitalio/DigitalInOut.c
msgid "Pin is input only" msgid "Pin is input only"
msgstr "" msgstr ""
@ -1978,6 +1982,10 @@ msgstr ""
msgid "RAISE mode is not implemented" msgid "RAISE mode is not implemented"
msgstr "" 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 #: ports/stm/common-hal/os/__init__.c
msgid "RNG DeInit Error" msgid "RNG DeInit Error"
msgstr "" msgstr ""
@ -2447,10 +2455,6 @@ msgstr ""
msgid "Unsupported operation" msgid "Unsupported operation"
msgstr "" msgstr ""
#: shared-bindings/digitalio/DigitalInOut.c
msgid "Unsupported pull value."
msgstr ""
#: ports/espressif/common-hal/dualbank/__init__.c #: ports/espressif/common-hal/dualbank/__init__.c
msgid "Update Failed" msgid "Update Failed"
msgstr "" msgstr ""

View File

@ -10,14 +10,14 @@
#include "supervisor/shared/translate.h" #include "supervisor/shared/translate.h"
void common_hal_countio_counter_construct(countio_counter_obj_t *self, 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 (!pin_a->has_extint) { if (!pin->has_extint) {
mp_raise_RuntimeError(translate("Pin must support hardware interrupts")); mp_raise_RuntimeError(translate("Pin must support hardware interrupts"));
} }
if (eic_get_enable()) { 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")); mp_raise_RuntimeError(translate("A hardware interrupt channel is already in use"));
} }
} else { } 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. // 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_function(self->pin, GPIO_PIN_FUNCTION_A);
gpio_set_pin_pull_mode(self->pin_a, GPIO_PULL_UP);
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; self->count = 0;
claim_pin(pin);
set_eic_handler(self->eic_channel, EIC_HANDLER_COUNTER);
claim_pin(pin_a); uint32_t sense_setting = EIC_CONFIG_SENSE0_BOTH_Val;
switch (edge) {
case EDGE_RISE:
set_eic_handler(self->eic_channel_a, EIC_HANDLER_COUNTER); sense_setting = EIC_CONFIG_SENSE0_RISE_Val;
turn_on_eic_channel(self->eic_channel_a, EIC_CONFIG_SENSE0_FALL_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) { 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) { 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; return;
} }
set_eic_handler(self->eic_channel_a, EIC_HANDLER_NO_INTERRUPT); set_eic_handler(self->eic_channel, EIC_HANDLER_NO_INTERRUPT);
turn_off_eic_channel(self->eic_channel_a); turn_off_eic_channel(self->eic_channel);
reset_pin_number(self->pin_a); reset_pin_number(self->pin);
self->pin_a = NO_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; 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) { void counter_interrupt_handler(uint8_t channel) {
countio_counter_obj_t *self = get_eic_channel_data(channel); countio_counter_obj_t *self = get_eic_channel_data(channel);

View File

@ -8,8 +8,8 @@
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
uint8_t pin_a; uint8_t pin;
uint8_t eic_channel_a : 4; uint8_t eic_channel : 4;
mp_int_t count; mp_int_t count;
} countio_counter_obj_t; } countio_counter_obj_t;

View File

@ -32,7 +32,7 @@
#include "supervisor/shared/translate.h" #include "supervisor/shared/translate.h"
void common_hal_countio_counter_construct(countio_counter_obj_t *self, 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); claim_pin(pin);
// Prepare configuration for the PCNT unit // 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, .pulse_gpio_num = pin->number,
.ctrl_gpio_num = PCNT_PIN_NOT_USED, .ctrl_gpio_num = PCNT_PIN_NOT_USED,
.channel = PCNT_CHANNEL_0, .channel = PCNT_CHANNEL_0,
// What to do on the positive / negative edge of pulse input? // What to do on the rising / falling edge of pulse input?
.pos_mode = PCNT_COUNT_INC, // Count up on the positive edge // If EDGE_RISE_AND_FALL, both modeswill do PCNT_COUNT_INC.
.neg_mode = PCNT_COUNT_DIS, // Keep the counter value on the negative edge .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 // Initialize PCNT unit
@ -53,6 +54,15 @@ void common_hal_countio_counter_construct(countio_counter_obj_t *self,
} }
self->pin = pin->number; 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; 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; self->count = new_count;
pcnt_counter_clear(self->unit); pcnt_counter_clear(self->unit);
} }
void common_hal_countio_counter_reset(countio_counter_obj_t *self) {
common_hal_countio_counter_set_count(self, 0);
}

View File

@ -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, 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; self->pin = pin->number;
_countio_objs[self->pin_a] = self; _countio_objs[self->pin] = self;
self->count = 0; 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 = { nrfx_gpiote_in_config_t cfg = {
.sense = NRF_GPIOTE_POLARITY_HITOLO, .sense = polarity,
.pull = NRF_GPIO_PIN_PULLUP, .pull = hal_pull,
.is_watcher = false, .is_watcher = false,
.hi_accuracy = true, .hi_accuracy = true,
.skip_gpio_setup = false .skip_gpio_setup = false,
}; };
nrfx_err_t err = nrfx_gpiote_in_init(self->pin, &cfg, _intr_handler);
nrfx_err_t err = nrfx_gpiote_in_init(self->pin_a, &cfg, _intr_handler);
if (err != NRFX_SUCCESS) { if (err != NRFX_SUCCESS) {
mp_raise_RuntimeError(translate("All channels in use")); 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) { 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) { void common_hal_countio_counter_deinit(countio_counter_obj_t *self) {
if (common_hal_countio_counter_deinited(self)) { if (common_hal_countio_counter_deinited(self)) {
return; return;
} }
_countio_objs[self->pin_a] = NULL; _countio_objs[self->pin] = NULL;
nrfx_gpiote_in_event_disable(self->pin_a); nrfx_gpiote_in_event_disable(self->pin);
nrfx_gpiote_in_uninit(self->pin_a); nrfx_gpiote_in_uninit(self->pin);
reset_pin_number(self->pin_a); reset_pin_number(self->pin);
self->pin_a = NO_PIN; self->pin = NO_PIN;
} }
mp_int_t common_hal_countio_counter_get_count(countio_counter_obj_t *self) { 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) { mp_int_t new_count) {
self->count = new_count; self->count = new_count;
} }
void common_hal_countio_counter_reset(countio_counter_obj_t *self) {
self->count = 0;
}

View File

@ -8,7 +8,7 @@
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
uint8_t pin_a; uint8_t pin;
mp_int_t count; mp_int_t count;
} countio_counter_obj_t; } countio_counter_obj_t;

View File

@ -4,6 +4,8 @@
#include "py/mpstate.h" #include "py/mpstate.h"
#include "supervisor/shared/translate.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 "common-hal/pwmio/PWMOut.h"
#include "src/rp2_common/hardware_gpio/include/hardware/gpio.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, 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")); mp_raise_RuntimeError(translate("Pin must be on PWM Channel B"));
} }
self->pin_a = pin_a->number; if (edge == EDGE_RISE_AND_FALL) {
self->slice_num = pwm_gpio_to_slice_num(self->pin_a); 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) { if (MP_STATE_PORT(counting)[self->slice_num] != NULL) {
mp_raise_RuntimeError(translate("PWM slice already in use")); 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)) { if (!pwmio_claim_slice_ab_channels(self->slice_num)) {
mp_raise_RuntimeError(translate("PWM slice channel A already in use")); 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); irq_set_enabled(PWM_IRQ_WRAP, true);
pwm_config cfg = pwm_get_default_config(); 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); 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; 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) { 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) { 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); 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; MP_STATE_PORT(counting)[self->slice_num] = NULL;
self->pin_a = 0; self->pin = 0;
self->slice_num = 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; 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) { void counter_interrupt_handler(void) {
uint32_t mask = pwm_get_irq_status_mask(); uint32_t mask = pwm_get_irq_status_mask();

View File

@ -8,7 +8,7 @@
typedef struct { typedef struct {
mp_obj_base_t base; mp_obj_base_t base;
uint8_t pin_a; uint8_t pin;
uint8_t slice_num; uint8_t slice_num;
mp_int_t count; mp_int_t count;
} countio_counter_obj_t; } countio_counter_obj_t;

View File

@ -453,8 +453,7 @@ $(filter $(SRC_PATTERNS), \
_eve/__init__.c \ _eve/__init__.c \
camera/ImageFormat.c \ camera/ImageFormat.c \
canio/Match.c \ canio/Match.c \
qrio/PixelPolicy.c \ countio/Edge.c \
qrio/QRInfo.c \
digitalio/Direction.c \ digitalio/Direction.c \
digitalio/DriveMode.c \ digitalio/DriveMode.c \
digitalio/Pull.c \ digitalio/Pull.c \
@ -468,6 +467,8 @@ $(filter $(SRC_PATTERNS), \
msgpack/ExtType.c \ msgpack/ExtType.c \
paralleldisplay/__init__.c \ paralleldisplay/__init__.c \
paralleldisplay/ParallelBus.c \ paralleldisplay/ParallelBus.c \
qrio/PixelPolicy.c \
qrio/QRInfo.c \
supervisor/RunReason.c \ supervisor/RunReason.c \
wifi/AuthMode.c \ wifi/AuthMode.c \
wifi/Packet.c \ wifi/Packet.c \

View File

@ -7,17 +7,21 @@
#include "py/runtime0.h" #include "py/runtime0.h"
#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/countio/Counter.h" #include "shared-bindings/countio/Counter.h"
#include "shared-bindings/countio/Edge.h"
#include "shared-bindings/util.h" #include "shared-bindings/util.h"
//| class Counter: //| class Counter:
//| """Counter will keep track of the number of falling edge transistions (pulses) on a //| """Count the number of rising- and/or falling-edge transitions on a given pin.
//| given pin""" //| """
//| //|
//| def __init__(self, pin_a: microcontroller.Pin) -> None: //| def __init__(self, pin: microcontroller.Pin, *, edge: Edge = Edge.FALL, pull: Optional[digitalio.Pull]) -> None:
//| """Create a Counter object associated with the given pin. It tracks the number of //| """Create a Counter object associated with the given pin that counts
//| falling pulses relative when the object is constructed. //| 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::
@ -25,29 +29,34 @@
//| import board //| import board
//| import countio //| import countio
//| //|
//| pin_counter = countio.Counter(board.D1) //| # Count rising edges only.
//| #reset the count after 100 counts //| pin_counter = countio.Counter(board.D1, edge=Edge.RISE)
//| # Reset the count after 100 counts.
//| while True: //| while True:
//| if pin_counter.count == 100: //| if pin_counter.count >= 100:
//| pin_counter.reset() //| pin_counter.reset()
//| print(pin_counter.count)""" //| 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) { 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[] = { 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_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); 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); countio_counter_obj_t *self = m_new_obj(countio_counter_obj_t);
self->base.type = &countio_counter_type; 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); 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) { STATIC mp_obj_t countio_counter_reset(mp_obj_t self_in) {
countio_counter_obj_t *self = MP_OBJ_TO_PTR(self_in); countio_counter_obj_t *self = MP_OBJ_TO_PTR(self_in);
check_for_deinit(self); check_for_deinit(self);
// set the position to zero for reset common_hal_countio_counter_set_count(self, 0);
common_hal_countio_counter_reset(self);
return mp_const_none; return mp_const_none;
} }

View File

@ -3,16 +3,17 @@
#include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Pin.h"
#include "common-hal/countio/Counter.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 const mp_obj_type_t countio_counter_type;
extern void common_hal_countio_counter_construct(countio_counter_obj_t *self, 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 void common_hal_countio_counter_deinit(countio_counter_obj_t *self);
extern bool common_hal_countio_counter_deinited(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 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, extern void common_hal_countio_counter_set_count(countio_counter_obj_t *self,
mp_int_t new_count); 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 #endif // MICROPY_INCLUDED_SHARED_BINDINGS_COUNTIO_COUNTER_H

View File

@ -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));
}

View File

@ -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

View File

@ -7,16 +7,12 @@
#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/countio/__init__.h" #include "shared-bindings/countio/__init__.h"
#include "shared-bindings/countio/Counter.h" #include "shared-bindings/countio/Counter.h"
#include "shared-bindings/countio/Edge.h"
//| """Support for edge counting //| """Support for edge counting
//| //|
//| The `countio` module contains logic to read and count edge transistions //| 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 //| 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 //| are no longer needed if the program continues after use. To do so, either
//| call :py:meth:`!deinit` or use a context manager. See //| call :py:meth:`!deinit` or use a context manager. See
@ -26,6 +22,7 @@
STATIC const mp_rom_map_elem_t countio_module_globals_table[] = { 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___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); STATIC MP_DEFINE_CONST_DICT(countio_module_globals, countio_module_globals_table);

View File

@ -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_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); mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
common_hal_digitalio_digitalinout_switch_to_input(self, validate_pull(args[ARG_pull].u_rom_obj, MP_QSTR_pull));
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);
return mp_const_none; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_KW(digitalio_digitalinout_switch_to_input_obj, 1, digitalio_digitalinout_switch_to_input); 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); digitalio_pull_t pull = common_hal_digitalio_digitalinout_get_pull(self);
if (pull == PULL_UP) { 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) { } 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; 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.")); mp_raise_AttributeError(translate("Pull not used when direction is output."));
return mp_const_none; return mp_const_none;
} }
digitalio_pull_t pull = PULL_NONE;
if (pull_obj == MP_ROM_PTR(&digitalio_pull_up_obj)) { common_hal_digitalio_digitalinout_set_pull(self, validate_pull(pull_obj, MP_QSTR_pull));
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);
return mp_const_none; return mp_const_none;
} }
MP_DEFINE_CONST_FUN_OBJ_2(digitalio_digitalinout_set_pull_obj, digitalio_digitalinout_obj_set_pull); MP_DEFINE_CONST_FUN_OBJ_2(digitalio_digitalinout_set_pull_obj, digitalio_digitalinout_obj_set_pull);

View File

@ -24,6 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "py/runtime.h"
#include "shared-bindings/digitalio/Pull.h" #include "shared-bindings/digitalio/Pull.h"
//| class Pull: //| class Pull:
@ -72,3 +73,15 @@ const mp_obj_type_t digitalio_pull_type = {
.print = digitalio_pull_print, .print = digitalio_pull_print,
.locals_dict = (mp_obj_dict_t *)&digitalio_pull_locals_dict, .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);
}

View File

@ -43,4 +43,6 @@ typedef struct {
extern const digitalio_pull_obj_t digitalio_pull_up_obj; extern const digitalio_pull_obj_t digitalio_pull_up_obj;
extern const digitalio_pull_obj_t digitalio_pull_down_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 #endif // MICROPY_INCLUDED_SHARED_BINDINGS_DIGITALIO_PULL_H