Remove pin ordering restriction in RP2040 ps2 driver (#26256)

This commit is contained in:
gitaen
2026-06-15 01:36:02 +02:00
committed by GitHub
parent 92dc82ae08
commit 4f6c5d2745
2 changed files with 36 additions and 28 deletions
+1 -1
View File
@@ -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
+35 -27
View File
@@ -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);