For some time, I've wanted to try implementing a Apple Desktop Bus (ADB) interface on a PIC. Other than a very short application note in the Microchip Handbook, I haven't seen any details on doing this. So, armed with the Macintosh Family Hardware Reference (from Apple, which describes the ADB interface and protocol in detail) I decided to roll my own. It isn't done yet, but it is a start. The code I've included at the end of this message does the following: It monitors the ADB bus for the Attention Signal (800 usec low). It then waits (delays) for 65 usec for the Sync Signal, then reads in the eight data bits of the command which is sent from the Mac. The first four bits are the address. The next two are the action (generally Talk or Listen), the last two are the register number (0-3). The program checks that the address is equal to 6 (arbitrarily picked by me for testing. A "real" ADB device supports address arbitration which occurs at bus reset time). If the address matches, the Talk and Register number bits are displayed via four LEDs connected to RA0 to RA3 outputs. The ADB bus is connected to RB bit 1. No provision for transmitting exists yet. This is all done on a 16C84, BTW, running at 8 MHz. 4 MHz operation should be possible, if you re-adjust the timing loops. Using the ADB Parser program (supplied on APDA CDs, *extremely useful*) I can send various commands over the bus, and verify that the program does what it should. This is just a start, but hopefully it can grow into a full fledged ADB Device controller. I wanted to see how easy it would be to hack something together. I'm interested in what others think, comments and criticisms are both welcome. I'd also like to work with others interested in ADB interfacing. (This is my first real PIC program, BTW) Chris (excuse the double spacing, the pc likes to put in extra linefeeds that the Mac doesn't want to take out) ;Apple Desktop Bus test ; Set the device type, oscillator type, watchdog timer status, and code ; protect status DEVICE PIC16C84,HS_OSC,WDT_OFF,PROTECT_OFF,PWRT_OFF id 'SMOL' org c Count0 = 10h ;Assign labels to registers w_copy = 11h st_copy = 12h ADBAddress = 13h ADBTalk = 14h ADBReg = 15h detector = rb.1 ; 1 if pinhole is present ; Start of program org 0 jmp Begin org 4 ; [currently] unused interrupt routine mov w_copy,w ;store w mov w,status ; mov st_copy,w ;store status mov w,st_copy mov status,w mov w,w_copy reti Begin clrb rp0 mov !RA,#00010000b ;Set data direction register for port A ;(make all bits output) mov !RB,#11111111b ;make all bits of Port B input setb rp0 ; mov !OPTION,#00000100b ; Set RTCC to divide by 32 ; mov INTCON,#10100000b ; Enable RTCC interrupts clrb rp0 mov RA,#0 Loop1 mov Count0,#1 ; each loop count is 5 usec mov ADBAddress,0 mov ADBTalk,0 mov ADBReg,0 Loop nop ;(1) nop ;(1) nop ;(1) nop ;(1) nop ;(1) jb detector,notdetected ; jump if no adb signal (2) ijnz Count0,Loop ; (3) notdetected dec Count0 cjb Count0,#150,Loop1 ; jmp back to loop if <200 ; ; ok, we have received an "attention" signal. ; ; now wait for 65 usec for the sync signal to finish ; (in an ideal world, we would actually verify that the sync signal was ; present for the 65 usec) ; mov Count0,#26 ;26 loops * 2.5 usec/loop = 65 usec WaitSync nop ;(1) nop ;(1) djnz Count0,WaitSync ;(3) ; ; Delay 50 usec to be centered on each bit of data ; mov Count0,#20 ;20 loops * 2.5 usec/loop = 50 usec WaitDelayA nop ;(1) nop ;(1) djnz Count0,WaitDelayA ;(3) ; now read first address bit jnb detector,AddressB ; jmp if a 0 (2/3) setb ADBAddress.3 ; (1) AddressB mov Count0,#39 ;39 loops * 2.5 usec/loop + 2.5 = 100 usec WaitDelayB nop ;(1) nop ;(1) djnz Count0,WaitDelayB ;(3) ; now read second address bit jnb detector,AddressC ; jmp if a 0 setb ADBAddress.2 AddressC mov Count0,#39 ;40 loops * 2.5 usec/loop +2.5 = 100 usec WaitDelayC nop ;(1) nop ;(1) djnz Count0,WaitDelayC ;(3) ; now read third address bit jnb detector,AddressD ; jmp if a 0 setb ADBAddress.1 AddressD mov Count0,#39 ;40 loops * 2.5 usec/loop +2.5 = 100 usec WaitDelayD nop ;(1) nop ;(1) djnz Count0,WaitDelayD ;(3) ; now read fourth address bit jnb detector,AddressE ; jmp if a 0 setb ADBAddress.0 AddressE mov Count0,#39 ;40 loops * 2.5 usec/loop +2.5 = 100 usec WaitDelayE nop ;(1) nop ;(1) djnz Count0,WaitDelayE ;(3) ; now read first talk bit jnb detector,AddressF ; jmp if a 0 setb ADBTalk.1 AddressF mov Count0,#39 ;40 loops * 2.5 usec/loop +2.5 = 100 usec WaitDelayF nop ;(1) nop ;(1) djnz Count0,WaitDelayF ;(3) ; now read second talk bit jnb detector,AddressG ; jmp if a 0 setb ADBTalk.0 AddressG mov Count0,#39 ;40 loops * 2.5 usec/loop +2.5 = 100 usec WaitDelayG nop ;(1) nop ;(1) djnz Count0,WaitDelayG ;(3) ; now read first reg bit jnb detector,AddressH ; jmp if a 0 setb ADBReg.1 AddressH mov Count0,#39 ;40 loops * 2.5 usec/loop +2.5 = 100 usec WaitDelayH nop ;(1) nop ;(1) djnz Count0,WaitDelayH ;(3) ; now read second talk bit jnb detector,AddressI ; jmp if a 0 setb ADBReg.0 AddressI ; xor RA,#00001000b ; Invert LED (bit 3 port B) cjne ADBAddress,#6,Loop1 movb RA.0,ADBTalk.0 movb RA.1,ADBTalk.1 movb RA.2,ADBReg.0 movb RA.3,ADBReg.1 ; xor RA,#00000001b ; Invert LED (bit 0 port A) jmp Loop1 ---------------------------------------------------------------------------- |Check out my WWW page at http://www.access.digex.net/~cps/ for ham radio | |software for the Mac; Free Radio, Shortwave Radio, and Spy Numbers Stations | |information. | |Finger me (cps@access.digex.net) for my PGP Public Key | ---------------------------------------------------------------------------- "Those who would gladly sacrifice liberty for security deserve neither." -Ben Franklin