-
Notifications
You must be signed in to change notification settings - Fork 0
machine.Pin constructor (make) + init #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: machine-pin
Are you sure you want to change the base?
Changes from all commits
ae142eb
480d00a
d2b5cff
4792b90
cf20f87
6d3ac1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| ); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| from machine import Pin | ||
|
|
||
| pin1_name = "P16_0" | ||
|
|
||
| pin_out = Pin(pin1_name, mode=Pin.OUT, value=True) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the other tests will be added after pin generations is it?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will start the test with 2 hardcoded pins, and add the rest of the machine.Pin() tests. With the creation of the pin class I will understand all the machine_pin_obj requirements, and from there I can handle the pin generation from make-pins.py. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we instead have a LUT for this pin so that we can extend it for other tests till we have pins generated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let´s discuss in the pairing how I should do that :)