diff options
author | tmk <nobody@nowhere> | 2014-10-27 21:39:02 +0900 |
---|---|---|
committer | Jun Wako <wakojun@gmail.com> | 2015-04-22 14:18:13 +0900 |
commit | d42aa47809c97a77c49e9396201c2b5c3956bb54 (patch) | |
tree | 07331fbb4b67630a5571f31af071021fbc9eb160 | |
parent | 5ea50bfb30fa9917f6c1209a7ae7f31b7e7b4095 (diff) | |
download | qmk_firmware-d42aa47809c97a77c49e9396201c2b5c3956bb54.tar.gz qmk_firmware-d42aa47809c97a77c49e9396201c2b5c3956bb54.zip |
Fix ibm4704 protocol with using interrupt
-rw-r--r-- | common/ring_buffer.h | 53 | ||||
-rw-r--r-- | converter/ibm4704_usb/config.h | 2 | ||||
-rw-r--r-- | converter/ibm4704_usb/matrix.c | 41 | ||||
-rw-r--r-- | tmk_core/protocol/ibm4704.c | 135 |
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 | ||
7 | static uint8_t rbuf[RBUF_SIZE]; | ||
8 | static uint8_t rbuf_head = 0; | ||
9 | static uint8_t rbuf_tail = 0; | ||
10 | static 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 | } | ||
23 | static 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 | } | ||
37 | static 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 | } | ||
45 | static 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 | ||
90 | void matrix_init(void) | 87 | void 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 | ||
21 | void ibm4704_init(void) | 22 | void 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; |
85 | ERROR: | 89 | ERROR: |
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 */ |
95 | uint8_t ibm4704_recv_response(void) | 99 | uint8_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 | */ |
122 | uint8_t ibm4704_recv(void) | 123 | uint8_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 */ | 132 | ISR(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? |
162 | ERROR: | 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 | 180 | ERROR: |
168 | return -1; | 181 | ibm4704_error = state; |
182 | while (ibm4704_send(0xFE)) _delay_ms(1); // resend | ||
183 | xprintf("R:%02X\n", data); | ||
184 | DONE: | ||
185 | state = INIT; | ||
186 | data = 0; | ||
187 | parity = false; | ||
188 | RETURN: | ||
189 | return; | ||
169 | } | 190 | } |