From fba08bff103b3bffd56c427bf818af52a85696d1 Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Fri, 3 Jul 2026 10:57:52 +0000 Subject: [PATCH 01/16] psoc-edge: Added Counter module. Signed-off-by: NaveenChengappa-IFX --- ports/psoc-edge/Makefile | 2 + ports/psoc-edge/boards/make-pins.py | 13 +- ports/psoc-edge/machine_counter.c | 440 ++++++++++++++++++++++++++++ ports/psoc-edge/machine_timer.c | 20 +- ports/psoc-edge/modmachine.c | 1 + ports/psoc-edge/modmachine.h | 1 + ports/psoc-edge/tcpwm.c | 4 +- 7 files changed, 465 insertions(+), 16 deletions(-) create mode 100644 ports/psoc-edge/machine_counter.c diff --git a/ports/psoc-edge/Makefile b/ports/psoc-edge/Makefile index 8e383415309..bd92434808e 100644 --- a/ports/psoc-edge/Makefile +++ b/ports/psoc-edge/Makefile @@ -351,6 +351,7 @@ PSE_LIB_SRC_C += $(addprefix $(PSE_LIB_TOP_DIR)/, \ mtb-dsl-pse8xxgp/pdl/drivers/source/cy_systick_v2.c \ mtb-dsl-pse8xxgp/pdl/drivers/source/cy_tcpwm_counter.c \ mtb-dsl-pse8xxgp/pdl/drivers/source/cy_tcpwm_pwm.c \ + mtb-dsl-pse8xxgp/pdl/drivers/source/cy_trigmux.c \ mtb-dsl-pse8xxgp/pdl/drivers/source/ppu_v1.c \ \ mtb-dsl-pse8xxgp/support/source/mtb_stdlib_stubs.c \ @@ -595,6 +596,7 @@ MOD_SRC_C += \ machine_scb.c \ tcpwm.c \ machine_timer.c \ + machine_counter.c \ machine_bitstream.c \ modpsocedge.c \ diff --git a/ports/psoc-edge/boards/make-pins.py b/ports/psoc-edge/boards/make-pins.py index 1a15cfb05e7..5a6a970e77e 100644 --- a/ports/psoc-edge/boards/make-pins.py +++ b/ports/psoc-edge/boards/make-pins.py @@ -426,14 +426,19 @@ def print_tcpwm_hw_map(self, out_header): print(file=out_header) print( - "// Unified TCPWM hardware map: timer_id, counter_num, IRQ, PCLK destination.", + "// Unified TCPWM map: timer_id, counter_num, IRQ, PCLK destination, and one-to-one trigger input route.", file=out_header, ) - print("// Each row: X(timer_id, tcpwm_counter_num, irq, pclk_dst)", file=out_header) - print("#define MICROPY_PY_MACHINE_TCPWM_HW_MAP(X) \\", file=out_header) + print( + "// Each row: X(timer_id, tcpwm_counter_num, irq, pclk_dst, trig_out_enum)", + file=out_header, + ) + print("#define MICROPY_PY_MACHINE_TCPWM_MAP(X) \\", file=out_header) for i, (tid, counter, irq, pclk) in enumerate(hw_entries): + counter_token = counter[:-1] if counter.endswith("U") else counter + trig = f"PERI_0_TRIG_OUT_MUX_3_TCPWM0_ONE_CNT_TR_IN{counter_token}" suffix = " \\" if i < len(hw_entries) - 1 else "" - print(f" X({tid:2d}, {counter}, {irq}, {pclk}){suffix}", file=out_header) + print(f" X({tid:2d}, {counter}, {irq}, {pclk}, {trig}){suffix}", file=out_header) print(file=out_header) def print_af_header(self, out_af_header): diff --git a/ports/psoc-edge/machine_counter.c b/ports/psoc-edge/machine_counter.c new file mode 100644 index 00000000000..c985f636a6c --- /dev/null +++ b/ports/psoc-edge/machine_counter.c @@ -0,0 +1,440 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2026 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#include "modmachine.h" +#include "machine_pin.h" +#include "tcpwm.h" + +#include "cy_gpio.h" +#include "cy_sysclk.h" +#include "cy_trigmux.h" +#include "cy_tcpwm_counter.h" +#include "cy_tcpwm.h" +#include "cycfg_peripheral_clocks.h" +#include "mtb_hal.h" + +#include "genhdr/pins_af.h" + +// Number of Counter object slots supported by this port. +#define MACHINE_COUNTER_NUM_INSTANCES (32) +// Shared TCPWM source clock frequency used by Counter. +#define COUNTER_CLK_HZ (1000000UL) +// Value used to disable optional TCPWM trigger inputs. +#define COUNTER_INPUT_DISABLED (0x7U) + +typedef enum { + COUNTER_EDGE_RISING = 1, + COUNTER_EDGE_FALLING = 2, +} machine_counter_edge_t; + +typedef enum { + COUNTER_DIR_UP = 1, + COUNTER_DIR_DOWN = 2, +} machine_counter_dir_t; + +typedef struct _machine_counter_obj_t { + mp_obj_base_t base; + uint8_t id; + uint32_t counter_num; + en_clk_dst_t pclk_dst; + const machine_pin_obj_t *src_pin; + en_hsiom_sel_t src_hsiom; + uint8_t direction; + mp_int_t offset; + bool configured; +} machine_counter_obj_t; + +const mp_obj_type_t machine_counter_type; + +// One Counter object per hardware id. +static machine_counter_obj_t *counter_obj[MACHINE_COUNTER_NUM_INSTANCES] = { NULL }; +static bool machine_counter_clock_configured = false; + +// --------------------------------------------------------------------------- +// Per-ID hardware mapping from generated AF data. +// --------------------------------------------------------------------------- + +// Expands generated map entries into id->hardware-counter lookup. +#define COUNTER_HW_ENTRY(id, counter, irq, pclk, trig) counter, +static const uint32_t counter_hw[MACHINE_COUNTER_NUM_INSTANCES] = { + MICROPY_PY_MACHINE_TCPWM_MAP(COUNTER_HW_ENTRY) +}; +#undef COUNTER_HW_ENTRY + +// Expands generated map entries into id->output-trigger-line lookup. +#define COUNTER_OUT_TRIG_ENTRY(id, counter, irq, pclk, trig) trig, +static const uint32_t counter_out_trig[MACHINE_COUNTER_NUM_INSTANCES] = { + MICROPY_PY_MACHINE_TCPWM_MAP(COUNTER_OUT_TRIG_ENTRY) +}; +#undef COUNTER_OUT_TRIG_ENTRY + +// This mapping is used to route a TCPWM0 counter's output trigger to a GPIO pin. +// Each row: X(port_num, pin_num, in_trig_line, pin_hsiom) +#define MACHINE_COUNTER_PIN_TRIGGER_MAP(X) \ + X(11, 0, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT0, P11_0_PERI0_TR_IO_INPUT0) \ + X(11, 1, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT1, P11_1_PERI0_TR_IO_INPUT1) \ + X(11, 2, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT2, P11_2_PERI0_TR_IO_INPUT2) \ + X(11, 3, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT3, P11_3_PERI0_TR_IO_INPUT3) \ + X(7, 5, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT4, P7_5_PERI0_TR_IO_INPUT4) \ + X(7, 6, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT5, P7_6_PERI0_TR_IO_INPUT5) \ + X(7, 7, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT6, P7_7_PERI0_TR_IO_INPUT6) \ + X(8, 0, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT7, P8_0_PERI0_TR_IO_INPUT7) + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +// Configure the shared peripheral clock once for all Counter objects. +static void machine_counter_configure_clock(void) { + if (machine_counter_clock_configured) { + return; + } + + cy_rslt_t rslt = mtb_hal_clock_set_peri_clock_freq(&CYBSP_GENERAL_PURPOSE_TIMER_clock_ref, + COUNTER_CLK_HZ, 1000); + if (rslt != CY_RSLT_SUCCESS) { + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("Counter clock setup failed (0x%lx)"), + (unsigned long)rslt); + } + + machine_counter_clock_configured = true; +} + +// Return the max period for this counter width (16-bit or 32-bit). +static uint32_t machine_counter_period_max(uint32_t counter_num) { + return (counter_num >= 256U) ? 0xFFFFU : UINT32_MAX; +} + +// Map a hardware counter number to its routed trigger output line. +static uint32_t machine_counter_out_trig_line(uint32_t counter_num) { + for (size_t i = 0; i < MP_ARRAY_SIZE(counter_hw); ++i) { + if (counter_hw[i] == counter_num) { + return counter_out_trig[i]; + } + } + + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("Counter(%lu) trigger route not supported"), + (unsigned long)counter_num); +} + +typedef struct _machine_counter_pin_trigger_map_t { + uint8_t port; + uint8_t pin; + uint32_t in_trig; + en_hsiom_sel_t hsiom; +} machine_counter_pin_trigger_map_t; + +// Expands pin mapping rows into lookup table entries. +#define PIN_TRIG_ENTRY(port_num, pin_num, in_trig_line, pin_hsiom) \ + { (uint8_t)(port_num), (uint8_t)(pin_num), (in_trig_line), (pin_hsiom) }, +static const machine_counter_pin_trigger_map_t machine_counter_pin_trigger_map[] = { + MACHINE_COUNTER_PIN_TRIGGER_MAP(PIN_TRIG_ENTRY) +}; +#undef PIN_TRIG_ENTRY + +// Resolve a source pin to its trigger input line and HSIOM function. +static bool machine_counter_pin_to_trigger(const machine_pin_obj_t *pin, + uint32_t *in_trig, en_hsiom_sel_t *hsiom) { + for (size_t i = 0; i < MP_ARRAY_SIZE(machine_counter_pin_trigger_map); ++i) { + const machine_counter_pin_trigger_map_t *entry = &machine_counter_pin_trigger_map[i]; + if (pin->port == entry->port && pin->pin == entry->pin) { + *in_trig = entry->in_trig; + *hsiom = entry->hsiom; + return true; + } + } + + return false; +} + +// Restore the routed source pin back to GPIO input mode. +static void machine_counter_restore_src_pin(machine_counter_obj_t *self) { + if (self->src_pin == NULL) { + return; + } + GPIO_PRT_Type *port = Cy_GPIO_PortToAddr(self->src_pin->port); + Cy_GPIO_SetHSIOM(port, self->src_pin->pin, HSIOM_SEL_GPIO); + Cy_GPIO_SetDrivemode(port, self->src_pin->pin, CY_GPIO_DM_HIGHZ); + self->src_pin = NULL; +} + +// Disable the underlying TCPWM counter channel. +static void machine_counter_stop_hw(machine_counter_obj_t *self) { + Cy_TCPWM_Counter_Disable(TCPWM0, self->counter_num); +} + +// Parse init args and configure routing, trigger mux, and TCPWM hardware. +static void machine_counter_init_helper(machine_counter_obj_t *self, + size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + enum { ARG_src, ARG_edge, ARG_direction }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_src, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_edge, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = COUNTER_EDGE_RISING} }, + { MP_QSTR_direction, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = COUNTER_DIR_UP} }, + }; + + 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 edge = args[ARG_edge].u_int; + if (edge != COUNTER_EDGE_RISING && edge != COUNTER_EDGE_FALLING) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid edge")); + } + + uint8_t direction = args[ARG_direction].u_int; + if (direction != COUNTER_DIR_UP && direction != COUNTER_DIR_DOWN) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid direction")); + } + + // Resolve source pin object and fetch its trigger-routing metadata. + const machine_pin_obj_t *src_pin = machine_pin_get_pin_obj(args[ARG_src].u_obj); + uint32_t in_trig = 0; + en_hsiom_sel_t hsiom = (en_hsiom_sel_t)0; + if (!machine_counter_pin_to_trigger(src_pin, &in_trig, &hsiom)) { + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("Pin %q does not support Counter input routing"), src_pin->name); + } + + // Tear down any previous run before programming new pin routing. + machine_counter_stop_hw(self); + machine_counter_restore_src_pin(self); + + // Ensure shared timer clock is configured and bound to this counter PCLK. + machine_counter_configure_clock(); + Cy_SysClk_PeriPclkAssignDivider(self->pclk_dst, + CY_SYSCLK_DIV_16_BIT, CYBSP_GENERAL_PURPOSE_TIMER_CLK_DIV_NUM); + + // Put pin in input mode and switch HSIOM to trigger-output function. + mp_hal_pin_input(src_pin); + GPIO_PRT_Type *src_port = Cy_GPIO_PortToAddr(src_pin->port); + Cy_GPIO_SetHSIOM(src_port, src_pin->pin, hsiom); + Cy_GPIO_SetDrivemode(src_port, src_pin->pin, CY_GPIO_DM_HIGHZ); + + // Connect selected pin trigger line to this counter's dedicated trigger input. + uint32_t out_trig = machine_counter_out_trig_line(self->counter_num); + cy_en_trigmux_status_t mux_rslt = Cy_TrigMux_Connect(in_trig, out_trig, false, TRIGGER_TYPE_LEVEL); + if (mux_rslt != CY_TRIGMUX_SUCCESS) { + // Roll back pin mux state if trigger connect fails. + machine_counter_restore_src_pin(self); + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("Counter route connect failed (0x%lx)"), + (unsigned long)mux_rslt); + } + + cy_stc_tcpwm_counter_config_t cfg = {0}; + cfg.period = machine_counter_period_max(self->counter_num); + cfg.clockPrescaler = CY_TCPWM_COUNTER_PRESCALER_DIVBY_1; + cfg.runMode = CY_TCPWM_COUNTER_CONTINUOUS; + cfg.countDirection = CY_TCPWM_COUNTER_COUNT_UP; + cfg.compareOrCapture = CY_TCPWM_COUNTER_MODE_COMPARE; + cfg.compare0 = 0; + cfg.compare1 = 0; + cfg.enableCompareSwap = false; + cfg.interruptSources = 0; + cfg.captureInputMode = COUNTER_INPUT_DISABLED & 0x3U; + cfg.captureInput = CY_TCPWM_INPUT_0; + cfg.reloadInputMode = COUNTER_INPUT_DISABLED & 0x3U; + cfg.reloadInput = CY_TCPWM_INPUT_0; + cfg.startInputMode = COUNTER_INPUT_DISABLED & 0x3U; + cfg.startInput = CY_TCPWM_INPUT_0; + cfg.stopInputMode = COUNTER_INPUT_DISABLED & 0x3U; + cfg.stopInput = CY_TCPWM_INPUT_0; + cfg.countInputMode = (edge == COUNTER_EDGE_RISING) ? CY_TCPWM_INPUT_RISINGEDGE : CY_TCPWM_INPUT_FALLINGEDGE; + // With TCPWM_TR_ONE_CNT_NR == 1 this selects one-to-one trigger input for this counter. + cfg.countInput = CY_TCPWM_INPUT_TRIG_0; + + #if (CY_IP_MXTCPWM_VERSION >= 2U) + cfg.capture1InputMode = COUNTER_INPUT_DISABLED & 0x3U; + cfg.capture1Input = CY_TCPWM_INPUT_0; + cfg.enableCompare1Swap = false; + cfg.compare2 = CY_TCPWM_GRP_CNT_CC0_DEFAULT; + cfg.compare3 = CY_TCPWM_GRP_CNT_CC0_BUFF_DEFAULT; + cfg.trigger0Event = CY_TCPWM_CNT_TRIGGER_ON_DISABLED; + cfg.trigger1Event = CY_TCPWM_CNT_TRIGGER_ON_DISABLED; + #endif + + cy_en_tcpwm_status_t rslt = Cy_TCPWM_Counter_Init(TCPWM0, self->counter_num, &cfg); + if (rslt != CY_TCPWM_SUCCESS) { + machine_counter_restore_src_pin(self); + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("Counter(%u) init failed (PDL error 0x%lx)"), + (unsigned)self->id, (unsigned long)rslt); + } + + Cy_TCPWM_Counter_SetCounter(TCPWM0, self->counter_num, 0); + Cy_TCPWM_Counter_Enable(TCPWM0, self->counter_num); + Cy_TCPWM_TriggerReloadOrIndex_Single(TCPWM0, self->counter_num); + + self->src_pin = src_pin; + self->src_hsiom = hsiom; + self->direction = direction; + self->offset = 0; + self->configured = true; +} + +// --------------------------------------------------------------------------- +// Constructor: Counter(id, ...) +// --------------------------------------------------------------------------- + +// Create a Counter object, reserve hardware, and run optional init. +static mp_obj_t machine_counter_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); + + mp_int_t id = mp_obj_get_int(args[0]); + if (id < 0 || id >= MACHINE_COUNTER_NUM_INSTANCES) { + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("Counter id must be in range 0-%d"), + MACHINE_COUNTER_NUM_INSTANCES - 1); + } + + if (counter_obj[id] != NULL) { + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("Counter(%u) already created."), (unsigned)id); + } + + machine_counter_obj_t *self = mp_obj_malloc(machine_counter_obj_t, &machine_counter_type); + counter_obj[id] = self; + + self->id = (uint8_t)id; + self->counter_num = counter_hw[id]; + self->pclk_dst = machine_tcpwm_counter_pclk(self->counter_num); + self->src_pin = NULL; + self->src_hsiom = (en_hsiom_sel_t)0; + self->direction = COUNTER_DIR_UP; + self->offset = 0; + self->configured = false; + + nlr_buf_t nl; + if (nlr_push(&nl) == 0) { + machine_tcpwm_counter_alloc(self->counter_num, MP_OBJ_FROM_PTR(self)); + if (n_args > 1 || n_kw > 0) { + mp_map_t kw_map; + mp_map_init_fixed_table(&kw_map, n_kw, args + n_args); + machine_counter_init_helper(self, n_args - 1, args + 1, &kw_map); + } + nlr_pop(); + } else { + machine_tcpwm_counter_free(self->counter_num, MP_OBJ_FROM_PTR(self)); + counter_obj[id] = NULL; + nlr_jump(nl.ret_val); + } + + return MP_OBJ_FROM_PTR(self); +} + +// --------------------------------------------------------------------------- +// counter.init(src, *, edge=, direction=) +// --------------------------------------------------------------------------- + +// Python binding for Counter.init(...). +static mp_obj_t machine_counter_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + machine_counter_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_KW(machine_counter_init_obj, 1, machine_counter_init); + +// --------------------------------------------------------------------------- +// counter.deinit() +// --------------------------------------------------------------------------- + +// Python binding for Counter.deinit(). +static mp_obj_t machine_counter_deinit(mp_obj_t self_in) { + machine_counter_obj_t *self = MP_OBJ_TO_PTR(self_in); + + machine_counter_stop_hw(self); + machine_counter_restore_src_pin(self); + + self->configured = false; + self->offset = 0; + + machine_tcpwm_counter_free(self->counter_num, MP_OBJ_FROM_PTR(self)); + counter_obj[self->id] = NULL; + + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(machine_counter_deinit_obj, machine_counter_deinit); + +// --------------------------------------------------------------------------- +// counter.value([value]) +// --------------------------------------------------------------------------- + +// Return current count, or reset logical origin when a value is provided. +static mp_obj_t machine_counter_value(size_t n_args, const mp_obj_t *args) { + machine_counter_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + if (!self->configured) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("not initialised")); + } + + uint32_t raw = Cy_TCPWM_Counter_GetCounter(TCPWM0, self->counter_num); + mp_int_t signed_count = (self->direction == COUNTER_DIR_DOWN) ? -(mp_int_t)raw : (mp_int_t)raw; + mp_int_t result = self->offset + signed_count; + + if (n_args == 2) { + self->offset = mp_obj_get_int(args[1]); + Cy_TCPWM_Counter_SetCounter(TCPWM0, self->counter_num, 0); + } + + return mp_obj_new_int(result); +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_counter_value_obj, 1, 2, machine_counter_value); + +// Print user-facing representation as Counter(). +static void machine_counter_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_counter_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "Counter(%u)", (unsigned)self->id); +} + +static const mp_rom_map_elem_t machine_counter_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_counter_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_counter_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_counter_value_obj) }, + + { MP_ROM_QSTR(MP_QSTR_RISING), MP_ROM_INT(COUNTER_EDGE_RISING) }, + { MP_ROM_QSTR(MP_QSTR_FALLING), MP_ROM_INT(COUNTER_EDGE_FALLING) }, + { MP_ROM_QSTR(MP_QSTR_UP), MP_ROM_INT(COUNTER_DIR_UP) }, + { MP_ROM_QSTR(MP_QSTR_DOWN), MP_ROM_INT(COUNTER_DIR_DOWN) }, +}; +static MP_DEFINE_CONST_DICT(machine_counter_locals_dict, machine_counter_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_counter_type, + MP_QSTR_Counter, + MP_TYPE_FLAG_NONE, + make_new, machine_counter_make_new, + print, machine_counter_print, + locals_dict, &machine_counter_locals_dict + ); diff --git a/ports/psoc-edge/machine_timer.c b/ports/psoc-edge/machine_timer.c index 524ec1422c1..de30e1ecf90 100644 --- a/ports/psoc-edge/machine_timer.c +++ b/ports/psoc-edge/machine_timer.c @@ -83,21 +83,21 @@ const mp_obj_type_t machine_timer_type; // forward declaration // --------------------------------------------------------------------------- // Per-ID hardware mapping — generated from the board AF configuration. -// Macro is defined in pins_af.h as MICROPY_PY_MACHINE_TIMER_HW_MAP(X). -// Each row: X(timer_id, tcpwm_counter_num, irq) +// Macro is defined in pins_af.h as MICROPY_PY_MACHINE_TCPWM_MAP(X). +// Each row: X(timer_id, tcpwm_counter_num, irq, pclk_dst, trig_out_enum) // --------------------------------------------------------------------------- -#define TIMER_HW_ENTRY(id, counter, irq, pclk) counter, +#define TIMER_HW_ENTRY(id, counter, irq, pclk, trig) counter, static const uint32_t timer_hw[MACHINE_TIMER_NUM_INSTANCES] = { - MICROPY_PY_MACHINE_TCPWM_HW_MAP(TIMER_HW_ENTRY) + MICROPY_PY_MACHINE_TCPWM_MAP(TIMER_HW_ENTRY) }; #undef TIMER_HW_ENTRY -#define TIMER_IRQ_CASE(id, counter, irq, pclk) case counter: \ +#define TIMER_IRQ_CASE(id, counter, irq, pclk, trig) case counter: \ return irq; static IRQn_Type machine_timer_counter_irq(uint32_t counter_num) { switch (counter_num) { - MICROPY_PY_MACHINE_TCPWM_HW_MAP(TIMER_IRQ_CASE) + MICROPY_PY_MACHINE_TCPWM_MAP(TIMER_IRQ_CASE) default: mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Timer counter %lu does not have an IRQ mapping"), @@ -153,19 +153,19 @@ static void machine_timer_isr(machine_timer_obj_t *self) { } // Generate one IRQ handler per timer id for direct dispatch without scanning. -#define TIMER_IRQ_HANDLER_DECL(id, counter, irq, pclk) \ +#define TIMER_IRQ_HANDLER_DECL(id, counter, irq, pclk, trig) \ static void machine_timer_irq_handler_##id(void) { \ machine_timer_obj_t *self = timer_obj[id]; \ if (self != NULL) { \ machine_timer_isr(self); \ } \ } -MICROPY_PY_MACHINE_TCPWM_HW_MAP(TIMER_IRQ_HANDLER_DECL) +MICROPY_PY_MACHINE_TCPWM_MAP(TIMER_IRQ_HANDLER_DECL) #undef TIMER_IRQ_HANDLER_DECL -#define TIMER_IRQ_HANDLER_ENTRY(id, counter, irq, pclk) machine_timer_irq_handler_##id, +#define TIMER_IRQ_HANDLER_ENTRY(id, counter, irq, pclk, trig) machine_timer_irq_handler_##id, static const cy_israddress machine_timer_irq_handlers[MACHINE_TIMER_NUM_INSTANCES] = { - MICROPY_PY_MACHINE_TCPWM_HW_MAP(TIMER_IRQ_HANDLER_ENTRY) + MICROPY_PY_MACHINE_TCPWM_MAP(TIMER_IRQ_HANDLER_ENTRY) }; #undef TIMER_IRQ_HANDLER_ENTRY diff --git a/ports/psoc-edge/modmachine.c b/ports/psoc-edge/modmachine.c index 47868f3523c..0c0c1b9761f 100644 --- a/ports/psoc-edge/modmachine.c +++ b/ports/psoc-edge/modmachine.c @@ -176,6 +176,7 @@ static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) { { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, \ { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, \ { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) }, \ + { MP_ROM_QSTR(MP_QSTR_Counter), MP_ROM_PTR(&machine_counter_type) }, \ { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, \ MICROPY_PY_MACHINE_SPITARGET_GLOBAL \ /* Reset cause constants */ \ diff --git a/ports/psoc-edge/modmachine.h b/ports/psoc-edge/modmachine.h index 51bab5f2c24..d32d9df878e 100644 --- a/ports/psoc-edge/modmachine.h +++ b/ports/psoc-edge/modmachine.h @@ -65,6 +65,7 @@ extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_ipc_type; extern const mp_obj_type_t machine_pwm_type; extern const mp_obj_type_t machine_timer_type; +extern const mp_obj_type_t machine_counter_type; extern const mp_obj_type_t machine_wdt_type; #if MICROPY_PY_MACHINE_SPI_TARGET diff --git a/ports/psoc-edge/tcpwm.c b/ports/psoc-edge/tcpwm.c index e62d3f23400..34c29cb9049 100644 --- a/ports/psoc-edge/tcpwm.c +++ b/ports/psoc-edge/tcpwm.c @@ -79,10 +79,10 @@ void machine_tcpwm_counter_free(uint32_t counter_num, mp_obj_t owner) { } en_clk_dst_t machine_tcpwm_counter_pclk(uint32_t counter_num) { -#define TCPWM_PCLK_CASE(id, counter, irq, pclk_dst) case counter: \ +#define TCPWM_PCLK_CASE(id, counter, irq, pclk_dst, trig) case counter: \ return pclk_dst; switch (counter_num) { - MICROPY_PY_MACHINE_TCPWM_HW_MAP(TCPWM_PCLK_CASE) + MICROPY_PY_MACHINE_TCPWM_MAP(TCPWM_PCLK_CASE) default: mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("TCPWM0 counter %lu is not supported"), counter_num); From 13bf881ff832ec39ba8d5b8e2187ecfa1af2c43e Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Mon, 6 Jul 2026 05:14:35 +0000 Subject: [PATCH 02/16] psoc-edge: Fixed Trigger MUX value. Signed-off-by: NaveenChengappa-IFX --- ports/psoc-edge/machine_counter.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ports/psoc-edge/machine_counter.c b/ports/psoc-edge/machine_counter.c index c985f636a6c..d6c30a2ed8a 100644 --- a/ports/psoc-edge/machine_counter.c +++ b/ports/psoc-edge/machine_counter.c @@ -98,14 +98,14 @@ static const uint32_t counter_out_trig[MACHINE_COUNTER_NUM_INSTANCES] = { // This mapping is used to route a TCPWM0 counter's output trigger to a GPIO pin. // Each row: X(port_num, pin_num, in_trig_line, pin_hsiom) #define MACHINE_COUNTER_PIN_TRIGGER_MAP(X) \ - X(11, 0, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT0, P11_0_PERI0_TR_IO_INPUT0) \ - X(11, 1, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT1, P11_1_PERI0_TR_IO_INPUT1) \ - X(11, 2, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT2, P11_2_PERI0_TR_IO_INPUT2) \ - X(11, 3, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT3, P11_3_PERI0_TR_IO_INPUT3) \ - X(7, 5, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT4, P7_5_PERI0_TR_IO_INPUT4) \ - X(7, 6, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT5, P7_6_PERI0_TR_IO_INPUT5) \ - X(7, 7, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT6, P7_7_PERI0_TR_IO_INPUT6) \ - X(8, 0, PERI_0_TRIG_IN_MUX_0_PERI0_HSIOM_TR_OUT7, P8_0_PERI0_TR_IO_INPUT7) + X(11, 0, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT0, P11_0_PERI0_TR_IO_INPUT0) \ + X(11, 1, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT1, P11_1_PERI0_TR_IO_INPUT1) \ + X(11, 2, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT2, P11_2_PERI0_TR_IO_INPUT2) \ + X(11, 3, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT3, P11_3_PERI0_TR_IO_INPUT3) \ + X(7, 5, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT4, P7_5_PERI0_TR_IO_INPUT4) \ + X(7, 6, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT5, P7_6_PERI0_TR_IO_INPUT5) \ + X(7, 7, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT6, P7_7_PERI0_TR_IO_INPUT6) \ + X(8, 0, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT7, P8_0_PERI0_TR_IO_INPUT7) // --------------------------------------------------------------------------- // Helpers From abbe77b168f5d5ea474446ae7403524951036ec7 Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Mon, 6 Jul 2026 07:58:13 +0000 Subject: [PATCH 03/16] psoc-edge/boards: Unhide pin P11_1. Signed-off-by: NaveenChengappa-IFX --- ports/psoc-edge/boards/KIT_PSE84_AI/pins.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/psoc-edge/boards/KIT_PSE84_AI/pins.csv b/ports/psoc-edge/boards/KIT_PSE84_AI/pins.csv index 1cf8bbeb1d6..4d383f2ab58 100644 --- a/ports/psoc-edge/boards/KIT_PSE84_AI/pins.csv +++ b/ports/psoc-edge/boards/KIT_PSE84_AI/pins.csv @@ -120,7 +120,7 @@ USER_LED1,P10_7 ,-P11_0 # PCKL level translator -,-P11_1 +,P11_1 # Bluetooth ,-P11_2 From 8901d40f4774b62d000405daff11aab18811ac48 Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Mon, 6 Jul 2026 08:13:37 +0000 Subject: [PATCH 04/16] tests/ports/psoc-edge: Add test case for Counterbasics. Signed-off-by: NaveenChengappa-IFX --- .../psoc-edge/board_ext_hw/single/counter.py | 84 +++++++++++++++++++ .../board_ext_hw/single/counter.py.exp | 11 +++ 2 files changed, 95 insertions(+) create mode 100644 tests/ports/psoc-edge/board_ext_hw/single/counter.py create mode 100644 tests/ports/psoc-edge/board_ext_hw/single/counter.py.exp diff --git a/tests/ports/psoc-edge/board_ext_hw/single/counter.py b/tests/ports/psoc-edge/board_ext_hw/single/counter.py new file mode 100644 index 00000000000..3d5f4d222d0 --- /dev/null +++ b/tests/ports/psoc-edge/board_ext_hw/single/counter.py @@ -0,0 +1,84 @@ +from machine import Counter, Pin +import time + + +# Counter HIL test +""" +Setup: Connect P16_7 -> P11_1 +""" + +PIN_OUT = "P16_7" +PIN_IN = "P11_1" + + +# Helper function to generate pulses on a pin. +# n is the number of pulses, delay_us is the delay in microseconds between high and low states. +def pulse(pin, n, delay_us=100): + for _ in range(n): + pin(1) + time.sleep_us(delay_us) + pin(0) + time.sleep_us(delay_us) + + +# Helper function to check if a value is close to an expected value within a tolerance. +def close_to(value, expected, tol=1): + return (expected - tol) <= value <= (expected + tol) + + +def prime_counter(counter, pin): + # Warm up the route so the first measured edge is not lost. + pulse(pin, 1) + counter.value(0) + time.sleep_ms(2) + + +def expect_value_error(label, fn): + try: + fn() + except ValueError as e: + print(label, e) + + +print("*****Counter tests*****") + +pin_out = Pin(PIN_OUT, mode=Pin.OUT, value=0) + +# Positive tests: rising/falling/down and value reset. +c = Counter(0, src=Pin(PIN_IN), edge=Counter.RISING, direction=Counter.UP) +prime_counter(c, pin_out) +pulse(pin_out, 100) +print("rising_count:", close_to(c.value(), 100)) +c.deinit() + +c = Counter(1, src=Pin(PIN_IN), edge=Counter.FALLING, direction=Counter.UP) +prime_counter(c, pin_out) +pulse(pin_out, 80) +print("falling_count:", close_to(c.value(), 80)) +c.deinit() + +c = Counter(2, src=Pin(PIN_IN), edge=Counter.RISING, direction=Counter.DOWN) +prime_counter(c, pin_out) +pulse(pin_out, 60) +print("down_count:", close_to(c.value(), -60)) + +c.value(0) +time.sleep_ms(2) +pulse(pin_out, 10) +print("value_reset:", close_to(c.value(), -10)) +c.deinit() + +# Negative tests: boundary and input validation (ValueError paths). +expect_value_error("invalid_id_-1:", lambda: Counter(-1, src=Pin(PIN_IN))) +expect_value_error("invalid_id_32:", lambda: Counter(32, src=Pin(PIN_IN))) +expect_value_error("invalid_edge:", lambda: Counter(3, src=Pin(PIN_IN), edge=3)) +expect_value_error("invalid_direction:", lambda: Counter(4, src=Pin(PIN_IN), direction=3)) +expect_value_error("invalid_src_pin:", lambda: Counter(5, src=Pin(PIN_OUT))) + +# Test duplicate counter ID. The second instantiation should raise a ValueError. +c_dup = Counter(6, src=Pin(PIN_IN)) +try: + expect_value_error("duplicate_counter_id:", lambda: Counter(6, src=Pin(PIN_IN))) +finally: + c_dup.deinit() + pin_out(0) diff --git a/tests/ports/psoc-edge/board_ext_hw/single/counter.py.exp b/tests/ports/psoc-edge/board_ext_hw/single/counter.py.exp new file mode 100644 index 00000000000..11f5bb25dc5 --- /dev/null +++ b/tests/ports/psoc-edge/board_ext_hw/single/counter.py.exp @@ -0,0 +1,11 @@ +*****Counter tests***** +rising_count: True +falling_count: True +down_count: True +value_reset: True +invalid_id_-1: Counter id must be in range 0-31 +invalid_id_32: Counter id must be in range 0-31 +invalid_edge: invalid edge +invalid_direction: invalid direction +invalid_src_pin: Pin P16_7 does not support Counter input routing +duplicate_counter_id: Counter(6) already created. From 3d6128b8b4e7279201725f3e8d790e9fd8a250f1 Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Mon, 6 Jul 2026 08:27:52 +0000 Subject: [PATCH 05/16] tests/ports/psoc-edge: Add board setup changes. Signed-off-by: NaveenChengappa-IFX --- tests/ports/psoc-edge/board_ext_hw/hw-connections.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ports/psoc-edge/board_ext_hw/hw-connections.md b/tests/ports/psoc-edge/board_ext_hw/hw-connections.md index 4d7d824f370..338a4c564b2 100644 --- a/tests/ports/psoc-edge/board_ext_hw/hw-connections.md +++ b/tests/ports/psoc-edge/board_ext_hw/hw-connections.md @@ -8,6 +8,8 @@ | | | | | | UART | P17_0 | P17_1 | UART RX to TX | | | P16_5 | P16_6 | UART CTS to RTS | +| | | | | +| Counter | P16_7 | P11_1 | GPIO pulse output to Counter input | # Pin Connections for HIL Test Setup Between 2 Boards From 5a72b2770601a38c033b90b96bceec001e9b5fc2 Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Mon, 6 Jul 2026 09:15:56 +0000 Subject: [PATCH 06/16] tests/ports/psoc-edge: Add counter to yml scripts. Signed-off-by: NaveenChengappa-IFX --- tests/ports/psoc-edge/BLR-Runner-devs.yml | 1 + tests/ports/psoc-edge/test-plan.yml | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/tests/ports/psoc-edge/BLR-Runner-devs.yml b/tests/ports/psoc-edge/BLR-Runner-devs.yml index 2b06ef08c85..f55fc779880 100644 --- a/tests/ports/psoc-edge/BLR-Runner-devs.yml +++ b/tests/ports/psoc-edge/BLR-Runner-devs.yml @@ -4,6 +4,7 @@ - pin - i2c - pwm + - counter - wifi-idn-b0653ac13e11 - name: KIT_PSE84_AI diff --git a/tests/ports/psoc-edge/test-plan.yml b/tests/ports/psoc-edge/test-plan.yml index 55e9761ca8d..bfe224f383e 100644 --- a/tests/ports/psoc-edge/test-plan.yml +++ b/tests/ports/psoc-edge/test-plan.yml @@ -89,6 +89,14 @@ features: - pwm +- name: counter + test: + script: ports/psoc-edge/board_ext_hw/single/counter.py + device: + - board: KIT_PSE84_AI + features: + - counter + - name: network type: multi test: From b8d5d66dcc042801a0c3792e5eae8f13d57983bf Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Tue, 7 Jul 2026 11:17:40 +0000 Subject: [PATCH 07/16] psoc-edge: Fixed code for review suggestions. Signed-off-by: NaveenChengappa-IFX --- ports/psoc-edge/machine_counter.c | 57 ++++++++++++++++++++----------- ports/psoc-edge/modmachine.c | 1 + ports/psoc-edge/modmachine.h | 1 + 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/ports/psoc-edge/machine_counter.c b/ports/psoc-edge/machine_counter.c index d6c30a2ed8a..a175c1fbe68 100644 --- a/ports/psoc-edge/machine_counter.c +++ b/ports/psoc-edge/machine_counter.c @@ -66,13 +66,12 @@ typedef struct _machine_counter_obj_t { en_clk_dst_t pclk_dst; const machine_pin_obj_t *src_pin; en_hsiom_sel_t src_hsiom; + uint8_t edge; uint8_t direction; mp_int_t offset; bool configured; } machine_counter_obj_t; -const mp_obj_type_t machine_counter_type; - // One Counter object per hardware id. static machine_counter_obj_t *counter_obj[MACHINE_COUNTER_NUM_INSTANCES] = { NULL }; static bool machine_counter_clock_configured = false; @@ -133,19 +132,6 @@ static uint32_t machine_counter_period_max(uint32_t counter_num) { return (counter_num >= 256U) ? 0xFFFFU : UINT32_MAX; } -// Map a hardware counter number to its routed trigger output line. -static uint32_t machine_counter_out_trig_line(uint32_t counter_num) { - for (size_t i = 0; i < MP_ARRAY_SIZE(counter_hw); ++i) { - if (counter_hw[i] == counter_num) { - return counter_out_trig[i]; - } - } - - mp_raise_msg_varg(&mp_type_ValueError, - MP_ERROR_TEXT("Counter(%lu) trigger route not supported"), - (unsigned long)counter_num); -} - typedef struct _machine_counter_pin_trigger_map_t { uint8_t port; uint8_t pin; @@ -235,6 +221,10 @@ static void machine_counter_init_helper(machine_counter_obj_t *self, Cy_SysClk_PeriPclkAssignDivider(self->pclk_dst, CY_SYSCLK_DIV_16_BIT, CYBSP_GENERAL_PURPOSE_TIMER_CLK_DIV_NUM); + // Record the source pin now so rollback can restore it on any failure below. + self->src_pin = src_pin; + self->src_hsiom = hsiom; + // Put pin in input mode and switch HSIOM to trigger-output function. mp_hal_pin_input(src_pin); GPIO_PRT_Type *src_port = Cy_GPIO_PortToAddr(src_pin->port); @@ -242,7 +232,7 @@ static void machine_counter_init_helper(machine_counter_obj_t *self, Cy_GPIO_SetDrivemode(src_port, src_pin->pin, CY_GPIO_DM_HIGHZ); // Connect selected pin trigger line to this counter's dedicated trigger input. - uint32_t out_trig = machine_counter_out_trig_line(self->counter_num); + uint32_t out_trig = counter_out_trig[self->id]; cy_en_trigmux_status_t mux_rslt = Cy_TrigMux_Connect(in_trig, out_trig, false, TRIGGER_TYPE_LEVEL); if (mux_rslt != CY_TRIGMUX_SUCCESS) { // Roll back pin mux state if trigger connect fails. @@ -298,6 +288,7 @@ static void machine_counter_init_helper(machine_counter_obj_t *self, self->src_pin = src_pin; self->src_hsiom = hsiom; + self->edge = edge; self->direction = direction; self->offset = 0; self->configured = true; @@ -333,6 +324,7 @@ static mp_obj_t machine_counter_make_new(const mp_obj_type_t *type, self->pclk_dst = machine_tcpwm_counter_pclk(self->counter_num); self->src_pin = NULL; self->src_hsiom = (en_hsiom_sel_t)0; + self->edge = COUNTER_EDGE_RISING; self->direction = COUNTER_DIR_UP; self->offset = 0; self->configured = false; @@ -387,6 +379,16 @@ static mp_obj_t machine_counter_deinit(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_1(machine_counter_deinit_obj, machine_counter_deinit); +// Module-level lifecycle called from machine_deinit(). +void machine_counter_deinit_all(void) { + for (uint8_t i = 0; i < MACHINE_COUNTER_NUM_INSTANCES; i++) { + machine_counter_obj_t *self = counter_obj[i]; + if (self != NULL) { + machine_counter_deinit(MP_OBJ_FROM_PTR(self)); + } + } +} + // --------------------------------------------------------------------------- // counter.value([value]) // --------------------------------------------------------------------------- @@ -399,23 +401,38 @@ static mp_obj_t machine_counter_value(size_t n_args, const mp_obj_t *args) { mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("not initialised")); } + if (n_args == 2) { + // Freeze counting during read/reset so no new edges arrive in this window. + Cy_TCPWM_Counter_Disable(TCPWM0, self->counter_num); + } uint32_t raw = Cy_TCPWM_Counter_GetCounter(TCPWM0, self->counter_num); - mp_int_t signed_count = (self->direction == COUNTER_DIR_DOWN) ? -(mp_int_t)raw : (mp_int_t)raw; - mp_int_t result = self->offset + signed_count; + long long signed_count = (self->direction == COUNTER_DIR_DOWN) ? -(long long)raw : (long long)raw; + long long result = (long long)self->offset + signed_count; if (n_args == 2) { self->offset = mp_obj_get_int(args[1]); Cy_TCPWM_Counter_SetCounter(TCPWM0, self->counter_num, 0); + Cy_TCPWM_Counter_Enable(TCPWM0, self->counter_num); + Cy_TCPWM_TriggerReloadOrIndex_Single(TCPWM0, self->counter_num); } - return mp_obj_new_int(result); + return mp_obj_new_int_from_ll(result); } static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_counter_value_obj, 1, 2, machine_counter_value); // Print user-facing representation as Counter(). static void machine_counter_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_counter_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "Counter(%u)", (unsigned)self->id); + const char *edge_str = (self->edge == COUNTER_EDGE_FALLING) ? "FALLING" : "RISING"; + const char *dir_str = (self->direction == COUNTER_DIR_DOWN) ? "DOWN" : "UP"; + + if (self->src_pin == NULL) { + mp_printf(print, "Counter(id=%u, src=None, edge=Counter.%s, direction=Counter.%s)", + (unsigned)self->id, edge_str, dir_str); + } else { + mp_printf(print, "Counter(id=%u, src=%q, edge=Counter.%s, direction=Counter.%s)", + (unsigned)self->id, self->src_pin->name, edge_str, dir_str); + } } static const mp_rom_map_elem_t machine_counter_locals_dict_table[] = { diff --git a/ports/psoc-edge/modmachine.c b/ports/psoc-edge/modmachine.c index 0c0c1b9761f..f3a33e8d1f9 100644 --- a/ports/psoc-edge/modmachine.c +++ b/ports/psoc-edge/modmachine.c @@ -99,6 +99,7 @@ void machine_deinit(void) { #endif machine_pdm_pcm_deinit_all(); machine_ipc_deinit_all(); + machine_counter_deinit_all(); machine_timer_deinit_all(); machine_wdt_deinit(); } diff --git a/ports/psoc-edge/modmachine.h b/ports/psoc-edge/modmachine.h index d32d9df878e..96a52719894 100644 --- a/ports/psoc-edge/modmachine.h +++ b/ports/psoc-edge/modmachine.h @@ -46,6 +46,7 @@ void machine_spi_target_deinit_all(void); void machine_pdm_pcm_deinit_all(void); void machine_ipc_deinit_all(void); void machine_timer_deinit_all(void); +void machine_counter_deinit_all(void); void machine_wdt_deinit(void); enum clock_freq_type { From 5d87c19b80dfe63ecd71e16288da089e4f7c2267 Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Tue, 7 Jul 2026 11:48:54 +0000 Subject: [PATCH 08/16] psoc-edge: Implemented X macro for counter pin mapping. Signed-off-by: NaveenChengappa-IFX --- ports/psoc-edge/boards/make-pins.py | 54 +++++++++++++++++++++++++++++ ports/psoc-edge/machine_counter.c | 11 ++---- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/ports/psoc-edge/boards/make-pins.py b/ports/psoc-edge/boards/make-pins.py index 5a6a970e77e..9098c8a295e 100644 --- a/ports/psoc-edge/boards/make-pins.py +++ b/ports/psoc-edge/boards/make-pins.py @@ -55,6 +55,8 @@ def __init__(self, cpu_pin_name): # List of PinAF instances self._afs = [] + # Optional Counter source routing metadata parsed from PERI0_TR_IO_INPUTx AFs. + self._counter_src = None def definition(self): return f"PIN({self._port}, {self._pin}, pin_{self.name()}_af)" @@ -137,6 +139,17 @@ def add_af(self, af_idx, af_name, af): if af_idx > af_act_max_idx + af_ds_num: return + # Counter source pin routing uses PERI0 trigger-input AFs. + # Example AF token: PERI0_TR_IO_INPUT1 + if af.startswith("PERI0_TR_IO_INPUT"): + input_idx = af[len("PERI0_TR_IO_INPUT") :] + if input_idx.isdigit(): + self._counter_src = { + "in_trig": f"PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT{input_idx}", + "hsiom": f"{self.name()}_{af}", + } + return + if af_idx <= af_act_max_idx: if af_name != "ACT_{:d}".format(af_idx): raise boardgen.PinGeneratorError( @@ -221,6 +234,8 @@ def __init__(self): self._pwm_pin_count = 0 # unique exposed pins with a TCPWM LINE AF self._tcpwm_counter_max = 0 # highest counter number seen across all LINE AFs self._tcpwm_counters = [] # sorted unique TCPWM counter IDs seen in LINE AFs + # Counter source routing entries filtered by unhidden CPU pins from pins.csv. + self._counter_src_entries = [] # Collect all unhidden ports from the available # pins. @@ -280,6 +295,21 @@ def add_tcpwm(self): self._tcpwm_counters = sorted(seen_counters) self._pwm_pin_count = len(seen_counters) + # Collect Counter source routing entries from unhidden pins that expose + # PERI0_TR_IO_INPUTx AFs. + def add_counter_src(self): + entries = [] + for pin in self.available_pins(exclude_hidden=True): + if pin._counter_src is None: + continue + entries.append( + (pin._port, pin._pin, pin._counter_src["in_trig"], pin._counter_src["hsiom"]) + ) + + # Keep output deterministic by sorting on port/pin. + entries.sort(key=lambda x: (x[0], x[1])) + self._counter_src_entries = entries + # Override the parse_board_csv to add # the unhidden ports after parsing the board CSV. def parse_board_csv(self, filename): @@ -287,6 +317,7 @@ def parse_board_csv(self, filename): self.add_ports() self.add_scbs() self.add_tcpwm() + self.add_counter_src() # Override the default implementation just to change the default arguments # (extra header row, skip first column). @@ -445,6 +476,29 @@ def print_af_header(self, out_af_header): self.print_scb_defines(out_af_header) self.print_tcpwm_defines(out_af_header) self.print_tcpwm_hw_map(out_af_header) + self.print_counter_src_map(out_af_header) + + def print_counter_src_map(self, out_header): + print(file=out_header) + print( + "// Counter source routing map filtered to unhidden pins from board pins.csv.", + file=out_header, + ) + print( + "// Each row: X(port_num, pin_num, in_trig_line, pin_hsiom)", + file=out_header, + ) + print("#define MICROPY_PY_MACHINE_COUNTER_SRC_PIN_MAP(X) \\", file=out_header) + + if not self._counter_src_entries: + print(" /* no available counter source pins */", file=out_header) + print(file=out_header) + return + + for i, (port, pin, in_trig, hsiom) in enumerate(self._counter_src_entries): + suffix = " \\" if i < len(self._counter_src_entries) - 1 else "" + print(f" X({port}, {pin}, {in_trig}, {hsiom}){suffix}", file=out_header) + print(file=out_header) # Add additional header file for AF defines and constants def extra_args(self, parser): diff --git a/ports/psoc-edge/machine_counter.c b/ports/psoc-edge/machine_counter.c index a175c1fbe68..c96abef434a 100644 --- a/ports/psoc-edge/machine_counter.c +++ b/ports/psoc-edge/machine_counter.c @@ -94,17 +94,10 @@ static const uint32_t counter_out_trig[MACHINE_COUNTER_NUM_INSTANCES] = { }; #undef COUNTER_OUT_TRIG_ENTRY -// This mapping is used to route a TCPWM0 counter's output trigger to a GPIO pin. +// Source pin map is generated from AF data and filtered by unhidden pins in pins.csv. // Each row: X(port_num, pin_num, in_trig_line, pin_hsiom) #define MACHINE_COUNTER_PIN_TRIGGER_MAP(X) \ - X(11, 0, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT0, P11_0_PERI0_TR_IO_INPUT0) \ - X(11, 1, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT1, P11_1_PERI0_TR_IO_INPUT1) \ - X(11, 2, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT2, P11_2_PERI0_TR_IO_INPUT2) \ - X(11, 3, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT3, P11_3_PERI0_TR_IO_INPUT3) \ - X(7, 5, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT4, P7_5_PERI0_TR_IO_INPUT4) \ - X(7, 6, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT5, P7_6_PERI0_TR_IO_INPUT5) \ - X(7, 7, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT6, P7_7_PERI0_TR_IO_INPUT6) \ - X(8, 0, PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT7, P8_0_PERI0_TR_IO_INPUT7) + MICROPY_PY_MACHINE_COUNTER_SRC_PIN_MAP(X) // --------------------------------------------------------------------------- // Helpers From 6831a32e1c8e34c564b88eec94c3e2d78ff2e1eb Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Wed, 8 Jul 2026 04:08:11 +0000 Subject: [PATCH 09/16] psoc-edge/machine_counter: Reuse init failures with helper function. Signed-off-by: NaveenChengappa-IFX --- ports/psoc-edge/machine_counter.c | 39 +++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/ports/psoc-edge/machine_counter.c b/ports/psoc-edge/machine_counter.c index c96abef434a..cc3e889ee5d 100644 --- a/ports/psoc-edge/machine_counter.c +++ b/ports/psoc-edge/machine_counter.c @@ -171,8 +171,19 @@ static void machine_counter_stop_hw(machine_counter_obj_t *self) { Cy_TCPWM_Counter_Disable(TCPWM0, self->counter_num); } +// Roll back Counter state and release channel ownership after init failure. +static void machine_counter_init_fail_cleanup(machine_counter_obj_t *self) { + machine_counter_stop_hw(self); + machine_counter_restore_src_pin(self); + self->configured = false; + self->offset = 0; + + machine_tcpwm_counter_free(self->counter_num, MP_OBJ_FROM_PTR(self)); + counter_obj[self->id] = NULL; +} + // Parse init args and configure routing, trigger mux, and TCPWM hardware. -static void machine_counter_init_helper(machine_counter_obj_t *self, +static void machine_counter_init_helper_impl(machine_counter_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_src, ARG_edge, ARG_direction }; @@ -287,6 +298,20 @@ static void machine_counter_init_helper(machine_counter_obj_t *self, self->configured = true; } +// Wrapper that enforces identical rollback semantics for constructor and init(). +static void machine_counter_init_helper(machine_counter_obj_t *self, + size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + nlr_buf_t nl; + if (nlr_push(&nl) == 0) { + machine_counter_init_helper_impl(self, n_args, pos_args, kw_args); + nlr_pop(); + } else { + machine_counter_init_fail_cleanup(self); + nlr_jump(nl.ret_val); + } +} + // --------------------------------------------------------------------------- // Constructor: Counter(id, ...) // --------------------------------------------------------------------------- @@ -325,18 +350,18 @@ static mp_obj_t machine_counter_make_new(const mp_obj_type_t *type, nlr_buf_t nl; if (nlr_push(&nl) == 0) { machine_tcpwm_counter_alloc(self->counter_num, MP_OBJ_FROM_PTR(self)); - if (n_args > 1 || n_kw > 0) { - mp_map_t kw_map; - mp_map_init_fixed_table(&kw_map, n_kw, args + n_args); - machine_counter_init_helper(self, n_args - 1, args + 1, &kw_map); - } nlr_pop(); } else { - machine_tcpwm_counter_free(self->counter_num, MP_OBJ_FROM_PTR(self)); counter_obj[id] = NULL; nlr_jump(nl.ret_val); } + if (n_args > 1 || n_kw > 0) { + mp_map_t kw_map; + mp_map_init_fixed_table(&kw_map, n_kw, args + n_args); + machine_counter_init_helper(self, n_args - 1, args + 1, &kw_map); + } + return MP_OBJ_FROM_PTR(self); } From 90cea1bafd50f76dc1c34d93f07321c007b4b2af Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Wed, 8 Jul 2026 05:33:33 +0000 Subject: [PATCH 10/16] psoc-edge/machine_counter: Introduce PERI_TR_IO_INPUT in AF. Signed-off-by: NaveenChengappa-IFX --- ports/psoc-edge/boards/make-pins.py | 18 +++++++++++++++ ports/psoc-edge/machine_counter.c | 34 +++++++++++++++++++---------- ports/psoc-edge/machine_pin_af.c | 1 + ports/psoc-edge/machine_pin_af.h | 2 ++ 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/ports/psoc-edge/boards/make-pins.py b/ports/psoc-edge/boards/make-pins.py index 9098c8a295e..1fd99a82704 100644 --- a/ports/psoc-edge/boards/make-pins.py +++ b/ports/psoc-edge/boards/make-pins.py @@ -13,6 +13,7 @@ "SPI": ["CLK", "MOSI", "MISO", "SELECT0", "SELECT1"], "PDM": ["CLK", "DATA"], "TCPWM": ["LINE"], + "PERI_TR_IO": ["INPUT"], # TODO: Other active functionalities that we need to figure out: # - TDM # - SMIF @@ -130,6 +131,22 @@ def add_af_tcpwm(self, af_idx, af_name, af): pin_af = PinAf(af_idx, af_fn, af_unit, af_signal, af_supported, af_name, af_ptr) self._afs.append(pin_af) + def add_af_peri_tr_io_input(self, af_idx, af_name, af): + # Map PERI0_TR_IO_INPUTx to regular pin AF objects so consumers can + # validate capability through the shared AF metadata path. + input_idx = af[len("PERI0_TR_IO_INPUT") :] + if not input_idx.isdigit(): + return + + af_ptr = "NULL" + af_fn = "PERI_TR_IO" + af_signal = "INPUT" + af_unit = input_idx + af_supported = af_fn in SUPPORTED_AF and af_signal in SUPPORTED_AF[af_fn] + + pin_af = PinAf(af_idx, af_fn, af_unit, af_signal, af_supported, af_name, af_ptr) + self._afs.append(pin_af) + def add_af(self, af_idx, af_name, af): # The AF index matches the column index for the ACTx functions 0-15 # while for DSx functions the columns 16-19 are mapped to DS2-DS5 respectively. @@ -142,6 +159,7 @@ def add_af(self, af_idx, af_name, af): # Counter source pin routing uses PERI0 trigger-input AFs. # Example AF token: PERI0_TR_IO_INPUT1 if af.startswith("PERI0_TR_IO_INPUT"): + self.add_af_peri_tr_io_input(af_idx, af_name, af) input_idx = af[len("PERI0_TR_IO_INPUT") :] if input_idx.isdigit(): self._counter_src = { diff --git a/ports/psoc-edge/machine_counter.c b/ports/psoc-edge/machine_counter.c index cc3e889ee5d..8d0a5bddc28 100644 --- a/ports/psoc-edge/machine_counter.c +++ b/ports/psoc-edge/machine_counter.c @@ -129,25 +129,22 @@ typedef struct _machine_counter_pin_trigger_map_t { uint8_t port; uint8_t pin; uint32_t in_trig; - en_hsiom_sel_t hsiom; } machine_counter_pin_trigger_map_t; // Expands pin mapping rows into lookup table entries. #define PIN_TRIG_ENTRY(port_num, pin_num, in_trig_line, pin_hsiom) \ - { (uint8_t)(port_num), (uint8_t)(pin_num), (in_trig_line), (pin_hsiom) }, + { (uint8_t)(port_num), (uint8_t)(pin_num), (in_trig_line) }, static const machine_counter_pin_trigger_map_t machine_counter_pin_trigger_map[] = { MACHINE_COUNTER_PIN_TRIGGER_MAP(PIN_TRIG_ENTRY) }; #undef PIN_TRIG_ENTRY -// Resolve a source pin to its trigger input line and HSIOM function. -static bool machine_counter_pin_to_trigger(const machine_pin_obj_t *pin, - uint32_t *in_trig, en_hsiom_sel_t *hsiom) { +// Resolve a source pin to its trigger input line. +static bool machine_counter_pin_to_trigger(const machine_pin_obj_t *pin, uint32_t *in_trig) { for (size_t i = 0; i < MP_ARRAY_SIZE(machine_counter_pin_trigger_map); ++i) { const machine_counter_pin_trigger_map_t *entry = &machine_counter_pin_trigger_map[i]; if (pin->port == entry->port && pin->pin == entry->pin) { *in_trig = entry->in_trig; - *hsiom = entry->hsiom; return true; } } @@ -207,15 +204,30 @@ static void machine_counter_init_helper_impl(machine_counter_obj_t *self, mp_raise_ValueError(MP_ERROR_TEXT("invalid direction")); } - // Resolve source pin object and fetch its trigger-routing metadata. - const machine_pin_obj_t *src_pin = machine_pin_get_pin_obj(args[ARG_src].u_obj); - uint32_t in_trig = 0; - en_hsiom_sel_t hsiom = (en_hsiom_sel_t)0; - if (!machine_counter_pin_to_trigger(src_pin, &in_trig, &hsiom)) { + // Resolve source pin object and validate it exposes Counter input AF. + const machine_pin_obj_t *src_pin = mp_hal_get_pin_obj(args[ARG_src].u_obj); + const machine_pin_af_obj_t *src_pin_af = NULL; + for (size_t i = 0; i < src_pin->af_num; ++i) { + const machine_pin_af_obj_t *af = &src_pin->af[i]; + if (af->signal == MACHINE_PIN_AF_SIGNAL_PERI_TR_IO_INPUT) { + src_pin_af = af; + break; + } + } + if (src_pin_af == NULL) { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Pin %q does not support Counter input routing"), src_pin->name); } + // Fetch trigger-routing metadata for the selected source pin. + uint32_t in_trig = 0; + if (!machine_counter_pin_to_trigger(src_pin, &in_trig)) { + mp_raise_msg_varg(&mp_type_ValueError, + MP_ERROR_TEXT("Pin %q is missing Counter input route data"), src_pin->name); + } + + en_hsiom_sel_t hsiom = src_pin_af->idx; + // Tear down any previous run before programming new pin routing. machine_counter_stop_hw(self); machine_counter_restore_src_pin(self); diff --git a/ports/psoc-edge/machine_pin_af.c b/ports/psoc-edge/machine_pin_af.c index 1e59431e17c..b233ad02cdc 100644 --- a/ports/psoc-edge/machine_pin_af.c +++ b/ports/psoc-edge/machine_pin_af.c @@ -45,6 +45,7 @@ const char *machine_pin_af_signal_str[] = { [MACHINE_PIN_AF_SIGNAL_PDM_DATA] = "PDM_DATA", [MACHINE_PIN_AF_SIGNAL_TCPWM_LINE] = "TCPWM_LINE", + [MACHINE_PIN_AF_SIGNAL_PERI_TR_IO_INPUT] = "PERI_TR_IO_INPUT", /* TODO: Add additional types */ }; diff --git a/ports/psoc-edge/machine_pin_af.h b/ports/psoc-edge/machine_pin_af.h index e3e078d6dfa..5f7abd74879 100644 --- a/ports/psoc-edge/machine_pin_af.h +++ b/ports/psoc-edge/machine_pin_af.h @@ -37,6 +37,7 @@ typedef enum { MACHINE_PIN_AF_FN_PDM, MACHINE_PIN_AF_FN_TCPWM, + MACHINE_PIN_AF_FN_PERI_TR_IO, /* TODO: Add additional functionalities */ MACHINE_PIN_AF_FN_NONE = 0xFF @@ -63,6 +64,7 @@ typedef enum { MACHINE_PIN_AF_SIGNAL_PDM_DATA, MACHINE_PIN_AF_SIGNAL_TCPWM_LINE, + MACHINE_PIN_AF_SIGNAL_PERI_TR_IO_INPUT, /* TODO: Add additional types */ } machine_pin_af_signal_t; From b3bfbff9f43063448dfcaac20cf29da1f52ec95d Mon Sep 17 00:00:00 2001 From: NaveenChengappa-IFX Date: Wed, 8 Jul 2026 05:58:34 +0000 Subject: [PATCH 11/16] psoc-edge: Counter trigger routes through AF. Signed-off-by: NaveenChengappa-IFX --- ports/psoc-edge/boards/make-pins.py | 49 +++++++++++++++-------------- ports/psoc-edge/machine_counter.c | 46 ++++++++++++--------------- 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/ports/psoc-edge/boards/make-pins.py b/ports/psoc-edge/boards/make-pins.py index 1fd99a82704..4582de5270c 100644 --- a/ports/psoc-edge/boards/make-pins.py +++ b/ports/psoc-edge/boards/make-pins.py @@ -163,6 +163,7 @@ def add_af(self, af_idx, af_name, af): input_idx = af[len("PERI0_TR_IO_INPUT") :] if input_idx.isdigit(): self._counter_src = { + "input_idx": int(input_idx), "in_trig": f"PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT{input_idx}", "hsiom": f"{self.name()}_{af}", } @@ -252,8 +253,8 @@ def __init__(self): self._pwm_pin_count = 0 # unique exposed pins with a TCPWM LINE AF self._tcpwm_counter_max = 0 # highest counter number seen across all LINE AFs self._tcpwm_counters = [] # sorted unique TCPWM counter IDs seen in LINE AFs - # Counter source routing entries filtered by unhidden CPU pins from pins.csv. - self._counter_src_entries = [] + # Counter input trigger entries indexed by PERI0_TR_IO_INPUT unit. + self._counter_input_entries = [] # Collect all unhidden ports from the available # pins. @@ -313,20 +314,22 @@ def add_tcpwm(self): self._tcpwm_counters = sorted(seen_counters) self._pwm_pin_count = len(seen_counters) - # Collect Counter source routing entries from unhidden pins that expose - # PERI0_TR_IO_INPUTx AFs. - def add_counter_src(self): - entries = [] + # Collect unique Counter trigger routes from PERI0_TR_IO_INPUTx units. + def add_counter_input_routes(self): + input_routes = {} for pin in self.available_pins(exclude_hidden=True): if pin._counter_src is None: continue - entries.append( - (pin._port, pin._pin, pin._counter_src["in_trig"], pin._counter_src["hsiom"]) - ) - # Keep output deterministic by sorting on port/pin. - entries.sort(key=lambda x: (x[0], x[1])) - self._counter_src_entries = entries + input_idx = pin._counter_src["input_idx"] + in_trig = pin._counter_src["in_trig"] + if input_idx in input_routes and input_routes[input_idx] != in_trig: + raise boardgen.PinGeneratorError( + f"Conflicting Counter route for PERI0_TR_IO_INPUT{input_idx}." + ) + input_routes[input_idx] = in_trig + + self._counter_input_entries = sorted(input_routes.items()) # Override the parse_board_csv to add # the unhidden ports after parsing the board CSV. @@ -335,7 +338,7 @@ def parse_board_csv(self, filename): self.add_ports() self.add_scbs() self.add_tcpwm() - self.add_counter_src() + self.add_counter_input_routes() # Override the default implementation just to change the default arguments # (extra header row, skip first column). @@ -494,28 +497,28 @@ def print_af_header(self, out_af_header): self.print_scb_defines(out_af_header) self.print_tcpwm_defines(out_af_header) self.print_tcpwm_hw_map(out_af_header) - self.print_counter_src_map(out_af_header) + self.print_counter_input_map(out_af_header) - def print_counter_src_map(self, out_header): + def print_counter_input_map(self, out_header): print(file=out_header) print( - "// Counter source routing map filtered to unhidden pins from board pins.csv.", + "// Counter trigger-input map indexed by PERI0_TR_IO_INPUT unit.", file=out_header, ) print( - "// Each row: X(port_num, pin_num, in_trig_line, pin_hsiom)", + "// Each row: X(input_idx, in_trig_line)", file=out_header, ) - print("#define MICROPY_PY_MACHINE_COUNTER_SRC_PIN_MAP(X) \\", file=out_header) + print("#define MICROPY_PY_MACHINE_COUNTER_IN_TRIG_MAP(X) \\", file=out_header) - if not self._counter_src_entries: - print(" /* no available counter source pins */", file=out_header) + if not self._counter_input_entries: + print(" /* no available counter input routes */", file=out_header) print(file=out_header) return - for i, (port, pin, in_trig, hsiom) in enumerate(self._counter_src_entries): - suffix = " \\" if i < len(self._counter_src_entries) - 1 else "" - print(f" X({port}, {pin}, {in_trig}, {hsiom}){suffix}", file=out_header) + for i, (input_idx, in_trig) in enumerate(self._counter_input_entries): + suffix = " \\" if i < len(self._counter_input_entries) - 1 else "" + print(f" X({input_idx}, {in_trig}){suffix}", file=out_header) print(file=out_header) # Add additional header file for AF defines and constants diff --git a/ports/psoc-edge/machine_counter.c b/ports/psoc-edge/machine_counter.c index 8d0a5bddc28..fff398f4103 100644 --- a/ports/psoc-edge/machine_counter.c +++ b/ports/psoc-edge/machine_counter.c @@ -65,7 +65,6 @@ typedef struct _machine_counter_obj_t { uint32_t counter_num; en_clk_dst_t pclk_dst; const machine_pin_obj_t *src_pin; - en_hsiom_sel_t src_hsiom; uint8_t edge; uint8_t direction; mp_int_t offset; @@ -94,10 +93,10 @@ static const uint32_t counter_out_trig[MACHINE_COUNTER_NUM_INSTANCES] = { }; #undef COUNTER_OUT_TRIG_ENTRY -// Source pin map is generated from AF data and filtered by unhidden pins in pins.csv. -// Each row: X(port_num, pin_num, in_trig_line, pin_hsiom) -#define MACHINE_COUNTER_PIN_TRIGGER_MAP(X) \ - MICROPY_PY_MACHINE_COUNTER_SRC_PIN_MAP(X) +// Counter trigger-input map generated from AF data. +// Each row: X(input_idx, in_trig_line) +#define MACHINE_COUNTER_IN_TRIG_MAP(X) \ + MICROPY_PY_MACHINE_COUNTER_IN_TRIG_MAP(X) // --------------------------------------------------------------------------- // Helpers @@ -125,25 +124,24 @@ static uint32_t machine_counter_period_max(uint32_t counter_num) { return (counter_num >= 256U) ? 0xFFFFU : UINT32_MAX; } -typedef struct _machine_counter_pin_trigger_map_t { - uint8_t port; - uint8_t pin; +typedef struct _machine_counter_in_trig_map_t { + uint16_t input_idx; uint32_t in_trig; -} machine_counter_pin_trigger_map_t; +} machine_counter_in_trig_map_t; -// Expands pin mapping rows into lookup table entries. -#define PIN_TRIG_ENTRY(port_num, pin_num, in_trig_line, pin_hsiom) \ - { (uint8_t)(port_num), (uint8_t)(pin_num), (in_trig_line) }, -static const machine_counter_pin_trigger_map_t machine_counter_pin_trigger_map[] = { - MACHINE_COUNTER_PIN_TRIGGER_MAP(PIN_TRIG_ENTRY) +// Expands input-route rows into lookup table entries. +#define IN_TRIG_ENTRY(input_idx, in_trig_line) \ + { (uint16_t)(input_idx), (in_trig_line) }, +static const machine_counter_in_trig_map_t machine_counter_in_trig_map[] = { + MACHINE_COUNTER_IN_TRIG_MAP(IN_TRIG_ENTRY) }; -#undef PIN_TRIG_ENTRY +#undef IN_TRIG_ENTRY -// Resolve a source pin to its trigger input line. -static bool machine_counter_pin_to_trigger(const machine_pin_obj_t *pin, uint32_t *in_trig) { - for (size_t i = 0; i < MP_ARRAY_SIZE(machine_counter_pin_trigger_map); ++i) { - const machine_counter_pin_trigger_map_t *entry = &machine_counter_pin_trigger_map[i]; - if (pin->port == entry->port && pin->pin == entry->pin) { +// Resolve PERI0_TR_IO_INPUT unit to trigger input line. +static bool machine_counter_input_to_trigger(uint16_t input_idx, uint32_t *in_trig) { + for (size_t i = 0; i < MP_ARRAY_SIZE(machine_counter_in_trig_map); ++i) { + const machine_counter_in_trig_map_t *entry = &machine_counter_in_trig_map[i]; + if (input_idx == entry->input_idx) { *in_trig = entry->in_trig; return true; } @@ -219,9 +217,9 @@ static void machine_counter_init_helper_impl(machine_counter_obj_t *self, MP_ERROR_TEXT("Pin %q does not support Counter input routing"), src_pin->name); } - // Fetch trigger-routing metadata for the selected source pin. + // Resolve trigger-routing metadata from the selected Counter input AF unit. uint32_t in_trig = 0; - if (!machine_counter_pin_to_trigger(src_pin, &in_trig)) { + if (!machine_counter_input_to_trigger(src_pin_af->unit, &in_trig)) { mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Pin %q is missing Counter input route data"), src_pin->name); } @@ -239,7 +237,6 @@ static void machine_counter_init_helper_impl(machine_counter_obj_t *self, // Record the source pin now so rollback can restore it on any failure below. self->src_pin = src_pin; - self->src_hsiom = hsiom; // Put pin in input mode and switch HSIOM to trigger-output function. mp_hal_pin_input(src_pin); @@ -302,8 +299,6 @@ static void machine_counter_init_helper_impl(machine_counter_obj_t *self, Cy_TCPWM_Counter_Enable(TCPWM0, self->counter_num); Cy_TCPWM_TriggerReloadOrIndex_Single(TCPWM0, self->counter_num); - self->src_pin = src_pin; - self->src_hsiom = hsiom; self->edge = edge; self->direction = direction; self->offset = 0; @@ -353,7 +348,6 @@ static mp_obj_t machine_counter_make_new(const mp_obj_type_t *type, self->counter_num = counter_hw[id]; self->pclk_dst = machine_tcpwm_counter_pclk(self->counter_num); self->src_pin = NULL; - self->src_hsiom = (en_hsiom_sel_t)0; self->edge = COUNTER_EDGE_RISING; self->direction = COUNTER_DIR_UP; self->offset = 0; From 95fa0238aaf8a1421a8a7c6af141d612f989a552 Mon Sep 17 00:00:00 2001 From: jaenrig-ifx Date: Mon, 13 Jul 2026 14:27:09 +0200 Subject: [PATCH 12/16] psoc-edge/machine_counter: Added scr_pin config based on mp_hal_pin_af. Signed-off-by: jaenrig-ifx --- ports/psoc-edge/machine_counter.c | 76 +++++++++---------------------- 1 file changed, 21 insertions(+), 55 deletions(-) diff --git a/ports/psoc-edge/machine_counter.c b/ports/psoc-edge/machine_counter.c index fff398f4103..137fac57a6d 100644 --- a/ports/psoc-edge/machine_counter.c +++ b/ports/psoc-edge/machine_counter.c @@ -64,7 +64,7 @@ typedef struct _machine_counter_obj_t { uint8_t id; uint32_t counter_num; en_clk_dst_t pclk_dst; - const machine_pin_obj_t *src_pin; + mp_hal_pin_obj_t src_pin; uint8_t edge; uint8_t direction; mp_int_t offset; @@ -93,11 +93,6 @@ static const uint32_t counter_out_trig[MACHINE_COUNTER_NUM_INSTANCES] = { }; #undef COUNTER_OUT_TRIG_ENTRY -// Counter trigger-input map generated from AF data. -// Each row: X(input_idx, in_trig_line) -#define MACHINE_COUNTER_IN_TRIG_MAP(X) \ - MICROPY_PY_MACHINE_COUNTER_IN_TRIG_MAP(X) - // --------------------------------------------------------------------------- // Helpers // --------------------------------------------------------------------------- @@ -124,31 +119,20 @@ static uint32_t machine_counter_period_max(uint32_t counter_num) { return (counter_num >= 256U) ? 0xFFFFU : UINT32_MAX; } -typedef struct _machine_counter_in_trig_map_t { - uint16_t input_idx; - uint32_t in_trig; -} machine_counter_in_trig_map_t; +/** + * TODO: + * The TrigMux functionality might be required for other modules, + * and these definitions might be move in the future to a separate + * c file to be shared by other modules. + * Only PERI0 is used here, but PERI1 is also available and could + * be used. + */ +#define MAP_COUNTER_PIN_INPUT_TRIGGER(id) \ + [id] = PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT##id, -// Expands input-route rows into lookup table entries. -#define IN_TRIG_ENTRY(input_idx, in_trig_line) \ - { (uint16_t)(input_idx), (in_trig_line) }, -static const machine_counter_in_trig_map_t machine_counter_in_trig_map[] = { - MACHINE_COUNTER_IN_TRIG_MAP(IN_TRIG_ENTRY) +static const en_peri0_trig_input_debugreducation1_t peri0_tr_io_input[MICROPY_PY_MACHINE_PERI0_TR_IO_INPUT_NUM_ENTRIES] = { + MICROPY_PY_MACHINE_FOR_ALL_PERI0_TR_IO_INPUTS(MAP_COUNTER_PIN_INPUT_TRIGGER) }; -#undef IN_TRIG_ENTRY - -// Resolve PERI0_TR_IO_INPUT unit to trigger input line. -static bool machine_counter_input_to_trigger(uint16_t input_idx, uint32_t *in_trig) { - for (size_t i = 0; i < MP_ARRAY_SIZE(machine_counter_in_trig_map); ++i) { - const machine_counter_in_trig_map_t *entry = &machine_counter_in_trig_map[i]; - if (input_idx == entry->input_idx) { - *in_trig = entry->in_trig; - return true; - } - } - - return false; -} // Restore the routed source pin back to GPIO input mode. static void machine_counter_restore_src_pin(machine_counter_obj_t *self) { @@ -203,28 +187,14 @@ static void machine_counter_init_helper_impl(machine_counter_obj_t *self, } // Resolve source pin object and validate it exposes Counter input AF. - const machine_pin_obj_t *src_pin = mp_hal_get_pin_obj(args[ARG_src].u_obj); - const machine_pin_af_obj_t *src_pin_af = NULL; - for (size_t i = 0; i < src_pin->af_num; ++i) { - const machine_pin_af_obj_t *af = &src_pin->af[i]; - if (af->signal == MACHINE_PIN_AF_SIGNAL_PERI_TR_IO_INPUT) { - src_pin_af = af; - break; - } - } - if (src_pin_af == NULL) { - mp_raise_msg_varg(&mp_type_ValueError, - MP_ERROR_TEXT("Pin %q does not support Counter input routing"), src_pin->name); - } + mp_hal_pin_obj_t src_pin = mp_hal_get_pin_obj(args[ARG_src].u_obj); - // Resolve trigger-routing metadata from the selected Counter input AF unit. - uint32_t in_trig = 0; - if (!machine_counter_input_to_trigger(src_pin_af->unit, &in_trig)) { - mp_raise_msg_varg(&mp_type_ValueError, - MP_ERROR_TEXT("Pin %q is missing Counter input route data"), src_pin->name); - } + mp_hal_pin_af_config_t src_pin_af_config = MP_HAL_PIN_AF_CONF_INIT(src_pin, CY_GPIO_DM_HIGHZ, 0, MACHINE_PIN_AF_SIGNAL_PERI_TR_IO_INPUT); - en_hsiom_sel_t hsiom = src_pin_af->idx; + machine_pin_af_unit_t fn_unit = MACHINE_PIN_AF_UNIT_NONE; + mp_hal_periph_pins_af_resolve_fn_unit(&src_pin_af_config, 1, MACHINE_PIN_AF_FN_PERI_TR_IO, &fn_unit); + + en_peri0_trig_input_debugreducation1_t in_trig = peri0_tr_io_input[fn_unit]; // Tear down any previous run before programming new pin routing. machine_counter_stop_hw(self); @@ -235,15 +205,11 @@ static void machine_counter_init_helper_impl(machine_counter_obj_t *self, Cy_SysClk_PeriPclkAssignDivider(self->pclk_dst, CY_SYSCLK_DIV_16_BIT, CYBSP_GENERAL_PURPOSE_TIMER_CLK_DIV_NUM); + mp_hal_periph_pins_af_init(&src_pin_af_config, 1); + // Record the source pin now so rollback can restore it on any failure below. self->src_pin = src_pin; - // Put pin in input mode and switch HSIOM to trigger-output function. - mp_hal_pin_input(src_pin); - GPIO_PRT_Type *src_port = Cy_GPIO_PortToAddr(src_pin->port); - Cy_GPIO_SetHSIOM(src_port, src_pin->pin, hsiom); - Cy_GPIO_SetDrivemode(src_port, src_pin->pin, CY_GPIO_DM_HIGHZ); - // Connect selected pin trigger line to this counter's dedicated trigger input. uint32_t out_trig = counter_out_trig[self->id]; cy_en_trigmux_status_t mux_rslt = Cy_TrigMux_Connect(in_trig, out_trig, false, TRIGGER_TYPE_LEVEL); From 5b0abcfa13012ebeeb246dd4b2675138eff63c74 Mon Sep 17 00:00:00 2001 From: jaenrig-ifx Date: Mon, 13 Jul 2026 16:58:08 +0200 Subject: [PATCH 13/16] tests/ports/psoc-edge/../counter: Updated invalid pin error msg. Signed-off-by: jaenrig-ifx --- tests/ports/psoc-edge/board_ext_hw/single/counter.py.exp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ports/psoc-edge/board_ext_hw/single/counter.py.exp b/tests/ports/psoc-edge/board_ext_hw/single/counter.py.exp index 11f5bb25dc5..7b14d8e85af 100644 --- a/tests/ports/psoc-edge/board_ext_hw/single/counter.py.exp +++ b/tests/ports/psoc-edge/board_ext_hw/single/counter.py.exp @@ -7,5 +7,5 @@ invalid_id_-1: Counter id must be in range 0-31 invalid_id_32: Counter id must be in range 0-31 invalid_edge: invalid edge invalid_direction: invalid direction -invalid_src_pin: Pin P16_7 does not support Counter input routing +invalid_src_pin: Pin 'P16_7' does not support 'PERI_TR_IO_INPUT'. duplicate_counter_id: Counter(6) already created. From d7de5e1c56f3dd1be8f65f82f07fea7a26aef90a Mon Sep 17 00:00:00 2001 From: jaenrig-ifx Date: Mon, 13 Jul 2026 18:12:46 +0200 Subject: [PATCH 14/16] psoc-edge/machine_pin_af: Added peri trigger output signal. Signed-off-by: jaenrig-ifx --- ports/psoc-edge/machine_pin_af.h | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/psoc-edge/machine_pin_af.h b/ports/psoc-edge/machine_pin_af.h index 5f7abd74879..5dab29e48be 100644 --- a/ports/psoc-edge/machine_pin_af.h +++ b/ports/psoc-edge/machine_pin_af.h @@ -65,6 +65,7 @@ typedef enum { MACHINE_PIN_AF_SIGNAL_TCPWM_LINE, MACHINE_PIN_AF_SIGNAL_PERI_TR_IO_INPUT, + MACHINE_PIN_AF_SIGNAL_PERI_TR_IO_OUTPUT, /* TODO: Add additional types */ } machine_pin_af_signal_t; From a604a52f69ddefc7c60bba6df2b5ef398bb0acf0 Mon Sep 17 00:00:00 2001 From: jaenrig-ifx Date: Mon, 13 Jul 2026 18:14:29 +0200 Subject: [PATCH 15/16] psoc-edge/boards/pse8x_af: Added missing peri trig entry. Signed-off-by: jaenrig-ifx --- ports/psoc-edge/boards/pse8x_af.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/psoc-edge/boards/pse8x_af.csv b/ports/psoc-edge/boards/pse8x_af.csv index 953820b34d2..b049d30f61f 100644 --- a/ports/psoc-edge/boards/pse8x_af.csv +++ b/ports/psoc-edge/boards/pse8x_af.csv @@ -57,7 +57,7 @@ Port10,P10_4, ,TCPWM0_LINE3 ,TCPW Port10,P10_5, ,TCPWM0_LINE_COMPL3 ,TCPWM0_LINE_COMPL259 , , , ,SCB4_SPI_SELECT1 , , , , , , , , ,ETH_RX_CTL , , , , Port10,P10_6, ,TCPWM0_LINE4 ,TCPWM0_LINE260 , , , , , , , , , , , , ,ETH_RXD0 , , , , Port10,P10_7, ,TCPWM0_LINE_COMPL4 ,TCPWM0_LINE_COMPL260 , , , , , , , , , , , , ,ETH_RXD1 , , , , -Port10,P11_0, ,TCPWM0_LINE5 ,TCPWM0_LINE261 , , ,TDM_TDM_TX_SCK1 , ,SCB6_I2C_SCL , , , , , , , ,ETH_RXD2 , , , , +Port10,P11_0, ,TCPWM0_LINE5 ,TCPWM0_LINE261 , , ,TDM_TDM_TX_SCK1 , ,SCB6_I2C_SCL , , ,PERI0_TR_IO_INPUT0 ,PERI1_TR_IO_INPUT0 , , , ,ETH_RXD2 , , , , Port11,P11_1, ,TCPWM0_LINE_COMPL5 ,TCPWM0_LINE_COMPL261 , , ,TDM_TDM_TX_FSYNC1,SCB6_SPI_MOSI ,SCB6_I2C_SDA ,SCB6_UART_TX , ,PERI0_TR_IO_INPUT1 ,PERI1_TR_IO_INPUT1 , , , ,ETH_RX_ER , , , , Port11,P11_2, ,TCPWM0_LINE6 ,TCPWM0_LINE262 , , ,TDM_TDM_TX_SD1 ,SCB6_SPI_MISO , ,SCB6_UART_CTS , ,PERI0_TR_IO_INPUT2 ,PERI1_TR_IO_INPUT2 , , , ,ETH_TXD0 , , , , Port11,P11_3, ,TCPWM0_LINE_COMPL6 ,TCPWM0_LINE_COMPL262 , , ,TDM_TDM_RX_MCK1 ,SCB6_SPI_SELECT0 , ,SCB6_UART_RTS , ,PERI0_TR_IO_INPUT3 ,PERI1_TR_IO_INPUT3 , , , ,ETH_TXD1 , , , , From 74ca3405ff80b2c7bec621136acf7b70e26a4ae2 Mon Sep 17 00:00:00 2001 From: jaenrig-ifx Date: Mon, 13 Jul 2026 18:16:07 +0200 Subject: [PATCH 16/16] psoc-edge/boards/make-pins: Generalized peri_tr_io AFs. Signed-off-by: jaenrig-ifx --- ports/psoc-edge/boards/make-pins.py | 150 +++++++++++++++++----------- 1 file changed, 94 insertions(+), 56 deletions(-) diff --git a/ports/psoc-edge/boards/make-pins.py b/ports/psoc-edge/boards/make-pins.py index 4582de5270c..fcbb3e49b8d 100644 --- a/ports/psoc-edge/boards/make-pins.py +++ b/ports/psoc-edge/boards/make-pins.py @@ -13,7 +13,7 @@ "SPI": ["CLK", "MOSI", "MISO", "SELECT0", "SELECT1"], "PDM": ["CLK", "DATA"], "TCPWM": ["LINE"], - "PERI_TR_IO": ["INPUT"], + "PERI_TR_IO": ["INPUT", "OUTPUT"], # TODO: Other active functionalities that we need to figure out: # - TDM # - SMIF @@ -131,17 +131,18 @@ def add_af_tcpwm(self, af_idx, af_name, af): pin_af = PinAf(af_idx, af_fn, af_unit, af_signal, af_supported, af_name, af_ptr) self._afs.append(pin_af) - def add_af_peri_tr_io_input(self, af_idx, af_name, af): - # Map PERI0_TR_IO_INPUTx to regular pin AF objects so consumers can + def add_af_peri_tr_io(self, af_idx, af_name, af): + # Map PERIx_TR_IO_INPUT/OUTPUTy to regular pin AF objects so consumers can # validate capability through the shared AF metadata path. - input_idx = af[len("PERI0_TR_IO_INPUT") :] - if not input_idx.isdigit(): + # Matches patterns like: PERI0_TR_IO_INPUT4, PERI1_TR_IO_OUTPUT1 + match = re.match(r"^(PERI\d+)_TR_IO_(INPUT|OUTPUT)(\d+)$", af) + if not match: return - af_ptr = "NULL" + af_ptr = match.group(1) # e.g., "PERI0", "PERI1" + af_signal = match.group(2) # e.g., "INPUT", "OUTPUT" + af_unit = match.group(3) # e.g., "4", "1" af_fn = "PERI_TR_IO" - af_signal = "INPUT" - af_unit = input_idx af_supported = af_fn in SUPPORTED_AF and af_signal in SUPPORTED_AF[af_fn] pin_af = PinAf(af_idx, af_fn, af_unit, af_signal, af_supported, af_name, af_ptr) @@ -156,19 +157,6 @@ def add_af(self, af_idx, af_name, af): if af_idx > af_act_max_idx + af_ds_num: return - # Counter source pin routing uses PERI0 trigger-input AFs. - # Example AF token: PERI0_TR_IO_INPUT1 - if af.startswith("PERI0_TR_IO_INPUT"): - self.add_af_peri_tr_io_input(af_idx, af_name, af) - input_idx = af[len("PERI0_TR_IO_INPUT") :] - if input_idx.isdigit(): - self._counter_src = { - "input_idx": int(input_idx), - "in_trig": f"PERI_0_TRIG_IN_MUX_3_PERI0_HSIOM_TR_OUT{input_idx}", - "hsiom": f"{self.name()}_{af}", - } - return - if af_idx <= af_act_max_idx: if af_name != "ACT_{:d}".format(af_idx): raise boardgen.PinGeneratorError( @@ -204,6 +192,8 @@ def add_af(self, af_idx, af_name, af): self.add_af_pdm(af_idx, af_name, af) elif "TCPWM" in af: self.add_af_tcpwm(af_idx, af_name, af) + elif af.startswith("PERI"): + self.add_af_peri_tr_io(af_idx, af_name, af) else: # TODO: Extend the parsing to other peripherals. pass @@ -253,8 +243,17 @@ def __init__(self): self._pwm_pin_count = 0 # unique exposed pins with a TCPWM LINE AF self._tcpwm_counter_max = 0 # highest counter number seen across all LINE AFs self._tcpwm_counters = [] # sorted unique TCPWM counter IDs seen in LINE AFs - # Counter input trigger entries indexed by PERI0_TR_IO_INPUT unit. - self._counter_input_entries = [] + + # Trigger routing + self._unhidden_peri0_tr_io_input = [] + self._unhidden_peri0_tr_io_output = [] + self._peri0_tr_io_input_max_index = 0 + self._peri0_tr_io_output_max_index = 0 + + self._unhidden_peri1_tr_io_input = [] + self._unhidden_peri1_tr_io_output = [] + self._peri1_tr_io_input_max_index = 0 + self._peri1_tr_io_output_max_index = 0 # Collect all unhidden ports from the available # pins. @@ -314,22 +313,37 @@ def add_tcpwm(self): self._tcpwm_counters = sorted(seen_counters) self._pwm_pin_count = len(seen_counters) - # Collect unique Counter trigger routes from PERI0_TR_IO_INPUTx units. - def add_counter_input_routes(self): - input_routes = {} + def add_peri_tr_ios(self): for pin in self.available_pins(exclude_hidden=True): - if pin._counter_src is None: - continue - - input_idx = pin._counter_src["input_idx"] - in_trig = pin._counter_src["in_trig"] - if input_idx in input_routes and input_routes[input_idx] != in_trig: - raise boardgen.PinGeneratorError( - f"Conflicting Counter route for PERI0_TR_IO_INPUT{input_idx}." - ) - input_routes[input_idx] = in_trig - - self._counter_input_entries = sorted(input_routes.items()) + for af in pin._afs: + if af.af_fn == "PERI_TR_IO": + if af.af_ptr == "PERI0": + if af.af_signal == "INPUT": + if af.af_unit not in self._unhidden_peri0_tr_io_input: + self._unhidden_peri0_tr_io_input.append(af.af_unit) + if int(af.af_unit) > self._peri0_tr_io_input_max_index: + self._peri0_tr_io_input_max_index = int(af.af_unit) + elif af.af_signal == "OUTPUT": + if af.af_unit not in self._unhidden_peri0_tr_io_output: + self._unhidden_peri0_tr_io_output.append(af.af_unit) + if int(af.af_unit) > self._peri0_tr_io_output_max_index: + self._peri0_tr_io_output_max_index = int(af.af_unit) + elif af.af_ptr == "PERI1": + if af.af_signal == "INPUT": + if af.af_unit not in self._unhidden_peri1_tr_io_input: + self._unhidden_peri1_tr_io_input.append(af.af_unit) + if int(af.af_unit) > self._peri1_tr_io_input_max_index: + self._peri1_tr_io_input_max_index = int(af.af_unit) + elif af.af_signal == "OUTPUT": + if af.af_unit not in self._unhidden_peri1_tr_io_output: + self._unhidden_peri1_tr_io_output.append(af.af_unit) + if int(af.af_unit) > self._peri1_tr_io_output_max_index: + self._peri1_tr_io_output_max_index = int(af.af_unit) + + self._unhidden_peri0_tr_io_input.sort(key=int) + self._unhidden_peri0_tr_io_output.sort(key=int) + self._unhidden_peri1_tr_io_input.sort(key=int) + self._unhidden_peri1_tr_io_output.sort(key=int) # Override the parse_board_csv to add # the unhidden ports after parsing the board CSV. @@ -338,7 +352,7 @@ def parse_board_csv(self, filename): self.add_ports() self.add_scbs() self.add_tcpwm() - self.add_counter_input_routes() + self.add_peri_tr_ios() # Override the default implementation just to change the default arguments # (extra header row, skip first column). @@ -493,34 +507,58 @@ def print_tcpwm_hw_map(self, out_header): print(f" X({tid:2d}, {counter}, {irq}, {pclk}, {trig}){suffix}", file=out_header) print(file=out_header) - def print_af_header(self, out_af_header): - self.print_scb_defines(out_af_header) - self.print_tcpwm_defines(out_af_header) - self.print_tcpwm_hw_map(out_af_header) - self.print_counter_input_map(out_af_header) - - def print_counter_input_map(self, out_header): + def print_peri_tr_io_defines(self, out_header): print(file=out_header) print( - "// Counter trigger-input map indexed by PERI0_TR_IO_INPUT unit.", + f"#define MICROPY_PY_MACHINE_PERI0_TR_IO_INPUT_NUM_ENTRIES ({self._peri0_tr_io_input_max_index + 1})", file=out_header, ) print( - "// Each row: X(input_idx, in_trig_line)", + f"#define MICROPY_PY_MACHINE_PERI0_TR_IO_OUTPUT_NUM_ENTRIES ({self._peri0_tr_io_output_max_index + 1})", file=out_header, ) - print("#define MICROPY_PY_MACHINE_COUNTER_IN_TRIG_MAP(X) \\", file=out_header) + print( + f"#define MICROPY_PY_MACHINE_PERI1_TR_IO_INPUT_NUM_ENTRIES ({self._peri1_tr_io_input_max_index + 1})", + file=out_header, + ) + print( + f"#define MICROPY_PY_MACHINE_PERI1_TR_IO_OUTPUT_NUM_ENTRIES ({self._peri1_tr_io_output_max_index + 1})", + file=out_header, + ) + print(file=out_header) - if not self._counter_input_entries: - print(" /* no available counter input routes */", file=out_header) - print(file=out_header) - return + print("#define MICROPY_PY_MACHINE_FOR_ALL_PERI0_TR_IO_INPUTS(DO) \\", file=out_header) + lines = [f"DO({in_idx})" for in_idx in self._unhidden_peri0_tr_io_input] + macro_body = " \\\n".join(lines) + print(macro_body, file=out_header) + print(file=out_header) - for i, (input_idx, in_trig) in enumerate(self._counter_input_entries): - suffix = " \\" if i < len(self._counter_input_entries) - 1 else "" - print(f" X({input_idx}, {in_trig}){suffix}", file=out_header) + print("#define MICROPY_PY_MACHINE_FOR_ALL_PERI0_TR_IO_OUTPUTS(DO) \\", file=out_header) + lines = [f"DO({out_idx})" for out_idx in self._unhidden_peri0_tr_io_output] + macro_body = " \\\n".join(lines) + print(macro_body, file=out_header) print(file=out_header) + print("#define MICROPY_PY_MACHINE_FOR_ALL_PERI1_TR_IO_INPUTS(DO) \\", file=out_header) + lines = [f"DO({in_idx})" for in_idx in self._unhidden_peri1_tr_io_input] + macro_body = " \\\n".join(lines) + print(macro_body, file=out_header) + print(file=out_header) + + print("#define MICROPY_PY_MACHINE_FOR_ALL_PERI1_TR_IO_OUTPUTS(DO) \\", file=out_header) + lines = [f"DO({out_idx})" for out_idx in self._unhidden_peri1_tr_io_output] + macro_body = " \\\n".join(lines) + print(macro_body, file=out_header) + print(file=out_header) + + print(file=out_header) + + def print_af_header(self, out_af_header): + self.print_scb_defines(out_af_header) + self.print_tcpwm_defines(out_af_header) + self.print_tcpwm_hw_map(out_af_header) + self.print_peri_tr_io_defines(out_af_header) + # Add additional header file for AF defines and constants def extra_args(self, parser): parser.add_argument("--output-af-header")