@ -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-130us
// low part of bit0: 60-70% of bit cell
// low part of bit1: 30-40% of bit cell
//
// bit cell time 70us 130us
// --------------------------------------------
// 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:
// 70us bit cell:
// ____________~~~~~~
// 42-49 21-28
//
// 130us bit cell:
// ____________~~~~~~
// 78-91 39-52
//
// bit1:
// 70us bit cell:
// ______~~~~~~~~~~~~
// 21-28 42-49
//
// 130us 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-260us
//
// 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/00591b.pdf
if ( ! wait_data_hi ( 500 ) ) { // Service Request(310us Adjustable Keyboard): just ignored
xprintf ( " R " ) ;
sei ( ) ;
return - 30 ; // something wrong
return 0 ;
}
if ( ! wait_data_lo ( 500 ) ) { // Tlt/Stop to Start(140-260us)
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
*/