aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2014-10-27 21:39:02 +0900
committerJun Wako <wakojun@gmail.com>2015-04-22 14:18:13 +0900
commitd42aa47809c97a77c49e9396201c2b5c3956bb54 (patch)
tree07331fbb4b67630a5571f31af071021fbc9eb160
parent5ea50bfb30fa9917f6c1209a7ae7f31b7e7b4095 (diff)
downloadqmk_firmware-d42aa47809c97a77c49e9396201c2b5c3956bb54.tar.gz
qmk_firmware-d42aa47809c97a77c49e9396201c2b5c3956bb54.zip
Fix ibm4704 protocol with using interrupt
-rw-r--r--common/ring_buffer.h53
-rw-r--r--converter/ibm4704_usb/config.h2
-rw-r--r--converter/ibm4704_usb/matrix.c41
-rw-r--r--tmk_core/protocol/ibm4704.c135
4 files changed, 149 insertions, 82 deletions
diff --git a/common/ring_buffer.h b/common/ring_buffer.h
new file mode 100644
index 000000000..7bdebbcf3
--- /dev/null
+++ b/common/ring_buffer.h
@@ -0,0 +1,53 @@
1#ifndef RING_BUFFER_H
2#define RING_BUFFER_H
3/*--------------------------------------------------------------------
4 * Ring buffer to store scan codes from keyboard
5 *------------------------------------------------------------------*/
6#define RBUF_SIZE 32
7static uint8_t rbuf[RBUF_SIZE];
8static uint8_t rbuf_head = 0;
9static uint8_t rbuf_tail = 0;
10static inline void rbuf_enqueue(uint8_t data)
11{
12 uint8_t sreg = SREG;
13 cli();
14 uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
15 if (next != rbuf_tail) {
16 rbuf[rbuf_head] = data;
17 rbuf_head = next;
18 } else {
19 print("rbuf: full\n");
20 }
21 SREG = sreg;
22}
23static inline uint8_t rbuf_dequeue(void)
24{
25 uint8_t val = 0;
26
27 uint8_t sreg = SREG;
28 cli();
29 if (rbuf_head != rbuf_tail) {
30 val = rbuf[rbuf_tail];
31 rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
32 }
33 SREG = sreg;
34
35 return val;
36}
37static inline bool rbuf_has_data(void)
38{
39 uint8_t sreg = SREG;
40 cli();
41 bool has_data = (rbuf_head != rbuf_tail);
42 SREG = sreg;
43 return has_data;
44}
45static inline void rbuf_clear(void)
46{
47 uint8_t sreg = SREG;
48 cli();
49 rbuf_head = rbuf_tail = 0;
50 SREG = sreg;
51}
52
53#endif /* RING_BUFFER_H */
diff --git a/converter/ibm4704_usb/config.h b/converter/ibm4704_usb/config.h
index 4f82f49ad..812d95c67 100644
--- a/converter/ibm4704_usb/config.h
+++ b/converter/ibm4704_usb/config.h
@@ -56,7 +56,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
56/* 56/*
57 * Pin interrupt 57 * Pin interrupt
58 */ 58 */
59#ifdef IBM4704_USE_INT
60#define IBM4704_INT_INIT() do { \ 59#define IBM4704_INT_INIT() do { \
61 EICRA |= ((1<<ISC11) | \ 60 EICRA |= ((1<<ISC11) | \
62 (0<<ISC10)); \ 61 (0<<ISC10)); \
@@ -68,7 +67,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
68 EIMSK &= ~(1<<INT1); \ 67 EIMSK &= ~(1<<INT1); \
69} while (0) 68} while (0)
70#define IBM4704_INT_VECT INT1_vect 69#define IBM4704_INT_VECT INT1_vect
71#endif
72 70
73 71
74#endif 72#endif
diff --git a/converter/ibm4704_usb/matrix.c b/converter/ibm4704_usb/matrix.c
index 0bfda2b15..857dea0f9 100644
--- a/converter/ibm4704_usb/matrix.c
+++ b/converter/ibm4704_usb/matrix.c
@@ -69,41 +69,34 @@ static void enable_break(void)
69{ 69{
70 uint8_t ret; 70 uint8_t ret;
71 print("Enable break: "); 71 print("Enable break: ");
72 // valid scancode: 00-77h 72 // valid scancode: 00-79h
73 for (uint8_t code = 0; code < 0x78; code++) { 73 for (uint8_t code = 0; code < 0x7A; code++) {
74 while (ibm4704_send(0x80|code) != 0) { 74 while (ibm4704_send(0x80|code)) _delay_ms(1);
75 print("z"); 75 // get none when ok, get FD when out of bound
76 _delay_us(500); 76 _delay_ms(5);
77 } 77 if ((ret = ibm4704_recv()) != 0xff) {
78 _delay_us(2000);
79 ret = ibm4704_recv();
80 if (ret != 0xff) {
81 xprintf("c%02X:r%02X ", code, ret); 78 xprintf("c%02X:r%02X ", code, ret);
82 } 79 }
83 _delay_us(1000); 80 _delay_ms(1);
84 } 81 }
85 _delay_us(1000); 82 _delay_us(1000);
86 while (ibm4704_send(0xFF) != 0) { _delay_us(500); } // End 83 while (ibm4704_send(0xFF)) { _delay_ms(1); } // End
87 print("End\n"); 84 print("End\n");
88} 85}
89 86
90void matrix_init(void) 87void matrix_init(void)
91{ 88{
92 uint8_t ret; 89 debug_enable = false;
93 debug_enable = true;
94 90
95 ibm4704_init(); 91 ibm4704_init();
96 matrix_clear(); 92 matrix_clear();
97 93
98 // read keyboard id 94 _delay_ms(2000); // wait for starting up debug console
99 while ((ret = ibm4704_recv()) == 0xFF) {
100 ibm4704_send(0xFE);
101 _delay_us(100);
102 }
103 95
104 _delay_ms(2000); // wait for starting up debug console
105 print("IBM 4704 converter\n"); 96 print("IBM 4704 converter\n");
106 xprintf("Keyboard ID: %02X\n", ret); 97 while (ibm4704_send(0xFE)) _delay_ms(1); // resend
98 _delay_ms(5);
99 xprintf("Keyboard ID: %02X\n", ibm4704_recv());
107 enable_break(); 100 enable_break();
108} 101}
109 102
@@ -116,14 +109,16 @@ uint8_t matrix_scan(void)
116 if (code==0xFF) { 109 if (code==0xFF) {
117 // Not receivd 110 // Not receivd
118 return 0; 111 return 0;
119 } else if ((code&0x78)==0x78) { 112 } else if ((code&0x7F) >= 0x7A) {
120 // 0xFF-F8 and 0x7F-78 is not scancode 113 // 0xFF-FA and 0x7F-7A is not scancode
121 xprintf("Error: %0X\n", code); 114 xprintf("Error: %02X\n", code);
122 matrix_clear(); 115 matrix_clear();
123 return 0; 116 return 0;
124 } else if (code&0x80) { 117 } else if (code&0x80) {
118 dprintf("%02X\n", code);
125 matrix_make(code); 119 matrix_make(code);
126 } else { 120 } else {
121 dprintf("%02X\n", code);
127 matrix_break(code); 122 matrix_break(code);
128 } 123 }
129 return 1; 124 return 1;
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}