diff --git a/esp8266/machine_pin.c b/esp8266/machine_pin.c index d4c6d3dea7..1a263601b4 100644 --- a/esp8266/machine_pin.c +++ b/esp8266/machine_pin.c @@ -287,7 +287,7 @@ STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, c } // constructor(id, ...) -STATIC mp_obj_t pyb_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); // get the wanted pin object @@ -436,7 +436,7 @@ const mp_obj_type_t pyb_pin_type = { { &mp_type_type }, .name = MP_QSTR_Pin, .print = pyb_pin_print, - .make_new = pyb_pin_make_new, + .make_new = mp_pin_make_new, .call = pyb_pin_call, .protocol = &pin_pin_p, .locals_dict = (mp_obj_t)&pyb_pin_locals_dict, diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h index b25bb8bb45..d0b4a7b4b9 100644 --- a/esp8266/mpconfigport.h +++ b/esp8266/mpconfigport.h @@ -73,6 +73,7 @@ #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_LWIP (1) #define MICROPY_PY_MACHINE (1) +#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_I2C (1) #define MICROPY_PY_MACHINE_SPI (1) diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c index de6c3ff320..b10d901662 100644 --- a/extmod/machine_signal.c +++ b/extmod/machine_signal.c @@ -27,6 +27,8 @@ #include "py/mpconfig.h" #if MICROPY_PY_MACHINE +#include + #include "py/obj.h" #include "py/runtime.h" #include "extmod/virtpin.h" @@ -41,20 +43,73 @@ typedef struct _machine_signal_t { } machine_signal_t; STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - enum { ARG_pin, ARG_inverted }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_, MP_ARG_OBJ | MP_ARG_REQUIRED }, - { MP_QSTR_inverted, MP_ARG_BOOL, {.u_bool = false} }, - }; + mp_obj_t pin = args[0]; + bool inverted = false; - mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)]; + #if defined(MICROPY_PY_MACHINE_PIN_MAKE_NEW) + mp_pin_p_t *pin_p = NULL; - mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args); + if (MP_OBJ_IS_OBJ(pin)) { + mp_obj_base_t *pin_base = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); + pin_p = (mp_pin_p_t*)pin_base->type->protocol; + } + + if (pin_p == NULL) { + // If first argument isn't a Pin-like object, we filter out "inverted" + // from keyword arguments and pass them all to the exported Pin + // constructor to create one. + mp_obj_t pin_args[n_args + n_kw * 2]; + memcpy(pin_args, args, n_args * sizeof(mp_obj_t)); + const mp_obj_t *src = args + n_args; + mp_obj_t *dst = pin_args + n_args; + mp_obj_t *sig_value = NULL; + for (size_t cnt = n_kw; cnt; cnt--) { + if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_inverted)) { + inverted = mp_obj_is_true(src[1]); + n_kw--; + } else { + *dst++ = *src; + *dst++ = src[1]; + } + if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_value)) { + // Value is pertained to Signal, so we should invert + // it for Pin if needed, and we should do it only when + // inversion status is guaranteedly known. + sig_value = dst - 1; + } + src += 2; + } + + if (inverted && sig_value != NULL) { + *sig_value = mp_obj_is_true(*sig_value) ? MP_OBJ_NEW_SMALL_INT(0) : MP_OBJ_NEW_SMALL_INT(1); + } + + // Here we pass NULL as a type, hoping that mp_pin_make_new() + // will just ignore it as set a concrete type. If not, we'd need + // to expose port's "default" pin type too. + pin = MICROPY_PY_MACHINE_PIN_MAKE_NEW(NULL, n_args, n_kw, pin_args); + } + else + #endif + // Otherwise there should be 1 or 2 args + { + if (n_args == 1) { + if (n_kw == 0) { + } else if (n_kw == 1 && args[1] == MP_OBJ_NEW_QSTR(MP_QSTR_inverted)) { + inverted = mp_obj_is_true(args[1]); + } else { + goto error; + } + } else { + error: + mp_raise_TypeError(NULL); + } + } machine_signal_t *o = m_new_obj(machine_signal_t); o->base.type = type; - o->pin = parsed_args[ARG_pin].u_obj; - o->inverted = parsed_args[ARG_inverted].u_bool; + o->pin = pin; + o->inverted = inverted; return MP_OBJ_FROM_PTR(o); } diff --git a/extmod/virtpin.h b/extmod/virtpin.h index 3821f9dec5..0410103505 100644 --- a/extmod/virtpin.h +++ b/extmod/virtpin.h @@ -38,3 +38,6 @@ typedef struct _mp_pin_p_t { int mp_virtual_pin_read(mp_obj_t pin); void mp_virtual_pin_write(mp_obj_t pin, int value); + +// If a port exposes a Pin object, it's constructor should be like this +mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);