diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 6114dcfaea..aa4f0f1f56 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -66,6 +66,14 @@ msgid "" "%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d" msgstr "" +#: shared-bindings/microcontroller/Pin.c +msgid "%q and %q contain duplicate pins" +msgstr "" + +#: shared-bindings/microcontroller/Pin.c +msgid "%q contains duplicate pins" +msgstr "" + #: ports/atmel-samd/common-hal/sdioio/SDCard.c msgid "%q failure: %d" msgstr "" diff --git a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk index e095d69403..9da7163743 100644 --- a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk +++ b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk @@ -16,3 +16,6 @@ MCU_PACKAGE = UFQFPN48 LD_COMMON = boards/common_default.ld LD_FILE = boards/STM32F411_nofs.ld + +# Too big for the flash +CIRCUITPY_ULAB = 0 diff --git a/shared-bindings/keypad/KeyMatrix.c b/shared-bindings/keypad/KeyMatrix.c index 0b854ef475..dbb4ac6822 100644 --- a/shared-bindings/keypad/KeyMatrix.c +++ b/shared-bindings/keypad/KeyMatrix.c @@ -90,6 +90,8 @@ STATIC mp_obj_t keypad_keymatrix_make_new(const mp_obj_type_t *type, size_t n_ar mcu_pin_obj_t *row_pins_array[num_row_pins]; mcu_pin_obj_t *column_pins_array[num_column_pins]; + validate_no_duplicate_pins_2(row_pins, column_pins, MP_QSTR_row_pins, MP_QSTR_column_pins); + for (size_t row = 0; row < num_row_pins; row++) { mcu_pin_obj_t *pin = validate_obj_is_free_pin(mp_obj_subscr(row_pins, MP_OBJ_NEW_SMALL_INT(row), MP_OBJ_SENTINEL)); diff --git a/shared-bindings/keypad/Keys.c b/shared-bindings/keypad/Keys.c index d616bcff84..dc533a2e2b 100644 --- a/shared-bindings/keypad/Keys.c +++ b/shared-bindings/keypad/Keys.c @@ -78,6 +78,7 @@ STATIC mp_obj_t keypad_keys_make_new(const mp_obj_type_t *type, size_t n_args, c mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_obj_t pins = args[ARG_pins].u_obj; + validate_no_duplicate_pins(pins, MP_QSTR_row_pins); // mp_obj_len() will be >= 0. const size_t num_pins = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(pins)); diff --git a/shared-bindings/microcontroller/Pin.c b/shared-bindings/microcontroller/Pin.c index acb1710f3d..78c1c90f4d 100644 --- a/shared-bindings/microcontroller/Pin.c +++ b/shared-bindings/microcontroller/Pin.c @@ -105,6 +105,45 @@ mcu_pin_obj_t *validate_obj_is_free_pin(mp_obj_t obj) { return pin; } +// Validate every element in the list is a unique pin +void validate_no_duplicate_pins(mp_obj_t seq, qstr arg_name) { + const size_t num_pins = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(seq)); + + for (size_t pin_cnt = 0; pin_cnt < num_pins; pin_cnt++) { + mp_obj_t pin1_obj = mp_obj_subscr(seq, MP_OBJ_NEW_SMALL_INT(pin_cnt), MP_OBJ_SENTINEL); + mcu_pin_obj_t *pin1 = validate_obj_is_pin(pin1_obj); + + for (size_t pin_cnt_2 = pin_cnt + 1; pin_cnt_2 < num_pins; pin_cnt_2++) { + mp_obj_t pin2_obj = mp_obj_subscr(seq, MP_OBJ_NEW_SMALL_INT(pin_cnt_2), MP_OBJ_SENTINEL); + mcu_pin_obj_t *pin2 = validate_obj_is_pin(pin2_obj); + if (pin1 == pin2) { + mp_raise_TypeError_varg(translate("%q contains duplicate pins"), arg_name); + } + } + } +} + +void validate_no_duplicate_pins_2(mp_obj_t seq1, mp_obj_t seq2, qstr arg_name1, qstr arg_name2) { + const size_t num_pins_1 = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(seq1)); + const size_t num_pins_2 = (size_t)MP_OBJ_SMALL_INT_VALUE(mp_obj_len(seq2)); + + validate_no_duplicate_pins(seq1, arg_name1); + validate_no_duplicate_pins(seq2, arg_name2); + + for (size_t pin_cnt_1 = 0; pin_cnt_1 < num_pins_1; pin_cnt_1++) { + mp_obj_t pin1_obj = mp_obj_subscr(seq1, MP_OBJ_NEW_SMALL_INT(pin_cnt_1), MP_OBJ_SENTINEL); + mcu_pin_obj_t *pin1 = validate_obj_is_pin(pin1_obj); + + for (size_t pin_cnt_2 = 0; pin_cnt_2 < num_pins_2; pin_cnt_2++) { + mp_obj_t pin2_obj = mp_obj_subscr(seq2, MP_OBJ_NEW_SMALL_INT(pin_cnt_2), MP_OBJ_SENTINEL); + mcu_pin_obj_t *pin2 = validate_obj_is_pin(pin2_obj); + if (pin1 == pin2) { + mp_raise_TypeError_varg(translate("%q and %q contain duplicate pins"), arg_name1, arg_name2); + } + } + } +} + // Validate every element in the list to be a free pin. void validate_list_is_free_pins(qstr what, mcu_pin_obj_t **pins_out, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out) { mp_int_t len = MP_OBJ_SMALL_INT_VALUE(mp_obj_len(seq)); diff --git a/shared-bindings/microcontroller/Pin.h b/shared-bindings/microcontroller/Pin.h index 44019ff267..a8ac6eeb1c 100644 --- a/shared-bindings/microcontroller/Pin.h +++ b/shared-bindings/microcontroller/Pin.h @@ -37,6 +37,8 @@ mcu_pin_obj_t *validate_obj_is_pin(mp_obj_t obj); mcu_pin_obj_t *validate_obj_is_pin_or_none(mp_obj_t obj); mcu_pin_obj_t *validate_obj_is_free_pin(mp_obj_t obj); mcu_pin_obj_t *validate_obj_is_free_pin_or_none(mp_obj_t obj); +void validate_no_duplicate_pins(mp_obj_t seq, qstr arg_name); +void validate_no_duplicate_pins_2(mp_obj_t seq1, mp_obj_t seq2, qstr arg_name1, qstr arg_name2); void validate_list_is_free_pins(qstr what, mcu_pin_obj_t **pins_out, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out); void validate_pins(qstr what, uint8_t *pin_nos, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out);