aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/protocol/ibm4704.c
diff options
context:
space:
mode:
authortmk <hasu@tmk-kbd.com>2015-04-10 01:32:04 +0900
committertmk <hasu@tmk-kbd.com>2015-04-10 01:32:04 +0900
commit1a02ebcc612e9a9c0d87e02295c7258de3a70ccc (patch)
treee517f3c70bb2d542797e57d13e9023c84af230fb /tmk_core/protocol/ibm4704.c
parent6746e37088ce8ba03529c1226bd216705edb2b1f (diff)
parenta074364c3731d66b56d988c8a6c960a83ea0e0a1 (diff)
downloadqmk_firmware-1a02ebcc612e9a9c0d87e02295c7258de3a70ccc.tar.gz
qmk_firmware-1a02ebcc612e9a9c0d87e02295c7258de3a70ccc.zip
Merge commit 'a074364c3731d66b56d988c8a6c960a83ea0e0a1' as 'tmk_core'
Diffstat (limited to 'tmk_core/protocol/ibm4704.c')
-rw-r--r--tmk_core/protocol/ibm4704.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/tmk_core/protocol/ibm4704.c b/tmk_core/protocol/ibm4704.c
new file mode 100644
index 000000000..10e229fd1
--- /dev/null
+++ b/tmk_core/protocol/ibm4704.c
@@ -0,0 +1,169 @@
1/*
2Copyright 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
18uint8_t ibm4704_error = 0;
19
20
21void ibm4704_init(void)
22{
23 inhibit();
24}
25
26/*
27Host to Keyboard
28----------------
29Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
30
31 ____ __ __ __ __ __ __ __ __ __ ________
32Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
33 ^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___
34Data ____|__/ 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
38Start bit: can be long as 300-350us.
39Request: Host pulls Clock line down to request to send a command.
40Timing: 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.
43Stop bit: Host releases or pulls up Data line to hi after 9th clock and waits for keyboard pull down the line to lo.
44*/
45uint8_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;
85ERROR:
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 */
95uint8_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/*
107Keyboard to Host
108----------------
109Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
110
111 ____ __ __ __ __ __ __ __ __ __ ________
112Clock \____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
113 ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
114Data ____/ X____X____X____X____X____X____X____X____X____X________
115 Start 0 1 2 3 4 5 6 7 P Stop
116
117Start bit: can be long as 300-350us.
118Inhibit: Pull Data line down to inhibit keyboard to send.
119Timing: Host reads bit while Clock is hi.
120Stop bit: Keyboard pulls down Data line to lo after 9th clock.
121*/
122uint8_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;
162ERROR:
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}