]> git.donarmstrong.com Git - qmk_firmware.git/blob - m0110.c
522c3ec0dc43fe0286de0044ac0d68848962e3b6
[qmk_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
38 #include <stdbool.h>
39 #include <avr/io.h>
40 #include <avr/interrupt.h>
41 #include <util/delay.h>
42 #include "m0110.h"
43 #include "debug.h"
44
45
46 static inline void clock_lo(void);
47 static inline void clock_hi(void);
48 static inline bool clock_in(void);
49 static inline void data_lo(void);
50 static inline void data_hi(void);
51 static inline bool data_in(void);
52 static inline uint16_t wait_clock_lo(uint16_t us);
53 static inline uint16_t wait_clock_hi(uint16_t us);
54 static inline uint16_t wait_data_lo(uint16_t us);
55 static inline uint16_t wait_data_hi(uint16_t us);
56 static inline void idle(void);
57 static inline void request(void);
58
59
60 /*
61 Primitive M0110 Library for AVR
62 ==============================
63
64
65 Signaling
66 ---------
67 CLOCK is always from KEYBOARD. DATA are sent with MSB first.
68
69 1) IDLE: both lines are high.
70     CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
71     DATA  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72
73 2) KEYBOARD->HOST: HOST reads bit on rising edge.
74     CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
75     DATA  ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
76                       <--> 160us(clock low)
77                          <---> 180us(clock high)
78
79 3) HOST->KEYBOARD: HOST asserts bit on falling edge.
80     CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
81     DATA  ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
82                 <----> 840us(request to send by host)                     <---> 80us(hold DATA)
83                       <--> 180us(clock low)
84                          <---> 220us(clock high)
85
86
87 Protocol
88 --------
89 COMMAND:
90     Inquiry     0x10    get key event
91     Instant     0x12    get key event
92     Model       0x14    get model number(M0110 responds with 0x09)
93                         bit 7   1 if another device connected(used when keypad exists?)
94                         bit4-6  next device model number
95                         bit1-3  keyboard model number
96                         bit 0   always 1
97     Test        0x16    test(ACK:0x7D/NAK:0x77)
98
99 KEY EVENT:
100     bit 7       key state(0:press 1:release)
101     bit 6-1     scan code(see below)
102     bit 0       always 1
103     To get scan code use this: ((bits&(1<<7)) | ((bits&0x7F))>>1).
104
105     Note: On the M0110A, the numpad keys and the arrow keys are preceded by 0x79.
106           Moreover, the numpad keys =, /, * and + are preceded by shift-down 0x71 on press and shift-up 0xF1 on release.
107           So, the data transferred by nupmad 5 is "79 2F" whereas for numpad + it's "71 79 0D".
108
109 SCAN CODE:
110     m0111_recv_key() function returns follwing scan codes instead of raw key events.
111     Scan codes are 1 byte long and bit7 is set when key is released. 
112
113     M0110
114     ,---------------------------------------------------------.
115     |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Backs|
116     |---------------------------------------------------------|
117     |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|  \|
118     |---------------------------------------------------------|
119     |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return|
120     |---------------------------------------------------------|
121     |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|        |
122     `---------------------------------------------------------'
123          |Opt|Mac |         Space               |Enter|Opt|
124          `------------------------------------------------'
125     ,---------------------------------------------------------.
126     | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33|
127     |---------------------------------------------------------|
128     |   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A|
129     |---------------------------------------------------------|
130     |    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27|    24|
131     |---------------------------------------------------------|
132     |      38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C|      38|
133     `---------------------------------------------------------'
134          | 3A|  37|             31              |   34| 3A|
135          `------------------------------------------------'
136
137     M0110A
138     ,---------------------------------------------------------. ,---------------.
139     |  `|  1|  2|  3|  4|  5|  6|  7|  8|  9|  0|  -|  =|Bcksp| |Clr|  =|  /|  *|
140     |---------------------------------------------------------| |---------------|
141     |Tab  |  Q|  W|  E|  R|  T|  Y|  U|  I|  O|  P|  [|  ]|   | |  7|  8|  9|  -|
142     |-----------------------------------------------------'   | |---------------|
143     |CapsLo|  A|  S|  D|  F|  G|  H|  J|  K|  L|  ;|  '|Return| |  4|  5|  6|  +|
144     |---------------------------------------------------------| |---------------|
145     |Shift   |  Z|  X|  C|  V|  B|  N|  M|  ,|  ,|  /|Shft|Up | |  1|  2|  3|   |
146     |---------------------------------------------------------' |-----------|Ent|
147     |Optio|Mac    |           Space           |  \|Lft|Rgt|Dn | |      0|  .|   |
148     `---------------------------------------------------------' `---------------'
149     ,---------------------------------------------------------. ,---------------.
150     | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18|   33| | 47| 68| 6D| 62|
151     |---------------------------------------------------------| |---------------|
152     |   30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E|   | | 59| 5B| 5C| 4E|
153     |-----------------------------------------------------'   | |---------------|
154     |    39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27|    24| | 56| 57| 58| 66|
155     |---------------------------------------------------------| |---------------|
156     |      38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C|  38| 4D| | 53| 54| 55|   |
157     |---------------------------------------------------------' |-----------| 4C|
158     |   3A|     37|            31             | 2A| 46| 42| 48| |     52| 41|   |
159     `---------------------------------------------------------' `---------------'
160
161
162 References
163 ----------
164 Technical Info for 128K/512K and Plus
165     ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf
166     ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf
167 Protocol:
168     Page 20 of Tech Info for 128K/512K
169     http://www.mac.linux-m68k.org/devel/plushw.php
170 Connector:
171     Page 20 of Tech Info for 128K/512K
172     http://www.kbdbabel.org/conn/kbd_connector_macplus.png
173 Signaling:
174     http://www.kbdbabel.org/signaling/kbd_signaling_mac.png
175     http://typematic.blog.shinobi.jp/Entry/14/
176 Scan Codes:
177     Page 22 of Tech Info for 128K/512K
178     Page 07 of Tech Info for Plus
179     http://m0115.web.fc2.com/m0110.jpg
180     http://m0115.web.fc2.com/m0110a.jpg
181 */
182
183
184 #define WAIT_US(stat, us, err) do { \
185     if (!wait_##stat(us)) { \
186         m0110_error = err; \
187         goto ERROR; \
188     } \
189 } while (0)
190
191 #define WAIT_MS(stat, ms, err) do { \
192     uint16_t _ms = ms; \
193     while (_ms) { \
194         if (wait_##stat(1000)) { \
195             break; \
196         } \
197         _ms--; \
198     } \
199     if (_ms == 0) { \
200         m0110_error = err; \
201         goto ERROR; \
202     } \
203 } while (0)
204
205
206 uint8_t m0110_error = 0;
207
208
209 void m0110_init(void)
210 {
211     uint8_t data;
212     idle();
213     _delay_ms(1000);
214
215     // Model Number
216     // M0110 : 0x09  00001001 : model number 4 (100)
217     // M0110A: 0x0B  00001011 : model number 5 (101)
218     // M0110 & M0120: ???
219     m0110_send(M0110_MODEL);
220     data = m0110_recv();
221     print("m0110_init model: "); phex(data); print("\n");
222
223     m0110_send(M0110_TEST);
224     data = m0110_recv();
225     print("m0110_init test: "); phex(data); print("\n");
226 }
227
228 uint8_t m0110_send(uint8_t data)
229 {
230     m0110_error = 0;
231
232     request();
233     WAIT_MS(clock_lo, 250, 1);  // keyboard may block long time
234     for (uint8_t bit = 0x80; bit; bit >>= 1) {
235         WAIT_US(clock_lo, 250, 3);
236         if (data&bit) {
237             data_hi();
238         } else {
239             data_lo();
240         }
241         WAIT_US(clock_hi, 200, 4);
242     }
243     _delay_us(100); // hold last bit for 80us
244     idle();
245     return 1;
246 ERROR:
247     print("m0110_send err: "); phex(m0110_error); print("\n");
248     _delay_ms(500);
249     idle();
250     return 0;
251 }
252
253 uint8_t m0110_recv(void)
254 {
255     uint8_t data = 0;
256     m0110_error = 0;
257
258     WAIT_MS(clock_lo, 250, 1);  // keyboard may block long time
259     for (uint8_t i = 0; i < 8; i++) {
260         data <<= 1;
261         WAIT_US(clock_lo, 200, 2);
262         WAIT_US(clock_hi, 200, 3);
263         if (data_in()) {
264             data |= 1;
265         }
266     }
267     idle();
268     return data;
269 ERROR:
270     print("m0110_recv err: "); phex(m0110_error); print("\n");
271     _delay_ms(500);
272     idle();
273     return 0xFF;
274 }
275
276 uint8_t m0110_recv_key(void)
277 {
278     uint8_t key;
279     m0110_send(M0110_INQUIRY);
280     key = m0110_recv();
281     if (key == 0xFF || key == M0110_NULL)
282         return M0110_NULL;
283     else 
284         return M0110_RAW2SCAN(key);
285 }
286
287
288 static inline void clock_lo()
289 {
290     M0110_CLOCK_PORT &= ~(1<<M0110_CLOCK_BIT);
291     M0110_CLOCK_DDR  |=  (1<<M0110_CLOCK_BIT);
292 }
293 static inline void clock_hi()
294 {
295     /* input with pull up */
296     M0110_CLOCK_DDR  &= ~(1<<M0110_CLOCK_BIT);
297     M0110_CLOCK_PORT |=  (1<<M0110_CLOCK_BIT);
298 }
299 static inline bool clock_in()
300 {
301     M0110_CLOCK_DDR  &= ~(1<<M0110_CLOCK_BIT);
302     M0110_CLOCK_PORT |=  (1<<M0110_CLOCK_BIT);
303     _delay_us(1);
304     return M0110_CLOCK_PIN&(1<<M0110_CLOCK_BIT);
305 }
306 static inline void data_lo()
307 {
308     M0110_DATA_PORT &= ~(1<<M0110_DATA_BIT);
309     M0110_DATA_DDR  |=  (1<<M0110_DATA_BIT);
310 }
311 static inline void data_hi()
312 {
313     /* input with pull up */
314     M0110_DATA_DDR  &= ~(1<<M0110_DATA_BIT);
315     M0110_DATA_PORT |=  (1<<M0110_DATA_BIT);
316 }
317 static inline bool data_in()
318 {
319     M0110_DATA_DDR  &= ~(1<<M0110_DATA_BIT);
320     M0110_DATA_PORT |=  (1<<M0110_DATA_BIT);
321     _delay_us(1);
322     return M0110_DATA_PIN&(1<<M0110_DATA_BIT);
323 }
324
325 static inline uint16_t wait_clock_lo(uint16_t us)
326 {
327     while (clock_in()  && us) { asm(""); _delay_us(1); us--; }
328     return us;
329 }
330 static inline uint16_t wait_clock_hi(uint16_t us)
331 {
332     while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
333     return us;
334 }
335 static inline uint16_t wait_data_lo(uint16_t us)
336 {
337     while (data_in() && us)  { asm(""); _delay_us(1); us--; }
338     return us;
339 }
340 static inline uint16_t wait_data_hi(uint16_t us)
341 {
342     while (!data_in() && us)  { asm(""); _delay_us(1); us--; }
343     return us;
344 }
345
346 static inline void idle(void)
347 {
348     clock_hi();
349     data_hi();
350 }
351
352 static inline void request(void)
353 {
354     clock_hi();
355     data_lo();
356 }