summaryrefslogtreecommitdiff
path: root/hid/pico/src/ph_ps2.pio
blob: 2313419d52ee429554afdf1e6097ddcd122b1c2b (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
84
85
86
;
; Copyright (c) 2022 No0ne (https://github.com/No0ne)
;           (c) 2023 Dustin Hoffman
;
; SPDX-License-Identifier: MIT
;

.program ps2device
.side_set 1 opt pindirs

  //mov y ! null
start:
.wrap_target
  set pindirs 0 side 0 // Clock and data to input mode.
  jmp pin sendcheck // If clock is high, see if we have data to send.
  // Clock is being pulled low.
  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 start // Not receiving, restart.

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
  //in null 1
.wrap

sendcheck:
  jmp !osre wait_to_write // See if we have data to send.
  jmp start // No data to send, restart.

wait_to_write:
  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.
  // Pin was low, host wants to send data.
  // Notify of failure to send data..
  //in null 8
  //in y 2
  jmp start
sendcontinue:
  out pindirs, 1 [6] // Write out data.
  set pindirs, 1 [6] // Set clock low.
  jmp x-- sendloop [6]
  //in y 10
  jmp start

% c-sdk {

  void ps2device_program_init(PIO pio, uint sm, uint offset, uint dat) {
    pio_sm_config c = ps2device_program_get_default_config(offset);
    
    uint 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 us,  640 is 5 us,  427 is 3.3333 us
    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);
  }

%}