1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
;
; Copyright (c) 2022 No0ne (https://github.com/No0ne)
; (c) 2023 Dustin Hoffman
;
; SPDX-License-Identifier: MIT
;
; Source: https://github.com/No0ne/ps2x2pico/blob/main/ps2phy.pio
.program ph_ps2_phy
.side_set 1 opt pindirs
restart:
set pindirs 0 [4] // set clock to input mode
irq clear 0 rel side 0 // clear busy flag, set data to input mode
receivecheck:
jmp pin sendcheck // if clock is high, see if we have data to send
irq set 0 rel // clock is being pulled low, set busy flag
wait 1 pin 1 // wait for clock to be pulled high
// we are not sending, look for a start bit (clock high, data low)
in pins 1 // read in from data
mov x isr // move what we read to x
mov isr null // clear ISR
jmp !x receive // if x is low, start the receive process
jmp restart // not receiving
receive:
set pindirs, 1 [6] // clock low
set x, 8 // set loop counter
receiveloop:
set pindirs, 0 [6] // clock high
in pins, 1 [4] // read a bit into ISR
set pindirs, 1 [6] // clock low
jmp x-- receiveloop [4] // iterate
set pindirs, 0 [6] // clock high
nop side 1 [6] // data low
set pindirs, 1 [7] // clock low
jmp restart
sendcheck:
jmp !osre wait_to_write // see if we have data to send
jmp receivecheck // no data to send, restart
wait_to_write:
irq set 0 rel // set busy flag
set x 10 // number of bits to write out
sendloop:
set pindirs, 0 [6] // clock set to input (high)
jmp pin sendcontinue // if clock is high, host is still receiving data
irq wait 4 rel // clock was low, host wants to send data, notify of failure to send data
jmp restart // and wait for restart
sendcontinue:
out pindirs, 1 [6] // write out data
set pindirs, 1 [6] // set clock low
jmp x-- sendloop [6]
% c-sdk {
void ph_ps2_phy_program_init(PIO pio, uint sm, uint offset, uint dat) {
pio_sm_config c = ph_ps2_phy_program_get_default_config(offset);
u8 clk = dat + 1;
pio_gpio_init(pio, clk);
pio_gpio_init(pio, dat);
// Use a frequency high enough to effectivly sample clock and data.
sm_config_set_clkdiv(&c, 427); // 2560 is 20 µs, 640 is 5 µs, 427 is 3.3333 µs
sm_config_set_jmp_pin(&c, clk);
sm_config_set_set_pins(&c, clk, 1);
sm_config_set_sideset_pins(&c, dat);
sm_config_set_out_pins(&c, dat, 1);
sm_config_set_out_shift(&c, true, true, 11);
sm_config_set_in_pins(&c, dat);
sm_config_set_in_shift(&c, true, true, 9);
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}
%}
|