]> git.donarmstrong.com Git - qmk_firmware.git/blob - protocol/ibm4704.c
Add Initial files of 4704_usb
[qmk_firmware.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     // POR
24     //_delay_ms(2500);
25     //while ( 0xA3 != ibm4704_recv() ) ;
26
27     inhibit();
28     DDRD |= 1<<3;
29     PORTD &= ~(1<<3);
30 }
31
32 uint8_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();
40 PIND |= 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);
49 PIND |= 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);
61 PIND |= 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;
75 ERROR:
76     inhibit();
77 xprintf("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 */
83 uint8_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 /*
95 Keyboard to Host:
96 Clock   ~~~~___~~_~~_~~_~~_~~_~~_~~_~~_~~_~~~~~~~~ H:60us/L:30us
97
98 Data    ____~~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 */
103 uint8_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;
143 ERROR:
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 }