From f9958417d8adb21147de776361a4414073cf7c77 Mon Sep 17 00:00:00 2001 From: Adam Green Date: Thu, 20 Apr 2023 22:23:46 -0700 Subject: [PATCH] rp2: Make rp2_state_machine_exec accept integers. Currently rp2.StateMachine.exec(instr_in) requires that the instr_in parameter be a string representing the PIO assembly language instruction to be encoded by rp2.asm_pio_encode(). This commit allows the parameter to also be of integral type. This is useful if the exec() method is being called often where the use of pre-encoded machine code is desireable. This commit still supports calls like: sm.exec("set(0, 1)") It also now supports calls like: # Performed once earlier, maybe in __init__() assembled_instr = rp2.asm_pio_encode("out(y, 8)", 0) # Performed multiple times later as the PIO state machine is # configured for its next run. sm.exec(assembled_instr) The existing examples/rp2/pio_exec.py and examples/rp2/pio_pwm.py that exercise the rp2.StateMachine.exec() method still work with this change. Signed-off-by: Adam Green --- docs/library/rp2.StateMachine.rst | 11 +++++++++-- ports/rp2/rp2_pio.c | 23 +++++++++++++---------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/docs/library/rp2.StateMachine.rst b/docs/library/rp2.StateMachine.rst index d39194e6ff..ee16ce3c51 100644 --- a/docs/library/rp2.StateMachine.rst +++ b/docs/library/rp2.StateMachine.rst @@ -82,11 +82,18 @@ Methods .. method:: StateMachine.exec(instr) - Execute a single PIO instruction. Uses `asm_pio_encode` to encode the - instruction from the given string *instr*. + Execute a single PIO instruction. + + If *instr* is a string then uses `asm_pio_encode` to encode the instruction + from the given string. >>> sm.exec("set(0, 1)") + If *instr* is an integer then it is treated as an already encoded PIO + machine code instruction to be executed. + + >>> sm.exec(rp2.asm_pio_encode("out(y, 8)", 0)) + .. method:: StateMachine.get(buf=None, shift=0) Pull a word from the state machine's RX FIFO. diff --git a/ports/rp2/rp2_pio.c b/ports/rp2/rp2_pio.c index 3ece26bd41..2e30475257 100644 --- a/ports/rp2/rp2_pio.c +++ b/ports/rp2/rp2_pio.c @@ -684,16 +684,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(rp2_state_machine_restart_obj, rp2_state_machin // StateMachine.exec(instr) STATIC mp_obj_t rp2_state_machine_exec(mp_obj_t self_in, mp_obj_t instr_in) { rp2_state_machine_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_t rp2_module = mp_import_name(MP_QSTR_rp2, mp_const_none, MP_OBJ_NEW_SMALL_INT(0)); - mp_obj_t asm_pio_encode = mp_load_attr(rp2_module, MP_QSTR_asm_pio_encode); - uint32_t sideset_count = self->pio->sm[self->sm].pinctrl >> PIO_SM0_PINCTRL_SIDESET_COUNT_LSB; - uint8_t sideset_opt = !!(self->pio->sm[self->sm].execctrl & (1 << PIO_SM0_EXECCTRL_SIDE_EN_LSB)); - mp_obj_t args[3]; - args[0] = instr_in; - args[1] = MP_OBJ_NEW_SMALL_INT(sideset_count); - args[2] = MP_OBJ_NEW_SMALL_INT(sideset_opt); - mp_obj_t encoded_obj = mp_call_function_n_kw(asm_pio_encode, 3, 0, args); - mp_int_t encoded = mp_obj_get_int(encoded_obj); + mp_int_t encoded = 0; + if (!mp_obj_get_int_maybe(instr_in, &encoded)) { + mp_obj_t rp2_module = mp_import_name(MP_QSTR_rp2, mp_const_none, MP_OBJ_NEW_SMALL_INT(0)); + mp_obj_t asm_pio_encode = mp_load_attr(rp2_module, MP_QSTR_asm_pio_encode); + uint32_t sideset_count = self->pio->sm[self->sm].pinctrl >> PIO_SM0_PINCTRL_SIDESET_COUNT_LSB; + uint8_t sideset_opt = !!(self->pio->sm[self->sm].execctrl & (1 << PIO_SM0_EXECCTRL_SIDE_EN_LSB)); + mp_obj_t args[3]; + args[0] = instr_in; + args[1] = MP_OBJ_NEW_SMALL_INT(sideset_count); + args[2] = MP_OBJ_NEW_SMALL_INT(sideset_opt); + mp_obj_t encoded_obj = mp_call_function_n_kw(asm_pio_encode, 3, 0, args); + encoded = mp_obj_get_int(encoded_obj); + } pio_sm_exec(self->pio, self->sm, encoded); return mp_const_none; }