From 4f6c5d274568ab1418fe15e0d33bcb2d4d0177fa Mon Sep 17 00:00:00 2001 From: gitaen Date: Mon, 15 Jun 2026 01:36:02 +0200 Subject: [PATCH] Remove pin ordering restriction in RP2040 ps2 driver (#26256) --- docs/features/ps2_mouse.md | 2 +- .../drivers/vendor/RP/RP2040/ps2_vendor.c | 62 +++++++++++-------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/docs/features/ps2_mouse.md b/docs/features/ps2_mouse.md index 6ef7e467682..9f875d9b816 100644 --- a/docs/features/ps2_mouse.md +++ b/docs/features/ps2_mouse.md @@ -166,7 +166,7 @@ In your keyboard config.h: The `PIO` subsystem is a Raspberry Pi RP2040 specific implementation, using the integrated PIO peripheral and is therefore only available on this MCU. -There are strict requirements for pin ordering but any pair of GPIO pins can be used. The GPIO used for clock must be directly after data, see the included info.json snippet for an example of correct order. +The GPIOs used for clock and data must be consecutive (in either order). You may optionally switch the PIO peripheral used with the following define in config.h: ```c diff --git a/platforms/chibios/drivers/vendor/RP/RP2040/ps2_vendor.c b/platforms/chibios/drivers/vendor/RP/RP2040/ps2_vendor.c index 1c61f196bde..3b18f4f4b8b 100644 --- a/platforms/chibios/drivers/vendor/RP/RP2040/ps2_vendor.c +++ b/platforms/chibios/drivers/vendor/RP/RP2040/ps2_vendor.c @@ -21,8 +21,16 @@ # endif #endif -#if PS2_DATA_PIN + 1 != PS2_CLOCK_PIN -# error PS/2 clock pin must be data pin + 1! +#if PS2_DATA_PIN + 1 == PS2_CLOCK_PIN +# define PS2_FIRST_PIN PS2_DATA_PIN +# define PS2_DATA_PINDIR_BIT 1 +# define PS2_CLOCK_PINDIR_BIT 2 +#elif PS2_DATA_PIN - 1 == PS2_CLOCK_PIN +# define PS2_FIRST_PIN PS2_CLOCK_PIN +# define PS2_DATA_PINDIR_BIT 2 +# define PS2_CLOCK_PINDIR_BIT 1 +#else +# error PS/2 clock and data pin must be consecutive! #endif static inline void pio_serve_interrupt(void); @@ -50,29 +58,29 @@ OSAL_IRQ_HANDLER(RP_PIO0_IRQ_0_HANDLER) { // clang-format off static const uint16_t ps2_program_instructions[] = { - // .wrap_target - 0x00c7, // 0: jmp pin, 7 - 0xe02a, // 1: set x, 10 - 0x2021, // 2: wait 0 pin, 1 - 0x4001, // 3: in pins, 1 - 0x20a1, // 4: wait 1 pin, 1 - 0x0042, // 5: jmp x--, 2 - 0x0000, // 6: jmp 0 - 0x00e9, // 7: jmp !osre, 9 - 0x0000, // 8: jmp 0 - 0xff81, // 9: set pindirs, 1 [31] - 0xe280, // 10: set pindirs, 0 [2] - 0xe082, // 11: set pindirs, 2 - 0x2021, // 12: wait 0 pin, 1 - 0xe029, // 13: set x, 9 - 0x6081, // 14: out pindirs, 1 - 0x20a1, // 15: wait 1 pin, 1 - 0x2021, // 16: wait 0 pin, 1 - 0x004e, // 17: jmp x--, 14 - 0xe083, // 18: set pindirs, 3 - 0x2021, // 19: wait 0 pin, 1 - 0x20a1, // 20: wait 1 pin, 1 - // .wrap + // .wrap_target + 0x00c7, // 0: jmp pin, 7 + 0xe02a, // 1: set x, 10 + 0x2000 | PS2_CLOCK_PIN, // 2: wait 0 gpio, CLK + 0x4001, // 3: in pins, 1 + 0x2080 | PS2_CLOCK_PIN, // 4: wait 1 gpio, CLK + 0x0042, // 5: jmp x--, 2 + 0x0000, // 6: jmp 0 + 0x00e9, // 7: jmp !osre, 9 + 0x0000, // 8: jmp 0 + 0xff80 | PS2_DATA_PINDIR_BIT, // 9: set pindirs, DATA [31] + 0xe280, // 10: set pindirs, 0 [2] + 0xe080 | PS2_CLOCK_PINDIR_BIT, // 11: set pindirs, CLK + 0x2000 | PS2_CLOCK_PIN, // 12: wait 0 gpio, CLK + 0xe029, // 13: set x, 9 + 0x6081, // 14: out pindirs, 1 + 0x2080 | PS2_CLOCK_PIN, // 15: wait 1 gpio, CLK + 0x2000 | PS2_CLOCK_PIN, // 16: wait 0 gpio, CLK + 0x004e, // 17: jmp x--, 14 + 0xe083, // 18: set pindirs, 3 + 0x2000 | PS2_CLOCK_PIN, // 19: wait 0 gpio, CLK + 0x2080 | PS2_CLOCK_PIN, // 20: wait 1 gpio, CLK + // .wrap }; // clang-format on @@ -133,9 +141,9 @@ void ps2_host_init(void) { sm_config_set_wrap(&c, offset + PS2_WRAP_TARGET, offset + PS2_WRAP); // Set pindirs to input (output enable is inverted below) - pio_sm_set_consecutive_pindirs(pio, state_machine, PS2_DATA_PIN, 2, true); + pio_sm_set_consecutive_pindirs(pio, state_machine, PS2_FIRST_PIN, 2, true); sm_config_set_clkdiv(&c, (float)clock_get_hz(clk_sys) / (200.0f * KHZ)); - sm_config_set_set_pins(&c, PS2_DATA_PIN, 2); + sm_config_set_set_pins(&c, PS2_FIRST_PIN, 2); sm_config_set_out_pins(&c, PS2_DATA_PIN, 1); sm_config_set_out_shift(&c, true, true, 10); sm_config_set_in_shift(&c, true, true, 11);