Subject: Re: Extended Keyboard II lights control
From: [email-masked] (Matt Deatherage)
Date: Wed, 22 Sep 1993 17:56:39 GMT
Newsgroups: comp.sys.apple2.programmer

I make absolutely _no_ guarantee this works, or that it will work on all
systems.  It was written in 1989 by an Apple II DTS engineer.

         COPY  2/AINCLUDE/E16.MEMORY
         MCOPY MYMACROS
         GEN   ON
         LONGA ON
         LONGI ON

Entry    START

DeRef    equ   $0                       ;temp storage for derefing handle
MyHandle equ   DeRef+4                  ;storage of handle
MyPtr    equ   MyHandle+4               ;MyHandle dereferenced to MyPtr
UserID   equ   MyPtr+4                  ;MM application UserID
ADBPtr   equ   UserID+2                 ;Ptr to ADB data buf in completion
rtn
ADBStat  equ   ADBPtr+4                 ;status for ADB device
MyPtr2   equ   ADBStat+2                ;MyPtr+100, for SendInfo buffer

Talk     equ   $000C                    ;talk mask for ADB calls
R0       equ   $0000                    ;Reg 0 mask for ADB calls
R1       equ   $0001                    ;Reg 1 mask for ADB calls
R2       equ   $0002                    ;Reg 2 mask for ADB calls
R3       equ   $0003                    ;Reg 3 mask for ADB calls
Addr0    equ   $0000                    ;Address 0 mask for ADB calls
Addr1    equ   $0010                    ;Address 0 mask for ADB calls
Addr2    equ   $0020                    ;Address 0 mask for ADB calls
Addr3    equ   $0030                    ;Address 0 mask for ADB calls
Addr4    equ   $0040                    ;Address 0 mask for ADB calls
Addr5    equ   $0050                    ;Address 0 mask for ADB calls
Addr6    equ   $0060                    ;Address 0 mask for ADB calls
Addr7    equ   $0070                    ;Address 0 mask for ADB calls
Addr8    equ   $0080                    ;Address 0 mask for ADB calls
Addr9    equ   $0090                    ;Address 0 mask for ADB calls
Addr10   equ   $00A0                    ;Address 0 mask for ADB calls
Addr11   equ   $00B0                    ;Address 0 mask for ADB calls
Addr12   equ   $00C0                    ;Address 0 mask for ADB calls
Addr13   equ   $00D0                    ;Address 0 mask for ADB calls
Addr14   equ   $00E0                    ;Address 0 mask for ADB calls
Addr15   equ   $00F0                    ;Address 0 mask for ADB calls
ADBBusy  equ   $0982                    ;ADB busy error (command pending)

         bra   Setup
ERROR    brk   $AB                      ;off with their header

SetUp    lda   #$FFFF                   ;set ADBStat to clear status
         sta   ADBStat                  ;put into our stat

LetsDoIt _TLStartUp                     ;start up the tool locator

         pea   $0000                    ;put space on stack for result
         _MMStartUp                     ;start up the memory manager
         pla                            ;pull User ID off stack
         sta   UserID                   ;save for shutdown

         _ADBStartUp                    ;start up the ADB tool set

GetMem   pea   $0000                    ;space for handle
         pea   $0000                    ;space for handle
         PushLong  #1000                ;get $1000 bytes of space
         lda   UserID                   ;get UserID for MM
         pha                            ;put onto stack
         PushWord  #attrLocked+attrFixed+attrNoCross+attrPage   
;attributes
         PushLong  #0                   ;space for locationPtr (unused)
         _NewHandle                     ;get a handle for our space
         bcs   ERROR                    ;if error, die horribly

DeRefIt  pla                            ;get first part of handle
         sta   MyHandle                 ;save for later
         sta   DeRef                    ;save to dereference it
         pla                            ;get second part of handle
         sta   MyHandle+2               ;save for later
         sta   DeRef+2                  ;save to dereference it

         ldy   #2                       ;set Y for upper word of PTR
         lda   [DeRef],Y                ;get upper word of PTR from handle
         tax                            ;save it in X for now.
         lda   [DeRef]                  ;get lower word of PTR from handle
         sta   MyPtr                    ;save lower into pointer
         stx   MyPtr+2                  ;save upper into pointer

SaveDir  tdc                            ;save off our direct page
         sta   >SaveDP                  ;put it into our Comp Rtn
         lda   #$0100                   ;how many bytes to add to our ptr
         ADD4  ,MyPtr,MyPtr2            ;add A to MyPtr, store in MyPtr2

SendFlus pea   $0000                    ;0 bytes in table
         PushLong #0                    ;Push nil for no pointer
         PushWord #$0003                ;send a flush command to device
         _SendInfo                      ;Send information to keyboard

;DBStats PushWord #Talk+R2+Addr2        ;extended keyboard status & LED Reg
ADBStats PushLong #CompRtn              ;push addr of completion rtn
         PushWord #$00E2                ;Talk Reg2, Device #2
         lda   #0000                    ;clear out A
         sta   >Boolean                 ;save to boolean flag for comp rtn
         _AsyncADBReceive               ;recieve data from ADB device
         bcs   ADBStats                 ;if error, keep calling

IsItDone lda   >Boolean                 ;get our flag from comp rtn
         beq   IsItDone                 ;wait for it to be none zero, then
go on

GetStat  lda   [MyPtr]                  ;get word from our buffer
         sta   ADBStat                  ;save status for later
         and   #$4000                   ;clear all but delete key
         beq   exit                     ;exit if delete key pressed

Main     lda   ADBStat                  ;get current values for ADB lights
A        lda   #$FFFE                   ;OFF OFF ON
         xba                            ;swap bytes for SendInfo
         sta   [MyPtr2]                 ;store them into MyPtr2 for
SendInfo
         jsr   SendIt                   ;output value!
         jsr   Timer                    ;delay
B        lda   ADBStat                  ;get current values for ADB lights
         lda   #$FFFD                   ;OFF ON OFF
         xba                            ;swap bytes for SendInfo
         sta   [MyPtr2]                 ;store them into MyPtr2 for
SendInfo
         jsr   SendIt                   ;output value!
         jsr   Timer                    ;delay
C        lda   ADBStat                  ;get current values for ADB Lights
         lda   #$FFFB                   ;ON OFF OFF
         xba                            ;swap bytes for SendInfo
         sta   [MyPtr2]                 ;store them into MyPtr2 for
SendInfo
         jsr   SendIt                   ;output value!
         jsr   Timer                    ;delay
D        lda   ADBStat                  ;get current values for ADB Lights
         lda   #$FFFD                   ;OFF ON OFF
         xba                            ;swap bytes for SendInfo
         sta   [MyPtr2]                 ;store them into MyPtr2 for
SendInfo
         jsr   SendIt                   ;output value!
         jsr   Timer                    ;delay
ClrAll   lda   #$FFFF                   ;set all LEDs off!
         sta   [MyPtr2]                 ;store them into MyPtr2 for
SendInfo
         jsr   SendIt                   ;output value!
         bra   ADBStats                 ;continue til stopped

SendIt   pea   $0002                    ;2 bytes in table
         PushLong MyPtr2                ;put SendInfo Ptr comand onto stack
         PushWord #$00A2                ;transmit 2 bytes to dev2, reg2
         _SendInfo                      ;Send information to keyboard
         rts                            ;return back to caller

Timer    lda   #$8000                   ;get counter value
Timer2   dec   a                        ;a=a-1
         nop                            ;delay 2 clocks
         nop                            ;delay 2 clocks
         bne   Timer2                   ;continue till timer = 0
         rts                            ;return back to caller

exit     lda   #$8000                   ;value for delay
next     dec   a                        ;a=a-1
         nop                            ;delay 2 clocks
         nop                            ;delay 2 clocks
         bne   next                     ;do til done
         lda   #$FFFF                   ;turn it all off
         sta   [MyPtr2]                 ;save to ADB buffer area
         jsr   SendIt                   ;restore original value to keyboard

ADBOff   _ADBShutDown                   ;kill off the ADB Toolset

ByeBye   lda   UserID                   ;get UserID so we can stop MM
         pha                            ;push on stack to shut down MM
         _MMShutDown                    ;shutdown the Memory Manager

         _TLShutDown                    ;shutdown the Tool Locator

         rtl                            ;return to where ever!

CompRtn  ANOP                           ;
         LONGA OFF                      ;
         LONGI OFF                      ;
         phd                            ;save off DP of system
         phb                            ;save current DBR
         phk                            ;load our PBR
         plb                            ;make it the DBR
         php                            ;save processor status for restore
         rep   #$30                     ;set 16 bit m and x
         LONGA ON                       ;
         LONGI ON                       ;
         lda   >SaveDP                  ;get our DP from bottom of this seg
         tcd                            ;put it into D
         lda   $08,s                    ;get upper 2 bytes of ptr off stack
         sta   ADBPtr                   ;save off to our DP
         lda   $0A,s                    ;get lower 2 bytes of ptr off stack
         sta   ADBPtr+2                 ;save off to our DP
         plp                            ;restore 8 bit m and x
         LONGA OFF                      ;
         LONGI OFF                      ;
         lda   [ADBPtr]                 ;get length byte of the ADB buffer
         tay                            ;save it off as an index
         iny                            ;add one to account for length byte
GetNext  lda   [ADBPtr],y               ;get a byte from ADB data buffer
         sta   [MyPtr],y                ;save into our buffer area
         dey                            ;index=index-1
         bne   GetNext                  ;do until done!
         plb                            ;get back system DBR
         pld                            ;get back system DP reg
         lda   #$FF                     ;get our flag value
         sta   >Boolean                 ;set flag to be done!
         rtl                            ;exit completion rtn
SaveDP   DS    2                        ;Storage for our DP
Boolean  DS    2                        ;Storage for Comp Rtn Flag
         END

============================================================================
Matt Deatherage, Developer Support Center, Apple Computer, Inc.
Personal mail only -- please POST technical questions, questions about
Apple and its policies, where to find documents and related inquiries.
The opinions I express don't represent Apple, which makes us both happy.
============================================================================