m0110.c (23443B)
1 /* 2 Copyright 2011,2012 Jun WAKO <wakojun@gmail.com> 3 4 This software is licensed with a Modified BSD License. 5 All of this is supposed to be Free Software, Open Source, DFSG-free, 6 GPL-compatible, and OK to use in both free and proprietary applications. 7 Additions and corrections to this file are welcome. 8 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions are met: 12 13 * Redistributions of source code must retain the above copyright 14 notice, this list of conditions and the following disclaimer. 15 16 * Redistributions in binary form must reproduce the above copyright 17 notice, this list of conditions and the following disclaimer in 18 the documentation and/or other materials provided with the 19 distribution. 20 21 * Neither the name of the copyright holders nor the names of 22 contributors may be used to endorse or promote products derived 23 from this software without specific prior written permission. 24 25 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 29 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 POSSIBILITY OF SUCH DAMAGE. 36 */ 37 /* M0110A Support was contributed by skagon@github */ 38 39 #include <stdbool.h> 40 #include <avr/io.h> 41 #include <avr/interrupt.h> 42 #include <util/delay.h> 43 #include "m0110.h" 44 #include "debug.h" 45 46 static inline uint8_t raw2scan(uint8_t raw); 47 static inline uint8_t inquiry(void); 48 static inline uint8_t instant(void); 49 static inline void clock_lo(void); 50 static inline void clock_hi(void); 51 static inline bool clock_in(void); 52 static inline void data_lo(void); 53 static inline void data_hi(void); 54 static inline bool data_in(void); 55 static inline uint16_t wait_clock_lo(uint16_t us); 56 static inline uint16_t wait_clock_hi(uint16_t us); 57 static inline uint16_t wait_data_lo(uint16_t us); 58 static inline uint16_t wait_data_hi(uint16_t us); 59 static inline void idle(void); 60 static inline void request(void); 61 62 #define WAIT_US(stat, us, err) \ 63 do { \ 64 if (!wait_##stat(us)) { \ 65 m0110_error = err; \ 66 goto ERROR; \ 67 } \ 68 } while (0) 69 70 #define WAIT_MS(stat, ms, err) \ 71 do { \ 72 uint16_t _ms = ms; \ 73 while (_ms) { \ 74 if (wait_##stat(1000)) { \ 75 break; \ 76 } \ 77 _ms--; \ 78 } \ 79 if (_ms == 0) { \ 80 m0110_error = err; \ 81 goto ERROR; \ 82 } \ 83 } while (0) 84 85 #define KEY(raw) ((raw)&0x7f) 86 #define IS_BREAK(raw) (((raw)&0x80) == 0x80) 87 88 uint8_t m0110_error = 0; 89 90 void m0110_init(void) { 91 idle(); 92 _delay_ms(1000); 93 94 /* Not needed to initialize in fact. 95 uint8_t data; 96 m0110_send(M0110_MODEL); 97 data = m0110_recv(); 98 print("m0110_init model: "); print_hex8(data); print("\n"); 99 100 m0110_send(M0110_TEST); 101 data = m0110_recv(); 102 print("m0110_init test: "); print_hex8(data); print("\n"); 103 */ 104 } 105 106 uint8_t m0110_send(uint8_t data) { 107 m0110_error = 0; 108 109 request(); 110 WAIT_MS(clock_lo, 250, 1); // keyboard may block long time 111 for (uint8_t bit = 0x80; bit; bit >>= 1) { 112 WAIT_US(clock_lo, 250, 3); 113 if (data & bit) { 114 data_hi(); 115 } else { 116 data_lo(); 117 } 118 WAIT_US(clock_hi, 200, 4); 119 } 120 _delay_us(100); // hold last bit for 80us 121 idle(); 122 return 1; 123 ERROR: 124 print("m0110_send err: "); 125 print_hex8(m0110_error); 126 print("\n"); 127 _delay_ms(500); 128 idle(); 129 return 0; 130 } 131 132 uint8_t m0110_recv(void) { 133 uint8_t data = 0; 134 m0110_error = 0; 135 136 WAIT_MS(clock_lo, 250, 1); // keyboard may block long time 137 for (uint8_t i = 0; i < 8; i++) { 138 data <<= 1; 139 WAIT_US(clock_lo, 200, 2); 140 WAIT_US(clock_hi, 200, 3); 141 if (data_in()) { 142 data |= 1; 143 } 144 } 145 idle(); 146 return data; 147 ERROR: 148 print("m0110_recv err: "); 149 print_hex8(m0110_error); 150 print("\n"); 151 _delay_ms(500); 152 idle(); 153 return 0xFF; 154 } 155 156 /* 157 Handling for exceptional case of key combinations for M0110A 158 159 Shift and Calc/Arrow key could be operated simultaneously: 160 161 Case Shift Arrow Events Interpret 162 ------------------------------------------------------------------- 163 1 Down Down 71, 79, DD Calc(d)*a *b 164 2 Down Up 71, 79, UU Arrow&Calc(u)*a 165 3 Up Down F1, 79, DD Shift(u) *c 166 4 Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a 167 168 Case Shift Calc Events Interpret 169 ------------------------------------------------------------------- 170 5(1) Down Down 71, 71, 79, DD Shift(d) and Cacl(d) 171 6(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a 172 7(1) Up Down F1, 71, 79, DD Shift(u) and Calc(d) 173 8(4) Up Up F1, F1, 79, UU Shift(ux2) and Arrow&Calc(u)*a 174 175 During Calc key is hold: 176 Case Shift Arrow Events Interpret 177 ------------------------------------------------------------------- 178 A(3) ---- Down F1, 79, DD Shift(u) *c 179 B ---- Up 79, UU Arrow&Calc(u)*a 180 C Down ---- F1, 71 Shift(u) and Shift(d) 181 D Up ---- F1 Shift(u) 182 E Hold Down 79, DD Normal 183 F Hold Up 79, UU Arrow&Calc(u)*a 184 G(1) Down Down F1, 71, 79, DD Shift(u)*b and Calc(d)*a 185 H(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a 186 I(3) Up Down F1, F1, 79, DD Shift(ux2) *c 187 J(4) Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a 188 189 Case Shift Calc Events Interpret 190 ------------------------------------------------------------------- 191 K(1) ---- Down 71, 79, DD Calc(d)*a 192 L(4) ---- Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a 193 M(1) Hold Down 71, 79, DD Calc(d)*a 194 N Hold Up 79, UU Arrow&Calc(u)*a 195 196 Where DD/UU indicates part of Keypad Down/Up event. 197 *a: Impossible to distinguish btween Arrow and Calc event. 198 *b: Shift(d) event is ignored. 199 *c: Arrow/Calc(d) event is ignored. 200 */ 201 uint8_t m0110_recv_key(void) { 202 static uint8_t keybuf = 0x00; 203 static uint8_t keybuf2 = 0x00; 204 static uint8_t rawbuf = 0x00; 205 uint8_t raw, raw2, raw3; 206 207 if (keybuf) { 208 raw = keybuf; 209 keybuf = 0x00; 210 return raw; 211 } 212 if (keybuf2) { 213 raw = keybuf2; 214 keybuf2 = 0x00; 215 return raw; 216 } 217 218 if (rawbuf) { 219 raw = rawbuf; 220 rawbuf = 0x00; 221 } else { 222 raw = instant(); // Use INSTANT for better response. Should be INQUIRY ? 223 } 224 switch (KEY(raw)) { 225 case M0110_KEYPAD: 226 raw2 = instant(); 227 switch (KEY(raw2)) { 228 case M0110_ARROW_UP: 229 case M0110_ARROW_DOWN: 230 case M0110_ARROW_LEFT: 231 case M0110_ARROW_RIGHT: 232 if (IS_BREAK(raw2)) { 233 // Case B,F,N: 234 keybuf = (raw2scan(raw2) | M0110_CALC_OFFSET); // Calc(u) 235 return (raw2scan(raw2) | M0110_KEYPAD_OFFSET); // Arrow(u) 236 } 237 break; 238 } 239 // Keypad or Arrow 240 return (raw2scan(raw2) | M0110_KEYPAD_OFFSET); 241 break; 242 case M0110_SHIFT: 243 raw2 = instant(); 244 switch (KEY(raw2)) { 245 case M0110_SHIFT: 246 // Case: 5-8,C,G,H 247 rawbuf = raw2; 248 return raw2scan(raw); // Shift(d/u) 249 break; 250 case M0110_KEYPAD: 251 // Shift + Arrow, Calc, or etc. 252 raw3 = instant(); 253 switch (KEY(raw3)) { 254 case M0110_ARROW_UP: 255 case M0110_ARROW_DOWN: 256 case M0110_ARROW_LEFT: 257 case M0110_ARROW_RIGHT: 258 if (IS_BREAK(raw)) { 259 if (IS_BREAK(raw3)) { 260 // Case 4: 261 print("(4)\n"); 262 keybuf2 = raw2scan(raw); // Shift(u) 263 keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(u) 264 return (raw2scan(raw3) | M0110_KEYPAD_OFFSET); // Arrow(u) 265 } else { 266 // Case 3: 267 print("(3)\n"); 268 return (raw2scan(raw)); // Shift(u) 269 } 270 } else { 271 if (IS_BREAK(raw3)) { 272 // Case 2: 273 print("(2)\n"); 274 keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(u) 275 return (raw2scan(raw3) | M0110_KEYPAD_OFFSET); // Arrow(u) 276 } else { 277 // Case 1: 278 print("(1)\n"); 279 return (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(d) 280 } 281 } 282 break; 283 default: 284 // Shift + Keypad 285 keybuf = (raw2scan(raw3) | M0110_KEYPAD_OFFSET); 286 return raw2scan(raw); // Shift(d/u) 287 break; 288 } 289 break; 290 default: 291 // Shift + Normal keys 292 keybuf = raw2scan(raw2); 293 return raw2scan(raw); // Shift(d/u) 294 break; 295 } 296 break; 297 default: 298 // Normal keys 299 return raw2scan(raw); 300 break; 301 } 302 } 303 304 static inline uint8_t raw2scan(uint8_t raw) { return (raw == M0110_NULL) ? M0110_NULL : ((raw == M0110_ERROR) ? M0110_ERROR : (((raw & 0x80) | ((raw & 0x7F) >> 1)))); } 305 306 static inline uint8_t inquiry(void) { 307 m0110_send(M0110_INQUIRY); 308 return m0110_recv(); 309 } 310 311 static inline uint8_t instant(void) { 312 m0110_send(M0110_INSTANT); 313 uint8_t data = m0110_recv(); 314 if (data != M0110_NULL) { 315 dprintf("%02X ", data); 316 } 317 return data; 318 } 319 320 static inline void clock_lo(void) { 321 M0110_CLOCK_PORT &= ~(1 << M0110_CLOCK_BIT); 322 M0110_CLOCK_DDR |= (1 << M0110_CLOCK_BIT); 323 } 324 static inline void clock_hi(void) { 325 /* input with pull up */ 326 M0110_CLOCK_DDR &= ~(1 << M0110_CLOCK_BIT); 327 M0110_CLOCK_PORT |= (1 << M0110_CLOCK_BIT); 328 } 329 static inline bool clock_in(void) { 330 M0110_CLOCK_DDR &= ~(1 << M0110_CLOCK_BIT); 331 M0110_CLOCK_PORT |= (1 << M0110_CLOCK_BIT); 332 _delay_us(1); 333 return M0110_CLOCK_PIN & (1 << M0110_CLOCK_BIT); 334 } 335 static inline void data_lo(void) { 336 M0110_DATA_PORT &= ~(1 << M0110_DATA_BIT); 337 M0110_DATA_DDR |= (1 << M0110_DATA_BIT); 338 } 339 static inline void data_hi(void) { 340 /* input with pull up */ 341 M0110_DATA_DDR &= ~(1 << M0110_DATA_BIT); 342 M0110_DATA_PORT |= (1 << M0110_DATA_BIT); 343 } 344 static inline bool data_in(void) { 345 M0110_DATA_DDR &= ~(1 << M0110_DATA_BIT); 346 M0110_DATA_PORT |= (1 << M0110_DATA_BIT); 347 _delay_us(1); 348 return M0110_DATA_PIN & (1 << M0110_DATA_BIT); 349 } 350 351 static inline uint16_t wait_clock_lo(uint16_t us) { 352 while (clock_in() && us) { 353 asm(""); 354 _delay_us(1); 355 us--; 356 } 357 return us; 358 } 359 static inline uint16_t wait_clock_hi(uint16_t us) { 360 while (!clock_in() && us) { 361 asm(""); 362 _delay_us(1); 363 us--; 364 } 365 return us; 366 } 367 static inline uint16_t wait_data_lo(uint16_t us) { 368 while (data_in() && us) { 369 asm(""); 370 _delay_us(1); 371 us--; 372 } 373 return us; 374 } 375 static inline uint16_t wait_data_hi(uint16_t us) { 376 while (!data_in() && us) { 377 asm(""); 378 _delay_us(1); 379 us--; 380 } 381 return us; 382 } 383 384 static inline void idle(void) { 385 clock_hi(); 386 data_hi(); 387 } 388 389 static inline void request(void) { 390 clock_hi(); 391 data_lo(); 392 } 393 394 /* 395 Primitive M0110 Library for AVR 396 ============================== 397 398 399 Signaling 400 --------- 401 CLOCK is always from KEYBOARD. DATA are sent with MSB first. 402 403 1) IDLE: both lines are high. 404 CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 405 DATA ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 406 407 2) KEYBOARD->HOST: HOST reads bit on rising edge. 408 CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ 409 DATA ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ 410 <--> 160us(clock low) 411 <---> 180us(clock high) 412 413 3) HOST->KEYBOARD: HOST asserts bit on falling edge. 414 CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ 415 DATA ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ 416 <----> 840us(request to send by host) <---> 80us(hold DATA) 417 <--> 180us(clock low) 418 <---> 220us(clock high) 419 420 421 Protocol 422 -------- 423 COMMAND: 424 Inquiry 0x10 get key event with block 425 Instant 0x12 get key event 426 Model 0x14 get model number(M0110 responds with 0x09) 427 bit 7 1 if another device connected(used when keypad exists?) 428 bit4-6 next device model number 429 bit1-3 keyboard model number 430 bit 0 always 1 431 Test 0x16 test(ACK:0x7D/NAK:0x77) 432 433 KEY EVENT: 434 bit 7 key state(0:press 1:release) 435 bit 6-1 scan code(see below) 436 bit 0 always 1 437 To get scan code use this: ((bits&(1<<7)) | ((bits&0x7F))>>1). 438 439 Note: On the M0110A, Keypad keys and Arrow keys are preceded by 0x79. 440 Moreover, some Keypad keys(=, /, * and +) are preceded by 0x71 on press and 0xF1 on release. 441 442 ARROW KEYS: 443 Arrow keys and Calc keys(+,*,/,= on keypad) share same byte sequence and preceding byte of 444 Calc keys(0x71 and 0xF1) means press and release event of SHIFT. This causes a very confusing situation, 445 it is difficult or impossible to tell Calc key from Arrow key plus SHIFT in some cases. 446 447 Raw key events: 448 press release 449 ---------------- ---------------- 450 Left: 0x79, 0x0D 0x79, 0x8D 451 Right: 0x79, 0x05 0x79, 0x85 452 Up: 0x79, 0x1B 0x79, 0x9B 453 Down: 0x79, 0x11 0x79, 0x91 454 Pad+: 0x71, 0x79, 0x0D 0xF1, 0x79, 0x8D 455 Pad*: 0x71, 0x79, 0x05 0xF1, 0x79, 0x85 456 Pad/: 0x71, 0x79, 0x1B 0xF1, 0x79, 0x9B 457 Pad=: 0x71, 0x79, 0x11 0xF1, 0x79, 0x91 458 459 460 RAW CODE: 461 M0110A 462 ,---------------------------------------------------------. ,---------------. 463 | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *| 464 |---------------------------------------------------------| |---------------| 465 |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -| 466 |-----------------------------------------------------' | |---------------| 467 |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +| 468 |---------------------------------------------------------| |---------------| 469 |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| | 470 |---------------------------------------------------------' |-----------|Ent| 471 |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| | 472 `---------------------------------------------------------' `---------------' 473 ,---------------------------------------------------------. ,---------------. 474 | 65| 25| 27| 29| 2B| 2F| 2D| 35| 39| 33| 3B| 37| 31| 67| |+0F|*11|*1B|*05| 475 |---------------------------------------------------------| |---------------| 476 | 61| 19| 1B| 1D| 1F| 23| 21| 41| 45| 3F| 47| 43| 3D| | |+33|+37|+39|+1D| 477 |-----------------------------------------------------' | |---------------| 478 | 73| 01| 03| 05| 07| 0B| 09| 4D| 51| 4B| 53| 4F| 49| |+2D|+2F|+31|*0D| 479 |---------------------------------------------------------| |---------------| 480 | 71| 0D| 0F| 11| 13| 17| 5B| 5D| 27| 5F| 59| 71|+1B| |+27|+29|+2B| | 481 |---------------------------------------------------------' |-----------|+19| 482 | 75| 6F| 63 | 55|+0D|+05|+11| | +25|+03| | 483 `---------------------------------------------------------' `---------------' 484 + 0x79, 0xDD / 0xF1, 0xUU 485 * 0x71, 0x79,DD / 0xF1, 0x79, 0xUU 486 487 488 MODEL NUMBER: 489 M0110: 0x09 00001001 : model number 4 (100) 490 M0110A: 0x0B 00001011 : model number 5 (101) 491 M0110 & M0120: ??? 492 493 494 Scan Code 495 --------- 496 m0110_recv_key() function returns following scan codes instead of M0110 raw codes. 497 Scan codes are 1 byte size and MSB(bit7) is set when key is released. 498 499 scancode = ((raw&0x80) | ((raw&0x7F)>>1)) 500 501 M0110 M0120 502 ,---------------------------------------------------------. ,---------------. 503 | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| |Clr| -|Lft|Rgt| 504 |---------------------------------------------------------| |---------------| 505 |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | 7| 8| 9|Up | 506 |---------------------------------------------------------| |---------------| 507 |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6|Dn | 508 |---------------------------------------------------------| |---------------| 509 |Shift | Z| X| C| V| B| N| M| ,| ,| /| | | 1| 2| 3| | 510 `---------------------------------------------------------' |-----------|Ent| 511 |Opt|Mac | Space |Enter|Opt| | 0| .| | 512 `------------------------------------------------' `---------------' 513 ,---------------------------------------------------------. ,---------------. 514 | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 4E| 46| 42| 515 |---------------------------------------------------------| |---------------| 516 | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| | 59| 5B| 5C| 4D| 517 |---------------------------------------------------------| |---------------| 518 | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 48| 519 |---------------------------------------------------------| |---------------| 520 | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| | 53| 54| 55| | 521 `---------------------------------------------------------' |-----------| 4C| 522 | 3A| 37| 31 | 34| 3A| | 52| 41| | 523 `------------------------------------------------' `---------------' 524 525 International keyboard(See page 22 of "Technical Info for 128K/512K") 526 ,---------------------------------------------------------. 527 | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| 528 |---------------------------------------------------------| 529 | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| 530 |------------------------------------------------------ | 531 | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 532 |---------------------------------------------------------| 533 | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 0A| 38| 534 `---------------------------------------------------------' 535 | 3A| 37| 34 | 31| 3A| 536 `------------------------------------------------' 537 538 M0110A 539 ,---------------------------------------------------------. ,---------------. 540 | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *| 541 |---------------------------------------------------------| |---------------| 542 |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -| 543 |-----------------------------------------------------' | |---------------| 544 |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +| 545 |---------------------------------------------------------| |---------------| 546 |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| | 547 |---------------------------------------------------------' |-----------|Ent| 548 |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| | 549 `---------------------------------------------------------' `---------------' 550 ,---------------------------------------------------------. ,---------------. 551 | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 68| 6D| 62| 552 |---------------------------------------------------------| |---------------| 553 | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| | | 59| 5B| 5C| 4E| 554 |-----------------------------------------------------' | |---------------| 555 | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 66| 556 |---------------------------------------------------------| |---------------| 557 | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| 4D| | 53| 54| 55| | 558 |---------------------------------------------------------' |-----------| 4C| 559 | 3A| 37| 31 | 2A| 46| 42| 48| | 52| 41| | 560 `---------------------------------------------------------' `---------------' 561 562 563 References 564 ---------- 565 Technical Info for 128K/512K and Plus 566 ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf 567 ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf 568 Protocol: 569 Page 20 of Tech Info for 128K/512K 570 http://www.mac.linux-m68k.org/devel/plushw.php 571 Connector: 572 Page 20 of Tech Info for 128K/512K 573 http://www.kbdbabel.org/conn/kbd_connector_macplus.png 574 Signaling: 575 http://www.kbdbabel.org/signaling/kbd_signaling_mac.png 576 http://typematic.blog.shinobi.jp/Entry/14/ 577 M0110 raw scan codes: 578 Page 22 of Tech Info for 128K/512K 579 Page 07 of Tech Info for Plus 580 http://m0115.web.fc2.com/m0110.jpg 581 http://m0115.web.fc2.com/m0110a.jpg 582 */