aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/protocol/ibm4704.c
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/protocol/ibm4704.c')
-rw-r--r--tmk_core/protocol/ibm4704.c135
1 files changed, 78 insertions, 57 deletions
diff --git a/tmk_core/protocol/ibm4704.c b/tmk_core/protocol/ibm4704.c
index 10e229fd1..152d7e61b 100644
--- a/tmk_core/protocol/ibm4704.c
+++ b/tmk_core/protocol/ibm4704.c
@@ -4,6 +4,7 @@ Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
4#include <stdbool.h> 4#include <stdbool.h>
5#include <util/delay.h> 5#include <util/delay.h>
6#include "debug.h" 6#include "debug.h"
7#include "ring_buffer.h"
7#include "ibm4704.h" 8#include "ibm4704.h"
8 9
9 10
@@ -20,7 +21,9 @@ uint8_t ibm4704_error = 0;
20 21
21void ibm4704_init(void) 22void ibm4704_init(void)
22{ 23{
23 inhibit(); 24 IBM4704_INT_INIT();
25 IBM4704_INT_ON();
26 idle();
24} 27}
25 28
26/* 29/*
@@ -47,6 +50,8 @@ uint8_t ibm4704_send(uint8_t data)
47 bool parity = true; // odd parity 50 bool parity = true; // odd parity
48 ibm4704_error = 0; 51 ibm4704_error = 0;
49 52
53 IBM4704_INT_OFF();
54
50 /* Request to send */ 55 /* Request to send */
51 idle(); 56 idle();
52 clock_lo(); 57 clock_lo();
@@ -57,7 +62,6 @@ uint8_t ibm4704_send(uint8_t data)
57 /* Data bit */ 62 /* Data bit */
58 for (uint8_t i = 0; i < 8; i++) { 63 for (uint8_t i = 0; i < 8; i++) {
59 WAIT(clock_hi, 100, 0x40+i); 64 WAIT(clock_hi, 100, 0x40+i);
60 //_delay_us(5);
61 if (data&(1<<i)) { 65 if (data&(1<<i)) {
62 parity = !parity; 66 parity = !parity;
63 data_hi(); 67 data_hi();
@@ -79,28 +83,25 @@ uint8_t ibm4704_send(uint8_t data)
79 /* End */ 83 /* End */
80 WAIT(data_lo, 100, 0x36); 84 WAIT(data_lo, 100, 0x36);
81 85
82 inhibit(); 86 idle();
83 _delay_us(200); // wait to recover clock to hi 87 IBM4704_INT_ON();
84 return 0; 88 return 0;
85ERROR: 89ERROR:
86 inhibit(); 90 idle();
87 if (ibm4704_error >= 0x30) { 91 if (ibm4704_error > 0x30) {
88 xprintf("x%02X ", ibm4704_error); 92 xprintf("S:%02X ", ibm4704_error);
89 } 93 }
90 _delay_us(200); // wait to recover clock to hi 94 IBM4704_INT_ON();
91 return -1; 95 return -1;
92} 96}
93 97
94/* receive data when host want else inhibit communication */ 98/* wait forever to receive data */
95uint8_t ibm4704_recv_response(void) 99uint8_t ibm4704_recv_response(void)
96{ 100{
97 // 250 * 100us(wait start bit in ibm4704_recv) 101 while (!rbuf_has_data()) {
98 uint8_t data = 0; 102 _delay_ms(1);
99 uint8_t try = 250; 103 }
100 do { 104 return rbuf_dequeue();
101 data = ibm4704_recv();
102 } while (try-- && ibm4704_error);
103 return data;
104} 105}
105 106
106/* 107/*
@@ -121,49 +122,69 @@ Stop bit: Keyboard pulls down Data line to lo after 9th clock.
121*/ 122*/
122uint8_t ibm4704_recv(void) 123uint8_t ibm4704_recv(void)
123{ 124{
124 uint8_t data = 0; 125 if (rbuf_has_data()) {
125 bool parity = true; // odd parity 126 return rbuf_dequeue();
126 ibm4704_error = IBM4704_ERR_NONE; 127 } else {
127 128 return -1;
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 } 129 }
130}
146 131
147 /* parity */ 132ISR(IBM4704_INT_VECT)
148 WAIT(clock_hi, 100, 0x17); 133{
149 if (data_in() != parity) { 134 static enum {
150 ibm4704_error = IBM4704_ERR_PARITY; 135 INIT, START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY,
151 goto ERROR; 136 } state = INIT;
152 } 137 // LSB first
153 WAIT(clock_lo, 150, 0x18); 138 static uint8_t data = 0;
154 139 // Odd parity
155 /* stop bit */ 140 static uint8_t parity = false;
156 WAIT(clock_hi, 100, 0x19);
157 WAIT(data_lo, 1, 0x19);
158 141
159 inhibit(); 142 ibm4704_error = 0;
160 _delay_us(200); // wait to recover clock to hi 143 // return unless falling edge
161 return data; 144 if (clock_in()) { goto RETURN; } // why this occurs?
162ERROR: 145
163 if (ibm4704_error > 0x12) { 146 state++;
164 xprintf("x%02X ", ibm4704_error); 147 switch (state) {
148 case START:
149 // Data:Low
150 WAIT(data_hi, 10, state);
151 break;
152 case BIT0:
153 case BIT1:
154 case BIT2:
155 case BIT3:
156 case BIT4:
157 case BIT5:
158 case BIT6:
159 case BIT7:
160 data >>= 1;
161 if (data_in()) {
162 data |= 0x80;
163 parity = !parity;
164 }
165 break;
166 case PARITY:
167 if (data_in()) {
168 parity = !parity;
169 }
170 if (!parity)
171 goto ERROR;
172 rbuf_enqueue(data);
173 ibm4704_error = IBM4704_ERR_NONE;
174 goto DONE;
175 break;
176 default:
177 goto ERROR;
165 } 178 }
166 inhibit(); 179 goto RETURN;
167 _delay_us(200); // wait to recover clock to hi 180ERROR:
168 return -1; 181 ibm4704_error = state;
182 while (ibm4704_send(0xFE)) _delay_ms(1); // resend
183 xprintf("R:%02X\n", data);
184DONE:
185 state = INIT;
186 data = 0;
187 parity = false;
188RETURN:
189 return;
169} 190}