diff --git a/ports/psoc-edge/Makefile b/ports/psoc-edge/Makefile index 8479e5301acb9..a4122fbbef029 100644 --- a/ports/psoc-edge/Makefile +++ b/ports/psoc-edge/Makefile @@ -98,6 +98,7 @@ SHARED_SRC_C += $(addprefix shared/,\ DRIVERS_SRC_C += MOD_SRC_C += \ + machine_pin.c \ machine_pdm_pcm.c\ \ modpsocedge.c diff --git a/ports/psoc-edge/machine_pin.c b/ports/psoc-edge/machine_pin.c new file mode 100644 index 0000000000000..4f7176de22e1f --- /dev/null +++ b/ports/psoc-edge/machine_pin.c @@ -0,0 +1,227 @@ +#include "py/obj.h" +#include "py/runtime.h" + +#include "cy_gpio.h" + +#include "extmod/modmachine.h" +#include "extmod/virtpin.h" + +#define pin_assert_raise_val(msg, ret) if (ret != CY_RSLT_SUCCESS) { \ + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT(msg), ret); \ +} + +enum {GPIO_MODE_NONE = 0, GPIO_MODE_IN, GPIO_MODE_OUT, GPIO_MODE_OPEN_DRAIN}; + +enum {GPIO_PULL_NONE = 0, GPIO_PULL_UP, GPIO_PULL_DOWN, GPIO_PULL_UP_DOWN}; + +typedef struct _machine_pin_obj_t { + mp_obj_base_t base; + qstr name; + uint8_t port; + uint8_t pin; +} +machine_pin_obj_t; + +// TODO: +// Initial hardcoded pin definitions can go here +// This will be generated by make-pins.py soon +const machine_pin_obj_t machine_pin_p16_0 = { + { &machine_pin_type }, + MP_QSTR_P16_0, + 16, + 0, +}; + +static uint32_t get_drive_mode(uint8_t mode, uint8_t pull) { + uint32_t drive_mode = CY_GPIO_DM_INVALID; + + if (mode == GPIO_MODE_IN) { + if (pull == GPIO_PULL_UP) { + drive_mode = CY_GPIO_DM_PULLUP; + } else if (pull == GPIO_PULL_DOWN) { + drive_mode = CY_GPIO_DM_PULLDOWN; + } else if (pull == GPIO_PULL_UP_DOWN) { + drive_mode = CY_GPIO_DM_PULLUP_DOWN; + } else { + drive_mode = CY_GPIO_DM_HIGHZ; + } + // TODO: Check if this will be used. + // CY_GPIO_DM_STRONG ?? + } else if (mode == GPIO_MODE_OUT) { + if (pull == GPIO_PULL_UP) { + drive_mode = CY_GPIO_DM_PULLUP_IN_OFF; + } else if (pull == GPIO_PULL_DOWN) { + drive_mode = CY_GPIO_DM_PULLDOWN_IN_OFF; + } else if (pull == GPIO_PULL_UP_DOWN) { + drive_mode = CY_GPIO_DM_PULLUP_DOWN_IN_OFF; + } else { + drive_mode = CY_GPIO_DM_STRONG_IN_OFF; + } + } else if (mode == GPIO_MODE_OPEN_DRAIN) { + drive_mode = CY_GPIO_DM_OD_DRIVESLOW_IN_OFF; + // TODO: Check if we support other open drain modes + // CY_GPIO_DM_OD_DRIVESLOW + // CY_GPIO_DM_OD_DRIVESHIGH + } else if (mode == GPIO_MODE_NONE) { + drive_mode = CY_GPIO_DM_INVALID; + } + + return drive_mode; +} + +static uint8_t get_validated_initial_value(uint8_t mode, uint8_t pull, int8_t value) { + // No value was selected by the user, + // Select it coherent with the pull resistor + // configuration and low by default + if (value == -1) { + return (pull == GPIO_PULL_UP) ? 1 : 0; + } + + if (mode == GPIO_MODE_IN) { + if (value == 0 && pull == GPIO_PULL_UP) { + mp_raise_msg(&mp_type_Exception, MP_ERROR_TEXT("machine.Pin incompatible configuration. Input pull-up can not be initialized low.\n")); + } else if (value == 1 && pull == GPIO_PULL_DOWN) { + mp_raise_msg(&mp_type_Exception, MP_ERROR_TEXT("machine.Pin incompatible configuration. Input pull-down can not be initialized high.\n")); + } else if (pull == GPIO_PULL_NONE || pull == GPIO_PULL_UP_DOWN) { + value = 0; // Default to low + mp_printf(&mp_plat_print, "machine.Pin warning: Initial value is undefined for input pull-none configuration.\n"); + } + return value; + } + + return value; +} + +static mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { + ARG_mode, ARG_pull, ARG_drive, ARG_value + }; + static const mp_arg_t allowed_args[] = { + {MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + {MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + {MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + {MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}} + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + uint8_t mode = GPIO_MODE_NONE; + if (args[ARG_mode].u_obj != mp_const_none) { + mode = mp_obj_get_uint(args[ARG_mode].u_obj); + } + + uint8_t pull = GPIO_PULL_NONE; + if (args[ARG_pull].u_obj != mp_const_none) { + pull = mp_obj_get_uint(args[ARG_pull].u_obj); + } + + int8_t value = -1; + if (args[ARG_value].u_obj != mp_const_none) { + value = mp_obj_is_true(args[ARG_value].u_obj); + } + + uint32_t drive = CY_GPIO_DRIVE_SEL_0; + if (args[ARG_drive].u_obj != mp_const_none) { + drive = mp_obj_get_uint(args[ARG_drive].u_obj); + } + + cy_stc_gpio_pin_config_t pin_config = { + .outVal = get_validated_initial_value(mode, pull, value), + .driveMode = get_drive_mode(mode, pull), + .hsiom = HSIOM_SEL_GPIO, + .intEdge = CY_GPIO_INTR_DISABLE, + .intMask = 0UL, + .vtrip = CY_GPIO_VTRIP_CMOS, + .slewRate = CY_GPIO_SLEW_FAST, + .driveSel = drive, + .vregEn = 0UL, + .ibufMode = 0UL, + .vtripSel = 0UL, + .vrefSel = 0UL, + .vohSel = 0UL, + .pullUpRes = CY_GPIO_PULLUP_RES_DISABLE, + .nonSec = 1, + }; + + cy_en_gpio_status_t rslt = Cy_GPIO_Pin_Init(Cy_GPIO_PortToAddr(self->port), self->pin, &pin_config); + pin_assert_raise_val("Pin initialization failed (PSE PDL error code: %lx)", rslt); + + return mp_const_none; +} + +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, 6, true); + + const machine_pin_obj_t *self = &machine_pin_p16_0; // TODO: This will be change by the proper pin allocation/find function machine_pin_finf(args[0]); + + if (n_args > 1 || n_kw > 0) { + // pin mode given, so configure this GPIO + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args); // skipping "id" as an arg as it is a part of self*. + } + + return MP_OBJ_FROM_PTR(self); +} + +static mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); +} +MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_obj_init_obj, 1, machine_pin_obj_init); + +static void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + // TODO: Placeholder. +} + +static mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // TODO: Placeholder. + return mp_const_none; +} + +static mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + // TODO: Placeholder. + return 0; +} + +static const mp_pin_p_t pin_pin_p = { + .ioctl = pin_ioctl, +}; + +static const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { + // Instance methods + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_obj_init_obj) }, + + // Const + { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_IN) }, + { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_OUT) }, + { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OPEN_DRAIN) }, + + { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULL_UP) }, + { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) }, + { MP_ROM_QSTR(MP_QSTR_PULL_UP_DOWN), MP_ROM_INT(GPIO_PULL_UP_DOWN) }, + + { MP_ROM_QSTR(MP_QSTR_DRIVE_0), MP_ROM_INT(CY_GPIO_DRIVE_SEL_0) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_1), MP_ROM_INT(CY_GPIO_DRIVE_SEL_1) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_2), MP_ROM_INT(CY_GPIO_DRIVE_SEL_2) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_3), MP_ROM_INT(CY_GPIO_DRIVE_SEL_3) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_4), MP_ROM_INT(CY_GPIO_DRIVE_SEL_4) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_5), MP_ROM_INT(CY_GPIO_DRIVE_SEL_5) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_6), MP_ROM_INT(CY_GPIO_DRIVE_SEL_6) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_7), MP_ROM_INT(CY_GPIO_DRIVE_SEL_7) } +}; + +static MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table); + + +MP_DEFINE_CONST_OBJ_TYPE( + machine_pin_type, + MP_QSTR_Pin, + MP_TYPE_FLAG_NONE, + make_new, mp_pin_make_new, + print, machine_pin_print, + call, machine_pin_call, + protocol, &pin_pin_p, + locals_dict, &machine_pin_locals_dict + ); diff --git a/ports/psoc-edge/modmachine.c b/ports/psoc-edge/modmachine.c index fb857c13cfa73..87b9a72b5eef3 100644 --- a/ports/psoc-edge/modmachine.c +++ b/ports/psoc-edge/modmachine.c @@ -70,6 +70,7 @@ static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) { #define MICROPY_PY_MACHINE_EXTRA_GLOBALS \ /* Modules */ \ + { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) }, \ { MP_ROM_QSTR(MP_QSTR_PDM_PCM), MP_ROM_PTR(&machine_pdm_pcm_type) }, \ #endif // MICROPY_PY_MACHINE diff --git a/ports/psoc-edge/mpconfigport.h b/ports/psoc-edge/mpconfigport.h index 2f1fb1d193553..8a91d28fbfce7 100644 --- a/ports/psoc-edge/mpconfigport.h +++ b/ports/psoc-edge/mpconfigport.h @@ -77,6 +77,8 @@ #define MICROPY_PY_MACHINE_PDM_PCM (1) #define MICROPY_PY_MACHINE_PDM_PCM_RING_BUF (1) +#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new + #define MICROPY_LOGGER_DEBUG (1) // type definitions for the specific machine diff --git a/tests/ports/psoc-edge/board_ext_hw/single/pin.py b/tests/ports/psoc-edge/board_ext_hw/single/pin.py new file mode 100644 index 0000000000000..aa3eb8de6e0c5 --- /dev/null +++ b/tests/ports/psoc-edge/board_ext_hw/single/pin.py @@ -0,0 +1,5 @@ +from machine import Pin + +pin1_name = "P16_0" + +pin_out = Pin(pin1_name, mode=Pin.OUT, value=True) diff --git a/tests/ports/psoc-edge/board_ext_hw/single/pin.py.exp b/tests/ports/psoc-edge/board_ext_hw/single/pin.py.exp new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/ports/psoc-edge/test-plan.yml b/tests/ports/psoc-edge/test-plan.yml index 5623ef85af70d..0b66f9074183d 100644 --- a/tests/ports/psoc-edge/test-plan.yml +++ b/tests/ports/psoc-edge/test-plan.yml @@ -1,5 +1,11 @@ - name: no-extended-hardware test: script: ports/psoc-edge/board_only_hw/single + device: + - board: KIT_PSE84_AI + +- name: pin + test: + script: ports/psoc-edge/board_ext_hw/single/pin.py device: - board: KIT_PSE84_AI \ No newline at end of file