rp2/machine_pin: Add mp_hal_pin_interrupt C interface.

So C can can easily configure a pin interrupt and callback.

Signed-off-by: Andrew Leech <andrew@alelec.net>
This commit is contained in:
Andrew Leech 2022-04-30 12:45:43 +10:00 committed by Damien George
parent 9bd6169b72
commit 05f927b624
2 changed files with 52 additions and 30 deletions

View File

@ -313,50 +313,62 @@ STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle);
// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False)
STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_handler, ARG_trigger, ARG_hard };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE} },
{ MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
};
machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
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);
STATIC machine_pin_irq_obj_t *machine_pin_get_irq(mp_hal_pin_obj_t pin) {
// Get the IRQ object.
machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_obj[self->id]);
machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_obj[pin]);
// Allocate the IRQ object if it doesn't already exist.
if (irq == NULL) {
irq = m_new_obj(machine_pin_irq_obj_t);
irq->base.base.type = &mp_irq_type;
irq->base.methods = (mp_irq_methods_t *)&machine_pin_irq_methods;
irq->base.parent = MP_OBJ_FROM_PTR(self);
irq->base.parent = MP_OBJ_FROM_PTR(&machine_pin_obj[pin]);
irq->base.handler = mp_const_none;
irq->base.ishard = false;
MP_STATE_PORT(machine_pin_irq_obj[self->id]) = irq;
MP_STATE_PORT(machine_pin_irq_obj[pin]) = irq;
}
return irq;
}
void mp_hal_pin_interrupt(mp_hal_pin_obj_t pin, mp_obj_t handler, mp_uint_t trigger, bool hard) {
machine_pin_irq_obj_t *irq = machine_pin_get_irq(pin);
// Disable all IRQs while data is updated.
gpio_set_irq_enabled(pin, GPIO_IRQ_ALL, false);
// Update IRQ data.
irq->base.handler = handler;
irq->base.ishard = hard;
irq->flags = 0;
irq->trigger = trigger;
// Enable IRQ if a handler is given.
if (handler != mp_const_none && trigger != MP_HAL_PIN_TRIGGER_NONE) {
gpio_set_irq_enabled(pin, trigger, true);
}
}
// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False)
STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_handler, ARG_trigger, ARG_hard };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = MP_HAL_PIN_TRIGGER_FALL | MP_HAL_PIN_TRIGGER_RISE} },
{ MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
};
machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
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);
machine_pin_irq_obj_t *irq = machine_pin_get_irq(self->id);
if (n_args > 1 || kw_args->used != 0) {
// Configure IRQ.
// Disable all IRQs while data is updated.
gpio_set_irq_enabled(self->id, GPIO_IRQ_ALL, false);
// Update IRQ data.
irq->base.handler = args[ARG_handler].u_obj;
irq->base.ishard = args[ARG_hard].u_bool;
irq->flags = 0;
irq->trigger = args[ARG_trigger].u_int;
// Enable IRQ if a handler is given.
if (args[ARG_handler].u_obj != mp_const_none) {
gpio_set_irq_enabled(self->id, args[ARG_trigger].u_int, true);
}
mp_obj_t handler = args[ARG_handler].u_obj;
mp_uint_t trigger = args[ARG_trigger].u_int;
bool hard = args[ARG_hard].u_bool;
mp_hal_pin_interrupt(self->id, handler, trigger, hard);
}
return MP_OBJ_FROM_PTR(irq);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq);

View File

@ -126,4 +126,14 @@ static inline void mp_hal_pin_high(mp_hal_pin_obj_t pin) {
gpio_set_mask(1 << pin);
}
enum mp_hal_pin_interrupt_trigger {
MP_HAL_PIN_TRIGGER_NONE,
MP_HAL_PIN_TRIGGER_LOW = GPIO_IRQ_LEVEL_LOW,
MP_HAL_PIN_TRIGGER_HIGH = GPIO_IRQ_LEVEL_HIGH,
MP_HAL_PIN_TRIGGER_FALL = GPIO_IRQ_EDGE_FALL,
MP_HAL_PIN_TRIGGER_RISE = GPIO_IRQ_EDGE_RISE,
};
void mp_hal_pin_interrupt(mp_hal_pin_obj_t pin, mp_obj_t handler, mp_uint_t trigger, bool hard);
#endif // MICROPY_INCLUDED_RP2_MPHALPORT_H