]> git.gir.st - tmk_keyboard.git/blob - protocol/ibm4704.c
Squashed 'tmk_core/' content from commit 05caacc
[tmk_keyboard.git] / protocol / ibm4704.c
1 /*
2 Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3 */
4 #include <stdbool.h>
5 #include <util/delay.h>
6 #include "debug.h"
7 #include "ibm4704.h"
8
9
10 #define WAIT(stat, us, err) do { \
11 if (!wait_##stat(us)) { \
12 ibm4704_error = err; \
13 goto ERROR; \
14 } \
15 } while (0)
16
17
18 uint8_t ibm4704_error = 0;
19
20
21 void ibm4704_init(void)
22 {
23 inhibit();
24 }
25
26 /*
27 Host to Keyboard
28 ----------------
29 Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
30
31 ____ __ __ __ __ __ __ __ __ __ ________
32 Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
33 ^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___
34 Data ____|__/ X____X____X____X____X____X____X____X____X____X \___
35 | Start 0 1 2 3 4 5 6 7 P Stop
36 Request by host
37
38 Start bit: can be long as 300-350us.
39 Request: Host pulls Clock line down to request to send a command.
40 Timing: After Request keyboard pull up Data and down Clock line to low for start bit.
41 After request host release Clock line once Data line becomes hi.
42 Host writes a bit while Clock is hi and Keyboard reads while low.
43 Stop bit: Host releases or pulls up Data line to hi after 9th clock and waits for keyboard pull down the line to lo.
44 */
45 uint8_t ibm4704_send(uint8_t data)
46 {
47 bool parity = true; // odd parity
48 ibm4704_error = 0;
49
50 /* Request to send */
51 idle();
52 clock_lo();
53
54 /* wait for Start bit(Clock:lo/Data:hi) */
55 WAIT(data_hi, 300, 0x30);
56
57 /* Data bit */
58 for (uint8_t i = 0; i < 8; i++) {
59 WAIT(clock_hi, 100, 0x40+i);
60 //_delay_us(5);
61 if (data&(1<<i)) {
62 parity = !parity;
63 data_hi();
64 } else {
65 data_lo();
66 }
67 WAIT(clock_lo, 100, 0x48+i);
68 }
69
70 /* Parity bit */
71 WAIT(clock_hi, 100, 0x34);
72 if (parity) { data_hi(); } else { data_lo(); }
73 WAIT(clock_lo, 100, 0x35);
74
75 /* Stop bit */
76 WAIT(clock_hi, 100, 0x34);
77 data_hi();
78
79 /* End */
80 WAIT(data_lo, 100, 0x36);
81
82 inhibit();
83 _delay_us(200); // wait to recover clock to hi
84 return 0;
85 ERROR:
86 inhibit();
87 if (ibm4704_error >= 0x30) {
88 xprintf("x%02X ", ibm4704_error);
89 }
90 _delay_us(200); // wait to recover clock to hi
91 return -1;
92 }
93
94 /* receive data when host want else inhibit communication */
95 uint8_t ibm4704_recv_response(void)
96 {
97 // 250 * 100us(wait start bit in ibm4704_recv)
98 uint8_t data = 0;
99 uint8_t try = 250;
100 do {
101 data = ibm4704_recv();
102 } while (try-- && ibm4704_error);
103 return data;
104 }
105
106 /*
107 Keyboard to Host
108 ----------------
109 Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
110
111 ____ __ __ __ __ __ __ __ __ __ ________
112 Clock \____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
113 ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
114 Data ____/ X____X____X____X____X____X____X____X____X____X________
115 Start 0 1 2 3 4 5 6 7 P Stop
116
117 Start bit: can be long as 300-350us.
118 Inhibit: Pull Data line down to inhibit keyboard to send.
119 Timing: Host reads bit while Clock is hi.
120 Stop bit: Keyboard pulls down Data line to lo after 9th clock.
121 */
122 uint8_t ibm4704_recv(void)
123 {
124 uint8_t data = 0;
125 bool parity = true; // odd parity
126 ibm4704_error = IBM4704_ERR_NONE;
127
128 idle();
129 _delay_us(5); // wait for line settles
130
131 /* start bit */
132 WAIT(clock_lo, 100, 0x11); // wait for keyboard to send
133 WAIT(data_hi, 100, 0x12); // can be delayed that long
134
135 WAIT(clock_hi, 100, 0x13); // first rising edge which can take longer
136 /* data */
137 for (uint8_t i = 0; i < 8; i++) {
138 WAIT(clock_hi, 100, 0x20+i);
139 //_delay_us(5);
140 if (data_in()) {
141 parity = !parity;
142 data |= (1<<i);
143 }
144 WAIT(clock_lo, 150, 0x28+i);
145 }
146
147 /* parity */
148 WAIT(clock_hi, 100, 0x17);
149 if (data_in() != parity) {
150 ibm4704_error = IBM4704_ERR_PARITY;
151 goto ERROR;
152 }
153 WAIT(clock_lo, 150, 0x18);
154
155 /* stop bit */
156 WAIT(clock_hi, 100, 0x19);
157 WAIT(data_lo, 1, 0x19);
158
159 inhibit();
160 _delay_us(200); // wait to recover clock to hi
161 return data;
162 ERROR:
163 if (ibm4704_error > 0x12) {
164 xprintf("x%02X ", ibm4704_error);
165 }
166 inhibit();
167 _delay_us(200); // wait to recover clock to hi
168 return -1;
169 }
Imprint / Impressum