]>
Commit | Line | Data |
---|---|---|
a074364c | 1 | /* |
2 | Copyright 2011 Jun WAKO <wakojun@gmail.com> | |
3 | Copyright 2013 Shay Green <gblargg@gmail.com> | |
4 | ||
5 | This software is licensed with a Modified BSD License. | |
6 | All of this is supposed to be Free Software, Open Source, DFSG-free, | |
7 | GPL-compatible, and OK to use in both free and proprietary applications. | |
8 | Additions and corrections to this file are welcome. | |
9 | ||
10 | ||
11 | Redistribution and use in source and binary forms, with or without | |
12 | modification, are permitted provided that the following conditions are met: | |
13 | ||
14 | * Redistributions of source code must retain the above copyright | |
15 | notice, this list of conditions and the following disclaimer. | |
16 | ||
17 | * Redistributions in binary form must reproduce the above copyright | |
18 | notice, this list of conditions and the following disclaimer in | |
19 | the documentation and/or other materials provided with the | |
20 | distribution. | |
21 | ||
22 | * Neither the name of the copyright holders nor the names of | |
23 | contributors may be used to endorse or promote products derived | |
24 | from this software without specific prior written permission. | |
25 | ||
26 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
27 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
28 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
29 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |
30 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
31 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
32 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
33 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
34 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
35 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
36 | POSSIBILITY OF SUCH DAMAGE. | |
37 | */ | |
38 | ||
39 | #include <stdbool.h> | |
40 | #include <util/delay.h> | |
41 | #include <avr/io.h> | |
42 | #include <avr/interrupt.h> | |
43 | #include "adb.h" | |
44 | ||
45 | ||
46 | // GCC doesn't inline functions normally | |
47 | #define data_lo() (ADB_DDR |= (1<<ADB_DATA_BIT)) | |
48 | #define data_hi() (ADB_DDR &= ~(1<<ADB_DATA_BIT)) | |
49 | #define data_in() (ADB_PIN & (1<<ADB_DATA_BIT)) | |
50 | ||
51 | #ifdef ADB_PSW_BIT | |
52 | static inline void psw_lo(void); | |
53 | static inline void psw_hi(void); | |
54 | static inline bool psw_in(void); | |
55 | #endif | |
56 | ||
57 | static inline void attention(void); | |
58 | static inline void place_bit0(void); | |
59 | static inline void place_bit1(void); | |
60 | static inline void send_byte(uint8_t data); | |
61 | static inline uint16_t wait_data_lo(uint16_t us); | |
62 | static inline uint16_t wait_data_hi(uint16_t us); | |
63 | ||
64 | ||
65 | void adb_host_init(void) | |
66 | { | |
67 | ADB_PORT &= ~(1<<ADB_DATA_BIT); | |
68 | data_hi(); | |
69 | #ifdef ADB_PSW_BIT | |
70 | psw_hi(); | |
71 | #endif | |
72 | } | |
73 | ||
74 | #ifdef ADB_PSW_BIT | |
75 | bool adb_host_psw(void) | |
76 | { | |
77 | return psw_in(); | |
78 | } | |
79 | #endif | |
80 | ||
81 | /* | |
82 | * Don't call this in a row without the delay, otherwise it makes some of poor controllers | |
83 | * overloaded and misses strokes. Recommended interval is 12ms. | |
84 | * | |
85 | * Thanks a lot, blargg! | |
86 | * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919> | |
87 | * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139> | |
88 | */ | |
230ed4bd | 89 | uint16_t adb_host_kbd_recv(uint8_t addr) |
4d116a04 | 90 | { |
230ed4bd | 91 | return adb_host_talk(addr, ADB_REG_0); |
4d116a04 | 92 | } |
93 | ||
94 | #ifdef ADB_MOUSE_ENABLE | |
95 | void adb_mouse_init(void) { | |
96 | return; | |
97 | } | |
98 | ||
99 | uint16_t adb_host_mouse_recv(void) | |
100 | { | |
d702fe75 | 101 | return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0); |
4d116a04 | 102 | } |
103 | #endif | |
104 | ||
d702fe75 | 105 | uint16_t adb_host_talk(uint8_t addr, uint8_t reg) |
a074364c | 106 | { |
107 | uint16_t data = 0; | |
108 | cli(); | |
109 | attention(); | |
d702fe75 | 110 | send_byte((addr<<4) | (ADB_CMD_TALK<<2) | reg); |
a074364c | 111 | place_bit0(); // Stopbit(0) |
112 | if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored | |
113 | sei(); | |
114 | return -30; // something wrong | |
115 | } | |
116 | if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us) | |
117 | sei(); | |
118 | return 0; // No data to send | |
119 | } | |
d702fe75 | 120 | |
a074364c | 121 | uint8_t n = 17; // start bit + 16 data bits |
122 | do { | |
123 | uint8_t lo = (uint8_t) wait_data_hi(130); | |
124 | if (!lo) | |
125 | goto error; | |
d702fe75 | 126 | |
a074364c | 127 | uint8_t hi = (uint8_t) wait_data_lo(lo); |
128 | if (!hi) | |
129 | goto error; | |
d702fe75 | 130 | |
a074364c | 131 | hi = lo - hi; |
132 | lo = 130 - lo; | |
d702fe75 | 133 | |
a074364c | 134 | data <<= 1; |
135 | if (lo < hi) { | |
136 | data |= 1; | |
137 | } | |
138 | else if (n == 17) { | |
139 | sei(); | |
140 | return -20; | |
141 | } | |
142 | } | |
143 | while ( --n ); | |
144 | ||
145 | // Stop bit can't be checked normally since it could have service request lenghtening | |
146 | // and its high state never goes low. | |
147 | if (!wait_data_hi(351) || wait_data_lo(91)) { | |
148 | sei(); | |
149 | return -21; | |
150 | } | |
151 | sei(); | |
152 | return data; | |
153 | ||
154 | error: | |
155 | sei(); | |
156 | return -n; | |
157 | } | |
158 | ||
230ed4bd | 159 | void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l) |
a074364c | 160 | { |
161 | cli(); | |
162 | attention(); | |
230ed4bd | 163 | send_byte((addr<<4) | (ADB_CMD_LISTEN<<2) | reg); |
a074364c | 164 | place_bit0(); // Stopbit(0) |
165 | _delay_us(200); // Tlt/Stop to Start | |
166 | place_bit1(); // Startbit(1) | |
d702fe75 | 167 | send_byte(data_h); |
a074364c | 168 | send_byte(data_l); |
169 | place_bit0(); // Stopbit(0); | |
170 | sei(); | |
171 | } | |
172 | ||
173 | // send state of LEDs | |
230ed4bd | 174 | void adb_host_kbd_led(uint8_t addr, uint8_t led) |
a074364c | 175 | { |
230ed4bd | 176 | // Listen Register2 |
177 | // upper byte: not used | |
178 | // lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock | |
179 | adb_host_listen(addr, 2, 0, led & 0x07); | |
a074364c | 180 | } |
181 | ||
182 | ||
183 | #ifdef ADB_PSW_BIT | |
184 | static inline void psw_lo() | |
185 | { | |
186 | ADB_DDR |= (1<<ADB_PSW_BIT); | |
187 | ADB_PORT &= ~(1<<ADB_PSW_BIT); | |
188 | } | |
189 | static inline void psw_hi() | |
190 | { | |
191 | ADB_PORT |= (1<<ADB_PSW_BIT); | |
192 | ADB_DDR &= ~(1<<ADB_PSW_BIT); | |
193 | } | |
194 | static inline bool psw_in() | |
195 | { | |
196 | ADB_PORT |= (1<<ADB_PSW_BIT); | |
197 | ADB_DDR &= ~(1<<ADB_PSW_BIT); | |
198 | return ADB_PIN&(1<<ADB_PSW_BIT); | |
199 | } | |
200 | #endif | |
201 | ||
202 | static inline void attention(void) | |
203 | { | |
204 | data_lo(); | |
205 | _delay_us(800-35); // bit1 holds lo for 35 more | |
206 | place_bit1(); | |
207 | } | |
208 | ||
209 | static inline void place_bit0(void) | |
210 | { | |
211 | data_lo(); | |
212 | _delay_us(65); | |
213 | data_hi(); | |
214 | _delay_us(35); | |
215 | } | |
216 | ||
217 | static inline void place_bit1(void) | |
218 | { | |
219 | data_lo(); | |
220 | _delay_us(35); | |
221 | data_hi(); | |
222 | _delay_us(65); | |
223 | } | |
224 | ||
225 | static inline void send_byte(uint8_t data) | |
226 | { | |
227 | for (int i = 0; i < 8; i++) { | |
228 | if (data&(0x80>>i)) | |
229 | place_bit1(); | |
230 | else | |
231 | place_bit0(); | |
232 | } | |
233 | } | |
234 | ||
235 | // These are carefully coded to take 6 cycles of overhead. | |
236 | // inline asm approach became too convoluted | |
237 | static inline uint16_t wait_data_lo(uint16_t us) | |
238 | { | |
239 | do { | |
240 | if ( !data_in() ) | |
241 | break; | |
242 | _delay_us(1 - (6 * 1000000.0 / F_CPU)); | |
243 | } | |
244 | while ( --us ); | |
245 | return us; | |
246 | } | |
247 | ||
248 | static inline uint16_t wait_data_hi(uint16_t us) | |
249 | { | |
250 | do { | |
251 | if ( data_in() ) | |
252 | break; | |
253 | _delay_us(1 - (6 * 1000000.0 / F_CPU)); | |
254 | } | |
255 | while ( --us ); | |
256 | return us; | |
257 | } | |
258 | ||
259 | ||
260 | /* | |
261 | ADB Protocol | |
262 | ============ | |
263 | ||
264 | Resources | |
265 | --------- | |
266 | ADB - The Untold Story: Space Aliens Ate My Mouse | |
267 | http://developer.apple.com/legacy/mac/library/#technotes/hw/hw_01.html | |
268 | ADB Manager | |
269 | http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Devices/ADB_Manager.pdf | |
270 | Service request(5-17) | |
271 | Apple IIgs Hardware Reference Second Edition [Chapter6 p121] | |
272 | ftp://ftp.apple.asimov.net/pub/apple_II/documentation/Apple%20IIgs%20Hardware%20Reference.pdf | |
273 | ADB Keycode | |
274 | http://72.0.193.250/Documentation/macppc/adbkeycodes/ | |
275 | http://m0115.web.fc2.com/m0115.jpg | |
276 | [Inside Macintosh volume V, pages 191-192] | |
277 | http://www.opensource.apple.com/source/IOHIDFamily/IOHIDFamily-421.18.3/IOHIDFamily/Cosmo_USB2ADB.c | |
278 | ADB Signaling | |
279 | http://kbdbabel.sourceforge.net/doc/kbd_signaling_pcxt_ps2_adb.pdf | |
280 | ADB Overview & History | |
281 | http://en.wikipedia.org/wiki/Apple_Desktop_Bus | |
282 | Microchip Application Note: ADB device(with code for PIC16C) | |
283 | http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011062 | |
284 | AVR ATtiny2131 ADB to PS/2 converter(Japanese) | |
285 | http://hp.vector.co.jp/authors/VA000177/html/KeyBoardA5DEA5CBA5A2II.html | |
286 | ||
287 | ||
288 | Pinouts | |
289 | ------- | |
290 | ADB female socket from the front: | |
291 | __________ | |
292 | | | <--- top | |
293 | | 4o o3 | | |
294 | |2o o1| | |
295 | | == | | |
296 | |________| <--- bottom | |
297 | | | <--- 4pins | |
298 | ||
299 | ||
300 | ADB female socket from bottom: | |
301 | ||
302 | ========== <--- front | |
303 | | | | |
304 | | | | |
305 | |2o o1| | |
306 | |4o o3| | |
307 | ---------- <--- back | |
308 | ||
309 | 1: Data | |
310 | 2: Power SW(low when press Power key) | |
311 | 3: Vcc(5V) | |
312 | 4: GND | |
313 | ||
314 | ||
315 | Commands | |
316 | -------- | |
317 | ADB command is 1byte and consists of 4bit-address, 2bit-command | |
318 | type and 2bit-register. The commands are always sent by Host. | |
319 | ||
320 | Command format: | |
321 | 7 6 5 4 3 2 1 0 | |
322 | | | | |------------ address | |
323 | | |-------- command type | |
324 | | |---- register | |
325 | ||
326 | bits commands | |
327 | ------------------------------------------------------ | |
230ed4bd | 328 | - - - - 0 0 0 0 Send Reset(reset all devices) |
a074364c | 329 | A A A A 0 0 0 1 Flush(reset a device) |
330 | - - - - 0 0 1 0 Reserved | |
331 | - - - - 0 0 1 1 Reserved | |
332 | - - - - 0 1 - - Reserved | |
333 | A A A A 1 0 R R Listen(write to a device) | |
334 | A A A A 1 1 R R Talk(read from a device) | |
335 | ||
336 | The command to read keycodes from keyboard is 0x2C which | |
d702fe75 | 337 | consist of keyboard address 2 and Talk against register 0. |
a074364c | 338 | |
339 | Address: | |
340 | 2: keyboard | |
341 | 3: mice | |
342 | ||
343 | Registers: | |
344 | 0: application(keyboard uses this to store its data.) | |
345 | 1: application | |
346 | 2: application(keyboard uses this for LEDs and state of modifiers) | |
347 | 3: status and command | |
348 | ||
349 | ||
350 | Communication | |
351 | ------------- | |
352 | This is a minimum information for keyboard communication. | |
353 | See "Resources" for detail. | |
354 | ||
355 | Signaling: | |
356 | ||
357 | ~~~~____________~~||||||||||||__~~~~~_~~|||||||||||||||__~~~~ | |
358 | ||
359 | |800us | |7 Command 0| | | |15-64 Data 0|Stopbit(0) | |
360 | +Attention | | | +Startbit(1) | |
361 | +Startbit(1) | +Tlt(140-260us) | |
362 | +stopbit(0) | |
363 | ||
364 | Bit cells: | |
365 | ||
366 | bit0: ______~~~ | |
367 | 65 :35us | |
368 | ||
369 | bit1: ___~~~~~~ | |
370 | 35 :65us | |
371 | ||
372 | bit0 low time: 60-70% of bit cell(42-91us) | |
373 | bit1 low time: 30-40% of bit cell(21-52us) | |
374 | bit cell time: 70-130us | |
375 | [from Apple IIgs Hardware Reference Second Edition] | |
376 | ||
377 | Criterion for bit0/1: | |
378 | After 55us if line is low/high then bit is 0/1. | |
379 | ||
380 | Attention & start bit: | |
381 | Host asserts low in 560-1040us then places start bit(1). | |
382 | ||
383 | Tlt(Stop to Start): | |
384 | Bus stays high in 140-260us then device places start bit(1). | |
385 | ||
386 | Global reset: | |
387 | Host asserts low in 2.8-5.2ms. All devices are forced to reset. | |
388 | ||
389 | Service request from device(Srq): | |
390 | Device can request to send at commad(Global only?) stop bit. | |
391 | Requesting device keeps low for 140-260us at stop bit of command. | |
392 | ||
393 | ||
394 | Keyboard Data(Register0) | |
395 | This 16bit data can contains two keycodes and two released flags. | |
396 | First keycode is palced in upper byte. When one keyocode is sent, | |
397 | lower byte is 0xFF. | |
398 | Release flag is 1 when key is released. | |
399 | ||
400 | 1514 . . . . . 8 7 6 . . . . . 0 | |
401 | | | | | | | | | | +-+-+-+-+-+-+- Keycode2 | |
402 | | | | | | | | | +--------------- Released2(1 when the key is released) | |
403 | | +-+-+-+-+-+-+----------------- Keycode1 | |
404 | +------------------------------- Released1(1 when the key is released) | |
405 | ||
406 | Keycodes: | |
407 | Scancode consists of 7bit keycode and 1bit release flag. | |
408 | Device can send two keycodes at once. If just one keycode is sent | |
409 | keycode1 contains it and keyocode2 is 0xFF. | |
410 | ||
411 | Power switch: | |
412 | You can read the state from PSW line(active low) however | |
413 | the switch has a special scancode 0x7F7F, so you can | |
414 | also read from Data line. It uses 0xFFFF for release scancode. | |
415 | ||
416 | Keyboard LEDs & state of keys(Register2) | |
417 | This register hold current state of three LEDs and nine keys. | |
418 | The state of LEDs can be changed by sending Listen command. | |
d702fe75 | 419 | |
a074364c | 420 | 1514 . . . . . . 7 6 5 . 3 2 1 0 |
421 | | | | | | | | | | | | | | | | +- LED1(NumLock) | |
422 | | | | | | | | | | | | | | | +--- LED2(CapsLock) | |
423 | | | | | | | | | | | | | | +----- LED3(ScrollLock) | |
424 | | | | | | | | | | | +-+-+------- Reserved | |
425 | | | | | | | | | | +------------- ScrollLock | |
426 | | | | | | | | | +--------------- NumLock | |
427 | | | | | | | | +----------------- Apple/Command | |
428 | | | | | | | +------------------- Option | |
429 | | | | | | +--------------------- Shift | |
430 | | | | | +----------------------- Control | |
431 | | | | +------------------------- Reset/Power | |
432 | | | +--------------------------- CapsLock | |
433 | | +----------------------------- Delete | |
434 | +------------------------------- Reserved | |
435 | ||
e6612962 | 436 | Address, Handler ID and bits(Register3) |
437 | 1514131211 . . 8 7 . . . . . . 0 | |
438 | | | | | | | | | | | | | | | | | | |
439 | | | | | | | | | +-+-+-+-+-+-+-+- Handler ID | |
440 | | | | | +-+-+-+----------------- Address | |
441 | | | | +------------------------- 0 | |
442 | | | +--------------------------- Service request enable(1 = enabled) | |
230ed4bd | 443 | | +----------------------------- Exceptional event(alwyas 1 if not used) |
e6612962 | 444 | +------------------------------- 0 |
445 | ||
d702fe75 | 446 | ADB Bit Cells |
447 | bit cell time: 70-130us | |
448 | low part of bit0: 60-70% of bit cell | |
449 | low part of bit1: 30-40% of bit cell | |
450 | ||
451 | bit cell time 70us 130us | |
452 | -------------------------------------------- | |
453 | low part of bit0 42-49 78-91 | |
454 | high part of bit0 21-28 39-52 | |
455 | low part of bit1 21-28 39-52 | |
456 | high part of bit1 42-49 78-91 | |
457 | ||
458 | ||
459 | bit0: | |
460 | 70us bit cell: | |
461 | ____________~~~~~~ | |
462 | 42-49 21-28 | |
463 | ||
464 | 130us bit cell: | |
465 | ____________~~~~~~ | |
466 | 78-91 39-52 | |
467 | ||
468 | bit1: | |
469 | 70us bit cell: | |
470 | ______~~~~~~~~~~~~ | |
471 | 21-28 42-49 | |
472 | ||
473 | 130us bit cell: | |
474 | ______~~~~~~~~~~~~ | |
475 | 39-52 78-91 | |
476 | ||
477 | [from Apple IIgs Hardware Reference Second Edition] | |
478 | ||
479 | Keyboard Handle ID | |
480 | Apple Standard Keyboard M0116: 0x01 | |
481 | Apple Extended Keyboard M0115: 0x02 | |
482 | Apple Extended Keyboard II M3501: 0x02 | |
483 | Apple Adjustable Keybaord: 0x10 | |
484 | ||
485 | http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L802 | |
486 | ||
a074364c | 487 | END_OF_ADB |
488 | */ |