]> git.donarmstrong.com Git - tmk_firmware.git/blob - protocol/ibm4704.c
Change error no and clean debug code
[tmk_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     inhibit();
24 }
25
26 uint8_t ibm4704_send(uint8_t data)
27 {
28     bool parity = true; // odd parity
29     ibm4704_error = 0;
30
31     /* Request to send */
32     idle();
33     clock_lo();
34
35     /* wait for Start bit(Clock:lo/Data:hi) */
36     WAIT(data_hi, 300, 0x30);
37
38     /* Data bit */
39     for (uint8_t i = 0; i < 8; i++) {
40         WAIT(clock_hi, 100, 0x40+i);
41         //_delay_us(5);
42         if (data&(1<<i)) {
43             parity = !parity;
44             data_hi();
45         } else {
46             data_lo();
47         }
48         WAIT(clock_lo, 100, 0x48+i);
49     }
50
51     /* Parity bit */
52     WAIT(clock_hi, 100, 0x34);
53     if (parity) { data_hi(); } else { data_lo(); }
54     WAIT(clock_lo, 100, 0x35);
55
56     /* Stop bit */
57     WAIT(clock_hi, 100, 0x34);
58     data_hi();
59
60     /* End */
61     WAIT(data_lo, 100, 0x36);
62
63     inhibit();
64     _delay_us(200); // wait to recover clock to hi
65     return 0;
66 ERROR:
67     inhibit();
68     if (ibm4704_error >= 0x30) {
69         xprintf("x%02X ", ibm4704_error);
70     }
71     _delay_us(200); // wait to recover clock to hi
72     return -1;
73 }
74
75 /* receive data when host want else inhibit communication */
76 uint8_t ibm4704_recv_response(void)
77 {
78     // 250 * 100us(wait start bit in ibm4704_recv)
79     uint8_t data = 0;
80     uint8_t try = 250;
81     do {
82         data = ibm4704_recv();
83     } while (try-- && ibm4704_error);
84     return data;
85 }
86
87 /*
88 Keyboard to Host:
89 Clock   ~~~~___~~_~~_~~_~~_~~_~~_~~_~~_~~_~~~~~~~~ H:60us/L:30us
90
91 Data    ____~~X==X==X==X==X==X==X==X==X==X________
92             |  0  1  2  3  4  5  6  7  P(odd)
93             |  LSB                MSB
94             Start bit(80us)
95 */
96 uint8_t ibm4704_recv(void)
97 {
98     uint8_t data = 0;
99     bool parity = true;    // odd parity
100     ibm4704_error = IBM4704_ERR_NONE;
101
102     idle();
103     _delay_us(5);   // wait for line settles
104
105     /* start bit */
106     WAIT(clock_lo, 100, 0x11); // wait for keyboard to send
107     WAIT(data_hi, 100, 0x12);  // can be delayed that long
108
109     WAIT(clock_hi, 100, 0x13); // first rising edge which can take longer
110     /* data */
111     for (uint8_t i = 0; i < 8; i++) {
112         WAIT(clock_hi, 100, 0x20+i);
113         //_delay_us(5);
114         if (data_in()) {
115             parity = !parity;
116             data |= (1<<i);
117         }
118         WAIT(clock_lo, 150, 0x28+i);
119     }
120
121     /* parity */
122     WAIT(clock_hi, 100, 0x17);
123     if (data_in() != parity) {
124         ibm4704_error = IBM4704_ERR_PARITY;
125         goto ERROR;
126     }
127     WAIT(clock_lo, 150, 0x18);
128
129     /* stop bit */
130     WAIT(clock_hi, 100, 0x19);
131     WAIT(data_lo, 1, 0x19);
132
133     inhibit();
134     _delay_us(200); // wait to recover clock to hi
135     return data;
136 ERROR:
137     if (ibm4704_error > 0x12) {
138         xprintf("x%02X ", ibm4704_error);
139     }
140     inhibit();
141     _delay_us(200); // wait to recover clock to hi
142     return -1;
143 }