aboutsummaryrefslogtreecommitdiff
path: root/protocol/ibm4704.c
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2014-02-09 02:42:17 +0900
committertmk <nobody@nowhere>2014-02-09 02:42:17 +0900
commitebe951a445b5d774542731d6165a9c5cd56beb2b (patch)
treef907b82fa3cbeeea4dc8cea96f83ee0d298372d5 /protocol/ibm4704.c
parentcb3a547ebff8e09401c7d635ed24585a7521bb19 (diff)
downloadqmk_firmware-ebe951a445b5d774542731d6165a9c5cd56beb2b.tar.gz
qmk_firmware-ebe951a445b5d774542731d6165a9c5cd56beb2b.zip
Add Initial files of 4704_usb
Diffstat (limited to 'protocol/ibm4704.c')
-rw-r--r--protocol/ibm4704.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/protocol/ibm4704.c b/protocol/ibm4704.c
new file mode 100644
index 000000000..26441ed52
--- /dev/null
+++ b/protocol/ibm4704.c
@@ -0,0 +1,150 @@
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 // POR
24 //_delay_ms(2500);
25 //while ( 0xA3 != ibm4704_recv() ) ;
26
27 inhibit();
28 DDRD |= 1<<3;
29 PORTD &= ~(1<<3);
30}
31
32uint8_t ibm4704_send(uint8_t data)
33{
34 bool parity = true; // odd parity
35 ibm4704_error = 0;
36
37 /* Request to send */
38 idle();
39 clock_lo();
40PIND |= 1<<3;
41
42 /* wait for Start bit(Clock:lo/Data:hi) */
43 WAIT(data_hi, 300, 0x30);
44
45 /* Data bit */
46 for (uint8_t i = 0; i < 8; i++) {
47 WAIT(clock_hi, 100, 0x31);
48 //_delay_us(5);
49PIND |= 1<<3;
50 if (data&(1<<i)) {
51 parity = !parity;
52 data_hi();
53 } else {
54 data_lo();
55 }
56 WAIT(clock_lo, 100, 0x32);
57 }
58
59 /* Parity bit */
60 WAIT(clock_hi, 100, 4);
61PIND |= 1<<3;
62 if (parity) { data_hi(); } else { data_lo(); }
63 WAIT(clock_lo, 100, 5);
64
65 /* Stop bit */
66 WAIT(clock_hi, 100, 4);
67 data_hi();
68
69 /* End */
70 WAIT(data_lo, 100, 6);
71
72 inhibit();
73 _delay_us(200); // wait to recover clock to hi
74 return 0;
75ERROR:
76 inhibit();
77xprintf("x%02X ", ibm4704_error);
78 _delay_us(200); // wait to recover clock to hi
79 return -1;
80}
81
82/* receive data when host want else inhibit communication */
83uint8_t ibm4704_recv_response(void)
84{
85 // 250 * 100us(wait start bit in ibm4704_recv)
86 uint8_t data = 0;
87 uint8_t try = 250;
88 do {
89 data = ibm4704_recv();
90 } while (try-- && ibm4704_error);
91 return data;
92}
93
94/*
95Keyboard to Host:
96Clock ~~~~___~~_~~_~~_~~_~~_~~_~~_~~_~~_~~~~~~~~ H:60us/L:30us
97
98Data ____~~X==X==X==X==X==X==X==X==X==X________
99 | 0 1 2 3 4 5 6 7 P(odd)
100 | LSB MSB
101 Start bit(80us)
102*/
103uint8_t ibm4704_recv(void)
104{
105 uint8_t data = 0;
106 bool parity = true; // odd parity
107 ibm4704_error = IBM4704_ERR_NONE;
108
109 idle();
110 _delay_us(5); // wait for line settles
111
112 /* start bit */
113 WAIT(clock_lo, 100, 1); // wait for keyboard to send
114 WAIT(data_hi, 100, 2); // can be delayed that long
115
116 WAIT(clock_hi, 100, 3); // first rising edge which can take longer
117 /* data */
118 for (uint8_t i = 0; i < 8; i++) {
119 WAIT(clock_hi, 100, 0x20+i);
120 //_delay_us(5);
121 if (data_in()) {
122 parity = !parity;
123 data |= (1<<i);
124 }
125 WAIT(clock_lo, 150, 0x28+i);
126 }
127
128 /* parity */
129 WAIT(clock_hi, 100, 7);
130 if (data_in() != parity) {
131 ibm4704_error = IBM4704_ERR_PARITY;
132 goto ERROR;
133 }
134 WAIT(clock_lo, 150, 8);
135
136 /* stop bit */
137 WAIT(clock_hi, 100, 9);
138 WAIT(data_lo, 1, 9);
139
140 inhibit();
141 _delay_us(200); // wait to recover clock to hi
142 return data;
143ERROR:
144 if (ibm4704_error > 2) {
145 xprintf("x%02X ", ibm4704_error);
146 }
147 inhibit();
148 _delay_us(200); // wait to recover clock to hi
149 return -1;
150}