summaryrefslogtreecommitdiff
path: root/hid/pico/src/ph_ps2_phy.pio
blob: 197861688b6d8f7ec3e3d843d5846cf4d9031524 (plain)
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
82
83
;
; 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                 // 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    nowait 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                [7]
  
sendcheck:
  jmp    !osre, send                // see if we have data to send
  jmp    receivecheck               // no data to send, restart

send:
  irq    nowait 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
  out    null, 32                   // clear OSR
  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);
  }
%}