3131#include "py/mperrno.h"
3232#include "py/mphal.h"
3333#include "shared/runtime/mpirq.h"
34+ #include "machine_pin.h"
3435#include "modrp2.h"
3536
3637#include "hardware/clocks.h"
@@ -54,7 +55,7 @@ typedef struct _rp2_state_machine_obj_t {
5455 PIO pio ;
5556 uint8_t irq ;
5657 uint8_t sm ; // 0-3
57- uint8_t id ; // 0-7
58+ uint8_t id ; // 0-7 on RP2040, or 0-11 on RP2350
5859} rp2_state_machine_obj_t ;
5960
6061typedef struct _rp2_state_machine_irq_obj_t {
@@ -63,11 +64,11 @@ typedef struct _rp2_state_machine_irq_obj_t {
6364 uint8_t trigger ;
6465} rp2_state_machine_irq_obj_t ;
6566
66- static const rp2_state_machine_obj_t rp2_state_machine_obj [8 ];
67- static uint8_t rp2_state_machine_initial_pc [8 ];
67+ static const rp2_state_machine_obj_t rp2_state_machine_obj [NUM_PIOS * 4 ];
68+ static uint8_t rp2_state_machine_initial_pc [NUM_PIOS * 4 ];
6869
6970// These masks keep track of PIO instruction memory used by this module.
70- static uint32_t rp2_pio_instruction_memory_usage_mask [2 ];
71+ static uint32_t rp2_pio_instruction_memory_usage_mask [NUM_PIOS ];
7172
7273static const rp2_state_machine_obj_t * rp2_state_machine_get_object (mp_int_t sm_id );
7374static void rp2_state_machine_reset_all (void );
@@ -104,8 +105,19 @@ static void pio1_irq0(void) {
104105 pio_irq0 (pio1 );
105106}
106107
108+ #if NUM_PIOS >= 3
109+ static void pio2_irq0 (void ) {
110+ pio_irq0 (pio2 );
111+ }
112+ #endif
113+
107114// Returns the correct irq0 handler wrapper for a given pio
108115static inline irq_handler_t rp2_pio_get_irq_handler (PIO pio ) {
116+ #if NUM_PIOS >= 3
117+ if (pio == pio2 ) {
118+ return pio2_irq0 ;
119+ }
120+ #endif
109121 return pio == pio0 ? pio0_irq0 : pio1_irq0 ;
110122}
111123
@@ -172,6 +184,12 @@ void rp2_pio_deinit(void) {
172184 irq_set_enabled (PIO1_IRQ_0 , false);
173185 irq_remove_handler (PIO1_IRQ_0 , pio1_irq0 );
174186 }
187+ #if NUM_PIOS >= 3
188+ if (irq_get_exclusive_handler (PIO2_IRQ_0 ) == pio2_irq0 ) {
189+ irq_set_enabled (PIO2_IRQ_0 , false);
190+ irq_remove_handler (PIO2_IRQ_0 , pio2_irq0 );
191+ }
192+ #endif
175193
176194 rp2_state_machine_reset_all ();
177195
@@ -180,6 +198,9 @@ void rp2_pio_deinit(void) {
180198 // and their PIO programs should remain intact.
181199 rp2_pio_remove_all_managed_programs (pio0 );
182200 rp2_pio_remove_all_managed_programs (pio1 );
201+ #if NUM_PIOS >= 3
202+ rp2_pio_remove_all_managed_programs (pio2 );
203+ #endif
183204}
184205
185206/******************************************************************************/
@@ -212,7 +233,7 @@ static void asm_pio_override_shiftctrl(mp_obj_t arg, uint32_t bits, uint32_t lsb
212233 }
213234}
214235
215- static void asm_pio_get_pins (const char * type , mp_obj_t prog_pins , mp_obj_t arg_base , asm_pio_config_t * config ) {
236+ static void asm_pio_get_pins (PIO pio , const char * type , mp_obj_t prog_pins , mp_obj_t arg_base , asm_pio_config_t * config ) {
216237 if (prog_pins != mp_const_none ) {
217238 // The PIO program specified pins for initialisation on out/set/sideset.
218239 if (mp_obj_is_integer (prog_pins )) {
@@ -238,13 +259,21 @@ static void asm_pio_get_pins(const char *type, mp_obj_t prog_pins, mp_obj_t arg_
238259 if (arg_base != mp_const_none ) {
239260 // The instantiation of the PIO program specified a base pin.
240261 config -> base = mp_hal_get_pin_obj (arg_base );
262+
263+ #if PICO_PIO_USE_GPIO_BASE
264+ // Check the base is within range of the configured gpio_base.
265+ uint gpio_base = pio_get_gpio_base (pio );
266+ if ((gpio_base == 0 && config -> base >= 32 ) || (gpio_base == 16 && config -> base < 16 )) {
267+ mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("%s_base not within gpio_base range" ), type );
268+ }
269+ #endif
241270 }
242271}
243272
244273static void asm_pio_init_gpio (PIO pio , uint32_t sm , asm_pio_config_t * config ) {
245- uint32_t pinmask = ((1 << config -> count ) - 1 ) << config -> base ;
246- pio_sm_set_pins_with_mask (pio , sm , config -> pinvals << config -> base , pinmask );
247- pio_sm_set_pindirs_with_mask (pio , sm , config -> pindirs << config -> base , pinmask );
274+ uint32_t pinmask = ((1 << config -> count ) - 1 ) << ( config -> base - pio_get_gpio_base ( pio )) ;
275+ pio_sm_set_pins_with_mask (pio , sm , config -> pinvals << ( config -> base - pio_get_gpio_base ( pio )) , pinmask );
276+ pio_sm_set_pindirs_with_mask (pio , sm , config -> pindirs << ( config -> base - pio_get_gpio_base ( pio )) , pinmask );
248277 for (size_t i = 0 ; i < config -> count ; ++ i ) {
249278 gpio_set_function (config -> base + i , GPIO_FUNC_PIO0 + pio_get_index (pio ));
250279 }
@@ -258,6 +287,9 @@ static const mp_irq_methods_t rp2_pio_irq_methods;
258287static rp2_pio_obj_t rp2_pio_obj [] = {
259288 { { & rp2_pio_type }, pio0 , PIO0_IRQ_0 },
260289 { { & rp2_pio_type }, pio1 , PIO1_IRQ_0 },
290+ #if NUM_PIOS >= 3
291+ { { & rp2_pio_type }, pio2 , PIO2_IRQ_0 },
292+ #endif
261293};
262294
263295static void rp2_pio_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
@@ -357,6 +389,31 @@ static mp_obj_t rp2_pio_state_machine(size_t n_args, const mp_obj_t *pos_args, m
357389}
358390MP_DEFINE_CONST_FUN_OBJ_KW (rp2_pio_state_machine_obj , 2 , rp2_pio_state_machine );
359391
392+ #if PICO_PIO_USE_GPIO_BASE
393+ // PIO.gpio_base([base])
394+ static mp_obj_t rp2_pio_gpio_base (size_t n_args , const mp_obj_t * args ) {
395+ rp2_pio_obj_t * self = MP_OBJ_TO_PTR (args [0 ]);
396+
397+ if (n_args > 1 ) {
398+ // Set gpio_base value.
399+ uint gpio_base = mp_hal_get_pin_obj (args [1 ]);
400+
401+ // Must be 0 for GPIOs 0 to 31 inclusive, or 16 for GPIOs 16 to 48 inclusive.
402+ if (!(gpio_base == 0 || gpio_base == 16 )) {
403+ mp_raise_ValueError ("invalid GPIO base" );
404+ }
405+
406+ if (pio_set_gpio_base (self -> pio , gpio_base ) != PICO_OK ) {
407+ mp_raise_OSError (MP_EINVAL );
408+ }
409+ }
410+
411+ // Return current gpio_base value.
412+ return pio_get_gpio_base (self -> pio ) == 0 ? (mp_obj_t )pin_GPIO0 : (mp_obj_t )pin_GPIO16 ;
413+ }
414+ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (rp2_pio_gpio_base_obj , 1 , 2 , rp2_pio_gpio_base ) ;
415+ #endif
416+
360417// PIO.irq(handler=None, trigger=IRQ_SM0|IRQ_SM1|IRQ_SM2|IRQ_SM3, hard=False)
361418static mp_obj_t rp2_pio_irq (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
362419 enum { ARG_handler , ARG_trigger , ARG_hard };
@@ -410,6 +467,9 @@ static mp_obj_t rp2_pio_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
410467static MP_DEFINE_CONST_FUN_OBJ_KW (rp2_pio_irq_obj , 1 , rp2_pio_irq ) ;
411468
412469static const mp_rom_map_elem_t rp2_pio_locals_dict_table [] = {
470+ #if PICO_PIO_USE_GPIO_BASE
471+ { MP_ROM_QSTR (MP_QSTR_gpio_base ), MP_ROM_PTR (& rp2_pio_gpio_base_obj ) },
472+ #endif
413473 { MP_ROM_QSTR (MP_QSTR_add_program ), MP_ROM_PTR (& rp2_pio_add_program_obj ) },
414474 { MP_ROM_QSTR (MP_QSTR_remove_program ), MP_ROM_PTR (& rp2_pio_remove_program_obj ) },
415475 { MP_ROM_QSTR (MP_QSTR_state_machine ), MP_ROM_PTR (& rp2_pio_state_machine_obj ) },
@@ -486,6 +546,12 @@ static const rp2_state_machine_obj_t rp2_state_machine_obj[] = {
486546 { { & rp2_state_machine_type }, pio1 , PIO1_IRQ_0 , 1 , 5 },
487547 { { & rp2_state_machine_type }, pio1 , PIO1_IRQ_0 , 2 , 6 },
488548 { { & rp2_state_machine_type }, pio1 , PIO1_IRQ_0 , 3 , 7 },
549+ #if NUM_PIOS >= 3
550+ { { & rp2_state_machine_type }, pio2 , PIO2_IRQ_0 , 0 , 8 },
551+ { { & rp2_state_machine_type }, pio2 , PIO2_IRQ_0 , 1 , 9 },
552+ { { & rp2_state_machine_type }, pio2 , PIO2_IRQ_0 , 2 , 10 },
553+ { { & rp2_state_machine_type }, pio2 , PIO2_IRQ_0 , 3 , 11 },
554+ #endif
489555};
490556
491557static const rp2_state_machine_obj_t * rp2_state_machine_get_object (mp_int_t sm_id ) {
@@ -604,14 +670,14 @@ static mp_obj_t rp2_state_machine_init_helper(const rp2_state_machine_obj_t *sel
604670
605671 // Configure out pins, if needed.
606672 asm_pio_config_t out_config = ASM_PIO_CONFIG_DEFAULT ;
607- asm_pio_get_pins ("out" , prog [PROG_OUT_PINS ], args [ARG_out_base ].u_obj , & out_config );
673+ asm_pio_get_pins (self -> pio , "out" , prog [PROG_OUT_PINS ], args [ARG_out_base ].u_obj , & out_config );
608674 if (out_config .base >= 0 ) {
609675 sm_config_set_out_pins (& config , out_config .base , out_config .count );
610676 }
611677
612678 // Configure set pin, if needed.
613679 asm_pio_config_t set_config = ASM_PIO_CONFIG_DEFAULT ;
614- asm_pio_get_pins ("set" , prog [PROG_SET_PINS ], args [ARG_set_base ].u_obj , & set_config );
680+ asm_pio_get_pins (self -> pio , "set" , prog [PROG_SET_PINS ], args [ARG_set_base ].u_obj , & set_config );
615681 if (set_config .base >= 0 ) {
616682 sm_config_set_set_pins (& config , set_config .base , set_config .count );
617683 }
@@ -623,7 +689,7 @@ static mp_obj_t rp2_state_machine_init_helper(const rp2_state_machine_obj_t *sel
623689
624690 // Configure sideset pin, if needed.
625691 asm_pio_config_t sideset_config = ASM_PIO_CONFIG_DEFAULT ;
626- asm_pio_get_pins ("sideset" , prog [PROG_SIDESET_PINS ], args [ARG_sideset_base ].u_obj , & sideset_config );
692+ asm_pio_get_pins (self -> pio , "sideset" , prog [PROG_SIDESET_PINS ], args [ARG_sideset_base ].u_obj , & sideset_config );
627693 if (sideset_config .base >= 0 ) {
628694 uint32_t count = sideset_config .count ;
629695 if (config .execctrl & (1 << PIO_SM0_EXECCTRL_SIDE_EN_LSB )) {
@@ -951,5 +1017,5 @@ static const mp_irq_methods_t rp2_state_machine_irq_methods = {
9511017 .info = rp2_state_machine_irq_info ,
9521018};
9531019
954- MP_REGISTER_ROOT_POINTER (void * rp2_pio_irq_obj [2 ]);
955- MP_REGISTER_ROOT_POINTER (void * rp2_state_machine_irq_obj [8 ]);
1020+ MP_REGISTER_ROOT_POINTER (void * rp2_pio_irq_obj [NUM_PIOS ]);
1021+ MP_REGISTER_ROOT_POINTER (void * rp2_state_machine_irq_obj [NUM_PIOS * 4 ]);
0 commit comments