|
39 | 39 | // MACRO CONSTANT TYPEDEF PROTYPES
|
40 | 40 | //--------------------------------------------------------------------+
|
41 | 41 |
|
| 42 | +// uncomment if you are using colemak layout |
| 43 | +// #define KEYBOARD_COLEMAK |
| 44 | + |
| 45 | +#ifdef KEYBOARD_COLEMAK |
| 46 | +const uint8_t colemak[128] = { |
| 47 | + 0 , 0, 0, 0, 0, 0, 0, 22, |
| 48 | + 9 , 23, 7, 0, 24, 17, 8, 12, |
| 49 | + 0 , 14, 28, 51, 0, 19, 21, 10, |
| 50 | + 15 , 0, 0, 0, 13, 0, 0, 0, |
| 51 | + 0 , 0, 0, 0, 0, 0, 0, 0, |
| 52 | + 0 , 0, 0, 0, 0, 0, 0, 0, |
| 53 | + 0 , 0, 0, 18, 0, 0, 0, 0, |
| 54 | + 0 , 0, 0, 0, 0, 0, 0, 0, |
| 55 | + 0 , 0, 0, 0, 0, 0, 0, 0, |
| 56 | + 0 , 0, 0, 0, 0, 0, 0, 0 |
| 57 | +}; |
| 58 | +#endif |
| 59 | + |
| 60 | +static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; |
| 61 | + |
42 | 62 | /* Blink pattern
|
43 | 63 | * - 250 ms : device not mounted
|
44 | 64 | * - 1000 ms : device mounted
|
@@ -137,85 +157,89 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
|
137 | 157 | printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
|
138 | 158 | }
|
139 | 159 |
|
140 |
| -const char* numbers = "0123456789"; |
141 |
| - |
142 |
| -// Uncomment if you use colemak and need to remap keys (like @tannewt.) |
143 |
| -// const uint8_t colemak[77] = { |
144 |
| -// 0, 0, 0, 0, 0, 0, 0, 22, |
145 |
| -// 9, 23, 7, 0, 24, 17, 8, 12, |
146 |
| -// 0, 14, 28, 51, 0, 19, 21, 10, |
147 |
| -// 15, 0, 0, 0, 13, 0, 0, 0, |
148 |
| -// 0, 0, 0, 0, 0, 0, 0, 0, |
149 |
| -// 0, 0, 0, 0, 0, 0, 0, 0, |
150 |
| -// 0, 0, 0, 18, 0, 0, 0, 0, |
151 |
| -// 0, 0, 0, 0, 0, 0, 0, 0, |
152 |
| -// 0, 0, 0, 0, 0, 0, 0, 0, |
153 |
| -// 0, 0, 0, 0, 0 |
154 |
| -// }; |
155 |
| - |
156 |
| -// This is the reverse mapping of the US key layout in Adafruit_CircuitPython_HID. |
157 |
| -const char* ascii = "\0\0\0\0abcdefghijklmnopqrstuvwxyz1234567890\n\x1b\x08\t -=[]\\\x00;\'`,./\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x7f"; |
158 |
| -const char* shifted = "\0\0\0\0ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()\0\0\0\0\0_+{}|\0:\"~<>?\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; |
159 |
| -// Bitmask of pressed keys. We use the current modifier state. |
160 |
| -uint32_t last_state[8]; |
| 160 | +// keycodes from last report to check if key is holding or newly pressed |
| 161 | +uint8_t last_keycodes[6] = {0}; |
| 162 | + |
| 163 | +// look up new key in previous keys |
| 164 | +static inline bool key_in_last_report(const uint8_t key_arr[6], uint8_t keycode) |
| 165 | +{ |
| 166 | + for(uint8_t i=0; i<6; i++) |
| 167 | + { |
| 168 | + if (key_arr[i] == keycode) return true; |
| 169 | + } |
| 170 | + |
| 171 | + return false; |
| 172 | +} |
161 | 173 |
|
162 | 174 | // Invoked when received report from device via interrupt endpoint
|
163 | 175 | void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
|
164 | 176 | {
|
165 |
| - if (len != 8 && len < 10) { |
166 |
| - tud_cdc_write("report len: ", 12); |
167 |
| - tud_cdc_write(numbers + len, 1); |
168 |
| - tud_cdc_write("\r\n", 2); |
| 177 | + if (len != 8) |
| 178 | + { |
| 179 | + char ch_num; |
| 180 | + |
| 181 | + tud_cdc_write_str("incorrect report len: "); |
| 182 | + |
| 183 | + if ( len > 10 ) |
| 184 | + { |
| 185 | + ch_num = '0' + (len / 10); |
| 186 | + tud_cdc_write(&ch_num, 1); |
| 187 | + len = len % 10; |
| 188 | + } |
| 189 | + |
| 190 | + ch_num = '0' + len; |
| 191 | + tud_cdc_write(&ch_num, 1); |
| 192 | + |
| 193 | + tud_cdc_write_str("\r\n"); |
169 | 194 | tud_cdc_write_flush();
|
170 |
| - } |
171 |
| - if (len != 8) { |
| 195 | + |
172 | 196 | // Don't request a new report for a wrong sized endpoint.
|
173 | 197 | return;
|
174 | 198 | }
|
175 |
| - uint8_t modifiers = report[0]; |
| 199 | + |
| 200 | + uint8_t const modifiers = report[0]; |
176 | 201 | bool flush = false;
|
177 |
| - for (int i = 2; i < 8; i++) { |
178 |
| - if (report[i] == 0) { |
179 |
| - continue; |
180 |
| - } |
181 |
| - uint8_t down = report[i]; |
182 |
| - uint32_t mask = 1 << (down % 32); |
183 |
| - bool was_down = (last_state[down / 32] & mask) != 0; |
184 |
| - // Only map keycodes 0 - 76. |
185 |
| - if (!was_down && down < 77) { |
186 |
| - const char* layer = ascii; |
187 |
| - // Check shift bits |
188 |
| - if ((modifiers & 0x22) != 0) { |
189 |
| - layer = shifted; |
190 |
| - } |
191 |
| - // Map the key code for Colemak layout so @tannewt can type. |
192 |
| - // uint8_t colemak_key_code = colemak[down]; |
193 |
| - // if (colemak_key_code != 0) { |
194 |
| - // down = colemak_key_code; |
195 |
| - // } |
196 |
| - char c = layer[down]; |
197 |
| - if (c == '\0') { |
198 |
| - continue; |
199 |
| - } |
200 |
| - if (c == '\n') { |
201 |
| - tud_cdc_write("\r", 1); |
| 202 | + |
| 203 | + for (int i = 2; i < 8; i++) |
| 204 | + { |
| 205 | + uint8_t keycode = report[i]; |
| 206 | + |
| 207 | + if (keycode) |
| 208 | + { |
| 209 | + if ( key_in_last_report(last_keycodes, keycode) ) |
| 210 | + { |
| 211 | + // exist in previous report means the current key is holding |
| 212 | + // do nothing |
| 213 | + }else |
| 214 | + { |
| 215 | + // not existed in previous report means the current key is pressed |
| 216 | + // Only print keycodes 0 - 128. |
| 217 | + if (keycode < 128) |
| 218 | + { |
| 219 | + // remap the key code for Colemak layout so @tannewt can type. |
| 220 | + #ifdef KEYBOARD_COLEMAK |
| 221 | + uint8_t colemak_key_code = colemak[keycode]; |
| 222 | + if (colemak_key_code != 0) keycode = colemak_key_code; |
| 223 | + #endif |
| 224 | + |
| 225 | + bool const is_shift = modifiers & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); |
| 226 | + char c = keycode2ascii[keycode][is_shift ? 1 : 0]; |
| 227 | + if (c) |
| 228 | + { |
| 229 | + if (c == '\n') tud_cdc_write("\r", 1); |
| 230 | + tud_cdc_write(&c, 1); |
| 231 | + flush = true; |
| 232 | + } |
| 233 | + } |
202 | 234 | }
|
203 |
| - tud_cdc_write(&c, 1); |
204 |
| - flush = true; |
205 |
| - } |
206 |
| - } |
207 |
| - if (flush) { |
208 |
| - tud_cdc_write_flush(); |
209 |
| - } |
210 |
| - // Now update last_state |
211 |
| - memset(last_state, 0, 8 * sizeof(uint32_t)); |
212 |
| - for (int i = 2; i < 8; i++) { |
213 |
| - if (report[i] == 0) { |
214 |
| - continue; |
215 | 235 | }
|
216 |
| - uint8_t down = report[i]; |
217 |
| - last_state[down / 32] |= 1 << (down % 32); |
218 | 236 | }
|
| 237 | + |
| 238 | + if (flush) tud_cdc_write_flush(); |
| 239 | + |
| 240 | + // save current report |
| 241 | + memcpy(last_keycodes, report+2, 6); |
| 242 | + |
219 | 243 | // continue to request to receive report
|
220 | 244 | if ( !tuh_hid_receive_report(dev_addr, instance) )
|
221 | 245 | {
|
|
0 commit comments