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 /tmk_core/protocol | |
| parent | 5ea50bfb30fa9917f6c1209a7ae7f31b7e7b4095 (diff) | |
| download | qmk_firmware-d42aa47809c97a77c49e9396201c2b5c3956bb54.tar.gz qmk_firmware-d42aa47809c97a77c49e9396201c2b5c3956bb54.zip | |
Fix ibm4704 protocol with using interrupt
Diffstat (limited to 'tmk_core/protocol')
| -rw-r--r-- | tmk_core/protocol/ibm4704.c | 135 |
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 | ||
| 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 | } |
