diff options
Diffstat (limited to 'protocol/m0110.c')
| -rw-r--r-- | protocol/m0110.c | 574 |
1 files changed, 574 insertions, 0 deletions
diff --git a/protocol/m0110.c b/protocol/m0110.c new file mode 100644 index 000000000..a669c85a4 --- /dev/null +++ b/protocol/m0110.c | |||
| @@ -0,0 +1,574 @@ | |||
| 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 | |||
| 47 | static inline uint8_t raw2scan(uint8_t raw); | ||
| 48 | static inline uint8_t inquiry(void); | ||
| 49 | static inline uint8_t instant(void); | ||
| 50 | static inline void clock_lo(void); | ||
| 51 | static inline void clock_hi(void); | ||
| 52 | static inline bool clock_in(void); | ||
| 53 | static inline void data_lo(void); | ||
| 54 | static inline void data_hi(void); | ||
| 55 | static inline bool data_in(void); | ||
| 56 | static inline uint16_t wait_clock_lo(uint16_t us); | ||
| 57 | static inline uint16_t wait_clock_hi(uint16_t us); | ||
| 58 | static inline uint16_t wait_data_lo(uint16_t us); | ||
| 59 | static inline uint16_t wait_data_hi(uint16_t us); | ||
| 60 | static inline void idle(void); | ||
| 61 | static inline void request(void); | ||
| 62 | |||
| 63 | |||
| 64 | #define WAIT_US(stat, us, err) do { \ | ||
| 65 | if (!wait_##stat(us)) { \ | ||
| 66 | m0110_error = err; \ | ||
| 67 | goto ERROR; \ | ||
| 68 | } \ | ||
| 69 | } while (0) | ||
| 70 | |||
| 71 | #define WAIT_MS(stat, ms, err) 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 | |||
| 89 | uint8_t m0110_error = 0; | ||
| 90 | |||
| 91 | |||
| 92 | void m0110_init(void) | ||
| 93 | { | ||
| 94 | uint8_t data; | ||
| 95 | idle(); | ||
| 96 | _delay_ms(1000); | ||
| 97 | |||
| 98 | m0110_send(M0110_MODEL); | ||
| 99 | data = m0110_recv(); | ||
| 100 | print("m0110_init model: "); phex(data); print("\n"); | ||
| 101 | |||
| 102 | m0110_send(M0110_TEST); | ||
| 103 | data = m0110_recv(); | ||
| 104 | print("m0110_init test: "); phex(data); print("\n"); | ||
| 105 | } | ||
| 106 | |||
| 107 | uint8_t m0110_send(uint8_t data) | ||
| 108 | { | ||
| 109 | m0110_error = 0; | ||
| 110 | |||
| 111 | request(); | ||
| 112 | WAIT_MS(clock_lo, 250, 1); // keyboard may block long time | ||
| 113 | for (uint8_t bit = 0x80; bit; bit >>= 1) { | ||
| 114 | WAIT_US(clock_lo, 250, 3); | ||
| 115 | if (data&bit) { | ||
| 116 | data_hi(); | ||
| 117 | } else { | ||
| 118 | data_lo(); | ||
| 119 | } | ||
| 120 | WAIT_US(clock_hi, 200, 4); | ||
| 121 | } | ||
| 122 | _delay_us(100); // hold last bit for 80us | ||
| 123 | idle(); | ||
| 124 | return 1; | ||
| 125 | ERROR: | ||
| 126 | print("m0110_send err: "); phex(m0110_error); print("\n"); | ||
| 127 | _delay_ms(500); | ||
| 128 | idle(); | ||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | uint8_t m0110_recv(void) | ||
| 133 | { | ||
| 134 | uint8_t data = 0; | ||
| 135 | m0110_error = 0; | ||
| 136 | |||
| 137 | WAIT_MS(clock_lo, 250, 1); // keyboard may block long time | ||
| 138 | for (uint8_t i = 0; i < 8; i++) { | ||
| 139 | data <<= 1; | ||
| 140 | WAIT_US(clock_lo, 200, 2); | ||
| 141 | WAIT_US(clock_hi, 200, 3); | ||
| 142 | if (data_in()) { | ||
| 143 | data |= 1; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | idle(); | ||
| 147 | return data; | ||
| 148 | ERROR: | ||
| 149 | print("m0110_recv err: "); phex(m0110_error); print("\n"); | ||
| 150 | _delay_ms(500); | ||
| 151 | idle(); | ||
| 152 | return 0xFF; | ||
| 153 | } | ||
| 154 | |||
| 155 | /* | ||
| 156 | Handling for exceptional case of key combinations for M0110A | ||
| 157 | |||
| 158 | Shift and Calc/Arrow key could be operated simultaneously: | ||
| 159 | |||
| 160 | Case Shift Arrow Events Interpret | ||
| 161 | ------------------------------------------------------------------- | ||
| 162 | 1 Down Down 71, 79, DD Calc(d)*a *b | ||
| 163 | 2 Down Up 71, 79, UU Arrow&Calc(u)*a | ||
| 164 | 3 Up Down F1, 79, DD Shift(u) *c | ||
| 165 | 4 Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a | ||
| 166 | |||
| 167 | Case Shift Calc Events Interpret | ||
| 168 | ------------------------------------------------------------------- | ||
| 169 | 5(1) Down Down 71, 71, 79, DD Shift(d) and Cacl(d) | ||
| 170 | 6(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a | ||
| 171 | 7(1) Up Down F1, 71, 79, DD Shift(u) and Calc(d) | ||
| 172 | 8(4) Up Up F1, F1, 79, UU Shift(ux2) and Arrow&Calc(u)*a | ||
| 173 | |||
| 174 | During Calc key is hold: | ||
| 175 | Case Shift Arrow Events Interpret | ||
| 176 | ------------------------------------------------------------------- | ||
| 177 | A(3) ---- Down F1, 79, DD Shift(u) *c | ||
| 178 | B ---- Up 79, UU Arrow&Calc(u)*a | ||
| 179 | C Down ---- F1, 71 Shift(u) and Shift(d) | ||
| 180 | D Up ---- F1 Shift(u) | ||
| 181 | E Hold Down 79, DD Normal | ||
| 182 | F Hold Up 79, UU Arrow&Calc(u)*a | ||
| 183 | G(1) Down Down F1, 71, 79, DD Shift(u)*b and Calc(d)*a | ||
| 184 | H(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a | ||
| 185 | I(3) Up Down F1, F1, 79, DD Shift(ux2) *c | ||
| 186 | J(4) Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a | ||
| 187 | |||
| 188 | Case Shift Calc Events Interpret | ||
| 189 | ------------------------------------------------------------------- | ||
| 190 | K(1) ---- Down 71, 79, DD Calc(d)*a | ||
| 191 | L(4) ---- Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a | ||
| 192 | M(1) Hold Down 71, 79, DD Calc(d)*a | ||
| 193 | N Hold Up 79, UU Arrow&Calc(u)*a | ||
| 194 | |||
| 195 | Where DD/UU indicates part of Keypad Down/Up event. | ||
| 196 | *a: Impossible to distinguish btween Arrow and Calc event. | ||
| 197 | *b: Shift(d) event is ignored. | ||
| 198 | *c: Arrow/Calc(d) event is ignored. | ||
| 199 | */ | ||
| 200 | uint8_t m0110_recv_key(void) | ||
| 201 | { | ||
| 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 | |||
| 305 | static inline uint8_t raw2scan(uint8_t raw) { | ||
| 306 | return (raw == M0110_NULL) ? M0110_NULL : ( | ||
| 307 | (raw == M0110_ERROR) ? M0110_ERROR : ( | ||
| 308 | ((raw&0x80) | ((raw&0x7F)>>1)) | ||
| 309 | ) | ||
| 310 | ); | ||
| 311 | } | ||
| 312 | |||
| 313 | static inline uint8_t inquiry(void) | ||
| 314 | { | ||
| 315 | m0110_send(M0110_INQUIRY); | ||
| 316 | return m0110_recv(); | ||
| 317 | } | ||
| 318 | |||
| 319 | static inline uint8_t instant(void) | ||
| 320 | { | ||
| 321 | m0110_send(M0110_INSTANT); | ||
| 322 | uint8_t data = m0110_recv(); | ||
| 323 | if (data != M0110_NULL) { | ||
| 324 | phex(data); print(" "); | ||
| 325 | } | ||
| 326 | return data; | ||
| 327 | } | ||
| 328 | |||
| 329 | static inline void clock_lo() | ||
| 330 | { | ||
| 331 | M0110_CLOCK_PORT &= ~(1<<M0110_CLOCK_BIT); | ||
| 332 | M0110_CLOCK_DDR |= (1<<M0110_CLOCK_BIT); | ||
| 333 | } | ||
| 334 | static inline void clock_hi() | ||
| 335 | { | ||
| 336 | /* input with pull up */ | ||
| 337 | M0110_CLOCK_DDR &= ~(1<<M0110_CLOCK_BIT); | ||
| 338 | M0110_CLOCK_PORT |= (1<<M0110_CLOCK_BIT); | ||
| 339 | } | ||
| 340 | static inline bool clock_in() | ||
| 341 | { | ||
| 342 | M0110_CLOCK_DDR &= ~(1<<M0110_CLOCK_BIT); | ||
| 343 | M0110_CLOCK_PORT |= (1<<M0110_CLOCK_BIT); | ||
| 344 | _delay_us(1); | ||
| 345 | return M0110_CLOCK_PIN&(1<<M0110_CLOCK_BIT); | ||
| 346 | } | ||
| 347 | static inline void data_lo() | ||
| 348 | { | ||
| 349 | M0110_DATA_PORT &= ~(1<<M0110_DATA_BIT); | ||
| 350 | M0110_DATA_DDR |= (1<<M0110_DATA_BIT); | ||
| 351 | } | ||
| 352 | static inline void data_hi() | ||
| 353 | { | ||
| 354 | /* input with pull up */ | ||
| 355 | M0110_DATA_DDR &= ~(1<<M0110_DATA_BIT); | ||
| 356 | M0110_DATA_PORT |= (1<<M0110_DATA_BIT); | ||
| 357 | } | ||
| 358 | static inline bool data_in() | ||
| 359 | { | ||
| 360 | M0110_DATA_DDR &= ~(1<<M0110_DATA_BIT); | ||
| 361 | M0110_DATA_PORT |= (1<<M0110_DATA_BIT); | ||
| 362 | _delay_us(1); | ||
| 363 | return M0110_DATA_PIN&(1<<M0110_DATA_BIT); | ||
| 364 | } | ||
| 365 | |||
| 366 | static inline uint16_t wait_clock_lo(uint16_t us) | ||
| 367 | { | ||
| 368 | while (clock_in() && us) { asm(""); _delay_us(1); us--; } | ||
| 369 | return us; | ||
| 370 | } | ||
| 371 | static inline uint16_t wait_clock_hi(uint16_t us) | ||
| 372 | { | ||
| 373 | while (!clock_in() && us) { asm(""); _delay_us(1); us--; } | ||
| 374 | return us; | ||
| 375 | } | ||
| 376 | static inline uint16_t wait_data_lo(uint16_t us) | ||
| 377 | { | ||
| 378 | while (data_in() && us) { asm(""); _delay_us(1); us--; } | ||
| 379 | return us; | ||
| 380 | } | ||
| 381 | static inline uint16_t wait_data_hi(uint16_t us) | ||
| 382 | { | ||
| 383 | while (!data_in() && us) { asm(""); _delay_us(1); us--; } | ||
| 384 | return us; | ||
| 385 | } | ||
| 386 | |||
| 387 | static inline void idle(void) | ||
| 388 | { | ||
| 389 | clock_hi(); | ||
| 390 | data_hi(); | ||
| 391 | } | ||
| 392 | |||
| 393 | static inline void request(void) | ||
| 394 | { | ||
| 395 | clock_hi(); | ||
| 396 | data_lo(); | ||
| 397 | } | ||
| 398 | |||
| 399 | |||
| 400 | |||
| 401 | /* | ||
| 402 | Primitive M0110 Library for AVR | ||
| 403 | ============================== | ||
| 404 | |||
| 405 | |||
| 406 | Signaling | ||
| 407 | --------- | ||
| 408 | CLOCK is always from KEYBOARD. DATA are sent with MSB first. | ||
| 409 | |||
| 410 | 1) IDLE: both lines are high. | ||
| 411 | CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 412 | DATA ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 413 | |||
| 414 | 2) KEYBOARD->HOST: HOST reads bit on rising edge. | ||
| 415 | CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ | ||
| 416 | DATA ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ | ||
| 417 | <--> 160us(clock low) | ||
| 418 | <---> 180us(clock high) | ||
| 419 | |||
| 420 | 3) HOST->KEYBOARD: HOST asserts bit on falling edge. | ||
| 421 | CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ | ||
| 422 | DATA ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ | ||
| 423 | <----> 840us(request to send by host) <---> 80us(hold DATA) | ||
| 424 | <--> 180us(clock low) | ||
| 425 | <---> 220us(clock high) | ||
| 426 | |||
| 427 | |||
| 428 | Protocol | ||
| 429 | -------- | ||
| 430 | COMMAND: | ||
| 431 | Inquiry 0x10 get key event with block | ||
| 432 | Instant 0x12 get key event | ||
| 433 | Model 0x14 get model number(M0110 responds with 0x09) | ||
| 434 | bit 7 1 if another device connected(used when keypad exists?) | ||
| 435 | bit4-6 next device model number | ||
| 436 | bit1-3 keyboard model number | ||
| 437 | bit 0 always 1 | ||
| 438 | Test 0x16 test(ACK:0x7D/NAK:0x77) | ||
| 439 | |||
| 440 | KEY EVENT: | ||
| 441 | bit 7 key state(0:press 1:release) | ||
| 442 | bit 6-1 scan code(see below) | ||
| 443 | bit 0 always 1 | ||
| 444 | To get scan code use this: ((bits&(1<<7)) | ((bits&0x7F))>>1). | ||
| 445 | |||
| 446 | Note: On the M0110A, Keypad keys and Arrow keys are preceded by 0x79. | ||
| 447 | Moreover, some Keypad keys(=, /, * and +) are preceded by 0x71 on press and 0xF1 on release. | ||
| 448 | |||
| 449 | ARROW KEYS: | ||
| 450 | Arrow keys and Calc keys(+,*,/,= on keypad) share same byte sequence and preceding byte of | ||
| 451 | Calc keys(0x71 and 0xF1) means press and release event of SHIFT. This causes a very confusing situation, | ||
| 452 | it is difficult or impossible to tell Calc key from Arrow key plus SHIFT in some cases. | ||
| 453 | |||
| 454 | Raw key events: | ||
| 455 | press release | ||
| 456 | ---------------- ---------------- | ||
| 457 | Left: 0x79, 0x0D 0x79, 0x8D | ||
| 458 | Right: 0x79, 0x05 0x79, 0x85 | ||
| 459 | Up: 0x79, 0x1B 0x79, 0x9B | ||
| 460 | Down: 0x79, 0x11 0x79, 0x91 | ||
| 461 | Pad+: 0x71, 0x79, 0x0D 0xF1, 0x79, 0x8D | ||
| 462 | Pad*: 0x71, 0x79, 0x05 0xF1, 0x79, 0x85 | ||
| 463 | Pad/: 0x71, 0x79, 0x1B 0xF1, 0x79, 0x9B | ||
| 464 | Pad=: 0x71, 0x79, 0x11 0xF1, 0x79, 0x91 | ||
| 465 | |||
| 466 | |||
| 467 | RAW CODE: | ||
| 468 | M0110A | ||
| 469 | ,---------------------------------------------------------. ,---------------. | ||
| 470 | | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *| | ||
| 471 | |---------------------------------------------------------| |---------------| | ||
| 472 | |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -| | ||
| 473 | |-----------------------------------------------------' | |---------------| | ||
| 474 | |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +| | ||
| 475 | |---------------------------------------------------------| |---------------| | ||
| 476 | |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| | | ||
| 477 | |---------------------------------------------------------' |-----------|Ent| | ||
| 478 | |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| | | ||
| 479 | `---------------------------------------------------------' `---------------' | ||
| 480 | ,---------------------------------------------------------. ,---------------. | ||
| 481 | | 65| 25| 27| 29| 2B| 2F| 2D| 35| 39| 33| 3B| 37| 31| 67| |+0F|*11|*1B|*05| | ||
| 482 | |---------------------------------------------------------| |---------------| | ||
| 483 | | 61| 19| 1B| 1D| 1F| 23| 21| 41| 45| 3F| 47| 43| 3D| | |+33|+37|+39|+1D| | ||
| 484 | |-----------------------------------------------------' | |---------------| | ||
| 485 | | 73| 01| 03| 05| 07| 0B| 09| 4D| 51| 4B| 53| 4F| 49| |+2D|+2F|+31|*0D| | ||
| 486 | |---------------------------------------------------------| |---------------| | ||
| 487 | | 71| 0D| 0F| 11| 13| 17| 5B| 5D| 27| 5F| 59| 71|+1B| |+27|+29|+2B| | | ||
| 488 | |---------------------------------------------------------' |-----------|+19| | ||
| 489 | | 75| 6F| 63 | 55|+0D|+05|+11| | +25|+03| | | ||
| 490 | `---------------------------------------------------------' `---------------' | ||
| 491 | + 0x79, 0xDD / 0xF1, 0xUU | ||
| 492 | * 0x71, 0x79,DD / 0xF1, 0x79, 0xUU | ||
| 493 | |||
| 494 | |||
| 495 | MODEL NUMBER: | ||
| 496 | M0110: 0x09 00001001 : model number 4 (100) | ||
| 497 | M0110A: 0x0B 00001011 : model number 5 (101) | ||
| 498 | M0110 & M0120: ??? | ||
| 499 | |||
| 500 | |||
| 501 | Scan Code | ||
| 502 | --------- | ||
| 503 | m0110_recv_key() function returns following scan codes instead of raw key events. | ||
| 504 | Scan codes are 1 byte long and MSB(bit7) is set when key is released. | ||
| 505 | |||
| 506 | M0110 | ||
| 507 | ,---------------------------------------------------------. | ||
| 508 | | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| | ||
| 509 | |---------------------------------------------------------| | ||
| 510 | |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | ||
| 511 | |---------------------------------------------------------| | ||
| 512 | |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | ||
| 513 | |---------------------------------------------------------| | ||
| 514 | |Shift | Z| X| C| V| B| N| M| ,| ,| /| | | ||
| 515 | `---------------------------------------------------------' | ||
| 516 | |Opt|Mac | Space |Enter|Opt| | ||
| 517 | `------------------------------------------------' | ||
| 518 | ,---------------------------------------------------------. | ||
| 519 | | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | ||
| 520 | |---------------------------------------------------------| | ||
| 521 | | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| | ||
| 522 | |---------------------------------------------------------| | ||
| 523 | | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | ||
| 524 | |---------------------------------------------------------| | ||
| 525 | | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| | ||
| 526 | `---------------------------------------------------------' | ||
| 527 | | 3A| 37| 31 | 34| 3A| | ||
| 528 | `------------------------------------------------' | ||
| 529 | |||
| 530 | M0110A | ||
| 531 | ,---------------------------------------------------------. ,---------------. | ||
| 532 | | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *| | ||
| 533 | |---------------------------------------------------------| |---------------| | ||
| 534 | |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -| | ||
| 535 | |-----------------------------------------------------' | |---------------| | ||
| 536 | |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +| | ||
| 537 | |---------------------------------------------------------| |---------------| | ||
| 538 | |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| | | ||
| 539 | |---------------------------------------------------------' |-----------|Ent| | ||
| 540 | |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| | | ||
| 541 | `---------------------------------------------------------' `---------------' | ||
| 542 | ,---------------------------------------------------------. ,---------------. | ||
| 543 | | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 68| 6D| 62| | ||
| 544 | |---------------------------------------------------------| |---------------| | ||
| 545 | | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| | | 59| 5B| 5C| 4E| | ||
| 546 | |-----------------------------------------------------' | |---------------| | ||
| 547 | | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 66| | ||
| 548 | |---------------------------------------------------------| |---------------| | ||
| 549 | | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| 4D| | 53| 54| 55| | | ||
| 550 | |---------------------------------------------------------' |-----------| 4C| | ||
| 551 | | 3A| 37| 31 | 2A| 46| 42| 48| | 52| 41| | | ||
| 552 | `---------------------------------------------------------' `---------------' | ||
| 553 | |||
| 554 | |||
| 555 | References | ||
| 556 | ---------- | ||
| 557 | Technical Info for 128K/512K and Plus | ||
| 558 | ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf | ||
| 559 | ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf | ||
| 560 | Protocol: | ||
| 561 | Page 20 of Tech Info for 128K/512K | ||
| 562 | http://www.mac.linux-m68k.org/devel/plushw.php | ||
| 563 | Connector: | ||
| 564 | Page 20 of Tech Info for 128K/512K | ||
| 565 | http://www.kbdbabel.org/conn/kbd_connector_macplus.png | ||
| 566 | Signaling: | ||
| 567 | http://www.kbdbabel.org/signaling/kbd_signaling_mac.png | ||
| 568 | http://typematic.blog.shinobi.jp/Entry/14/ | ||
| 569 | Scan Codes: | ||
| 570 | Page 22 of Tech Info for 128K/512K | ||
| 571 | Page 07 of Tech Info for Plus | ||
| 572 | http://m0115.web.fc2.com/m0110.jpg | ||
| 573 | http://m0115.web.fc2.com/m0110a.jpg | ||
| 574 | */ | ||
