]> git.donarmstrong.com Git - tmk_firmware.git/blob - m0110.c
Fix bug on RAW2SCAN. Add work around for M0110A.
[tmk_firmware.git] / m0110.c
1 /*
2 Copyright 2011 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
86 uint8_t m0110_error = 0;
87
88
89 void m0110_init(void)
90 {
91     uint8_t data;
92     idle();
93     _delay_ms(1000);
94
95     // Model Number
96     // M0110 : 0x09  00001001 : model number 4 (100)
97     // M0110A: 0x0B  00001011 : model number 5 (101)
98     // M0110 & M0120: ???
99     m0110_send(M0110_MODEL);
100     data = m0110_recv();
101     print("m0110_init model: "); phex(data); print("\n");
102
103     m0110_send(M0110_TEST);
104     data = m0110_recv();
105     print("m0110_init test: "); phex(data); print("\n");
106 }
107
108 uint8_t m0110_send(uint8_t data)
109 {
110     m0110_error = 0;
111
112     request();
113     WAIT_MS(clock_lo, 250, 1);  // keyboard may block long time
114     for (uint8_t bit = 0x80; bit; bit >>= 1) {
115         WAIT_US(clock_lo, 250, 3);
116         if (data&bit) {
117             data_hi();
118         } else {
119             data_lo();
120         }
121         WAIT_US(clock_hi, 200, 4);
122     }
123     _delay_us(100); // hold last bit for 80us
124     idle();
125     return 1;
126 ERROR:
127     print("m0110_send err: "); phex(m0110_error); print("\n");
128     _delay_ms(500);
129     idle();
130     return 0;
131 }
132
133 uint8_t m0110_recv(void)
134 {
135     uint8_t data = 0;
136     m0110_error = 0;
137
138     WAIT_MS(clock_lo, 250, 1);  // keyboard may block long time
139     for (uint8_t i = 0; i < 8; i++) {
140         data <<= 1;
141         WAIT_US(clock_lo, 200, 2);
142         WAIT_US(clock_hi, 200, 3);
143         if (data_in()) {
144             data |= 1;
145         }
146     }
147     idle();
148     return data;
149 ERROR:
150     print("m0110_recv err: "); phex(m0110_error); print("\n");
151     _delay_ms(500);
152     idle();
153     return 0xFF;
154 }
155
156 uint8_t m0110_recv_key(void)
157 {
158     static uint8_t keybuf = 0x00;
159     uint8_t key, key2, key3;
160
161     if (keybuf) {
162         key = keybuf;
163         keybuf = 0x00;
164         return key;
165     }
166     key = instant();  // Use INSTANT for better response. Should be INQUIRY ?
167     switch (key & 0x7F) {
168         case M0110_KEYPAD:
169             // Pad/Arrow keys
170             return (raw2scan(instant()) | M0110_KEYPAD_OFFSET);
171             break;
172         case M0110_SHIFT:
173             key2 = instant();
174             if (key2 == M0110_KEYPAD) {
175                 key3 = instant();
176                 switch (key3 & 0x7F) {
177                     case M0110_ARROW_UP:
178                     case M0110_ARROW_DOWN:
179                     case M0110_ARROW_LEFT:
180                     case M0110_ARROW_RIGHT:
181                         // Calc keys
182                         return (raw2scan(key3) | M0110_CALC_OFFSET);
183                     default:
184                         // Shift + Pad/Arrow keys
185                         keybuf = raw2scan(key3);
186                         return (raw2scan(key) | M0110_KEYPAD_OFFSET);
187                 }
188             } else {
189                 // Shift + other keys
190                 keybuf = raw2scan(key2);
191                 return raw2scan(key);
192             }
193             break;
194         default:
195             // other keys
196             return raw2scan(key);
197             break;
198     }
199 }
200
201
202 static inline uint8_t raw2scan(uint8_t raw) {
203     return (raw == M0110_NULL) ?  M0110_NULL : (
204                 (raw == M0110_ERROR) ?  M0110_ERROR : (
205                     ((raw&0x80) | ((raw&0x7F)>>1))
206                 )
207            );
208 }
209
210 static inline uint8_t inquiry(void)
211 {
212     m0110_send(M0110_INQUIRY);
213     return m0110_recv();
214 }
215
216 static inline uint8_t instant(void)
217 {
218     m0110_send(M0110_INSTANT);
219     //return m0110_recv();
220     uint8_t data = m0110_recv();
221     if (data != 0x7B) {
222         print("data: "); phex(data); print("\n");
223     }
224     return data;
225 }
226
227 static inline void clock_lo()
228 {
229     M0110_CLOCK_PORT &= ~(1<<M0110_CLOCK_BIT);
230     M0110_CLOCK_DDR  |=  (1<<M0110_CLOCK_BIT);
231 }
232 static inline void clock_hi()
233 {
234     /* input with pull up */
235     M0110_CLOCK_DDR  &= ~(1<<M0110_CLOCK_BIT);
236     M0110_CLOCK_PORT |=  (1<<M0110_CLOCK_BIT);
237 }
238 static inline bool clock_in()
239 {
240     M0110_CLOCK_DDR  &= ~(1<<M0110_CLOCK_BIT);
241     M0110_CLOCK_PORT |=  (1<<M0110_CLOCK_BIT);
242     _delay_us(1);
243     return M0110_CLOCK_PIN&(1<<M0110_CLOCK_BIT);
244 }
245 static inline void data_lo()
246 {
247     M0110_DATA_PORT &= ~(1<<M0110_DATA_BIT);
248     M0110_DATA_DDR  |=  (1<<M0110_DATA_BIT);
249 }
250 static inline void data_hi()
251 {
252     /* input with pull up */
253     M0110_DATA_DDR  &= ~(1<<M0110_DATA_BIT);
254     M0110_DATA_PORT |=  (1<<M0110_DATA_BIT);
255 }
256 static inline bool data_in()
257 {
258     M0110_DATA_DDR  &= ~(1<<M0110_DATA_BIT);
259     M0110_DATA_PORT |=  (1<<M0110_DATA_BIT);
260     _delay_us(1);
261     return M0110_DATA_PIN&(1<<M0110_DATA_BIT);
262 }
263
264 static inline uint16_t wait_clock_lo(uint16_t us)
265 {
266     while (clock_in()  && us) { asm(""); _delay_us(1); us--; }
267     return us;
268 }
269 static inline uint16_t wait_clock_hi(uint16_t us)
270 {
271     while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
272     return us;
273 }
274 static inline uint16_t wait_data_lo(uint16_t us)
275 {
276     while (data_in() && us)  { asm(""); _delay_us(1); us--; }
277     return us;
278 }
279 static inline uint16_t wait_data_hi(uint16_t us)
280 {
281     while (!data_in() && us)  { asm(""); _delay_us(1); us--; }
282     return us;
283 }
284
285 static inline void idle(void)
286 {
287     clock_hi();
288     data_hi();
289 }
290
291 static inline void request(void)
292 {
293     clock_hi();
294     data_lo();
295 }
296
297
298
299 /*
300 Primitive M0110 Library for AVR
301 ==============================
302
303
304 Signaling
305 ---------
306 CLOCK is always from KEYBOARD. DATA are sent with MSB first.
307
308 1) IDLE: both lines are high.
309     CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
310     DATA  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
311
312 2) KEYBOARD->HOST: HOST reads bit on rising edge.
313     CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
314     DATA  ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
315                       <--> 160us(clock low)
316                          <---> 180us(clock high)
317
318 3) HOST->KEYBOARD: HOST asserts bit on falling edge.
319     CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
320     DATA  ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
321                 <----> 840us(request to send by host)                     <---> 80us(hold DATA)
322                       <--> 180us(clock low)
323                          <---> 220us(clock high)
324
325
326 Protocol
327 --------
328 COMMAND:
329     Inquiry     0x10    get key event
330     Instant     0x12    get key event
331     Model       0x14    get model number(M0110 responds with 0x09)
332                         bit 7   1 if another device connected(used when keypad exists?)
333                         bit4-6  next device model number
334                         bit1-3  keyboard model number
335                         bit 0   always 1
336     Test        0x16    test(ACK:0x7D/NAK:0x77)
337
338 KEY EVENT:
339     bit 7       key state(0:press 1:release)
340     bit 6-1     scan code(see below)
341     bit 0       always 1
342     To get scan code use this: ((bits&(1<<7)) | ((bits&0x7F))>>1).
343
344     Note: On the M0110A, the numpad keys and the arrow keys are preceded by 0x79.
345           Moreover, the numpad keys =, /, * and + are preceded by shift-down 0x71 on press and shift-up 0xF1 on release.
346           So, the data transferred by nupmad 5 is "79 2F" whereas for numpad + it's "71 79 0D".
347
348 ARROW KEYS:
349     Arrow keys and Pad+,*,/,=(Calc keys) share same byte sequence and its preceding byte
350     0x71 and 0xF1 means press and release event of SHIFT. These cause very confusing situation.
351     It is difficult or impossible to tell Calc key from Arrow key with SHIFT in some cases.
352
353     Raw key events:
354             press               release
355             ----------------    ----------------
356     Left:         0x79, 0x0D          0x79, 0x8D
357     Right:        0x79, 0x05          0x79, 0x85
358     Up:           0x79, 0x1B          0x79, 0x9B
359     Down:         0x79, 0x11          0x79, 0x91
360     Pad+:   0x71, 0x79, 0x0D    0xF1, 0x79, 0x8D
361     Pad*:   0x71, 0x79, 0x05    0xF1, 0x79, 0x85
362     Pad/:   0x71, 0x79, 0x1B    0xF1, 0x79, 0x9B
363     Pad=:   0x71, 0x79, 0x11    0xF1, 0x79, 0x91
364
365 SCAN CODE:
366     m0111_recv_key() function returns follwing scan codes instead of raw key events.
367     Scan codes are 1 byte long and bit7 is set when key is released. 
368
369     M0110
370     ,---------------------------------------------------------.
371     |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backs|
372     |---------------------------------------------------------|
373     |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \|
374     |---------------------------------------------------------|
375     |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return|
376     |---------------------------------------------------------|
377     |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|        |
378     `---------------------------------------------------------'
379          |Opt|Mac |         Space               |Enter|Opt|
380          `------------------------------------------------'
381     ,---------------------------------------------------------.
382     | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33|
383     |---------------------------------------------------------|
384     |   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A|
385     |---------------------------------------------------------|
386     |    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27|    24|
387     |---------------------------------------------------------|
388     |      38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C|      38|
389     `---------------------------------------------------------'
390          | 3A|  37|             31              |   34| 3A|
391          `------------------------------------------------'
392
393     M0110A
394     ,---------------------------------------------------------. ,---------------.
395     |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bcksp| |Clr|  =|  /|  *|
396     |---------------------------------------------------------| |---------------|
397     |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|   | |  7|  8|  9|  -|
398     |-----------------------------------------------------'   | |---------------|
399     |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| |  4|  5|  6|  +|
400     |---------------------------------------------------------| |---------------|
401     |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shft|Up | |  1|  2|  3|   |
402     |---------------------------------------------------------' |-----------|Ent|
403     |Optio|Mac    |           Space           |  \|Lft|Rgt|Dn | |      0|  .|   |
404     `---------------------------------------------------------' `---------------'
405     ,---------------------------------------------------------. ,---------------.
406     | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33| | 47| 68| 6D| 62|
407     |---------------------------------------------------------| |---------------|
408     |   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E|   | | 59| 5B| 5C| 4E|
409     |-----------------------------------------------------'   | |---------------|
410     |    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27|    24| | 56| 57| 58| 66|
411     |---------------------------------------------------------| |---------------|
412     |      38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C|  38| 4D| | 53| 54| 55|   |
413     |---------------------------------------------------------' |-----------| 4C|
414     |   3A|     37|            31             | 2A| 46| 42| 48| |     52| 41|   |
415     `---------------------------------------------------------' `---------------'
416
417
418 References
419 ----------
420 Technical Info for 128K/512K and Plus
421     ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf
422     ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf
423 Protocol:
424     Page 20 of Tech Info for 128K/512K
425     http://www.mac.linux-m68k.org/devel/plushw.php
426 Connector:
427     Page 20 of Tech Info for 128K/512K
428     http://www.kbdbabel.org/conn/kbd_connector_macplus.png
429 Signaling:
430     http://www.kbdbabel.org/signaling/kbd_signaling_mac.png
431     http://typematic.blog.shinobi.jp/Entry/14/
432 Scan Codes:
433     Page 22 of Tech Info for 128K/512K
434     Page 07 of Tech Info for Plus
435     http://m0115.web.fc2.com/m0110.jpg
436     http://m0115.web.fc2.com/m0110a.jpg
437 */