Searching \ for 'Apple Desktop Bus (ADB) Interfacing' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/index.htm?key=apple+desktop+bus
Search entire site for: 'Apple Desktop Bus (ADB) Interfacing'.

Truncated match.
PICList Thread
'Apple Desktop Bus (ADB) Interfacing'
1995\11\04@220056 by Chris Smolinski

flavicon
face
Well, I spent a few more hours playing around with the simple ADB code I
posted to the list earlier, and have made a few improvements:

It now sort-of supports address re-location (which occurs when the bus is
reset, and the Mac has to shuffle conflicting device addresses around). I
say sort of because it still doesn't monitor for collisions during this
process, which all good ADB devices should do. This obviously is bad if you
choose the same address as another device (such as your mouse). But I start
at address 6, which is probably never used (and certainly isn't on my
setup), so it works for me. Something to be fixed later.

Data can be sent to register 1. The 24 bits sent are shuffled out another
of the PIC's output pins to a Maxim MAX532 Dual 12 bit D/A converter (along
with an output for the data clock and one for chip select). Now my Mac can
send two analog signals to the outside world!

Data can be read from register 1. When a Talk request is made, the PIC
tells a Burr Brown ADS7807 16 bit A/S converter to perform a conversion.
The 16 bits of data are then read in a digital input (using the same clock
pin as for the D/A) and sent to the Mac. Now my Mac can read an analog
signal from the outside world!

As I said earlier, collision detection is not performed. That should be one
of my next goals.

I was using register 0 for my analog I/O, but the Mac always checks
register 0 of the last addressed ADB device to see if it has anything else
to send. That resulted in data continuously being sent from the PIC once it
started. Not good. Well behaved ADB devices only respond to a Register 0
Talk command if they have something new to send (which isn't really
possible to implement for my uses).

Next step is to add some digital I/O. I was thinking of using some shift
registers to get the data into and out of the PIC. They would appear as
register 2 to the Mac.

I also have four LEDs hooked up to RA0-RA3 outputs. They indicate the PICs
new address when you send a Listen Register 3 command. Since they're just
for diagnostic purposes, they will probably have to go to make room for the
I/O necessary to talk to the shift registers.

Anyone know how Apple handles requests to license use of the ADB bus (they
apparently have a patent on it). It is just a formality (fill in a form)?
Or do they want big bucks $$$ too? I'd like to market a cheap
analog/digital I/O device for the Mac using the ADB for the interface.

Well, I hope this stimulates some more ADB interfacing projects on the
list, and I hope to hear from others. Thanks to those who have written to
me already. I have cleaned up the interrupt handler as was suggested
(although it isn't being used in this application).

Chris





;Apple Desktop Bus test
;4 November 1995
;Copyright 1995 Chris Smolinski
;No portion of this software may be used in any commercial application without
;express written consent. blah blah blah...  - the lawyers
;
;Communicates with:
;MAX532 Dual 12 bit D/A converter  (Listen Register 1)
;ADS7807 16 bit A/D converter      (Talk Register 1)


; 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
Byte0           =       16h
Temp            =       17h
Count1          =       18h
Reg3h           =       19h
Reg3l           =       1ah
OurAddress      =       1bh

detector        =       rb.1            ; 1 if pinhole is present
adData          =       rb.2            ; A/D converter data
adCtrl          =       rb.3            ; R/C line on A/D
SCLK            =       rb.4            ; SCLK
DATA            =       rb.5            ; DATA
CS              =       rb.6            ; CS
TX              =       rb.7            ; TX (adb transmit output)

; 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
               swap    w_copy
               mov     w,<>w_copy
               reti

Begin           clrb    rp0
               mov     !RA,#00010000b  ;Set data direction register for port A
                                       ;(make all bits output)

               mov     !RB,#00000111b  ;Set Port B direction registers

               setb    rp0
;               mov     !OPTION,#00000100b      ; Set RTCC to divide by 32
;               mov     INTCON,#10100000b       ; Enable RTCC interrupts
               clrb    rp0

               mov     RA,#0
               clrb    SCLK                    ;make SCLK low
               setb    CS                      ;de-assert CS
               clrb    DATA                    ;make DATA low
               clrb    TX                      ;make TX low
               setb    adCtrl                  ;A/D converter control line

               mov     Reg3h,#01000110b
               mov     Reg3l,#54               ;Device Handler ID
               mov     OurAddress,#6           ;Inital Address

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 reg bit

               jnb     detector,AddressI  ; jmp if a 0
               setb    ADBReg.0

AddressI

               cjne    ADBAddress,OurAddress,Loop1     ; Our address ?

               mov     Count0,#100     ;100 loops * 2.5 usec/loop = 250 usec
WaitStop        nop                     ;(1)
               nop                     ;(1)
               djnz    Count0,WaitStop ;(3)

               cje     ADBTalk,#2,Listen       ; Listen CMD? (5)

Talk

               mov     Count0,#30      ;75 loops * 2.5 usec/loop = 75 usec
WaitStop1       nop                     ;(1)
               nop                     ;(1)
               djnz    Count0,WaitStop1 ;(3)

               cje     ADBReg,#1,TalkReg1      ; Talk Register 1?
               cje     ADBReg,#3,TalkReg3      ; Talk Register 3?
               jmp     Loop1                   ; not implemented [yet]



TalkReg1
               clrb    SCLK                    ; serial data clock to low
               clrb    adCtrl                  ; initiate A/D conversion
               call    SendBit1                ; send a 1 (start)
               setb    adCtrl

               mov     Count1,#16              ; counts 8 bits of data

TalkReg1A       setb    SCLK                    ; clock out data bit
               movb    Temp.0,/adData          ; get complement of input
               mov     W,>>Temp                ; input now in Carry bit
               call    SendBit
               clrb    SCLK                    ;
               djnz    Count1,TalkReg1A

               call    SendBit0                ; send a 0 (stop)
               jmp     Loop1                   ; all done


TalkReg3
               call    SendBit1                ; send a 1 (start)

               mov     Temp,Reg3h              ; copy reg 3h
               mov     Count1,#8               ; counts 8 bits of data

TalkReg3A       rl      Temp                    ; shift bit into carry
               call    SendBit
               djnz    Count1,TalkReg3A

               mov     Temp,Reg3l              ; copy reg 3l
               mov     Count1,#8               ; counts 8 bits of data

TalkReg3B       rl      Temp                    ; shift bit into carry
               call    SendBit
               djnz    Count1,TalkReg3B

               call    SendBit0                ; send a 0 (stop)
               jmp     Loop1                   ; all done


Listen          cje     ADBReg,#1,DASet
               cje     ADBReg,#3,ListenReg3
               jmp     Loop1                   ; unimplemented register


ListenReg3
               mov     Count1,#16      ; counts 16 bits of input

ListenReg3A     jb      detector,ListenReg3A ; jmp if a 1, wait for start bit

               mov     Count0,#34      ;34 loops * 2.5 usec/loop = 85 usec
ListenReg3B     nop                     ;(1)
               nop                     ;(1)
               djnz    Count0,ListenReg3B ;(3)

; this section receives 16 bits of information for Register 3

ListenReg3C     jb      detector,ListenReg3C   ; jmp if a 1, wait for low

               mov     Count0,#20      ;20 loops * 2.5 usec/loop = 50 usec
ListenReg3D     nop                     ;(1)
               nop                     ;(1)
               djnz    Count0,ListenReg3D ;(3)

               movb    Temp.0,detector         ; get input (4)
               mov     W,>>Temp                ; input now in Carry bit (1)
               rl      Reg3l                   ; input now in storage  (1)
               rl      Reg3h                   ; input now in storage  (1)

ListenReg3E    jnb     detector,ListenReg3E  ; jmp if a 0, wait for high

               djnz    Count1,ListenReg3C  ;(3)

               setb    CS                      ; de-assert D/A CS line

               movb    OurAddress.0,Reg3h.0
               movb    OurAddress.1,Reg3h.1
               movb    OurAddress.2,Reg3h.2
               movb    OurAddress.3,Reg3h.3
               movb    RA.0,Reg3h.0
               movb    RA.1,Reg3h.1
               movb    RA.2,Reg3h.2
               movb    RA.3,Reg3h.3

               jmp     Loop1




DASet
               mov     Count1,#24      ; counts 24 bits of input
               clrb    CS              ; assert D/A CS line

WaitStart       jb      detector,WaitStart ; jmp if a 1, wait for start bit

               mov     Count0,#34      ;34 loops * 2.5 usec/loop = 85 usec
WaitStartA      nop                     ;(1)
               nop                     ;(1)
               djnz    Count0,WaitStartA ;(3)



; this section receives 24 bits of information for the D/A converter


DataLoop        jb      detector,DataLoop   ; jmp if a 1, wait for low

               mov     Count0,#20      ;20 loops * 2.5 usec/loop = 50 usec
WaitStartB      nop                     ;(1)
               nop                     ;(1)
               djnz    Count0,WaitStartB ;(3)

               movb    Temp.0,detector         ; get input (4)
               mov     W,>>Temp                ; input now in Carry bit (1)
               rl      Byte0                   ; input now in storage  (1)
               movb    DATA,detector           ; D/A data line (4)
               setb    SCLK                    ; strobe SCLK (1)
               clrb    SCLK                    ; (1)

DataLoopB       jnb     detector,DataLoopB  ; jmp if a 0, wait for high

               djnz    Count1,DataLoop  ;(3)

               setb    CS                      ; de-assert D/A CS line

               movb    RA.0,Byte0.4
               movb    RA.1,Byte0.5
               movb    RA.2,Byte0.6
               movb    RA.3,Byte0.7

;               xor     RA,#00000001b   ; Invert LED (bit 0 port A)
               jmp     Loop1



; if carry is set, a 1 is transmitted, otherwise a 0 is transmitted
; note, since a transistor is used to pull the ADB data line low, the
; TX output is set to a 1 to pull the data line low to a zero. Got it?
;
SendBit         jc SendBit1

SendBit0        setb    TX      ; pull line low, start of bit
               mov     Count0,#26      ;26 loops * 2.5 usec/loop = 65 usec
SendBit0A       nop                     ;(1)
               nop                     ;(1)
               djnz    Count0,SendBit0A ;(3)
               clrb    TX      ; pull line high, end of bit
               mov     Count0,#14      ;14 loops * 2.5 usec/loop = 35 usec
SendBit0B       nop                     ;(1)
               nop                     ;(1)
               djnz    Count0,SendBit0B ;(3)
               ret

SendBit1        setb    TX      ; pull line low, start of bit
               mov     Count0,#14      ;14 loops * 2.5 usec/loop = 35 usec
SendBit1A       nop                     ;(1)
               nop                     ;(1)
               djnz    Count0,SendBit1A ;(3)
               clrb    TX      ; pull line high, end of bit
               mov     Count0,#26      ;26 loops * 2.5 usec/loop = 65 usec
SendBit1B       nop                     ;(1)
               nop                     ;(1)
               djnz    Count0,SendBit1B ;(3)
               ret


----------------------------------------------------------------------------
|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 (spam_OUTcpsTakeThisOuTspamaccess.digex.net) for my PGP Public Key                      |
----------------------------------------------------------------------------

"Those who would gladly sacrifice liberty for security deserve neither."
                      -Ben Franklin

1995\11\05@133055 by Eric Brewer

flavicon
face
Chris Smolinski <.....cpsKILLspamspam@spam@ACCESS.DIGEX.NET> wrote:
>Well, I spent a few more hours playing around with the simple ADB code I
>posted to the list earlier, and have made a few improvements:
> .................. SNIP............
>
>Anyone know how Apple handles requests to license use of the ADB bus (they
>apparently have a patent on it). It is just a formality (fill in a form)?
>Or do they want big bucks $$$ too? I'd like to market a cheap
>analog/digital I/O device for the Mac using the ADB for the interface.
>
> .................. SNIP............

Apple charges a one time $50 license for ADB. The give you several documents
regarding the low level timing of ADB which is different from Inside Mac.

You need to contact someone in the Developer Services group.

In addition to supporting an initial address (which you have as 6), you need to
have your own handler ID (which Apple assigns).

Hope it helps,
eric

More... (looser matching)
- Last day of these posts
- In 1995 , 1996 only
- Today
- New search...