; ; Originally coded in 2009 by Matthew A. Hudson hexsane ; at gmail.com ; Code style & format borrowed from CFFA v1 source code ; use ca65 to assemble (options elude me as I wrote this code ; over a decade ago as I type this) ; ; HP-IB AMIGO protocol ROM replacement for genuine Apple II GP-IB controller. ; ; Was assembled and working for floppy drive in HP9133xv ; It will work with the hard drive but you will need to change the ; geometry and re assemble. ; ; Note about assembly: I had to offset the code by either 128 or 256 bytes ; (meaning you lose that space in the ROM) but I can't recall why. You may ; need to fiddle around with options to get it in the correct location to ; make the card happy. I've forgotten most of the Apple II I/O layout at this ; point in time. ; ; There is probably code in here from other sources but I couldn't recall from ; who at this point. If you see something that needs credit please let me know ; and I will happily do so. ; ; Constant equates and 'magic' numbers ; CR = $0D ; ASCII carriage return RDY = $AE ; offset in ROM to "READY." message VBLNK = $20 ; mask for vertical blank bit in VIA OFFM = $00 ; turns off AUTO, TRACE or STEP POSMSK = $7F ; mask to force positive byte AUTOM = $01 ; AUTO mode marker TRACEM = $02 ; TRACE mode marker STEPM = $03 ; STEP mode marker SCREEN = $8000 ; SCREEN RAM starting location TKNTO = $A4 ; BASIC token for TO statement TKNMIN = $AB ; BASIC token for minus sign: - MAXLIN = $F9FF ; maximum line number for BASIC (63999) BASPG = $B4 ; BASIC page for direct mode CHRGET call ; ; -- Handle new BASIC line input page. VERSION = 0 ; Zero page locations ; COUNT = $0005 ; temporary byte storage for counters, etc. _FLAG1 = $0009 ; Misc. flag or index value TMPINT = $0011 ; integer temp _STRPTR = $001F ; pointer to string variable _TMPTR0 = $0021 ; temporary pointer to BASIC text _BASPTR = $0028 ; pointer to start of BASIC program _VARPTR = $002A ; pointer to start of BASIC variables _ARRPTR = $002C ; pointer to start of BASIC arrays _MEMSZ = $0034 ; highest memory location used by BASIC CURRLN = $0036 ; current BASIC line number _VARNAM = $0042 ; current VARIABLE name _VARADR = $0044 ; address of VARIABLE TMPTR1 = $0055 ; temporary storage for integers or pointers TMPTR2 = $0057 ; " " TMPTR3 = $005C ; " " CYLH = $0055 CYLL = $0056 HEAD = $0057 SECTOR = $0058 _FACCM = $005F ; f.p. mantissa (int. storage for conversion) CHRGET = $0070 ; The infamous BASIC character/token fetch CHRGOT = $0076 ; get last character TXTPTR = $0077 ; pointer into BASIC program MODE = $007C ; OFF, AUTO, STEP or TRACE marker (0,1,2 or 3) _LINNUM1 = $0080 ; work area and storage for BASIC line _LINNUM2 = $0082 ; numbers used by AUTO and RENUMBER _TMPTR4 = $0084 ; temporary pointer _TMPTR5 = $0086 ; temporary pointer or byte storage (see below) _TMPERR = $0086 ; temporary offset to char used by HELP routine A0BYTE = $A0 A5BYTE = $A5 ACBYTE = $80 BTBYTE = $81 EFBYTE = $82 MXHEAD = $83 MXSECTOR = $84 MXCYLH = $85 MXCYLL = $86 ;SPARE1 = $82 ;BYBYTE = $82 SAVEX = $0087 ; temporary storage for BASIC 'x' register _STATUS = $0096 ; BASIC status byte _SHIFTKEY = $0098 ; SHIFT key pressed = 1, not pressed = 0 _LDVERF = $009D ; LOAD/VERIFY flag for cassette _NUMCHR = $009E ; number of characters in keyboard buffer _REVFLG = $009F ; screen reverse field flag TAPETMP1 = $00C7 ; temporary pointers for tape handler _TAPETMP2 = $00C9 ; " " " _FNLEN = $00D1 ; number of characters in file name DEVID = $00D4 ; device ID DISKNUM = $033b ; D# from command line. _TAPBUFF = $00D6 ; pointer to start of tape buffer ; ; stack page ; STKPAG = $0100 ; ; BASIC input buffer ; INBUFF = $0200 ; direct mode input buffer and work area KEYBUFF = $026F ; BASIC keyboard buffer ; ; cassette buffer ; SAFTMP1 = $03E0 ; safe temporary when cassette #2 not used SAFTMP2 = $03E1 ; " " " STEPSZ = $03E2 ; line spacing for AUTO and RENUMBER LNBUFF = $03E4 ; Line buffer for TRACE and STEP scrolling TRCBUF = $03E6 ; buffer for displayed TRACE lines (integers) ; ; BASIC entry points ; KWDLST = $C092 ; list of BASIC keywords PRTERR = $C355 ; print error message ERRMSG = $C377 ; print ERROR RDYMSG = $B3FF ; print READY. FIXLINKS = $C439 ; reset BASIC line links LOOKUP = $b4fb ; get BASIC token for keyword FINDLINE = $C52C ; get ptr to BASIC line. num ($11), ptr: ($5C) RST_PTRS = $C572 ; reset BASIC pointers to default values RD_INT = $C873 ; convert ASCII string to integer in $11,$12 PUT_CRLF = $C9DE ; print CR/LF to device PUT_STRING = $bb1d ; prepare and print ASCII string to device PRTSTR = $CA22 ; print string PUTCHR = $bb46 ; print character SYNERR = $CE03 ; display ?SYNTAX ERROR msg LOCVAR = $D069 ; find an f.p. variable by name FX2FLT = $D26D ; convert fixed point to floating point LDFACC = $DAAE ; load f.p. number fo FACC1 INT2FP = $DB55 ; convert integer to f.p. PRTLIN = $DCD5 ; print line number PRTINT = $cf83 ; print integer in a(hi),x(lo) CNV_PRT = $DCE3 ; convert f.p. in FACC1 to ASCII and print FP2ASC = $DCE9 ; convert to ASCII string at bottom of stack ;PARSEDOS = $de2c ; Parse DOS BASIC command line PARSEDOS = $dc68 ; Parse DOS BASIC command line PRTHEX = $d722 ; Print A as HEX to output ; ; Screen editor ; NUMCHK = $d3aa ; clear carry if 'a' contains ASCII digit ; ; I/O ports VIA = $E840 ; misc. operating system flags and VBLANK ; ; Kernel (kernal) entry points ; PRTMON = $F156 ; print MONITOR message at index in 'y' PRTLOAD = $F3E6 ; print LOAD message PRTRDY = $F3EF ; print READY. message PRTSRCH = $F40A ; print SEARCHING message GETPARM = $F47d ; get device parameters GETHDR = $F494 ; get tape program header PRTFNF = $F56E ; print FILE NOT FOUND message SRCH_HDR = $F5A6 ; search tape for next header RD_HDR = $F63C ; get tape program start & end addresses SET_BUFF = $F656 ; set buffer start address WT_PLAY = $F812 ; wait for cassette PLAY switch RD_TAPE = $F85E ; read cassette tape WT_IO = $F8E6 ; wait for I/O completion STOPKEY = $FFE1 ; check for stop key and restart BASIC ; IEEE 488 NRFDOUT = $e840 NDACOUT = $e821 EOIOUT = $e811 DAVOUT = $e823 HIGH = $3c LOW = $34 DATAOUT = $e822 DATAIN = $e820 NRFDIN = $e840 DAVIN = $e840 ATNOUT = $e840 NDACIN = $e840 EOIIN = $e810 ; ; AMIGO DOS START ; ; Call with SYS(28672) ; ;.segment "szzz" ;.org $7000 .word *+2 ;.segment "STARTUP" ;.code AMIGODOS: jmp INITROM ; Toolkit initialization. ; Need jump table here. INITROM: ldx #$07 ; Initialize Toolkit ROM. @B: lda WEDGE-1,x ; Gopy 'wedge' to CHRGET sta TXTPTR+1,x ; following TXTPTR. dex bne @B lda #CPYRT ; notice. jsr PUT_STRING lda #$05 sta DEVID ; Set default DEVICE BYTE FIXME lda #$00 sta A0BYTE sta EFBYTE rts ;jmp INITVAR ; Initialize Toolkit vars. ; ; 'wedge' code for insertion in CHRGET routine ; WEDGE: jmp AD_ENTRY brk ; Location for MODE byte. jmp AD_CONT ; ; This is the entry point for the Toolkit 'wedge' code. Normal BASIC ; calls to the CHRGET routine are intercepted to test for Toolkit ; command processing. If no Toolkit action is performed, BASIC is ; continued. ; AD_ENTRY: pha ; Toolkit entry from CHRGET wedge. stx SAVEX ; Save 'x' register for BASIC. lda TXTPTR+1 ; Test for direct mode: cmp #>INBUFF ; - are we pointing into bne @F ; the BASIC buffer? ($02XX) lda TXTPTR cmp #(_LOOP-1) .byte >(_DSJ-1) .byte >(_STAT-1) .byte >(_SEEK-1) .byte >(_HEADER-1) ; ; low bytes of Toolkit routine entry points ; ADADDRLO:.byte <(_LOOP-1) .byte <(_DSJ-1) .byte <(_STAT-1) .byte <(_SEEK-1) .byte <(_HEADER-1) GO_BAS: lda #$FF sta CURRLN+1 jmp RDYMSG ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; LISTEN Command 30 TALK Command 30 ;; LOOPBACK Test ;; _LOOP: lda #$00 sta A0BYTE sta EFBYTE lda #$05 sta DEVID jsr LISTEN lda #$1e ; Write Loopback Record sta ACBYTE jsr SECLIST lda #65 sta ACBYTE jsr QOUT lda #66 sta ACBYTE jsr QOUT lda #67 sta ACBYTE jsr QOUT lda #68 sta ACBYTE jsr QOUT lda #69 sta ACBYTE jsr QOUT jsr PPUNL jsr TALK lda #$1e ;Read Loopback record sta ACBYTE jsr SECTALK @B: jsr QIN lda ACBYTE jsr PUTCHR lda EFBYTE beq @B jsr UNTALK jmp GO_BAS .IF 0 PRTHEXI: pha lsr lsr lsr lsr clc adc #48 cmp #58 bmi @F1 clc adc #7 @F1: jsr PUTCHR pla and #$0f clc adc #48 cmp #58 bmi @F2 clc adc #7 @F2: jsr PUTCHR rts .ENDIF ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; DOS Command HEADER - Format Disk ;; _HEADER:lda #$00 sta A0BYTE sta EFBYTE jsr CHRGET jsr LOOKUP jsr CHRGET jsr PARSEDOS ;jsr FORMAT ; FIXME ENABLE ; FIXME Will need identify table for these values. lda #2 sta MXHEAD lda #16 sta MXSECTOR lda #35 sta MXCYLL lda #0 sta MXCYLH ;Track 0 Sector 0 lda #$00 sta HEAD sta CYLH sta CYLL sta SECTOR jsr SEEK jsr OWRITE ; Output data to be written to sector (256 Bytes Max) lda #VERSION ; Our version # sta ACBYTE jsr QOUT lda #00 ; # or tracks (cylinders) hi sta ACBYTE jsr QOUT lda #35 ; # of tracks (cylinders) lo sta ACBYTE jsr QOUT lda #16 ; # of sectors per track sta ACBYTE jsr QOUT lda #2 ; # of heads sta ACBYTE jsr QOUT lda #1 ; #of Partitions sta ACBYTE jsr QOUT lda #00 ; Partition start track sta ACBYTE jsr QOUT lda #01 sta ACBYTE jsr QOUT lda #00 ; Partition end track sta ACBYTE jsr QOUT lda #34 sta ACBYTE jsr QOUT jsr CWRITE ;Track 18 Sector 0 lda #$00 sta HEAD sta CYLH sta SECTOR lda #18 sta CYLL jsr SEEK jsr OWRITE lda #<(T18SC0) sta TAPETMP1 lda #>(T18SC0) sta TAPETMP1+1 jsr BUILDSECTOR jsr CWRITE ;Track 18 Sector 1 jsr NXTSECTOR jsr SEEK jsr OWRITE lda #<(T18SC1) sta TAPETMP1 lda #>(T18SC1) sta TAPETMP1+1 jsr BUILDSECTOR jsr CWRITE ;Track 18 Sector 2 jsr NXTSECTOR jsr SEEK jsr OWRITE lda #<(T18SC2) sta TAPETMP1 lda #>(T18SC2) sta TAPETMP1+1 jsr BUILDSECTOR jsr CWRITE ;Track 18 Sector 3 ldx #3 @NXTDIRSEC: jsr NXTSECTOR jsr SEEK jsr OWRITE lda #18 inx cpx #32 bne @NOTLAST lda #0 ldx #$ff @NOTLAST: sta ACBYTE jsr QOUT txa sta ACBYTE jsr QOUT jsr CWRITE cpx #$ff bne @NXTDIRSEC jsr CWRITE jmp GO_BAS BUILDSECTOR: ldy #$00 sty COUNT @NXTBYTE: inc COUNT lda (TAPETMP1), y iny cmp #$80 bmi @SEND cmp #$ff ;$ff = End beq @DONE cmp 'n'|128 ;n+high bit = name bne @f1 ldx #$00 ;FIXME NEED TO VALIDATE FILE NAME/DISK NAME @NXTFNCHAR: lda $0342,x sta ACBYTE jsr QOUT inx cpy $d1 bne @NXTFNCHAR lda #$10 sec sbc $d1 beq @NXTBYTE tax @NXTSSPC: lda #$a0 sta ACBYTE jsr QOUT dex bne @NXTSSPC jmp @NXTBYTE @f1: cmp 'i'|128 ;i+high bit = Disk ID bne @f2 lda $033f sta ACBYTE jsr QOUT lda $0340 sta ACBYTE jsr QOUT @f2: cmp 'r'|128 ;repeat group bne @f3 lda (TAPETMP1), y pha ; push counter iny ; offset to restore @NXTGROUP: tya pha ; push restore offset jsr @NXTBYTE pla tsx dec $100,x beq @GROUPDONE tay ;restore offset jmp @NXTGROUP @GROUPDONE: ;Y should be set beyond the group pla jmp @NXTBYTE @f3: and #$80 sta COUNT lda (TAPETMP1), y ;Repeat COUNT times iny @SEND: sta ACBYTE jsr QOUT dec COUNT bne @SEND jmp @NXTBYTE @DONE: rts NXTSECTOR: ldx #0 inc HEAD lda HEAD cmp MXHEAD beq @INCSECTOR rts @INCSECTOR: stx HEAD inc SECTOR lda SECTOR cmp MXSECTOR beq @INCCYLL rts @INCCYLL: stx SECTOR clc lda CYLL adc #1 bcs @INCCYLH sta CYLL cmp MXCYLL beq @ERROR rts @INCCYLH: stx CYLL lda CYLH adc #1 bcs @ERROR sta CYLH cmp MXCYLH beq @ERROR rts @ERROR: ;FIXME NEED ERROR HERE lda #'e' jsr PUTCHR lda #$0d jsr PUTCHR brk ; Track 18, Sector 0 T18SC0: .byte 18, 3, 0, 0, 'n'|128, 'i'|128, $81, $a0, 0, 0, $82, $a0, $ff ; Track 18 Sector 1 T18SC1: .byte 18, 2, 0, 0, 'i'|128, 0, 0, 8|128, 0 .byte 31, 1|128, $fe, 4|128, $ff .byte 'r'|128, 16, 32, 5|128, $ff, $ff .byte 6|128, 0 .byte 'r'|128, 17, 32, 5|128, $ff, $ff .byte 'r'|128, 5, 6|128, 0, $ff .byte $ff ; Track 18 Sector 2 T18SC2: .byte 0, $ff, 0, 0, 'i'|128, 0, 0, 8|128, 0 .byte 'r'|128, 35, 32, 5|128, $ff, $ff .byte 'r'|128, 5, 0, 5|128, 0, $ff .byte $ff ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; LISTEN Command 12 TALK OpCode 24 ;; FORMAT Low level format the drive for sector writing. ;; (Internal Subroutine) ;; FORMAT: lda #$00 sta A0BYTE sta EFBYTE lda #$05 sta DEVID jsr LISTEN lda #12 ;FORMAT Command sta ACBYTE jsr SECLIST @B: lda #24 sta ACBYTE jsr QOUT lda DISKNUM sta ACBYTE jsr QOUT lda #$80 sta ACBYTE jsr QOUT lda #9 sta ACBYTE jsr QOUT lda #0 sta ACBYTE jsr QOUT jsr PPUNL rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; LISTEN Command 8 TALK Command 8 ;; Request Status / Send Status ;; _STAT: lda #$00 sta A0BYTE sta EFBYTE jsr CHRGET jsr LOOKUP jsr CHRGET jsr PARSEDOS lda DEVID bne EXSTAT lda #$05 sta DEVID EXSTAT: jsr STAT lda #ST1 jsr PUT_STRING lda TMPTR1 jsr PRTHEX lda TMPTR1+1 jsr PRTHEX lda #$0d jsr PUTCHR lda #ST2 jsr PUT_STRING lda TMPTR1+2 jsr PRTHEX lda TMPTR1+3 jsr PRTHEX lda #$0d jsr PUTCHR jmp GO_BAS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Request Status / Send Status (Internal Subroutine) ;; STAT: jsr LISTEN lda #8 ; Request Status sta ACBYTE jsr SECLIST lda #3 sta ACBYTE jsr QOUT lda DISKNUM ; Disk (Unit) Number sta ACBYTE jsr QOUT jsr PPUNL jsr TALK lda #8 ;Send Status sta ACBYTE jsr SECTALK jsr QIN lda ACBYTE sta TMPTR1 jsr QIN lda ACBYTE sta TMPTR1+1 jsr QIN lda ACBYTE sta TMPTR1+2 jsr QIN lda ACBYTE sta TMPTR1+3 @B: jsr QIN lda ACBYTE lda EFBYTE beq @B jsr UNTALK rts ST1: .asciiz "st1:$" ST2: .asciiz "st2:$" STDSJ: .asciiz "dsj:" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; TALK Command 16 ;; _DSJ - Device Specified Jump ;; _DSJ: lda #$00 sta A0BYTE sta EFBYTE jsr CHRGET jsr LOOKUP jsr CHRGET jsr PARSEDOS lda DEVID bne @HAVEDV lda #$05 sta DEVID @HAVEDV:jsr DSJ lda #STDSJ jsr PUT_STRING lda TMPINT clc adc #48 jsr PUTCHR lda #$0d jsr PUTCHR jmp GO_BAS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; DSJ - Device Specified Jump (Internal Subroutine) ;; DSJ: jsr TALK lda #16 ;Get DSJ sta ACBYTE jsr SECTALK @B: jsr QIN lda ACBYTE sta TMPINT lda EFBYTE beq @B jsr UNTALK rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; LISTEN Command 8 OpCode 2 ;; _SEEK - Seek drive head to DISKNUM,CYLH,CYLL,HEAD,SECTOR ;; _SEEK: lda #$00 sta A0BYTE sta EFBYTE jsr CHRGET jsr LOOKUP jsr CHRGET jsr PARSEDOS lda DEVID bne @HAVEDV lda #$05 sta DEVID @HAVEDV:jsr SEEK jsr DSJ lda TMPINT beq @SKIPSTAT lda #STDSJ jsr PUT_STRING lda TMPINT clc adc #48 jsr PUTCHR lda #$0d jsr PUTCHR jmp EXSTAT @SKIPSTAT: jmp GO_BAS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; SEEK Seek drive head to D#,CYLH,CYLL,HEAD,SECTOR ;; (Internal Subroutine) ;; SEEK: lda DEVID jsr LISTEN lda #8 ;Get DSJ sta ACBYTE jsr SECLIST @B: lda #'s' jsr PUTCHR lda #$0d jsr PUTCHR lda #$02 sta ACBYTE jsr QOUT lda DISKNUM sta ACBYTE jsr QOUT lda CYLH sta ACBYTE jsr QOUT lda CYLL sta ACBYTE jsr QOUT lda HEAD sta ACBYTE jsr QOUT lda SECTOR sta ACBYTE jsr QOUT jsr PPUNL rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; _WRITE - Buffered Write to current seeked sector. ;; _WRITE: lda #$00 sta A0BYTE sta EFBYTE jsr CHRGET jsr LOOKUP jsr CHRGET jsr PARSEDOS lda DEVID bne @HAVEDV lda #$05 sta DEVID @HAVEDV:;jsr OWRITE jsr DSJ lda TMPINT beq @SKIPSTAT lda #STDSJ jsr PUT_STRING lda TMPINT clc adc #48 jsr PUTCHR lda #$0d jsr PUTCHR jmp EXSTAT @SKIPSTAT: jmp GO_BAS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; OWRITE - OPEN Buffered Write to current seeked sector ;; (Internal Subroutine) ;; 256 Byte sectors must be written as a whole. (partial sectors filled with 00) ;; OWRITE: jsr LISTEN lda #9 ;Buffered Write sta ACBYTE jsr SECLIST @B: lda #'w' jsr PUTCHR lda #$0d jsr PUTCHR lda #$08 sta ACBYTE jsr QOUT lda DISKNUM sta ACBYTE jsr QOUT rts ; lda $fc ; ; pha ; lda $fb ; Start Address for write ; pha ; lda $ca ; ; pha ; lda $c9 ; End Address for write ; pha ; FIXME Buffer in 2 chunks of 128 bytes. ; OR 192 Bytes followed by 64 bytes? (It would be consistant ; with the way CBM did it) ; lda SECTOR ; sta ACBYTE ; jsr QOUT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; CWRITE - CLOSE Buffered Write to current seeked sector ;; (Internal Subroutine) ;; 256 Byte sectors must be written as a whole. (partial sectors filled with 00) ;; CWRITE: jsr PPUNL rts ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Using Accumulator to hold byte out TALK: lda #$40 jmp TSKIP LISTEN: lda #$20 TSKIP: sta ACBYTE sta BTBYTE ;store variables lda #$02 ora NRFDOUT sta NRFDOUT ;NRFD high lda #HIGH sta NDACOUT ;NDAC high lda A0BYTE beq @NOEOI ;IF A0 = 0 branch lda #LOW sta EOIOUT ;EOI LOW jsr IEEEOUT lda #$00 sta A0BYTE lda #HIGH sta EOIOUT ;EOI HIGH @NOEOI: lda BTBYTE ora DEVID sta A5BYTE lda #HIGH sta DAVOUT @DAVINCHK: lda #$80 bit DAVIN beq @DAVINCHK ;Wait for DAV HIGH lda DAVIN and #$fb sta ATNOUT ;ATN LOW ; Write Byte with handshaking to IEEE Bus ; can't use x, y IEEEOUT: lda #HIGH sta DAVOUT ;DAV OUT HIGH lda NRFDIN and #$41 cmp #$41 ;Does the device exist? beq NODEVICE lda A5BYTE eor #$ff ;Invert bits (IEEE-488 is active low) sta DATAOUT NRFDCHK: lda #$64 bit NRFDIN beq NRFDCHK lda #LOW sta DAVOUT ;DAV OUT LOW UNKCHK: lda #$01 bit NRFDIN beq UNKCHK ;This is in the BASIC source Why? lda #HIGH sta DAVOUT ;DAV OUT HIGH lda #$ff sta DATAOUT ;DATA high rts NODEVICE: lda #DEVNF jsr PUT_STRING jmp GO_BAS ; Send Secondary Listen Address SECLIST: lda ACBYTE ora #96 sta ACBYTE ;FIXME Need to save this? sta A5BYTE jsr IEEEOUT ATNHI: lda ATNOUT ora #$04 sta ATNOUT rts ; Send Secondary Talk Address SECTALK: lda ACBYTE ora #96 sta ACBYTE sta A5BYTE jsr IEEEOUT lda NRFDOUT and #$fd sta NRFDOUT ;NRFD OUT LOW lda #LOW sta NDACOUT ;NDAC OUT LOW jmp ATNHI ;Send untalk command UNTALK: lda ATNOUT and #$fb sta ATNOUT ;ATN OUT HIGH lda #$5f jsr TSKIP jmp ATNHI ; Write queued bytes to IEEE BUS ; can't use x, y QOUT: lda A0BYTE and #$80 bne A0MAXED lda A0BYTE sec sbc #$01 sta A0BYTE bmi QBYTE lda #$ff sta A0BYTE jmp QBYTE A0MAXED: ; lda ACBYTE ;sta BYBYTE jsr IEEEOUT ;lda BYBYTE ;sta ACBYTE QBYTE: lda ACBYTE sta A5BYTE rts ; Read from the IEEE BUS QIN: lda #HIGH sta DAVOUT lda #LOW sta NDACOUT lda NRFDOUT ora #$02 sta NRFDOUT ;NRFD OUT HIGH @B1: lda DAVIN and #$80 bne @B1 ;Wait for DAV LOW. lda NRFDOUT and #$fd sta NRFDOUT ;NRFD OUT LOW lda #$40 bit EOIIN bne @F lda EFBYTE ora #$40 sta EFBYTE @F: lda #$ff sec sbc DATAIN sta ACBYTE ;sta BYBYTE lda #HIGH sta NDACOUT @B2: lda #$80 bit DAVIN beq @B2 ;Wait for DAV HIGH lda #LOW sta NDACOUT rts ; UNLISTEN With Parallel Polling. PPUNL: lda #63 sta ACBYTE sta BTBYTE lda NRFDOUT ora #$02 sta NRFDOUT ;NRFD high lda #HIGH sta NDACOUT ;NDAC high lda A0BYTE cmp #$00 beq @F lda #LOW sta EOIOUT ;EOI LOW jsr IEEEOUT lda #HIGH sta EOIOUT ;EOI HIGH lda #$00 sta A0BYTE @F: lda BTBYTE ora DEVID sta A5BYTE lda #HIGH sta DAVOUT @B: lda DAVIN and #$80 beq @B ;Wait for DAV HIGH CHKPOLL: lda #LOW sta EOIOUT ;EOI LOW lda ATNOUT and #$fb sta ATNOUT ;ATN LOW (EOI + ATN = Parallel Poll) ldx #$06 jsr JIFDLY ldy DATAIN ;Y Holds the POLL lda #HIGH sta EOIOUT ;EOI HIGH lda ATNOUT ora #$04 sta ATNOUT ;ATN HIGH lda #$08 sec sbc DEVID tax lda #$00 sec @B: rol dex bne @B ;HP-IB devices respond to poll on DIO# = 8 - device ID sta TMPINT tya and TMPINT bne CHKPOLL lda ATNOUT and #$fb sta ATNOUT jsr IEEEOUT jmp ATNHI ; X = # delay loops JIFDLY: lda $8f @B: cmp $8f beq @B dex bne JIFDLY rts ; ; Matthew Hudson Copyright ; CPYRT: .byte "(c) 2009 matthew a hudson" .byte $0D .byte $00 DEVNF: .byte "device not found!" .byte $0D .byte $00 .end