@ -1,5 +1,5 @@
/*
Copyright 2011 Jun WAKO < wakojun @ gmail . com >
Copyright 2011 - 19 Jun WAKO < wakojun @ gmail . com >
Copyright 2013 Shay Green < gblargg @ gmail . com >
This software is licensed with a Modified BSD License .
@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
# include <avr/io.h>
# include <avr/interrupt.h>
# include "adb.h"
# include "print.h"
/ / GCC doesn ' t inline functions normally
# define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT))
@ -59,7 +60,6 @@ static inline void place_bit1(void);
static inline void send_byte ( uint8_t data ) ;
static inline uint16_t wait_data_lo ( uint16_t us ) ;
static inline uint16_t wait_data_hi ( uint16_t us ) ;
static inline uint16_t adb_host_dev_recv ( uint8_t device ) ;
void adb_host_init ( void ) {
ADB_PORT & = ~ ( 1 < < ADB_DATA_BIT ) ;
@ -81,119 +81,164 @@ bool adb_host_psw(void) { return psw_in(); }
* < http : / / geekhack . org / index . php ? topic = 14290. msg1068919 # msg1068919 >
* < http : / / geekhack . org / index . php ? topic = 14290. msg1070139 # msg1070139 >
*/
/ / ADB Bit Cells
/ /
/ / bit cell time : 70 - 130u s
/ / low part of bit0 : 60 - 70 % of bit cell
/ / low part of bit1 : 30 - 40 % of bit cell
/ /
/ / bit cell time 70u s 130u s
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/ / low part of bit0 42 - 49 78 - 91
/ / high part of bit0 21 - 28 39 - 52
/ / low part of bit1 21 - 28 39 - 52
/ / high part of bit1 42 - 49 78 - 91
/ /
/ /
/ / bit0 :
/ / 70u s bit cell :
/ / ____________ ~ ~ ~ ~ ~ ~
/ / 42 - 49 21 - 28
/ /
/ / 130u s bit cell :
/ / ____________ ~ ~ ~ ~ ~ ~
/ / 78 - 91 39 - 52
/ /
/ / bit1 :
/ / 70u s bit cell :
/ / ______ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
/ / 21 - 28 42 - 49
/ /
/ / 130u s bit cell :
/ / ______ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
/ / 39 - 52 78 - 91
/ /
/ / [ from Apple IIgs Hardware Reference Second Edition ]
enum { ADDR_KEYB = 0x20 , ADDR_MOUSE = 0x30 } ;
uint16_t adb_host_kbd_recv ( void ) { return adb_host_dev_recv ( ADDR_KEYB ) ; }
uint16_t adb_host_kbd_recv ( void ) { return adb_host_talk ( ADB_ADDR_KEYBOARD , ADB_REG_0 ) ; }
# ifdef ADB_MOUSE_ENABLE
void adb_mouse_init ( void ) { return ; }
__attribute__ ( ( weak ) ) void adb_mouse_init ( void ) { return ; }
__attribute__ ( ( weak ) ) void adb_mouse_task ( void ) { return ; }
uint16_t adb_host_mouse_recv ( void ) { return adb_host_dev_recv ( ADDR_MOUSE ) ; }
uint16_t adb_host_mouse_recv ( void ) { return adb_host_talk ( ADB_ADDR_MOUSE , ADB_REG_0 ) ; }
# endif
static inline uint16_t adb_host_dev_recv ( uint8_t device ) {
uint16_t data = 0 ;
/ / This sends Talk command to read data from register and returns length of the data .
uint8_t adb_host_talk_buf ( uint8_t addr , uint8_t reg , uint8_t * buf , uint8_t len ) {
for ( int8_t i = 0 ; i < len ; i + + ) buf [ i ] = 0 ;
cli ( ) ;
attention ( ) ;
send_byte ( device | 0x0C ) ; / / Addr : Keyboard ( 0010 ) / Mouse ( 0011 ) , Cmd : Talk ( 11 ) , Register0 ( 00 )
place_bit0 ( ) ; / / Stopbit ( 0 )
send_byte ( ( addr < < 4 ) | ADB_CMD_TALK | reg ) ;
place_bit0 ( ) ; / / Stopbit ( 0 )
/ / TODO : Service Request ( Srq ) :
/ / Device holds low part of comannd stopbit for 140 - 260u s
/ /
/ / Command :
/ / . . . . . . . _ ______________________ ___ . . . . . . . . . . . . _ - - - - - - -
/ / | | | | | | |
/ / Command | | | | | Data bytes | |
/ / . . . . . . . . | ___ | | 140 - 260 | __ | | _ . . . . . . . . . . . . | ___ |
/ / | stop0 | Tlt Stop - to - Start | start1 | | stop0 |
/ /
/ / Command without data :
/ / . . . . . . . _ __________________________
/ / | |
/ / Command | |
/ / . . . . . . . . | ___ | | 140 - 260 |
/ / | stop0 | Tlt Stop - to - Start |
/ /
/ / Service Request :
/ / . . . . . . . _ ______ ___ . . . . . . . . . . . . _ - - - - - - -
/ / | 140 - 260 | | | | | |
/ / Command | Service Request | | | | Data bytes | |
/ / . . . . . . . . | ___________________ | | __ | | _ . . . . . . . . . . . . | ___ |
/ / | stop0 | | start1 | | stop0 |
/ / . . . . . . . _ __________
/ / | 140 - 260 |
/ / Command | Service Request |
/ / . . . . . . . . | ___________________ |
/ / | stop0 |
/ / This can be happened ?
/ / . . . . . . . _ ______________________ ___ . . . . . . . . . . . . _ - - - - -
/ / | | | | | | 140 - 260 |
/ / Command | | | | | Data bytes | Service Request |
/ / . . . . . . . . | ___ | | 140 - 260 | __ | | _ . . . . . . . . . . . . | _________________ |
/ / | stop0 | Tlt Stop - to - Start | start1 | | stop0 |
/ /
/ / " Service requests are issued by the devices during a very specific time at the
/ / end of the reception of the command packet .
/ / If a device in need of service issues a service request , it must do so within
/ / the 65 µ s of the Stop Bit ’ s low time and maintain the line low for a total of 300 µ s . "
/ /
/ / " A device sends a Service Request signal by holding the bus low during the low
/ / portion of the stop bit of any command or data transaction . The device must lengthen
/ / the stop by a minimum of 140 J . lS beyond its normal duration , as shown in Figure 8 - 15. "
/ / http : / / ww1 . microchip . com / downloads / en / AppNotes / 005 91 b . pdf
if ( ! wait_data_hi ( 500 ) ) { / / Service Request ( 310u s Adjustable Keyboard ) : just ignored
xprintf ( " R " ) ;
sei ( ) ;
return - 30 ; / / something wrong
return 0 ;
}
if ( ! wait_data_lo ( 500 ) ) { / / Tlt / Stop to Start ( 140 - 260u s )
sei ( ) ;
return 0 ; / / No data to send
return 0 ; / / No data from device ( not error ) ;
}
/ / start bit ( 1 )
if ( ! wait_data_hi ( 40 ) ) {
xprintf ( " S " ) ;
sei ( ) ;
return 0 ;
}
if ( ! wait_data_lo ( 100 ) ) {
xprintf ( " s " ) ;
sei ( ) ;
return 0 ;
}
uint8_t n = 17 ; / / start bit + 16 data bits
uint8_t n = 0 ; / / bit count
do {
/ /
/ / | < - bit_cell_max ( 130 ) - > |
/ / | | < - lo - > |
/ / | | | < - hi - > |
/ / _______
/ / | | |
/ / | 130 - lo | lo - hi |
/ / | ________ | |
/ /
uint8_t lo = ( uint8_t ) wait_data_hi ( 130 ) ;
if ( ! lo ) goto error ;
if ( ! lo ) goto error ; / / no more bit or after stop bit
uint8_t hi = ( uint8_t ) wait_data_lo ( lo ) ;
if ( ! hi ) goto error ;
if ( ! hi ) goto error ; / / stop bit extedned by Srq ?
hi = lo - hi ;
lo = 130 - lo ;
if ( n / 8 > = len ) continue ; / / can ' t store in buf
data < < = 1 ;
if ( lo < hi ) {
data | = 1 ;
} else if ( n = = 17 ) {
sei ( ) ;
return - 20 ;
buf [ n / 8 ] < < = 1 ;
if ( ( 130 - lo ) < ( lo - hi ) ) {
buf [ n / 8 ] | = 1 ;
}
} while ( - - n ) ;
/ / Stop bit can ' t be checked normally since it could have service request lenghtening
/ / and its high state never goes low .
if ( ! wait_data_hi ( 351 ) | | wait_data_lo ( 91 ) ) {
sei ( ) ;
return - 21 ;
}
sei ( ) ;
return data ;
} while ( + + n ) ;
error :
sei ( ) ;
return - n ;
return n / 8 ;
}
void adb_host_listen ( uint8_t cmd , uint8_t data_h , uint8_t data_l ) {
uint16_t adb_host_talk ( uint8_t addr , uint8_t reg ) {
uint8_t len ;
uint8_t buf [ 8 ] ;
len = adb_host_talk_buf ( addr , reg , buf , 8 ) ;
if ( len ! = 2 ) return 0 ;
return ( buf [ 0 ] < < 8 | buf [ 1 ] ) ;
}
void adb_host_listen_buf ( uint8_t addr , uint8_t reg , uint8_t * buf , uint8_t len ) {
cli ( ) ;
attention ( ) ;
send_byte ( cmd ) ;
place_bit0 ( ) ; / / Stopbit ( 0 )
send_byte ( ( addr < < 4 ) | ADB_CMD_LISTEN | reg ) ;
place_bit0 ( ) ; / / Stopbit ( 0 )
/ / TODO : Service Request
_delay_us ( 200 ) ; / / Tlt / Stop to Start
place_bit1 ( ) ; / / Startbit ( 1 )
send_byte ( data_h ) ;
send_byte ( data_l ) ;
for ( int8_t i = 0 ; i < len ; i + + ) {
send_byte ( buf [ i ] ) ;
/ / xprintf ( " %02X " , buf [ i ] ) ;
}
place_bit0 ( ) ; / / Stopbit ( 0 ) ;
sei ( ) ;
}
void adb_host_listen ( uint8_t addr , uint8_t reg , uint8_t data_h , uint8_t data_l ) {
uint8_t buf [ 2 ] = { data_h , data_l } ;
adb_host_listen_buf ( addr , reg , buf , 2 ) ;
}
void adb_host_flush ( uint8_t addr ) {
cli ( ) ;
attention ( ) ;
send_byte ( ( addr < < 4 ) | ADB_CMD_FLUSH ) ;
place_bit0 ( ) ; / / Stopbit ( 0 )
_delay_us ( 200 ) ; / / Tlt / Stop to Start
sei ( ) ;
}
/ / send state of LEDs
void adb_host_kbd_led ( uint8_t led ) {
/ / Addr : Keyboard ( 0010 ) , Cmd : Listen ( 10 ) , Register2 ( 10 )
/ / send upper byte ( not used )
/ / send lower byte ( bit2 : ScrollLock , bit1 : CapsLock , bit0 :
adb_host_listen ( 0x2A , 0 , led & 0x07 ) ;
/ / Listen Register2
/ / upper byte : not used
/ / lower byte : bit2 = ScrollLock , bit1 = CapsLock , bit0 = NumLock
adb_host_listen ( ADB_ADDR_KEYBOARD , ADB_REG_2 , 0 , led & 0x07 ) ;
}
# ifdef ADB_PSW_BIT
@ -327,7 +372,7 @@ Commands
bits commands
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - 0 0 0 0 Send Reque st ( reset all devices )
- - - - 0 0 0 0 Send Rese t ( reset all devices )
A A A A 0 0 0 1 Flush ( reset a device )
- - - - 0 0 1 0 Reserved
- - - - 0 0 1 1 Reserved
@ -435,5 +480,56 @@ Keyboard LEDs & state of keys(Register2)
| + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Delete
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Reserved
Address , Handler ID and bits ( Register3 )
1514131211 . . 8 7 . . . . . . 0
| | | | | | | | | | | | | | | |
| | | | | | | | + - + - + - + - + - + - + - + - Handler ID
| | | | + - + - + - + - - - - - - - - - - - - - - - - - Address
| | | + - - - - - - - - - - - - - - - - - - - - - - - - - 0
| | + - - - - - - - - - - - - - - - - - - - - - - - - - - - Service request enable ( 1 = enabled )
| + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Exceptional event ( alwyas 1 if not used )
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0
ADB Bit Cells
bit cell time : 70 - 130u s
low part of bit0 : 60 - 70 % of bit cell
low part of bit1 : 30 - 40 % of bit cell
bit cell time 70u s 130u s
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
low part of bit0 42 - 49 78 - 91
high part of bit0 21 - 28 39 - 52
low part of bit1 21 - 28 39 - 52
high part of bit1 42 - 49 78 - 91
bit0 :
70u s bit cell :
____________ ~ ~ ~ ~ ~ ~
42 - 49 21 - 28
130u s bit cell :
____________ ~ ~ ~ ~ ~ ~
78 - 91 39 - 52
bit1 :
70u s bit cell :
______ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
21 - 28 42 - 49
130u s bit cell :
______ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
39 - 52 78 - 91
[ from Apple IIgs Hardware Reference Second Edition ]
Keyboard Handle ID
Apple Standard Keyboard M0116 : 0x01
Apple Extended Keyboard M0115 : 0x02
Apple Extended Keyboard II M3501 : 0x02
Apple Adjustable Keybaord : 0x10
http : / / lxr . free - electrons . com / source / drivers / macintosh / adbhid . c ? v = 4.4 # L802
END_OF_ADB
*/