home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
BEEHIVE
/
COMMS
/
IMP-ICE.ARC
/
ICEMODM.A65
< prev
next >
Wrap
Text File
|
1990-09-20
|
22KB
|
1,118 lines
.WIDTH 96
;************************************
;ROUTINE: ICEMODEM.A65
;PURP: PCPI STARCARD CHARACTER DRIVER FOR AUTOMATIC
; ICE MODEM WITH HAYES COMPATIBLE DIALING
;MAY 1987. KCM Lau
;************************************
FALSE .EQU 0 ;ASSEMBLY TIME FALSE
TRUE .EQU NOT FALSE
BASEP0: .QUERY "ENTER BASE OF PAGE 0: "
PAGE0W0: .EQU BASEP0 ;WORD 0 OF PAGE 0
PAGE0W1: .EQU PAGE0W0+2 ;WORD 1 OF PAGE 0
LENP0: .EQU 4 ;4 BYTES OF PAGE 0
;HEADER FOR RELOCATION
TOP:
.WORD 0 ;IF THIS WORD IS 0 THEN
; RELOCATABLE DRIVER
; AND A RELOCATING BIT MAP IS EXPECTED
;ELSE
; THE DRIVER STORED WHERE INDICATED
.WORD ((BOTTOM-TOP)+0FFH) AND 0FF00H ;LENGTH OF THIS CODE
; TO NEXT PAGE BOUNDRY
.BYTE LENP0 ;THIS IS THE NUMBER OF PAGE 0 BYTES
; REQUIRED. IF ITS NO ZERO THEN A RELOCATING
; BIT MAP IS EXPECTED FOR PAGE 0
.BYTE 0 ;TAG FIELD
.WORD 12H ;DEVICE NUMBER (12 = CHARACTER DEVICE 2)
.WORD 1 ;NUMBER OF DEVICES THIS DRIVER WILL SERVICE
.WORD INITENTRY ;INIT ENTRY POINT
.WORD INENTRY ;INPUT ENTRY POINT
.WORD OUTENTRY ;OUTPUT ENTRY POINT
.WORD OTHERENTRY ;OTHER ENTRY POINT
.WORD POLLENTRY ;POLL ENTRY POINT
.WORD 1 ;VERSION NUMBER
NAME: .BYTE 15,"AUTOICE MODEM " ;NAME OF DRIVER (MUST BE 15 BYTES PLUS
; THE LENGTH BYTE)
;SYSTEM EQUATES
OPG0BASE .EQU 80H
SYSP1 .EQU OPG0BASE+2
CP65 .EQU 0B000H
POLLROUTINE .EQU CP65+3
RD1Z80BYTE .EQU CP65+9
WR1Z80BYTE .EQU CP65+12
AZ80SLOT .EQU CP65+46
AWCMDCNT .EQU CP65+68
ARESETIFLGS .EQU CP65+120
SNDNAMECMD .EQU 15
FASTPOLL .EQU TRUE ;Customise for system
TM1SEC .EQU 24 ;Time count for 1 sec
SIGNON .BYTE "Automatic Ice card modem driver installed",13,10,0
;------ SIO ---------
; Serial drivers for Automatic Ice Card Modem. Ken Lau. May 87.
; Main routines : INITSER, SERIN, SEROUT, SEROUTX, POLLSIO, SISTATUS, SOSTATUS
; Support routines: CLRQ, ADDQ, POPQ, QSTATUS
;
; Card equates
ICEUNZ .EQU 0C2C3H ;Unzap
;
; Card vectors. To be patched.
ICEINIT JMP 0C2A0H
ICESTAT JMP 0C251H
ICERD JMP 0C26FH
ICEWR JMP 0C2D0H
;
; Action : initialize serial ports
;
INITSER BIT INITSFT
BPL INITSE1 ;--> Not first time
LDA 0C20DH ;Patch card entry vectors
STA ICEINIT+1
LDA 0C210H
STA ICESTAT+1
LDA 0C20EH
STA ICERD+1
LDA 0C20FH
STA ICEWR+1
LDA #0 ;First time = false
STA INITSFT
INITSE1 JSR ICEINIT ;Initialize card
JSR INITZAP
JSR CLRQ ;Clear queue
RTS
;Set card to dumb mode
INITZAP JSR ICEUNZ ;Unzap
LDA #81H ;^A
JSR SEROUT
LDA #DAH ;Z
JSR SEROUT
LDA #8DH ;CR
JMP SEROUT
;
; Action : send a byte. Queue incoming bytes
; Entry : [A] = byte
; Exit : [A][X][Y] destroyed
;
SEROUT JSR POLLSIO
BIT SOCHFL ;Wait SOCH empty
BMI SEROUT
STA SOCH ;Store char to be send in SOCH
LDA #0FFH ;Indicate SOCH filled
STA SOCHFL
JMP POLLSIO ;If ready send byte (else let polling do it later)
;
; Let through special characters (^A)
SEROUTX PHA
JSR ICEUNZ ;Unzap
PLA
PHA
JSR SEROUT
PLA
AND #7FH ;If CR then revert to dumb mode
CMP #0DH
BEQ INITZAP
RTS
;
; Action : get last byte received
;
SERIN JSR POLLSIO
JSR POPQ
BCS SERIN
RTS
;
; Action : queue any incoming serial bytes if present,
; send ser out chars waiting in SOCH
; Exit : all regs preserved except flags
;
POLLSIO PHA ;Save regs
STX POLLSI8
STY POLLSI9
LDA 05FAH
CMP #0E2H ;Hungup value?
BEQ POLLSI1
LDA #1 ;Check if byte received
JSR ICESTAT
BCS POLLSI3
POLLSI1 LDA SOCHFL ;SOCH filled?
BMI POLLSI4 ;--> yes
POLLSI2 LDY POLLSI9 ;Restore regs
LDX POLLSI8
PLA
RTS
POLLSI3 JSR ICERD ;Receive byte to queue
JSR ADDQ
JMP POLLSI1
POLLSI4 LDA #0 ;Card write status ready?
JSR ICESTAT
BCC POLLSI2 ;--> No
LDA SOCH
JSR ICEWR ;Send SOCH
LDA #0 ;SOCH filled = false
STA SOCHFL
JMP POLLSI2
;
; Action : check if byte avail
; Exit : if avail then NE, Carry set, [A] = 0FFh
;
SISTATUS JSR POLLSIO
JSR QSTATUS
BNE SISTAT1 ;branch if ser in avail
CLC
RTS
SISTAT1 LDA #0FFH
SEC
RTS
;
; Action : check if ready for serial out
; Exit : if ready then [A] = 0FFh, NE, Carry set
;
SOSTATUS JSR POLLSIO
LDA SOCHFL ;SOCH filled?
BNE SOSTAT1 ;--> Yes, not ready
LDA #0FFH
SEC
RTS
SOSTAT1 LDA #0
CLC
RTS
;
; Action : routines to handle 256 byte queue (FIFO)
; Exit : [X] corrupted
;
CLRQ LDA #0 ;clear queue
STA FIRSTPTR
STA NEXTPTR
RTS
;
ADDQ LDX NEXTPTR ;add byte to queue
STA QUEUE,X
INX
STX NEXTPTR
CPX FIRSTPTR
BNE ADDQQ
INC FIRSTPTR
ADDQQ RTS
;
POPQ LDX FIRSTPTR ;get byte from queue
CPX NEXTPTR
BEQ POPQQ
LDA QUEUE,X
INC FIRSTPTR
CLC
POPQQ RTS ;carry set if queue empty
;
QSTATUS LDA FIRSTPTR ;if queue empty [A]=0 and EQ set
EOR NEXTPTR
RTS
;
; Variables
;
RBIT .BYTE 0
RTIME .BYTE 0
RDATA .BYTE 0
SBIT .BYTE 0
STIME .BYTE 0
SDATA .BYTE 0
POLLSI8 .BYTE 0
POLLSI9 .BYTE 0
INITSFT .BYTE 0FFH ;True for first time
SOCH .BYTE 0 ;Serial out char
SOCHFL .BYTE 0 ;True if SOCH has valid contents
;
FIRSTPTR .BYTE 0
NEXTPTR .BYTE 0
QUEUE .BLOCK 256
;
;------ END SIO -----
;-------- DIAL --------
; Dialing routine. Apr 87. Ken Lau
; Main routines: HANGUP, PICKUP, DIALBEG, DIALDIG, DIALEND, DIALST
;
;Send string at call addr until 0 (ctrl chars allowed thru)
SNDSTR PLA
STA SNDSTR3+1
PLA
STA SNDSTR3+2
BNE SNDSTR2
SNDSTR1 JSR SEROUTX ;send byte
SNDSTR2 INC SNDSTR3+1
BNE SNDSTR3
INC SNDSTR3+2
SNDSTR3 LDA 0FFFFH ;to be patched
BNE SNDSTR1
LDA SNDSTR3+2
PHA
LDA SNDSTR3+1
PHA
RTS
;Pick up phone (on line)
PICKUP RTS
;Hang up phone (off line)
HANGUP JSR SNDSTR
.BYTE 81H,C8H,8DH,0 ;^AH<CR>
RTS
;Prepare to accept dial digits via DIALDIG routine
DIALBEG JSR SNDSTR
.BYTE 81H,C4H,0 ;^AD
RTS
;Dial digit in [A]. [XY] preserved
DIALDIG CMP #10 ;check for 0..9
BCS DIALDIQ
ADC #0B0H ;convert to ascii digit
JSR SEROUT
DIALDIQ RTS
;Finish dialing
DIALEND LDA #8DH ;<CR>
JMP SEROUT
;
;Return dial status. If still waiting then carry clear else code in [A]:
;(3=no carrier, 1=300 or 75 bps connect, 5=1200 bps connect)
DIALST LDA 2042
CMP #51
BEQ DIALST2 ;--> 300 bps
CMP #72
BEQ DIALST3 ;--> 75/1200 bps
CMP #61
BEQ DIALST3 ;--> 1200/75 bps
LDA #3 ;no carrier
SEC
RTS
DIALST2 LDA #1
SEC
RTS
DIALST3 LDA #5
SEC
RTS
;-------- END DIAL --------
;*************************************
;ROUTINE: INITENTRY
;PURP: INITIALIZE
;ENTRY: NONE
;USED: ALL
;*************************************
INITENTRY: JSR INITSER
BIT FIRSTTIME ;if firsttime then patch vectors
BPL INIT2
PHP ;disable intr
SEI
LDA #0FFh ;call init on reset
LDX TOP+6
STA ARESETIFLGS,X
.IF FASTPOLL
LDA #1 ;number of checks of Z80 between polling
STA AWCMDCNT
LDA POLLROUTINE+1 ;redirect POLLROUTINE
STA OLDPOLL+1
LDA POLLROUTINE+2
STA OLDPOLL+2
LDA NPOLLADDR
STA POLLROUTINE+1
LDA NPOLLADDR+1
STA POLLROUTINE+2
LDA NRD1Z80ADDR ;redirect RD1Z80BYTE
STA RD1Z80BYTE+1
LDA NRD1Z80ADDR+1
STA RD1Z80BYTE+2
LDA NWR1Z80ADDR ;redirect WR1Z80BYTE
STA WR1Z80BYTE+1
LDA NWR1Z80ADDR+1
STA WR1Z80BYTE+2
.ENDC
LDY #84H+(8*3) ;find vector to video out
LDA (SYSP1),Y
STA INITVD
INY
LDA (SYSP1),Y
STA INITVD+1
LDX #0 ;reset string pointer
STX MESIND
JMP INIT3
INIT4 .BYTE 20H ;JSR
INITVD .WORD 0FF69H ;patched to video out
INC MESIND
INIT3 LDX MESIND
LDA SIGNON,X
BNE INIT4 ;print until 0
LDA #0 ;FIRSTTIME := false
STA FIRSTTIME
PLP ;restore intr
INIT2: JMP EXZ ;reset AT modes and flags
FIRSTTIME .BYTE 0FFh ;true
.IF FASTPOLL
;Replacement routine for POLLROUTINE
NPOLLADDR .WORD NEWPOLL
NEWPOLL JSR POLLSIO
OLDPOLL JSR 0FF58h ;patch to old pollentry
JMP POLLSIO
;Replacement routine for RD1Z80BYTE
NRD1Z80ADDR .WORD NEWRD1Z80
NEWRD1Z80 LDX AZ80SLOT
NEWRD1ZA JSR POLLSIO
LDA 0C083h,X
BPL NEWRD1ZA
LDA 0C080h,X
RTS
;Replacemnt routine for WR1Z80BYTE
NWR1Z80ADDR .WORD NEWWR1Z80
NEWWR1Z80 LDX AZ80SLOT
TAY
NEWWRZA JSR POLLSIO
LDA 0C082h,X
BMI NEWWRZA
TYA
STA 0C081h,X
RTS
.ENDC
;***********************************
;ROUTINE: INENTRY:
;PURP: INPUT A CHARACTER
;ENTRY: Y = n0
; X = Cn
; WHERE n IS THE SLOT NUMBER
;EXIT: A = CHARACTER
;USED: ALL
;***********************************
INENTRY JSR POLLENTRY
JSR INSTAT ;wait for byte avail
BEQ INENTRY
JMP SERIN ;read it
;***********************************
;ROUTINE: OUTENTRY
;PURP: OUTPUT A CHARACTER TO THE DEVICE
;ENTRY: A = CHARACTER
; Y = n0
; X = Cn
; WHERE n IS THE SLOT NUMBER
;EXIT: NONE
;USED: ALL
;************************************
OUTENTRY .BYTE 4CH ;JMP
OUTVEC .WORD CHKA ;To be patched
;Set output vector from table using [A] as index. [AX] used.
SETOVEC ASL A
TAX
LDA OVECTBL,X
STA OUTVEC
LDA OVECTBL+1,X
STA OUTVEC+1
RTS
OVECTBL .WORD CHKA ;#0 Check for 1st char of 'AT'
.WORD CHKAT ;#1 Check for 2nd char of 'AT'
.WORD ATMODE ;#2 Store AT command line and execute it
.WORD OUTNRM ;#3 Usual output. Checks for 1st + of +++
.WORD OUTPLB ;#4 Check for 2nd + of +++
.WORD OUTPLC ;#5 Check for 3rd + of +++
.WORD OUTPLD ;#6 Check for 1 sec guard time after +++
;Change to mode 0 and reset timer
SETOV0 LDA #0
SETOV0A JSR SETOVEC
LDA #TM1SEC
STA TIMER
RTS
;Change to mode 1 and reset timer
SETOV1 LDA #1
JMP SETOV0A
;Change to mode 3 and reset timer
SETOV3 LDA #3
JMP SETOV0A
;Change to mode 6 and reset timer
SETOV6 LDA #6
JMP SETOV0A
;Usual output routine. Checks for +++
OUTNRM CMP #2BH ;'+' ?
BEQ OUTNRM2
CMP #0ABH
BEQ OUTNRM2
OUTNRM1 JSR SEROUT ;Send char
LDA #TM1SEC ;Reset timer to 1 sec
STA TIMER
RTS
OUTNRM2 LDX TIMER ;Timer=0 ?
BNE OUTNRM1
STA PLUSCH1 ;Save 1st '+'
LDA #4 ;Change mode to check for 2nd +
JMP SETOVEC
;Check for 2nd +
OUTPLB CMP #2BH ;'+' ?
BEQ OUTPLB1
CMP #0ABH
BEQ OUTPLB1
PHA ;Send '+' <this char> and revert to normal mode
LDA PLUSCH1
JMP OUTPLD1
OUTPLB1 STA PLUSCH2 ;Save 2nd '+'
LDA #5 ;Change mode to check for 3rd +
JMP SETOVEC
;Check for 3rd +
OUTPLC CMP #2BH ;'+'?
BEQ OUTPLC1
CMP #0ABH
BEQ OUTPLC1
PHA ;Send '++' <this char> and revert to normal mode
LDA PLUSCH1
JSR SEROUT
LDA PLUSCH2
JMP OUTPLD1
OUTPLC1 STA PLUSCH3 ;Save 3rd '+'
JMP SETOV6 ;Change mode to check for 1 sec guard time
;Check for 1 sec guard time after +++
OUTPLD LDX TIMER ;1 sec timeout?
BEQ OUTPLD2 ;--> yes, check for 'A' of 'AT'
OUTPLD3 PHA
LDA PLUSCH1 ;Send last 3 '+++'
JSR SEROUT
LDA PLUSCH2
JSR SEROUT
LDA PLUSCH3
OUTPLD1 JSR SEROUT
PLA ;Send this char
JSR SEROUT
JMP SETOV3
OUTPLD2 CMP #41H ;Check for 'A' of '+++AT'
BEQ CHKA
CMP #0C1H
BEQ CHKA
PHA
LDA PLUSCH1 ;Send last 3 '+++'
JSR SEROUT
LDA PLUSCH2
JSR SEROUT
LDA PLUSCH3
JSR SEROUT
LDA #3 ;Change to mode 3
JSR SETOVEC
PLA
JMP OUTENTRY ;Send this char (check for +++ though)
;Check for 1st letter of 'AT' after reset
CHKA TAY ;Save char --> Y
AND #7FH
CMP #41H ;'A'
BEQ CHKA1
LDA #3 ;Set vector to OUTNRM
JSR SETOVEC
TYA ;Restore char and transmit it (check for +++ though)
JMP OUTENTRY
CHKA1 STY LINE ;Save 'A'
JMP SETOV1 ;Set output vector to CHKAT
;Check for 2nd letter of 'AT'
CHKAT STA LINE+1 ;Save char
AND #7FH
CMP #54H ;'T'
BEQ CHKAT1
CMP #2FH ;'/'
BEQ CHKAT2
LDA #3 ;Set output vector to OUTNRM
JSR SETOVEC
LDA LINE ;Transmit previous 'A'
JSR SEROUT
LDA LINE+1 ;Transmit this char (check for +++ though)
JMP OUTENTRY
CHKAT1 LDA #2 ;Set output vector to ATMODE
JSR SETOVEC
LDX #2 ;Set line length
STX LNLEN
LDA EFL ;Echo AT if E1
BEQ CHKATQ
LDA LINE
JSR ADDQ
LDA LINE+1
JSR ADDQ
CHKATQ RTS
CHKAT2 JMP EXLN ;Re-execute previous command line
;Store chars in command line buffer until CR (then execute it)
ATMODE LDX LNLEN ;Append char to buffer. Update length unless full
CMP #8 ;BS?
BEQ AT3
STA LINE,X
CPX #40
BCS AT1
INX
AT1 STX LNLEN
AND #7FH
LDX EFL ;Echo to queue for E1
BEQ AT2
JSR ADDQ
AT2 CMP #0DH ;CR?
BEQ AT4
ATQ RTS
;BS handling
AT3 CPX #3 ;Can't backspace over 'AT'
BCC ATQ
DEX
JMP AT1
;CR handling
AT4 LDX EFL ;Echo LF after CR for E1
BEQ EXLN
LDA #0AH
JSR ADDQ ;Fall thru to EXLN
;Executes command line in buffer
EXLN LDX #2 ;Resets buf index to start reading
STX LNIND
LDA #0 ;Assume OK response will be given
STA RESPONS
EXLN1 JSR GETCH ;Fetch non-space char
BCS EXLN2 ;--> end of line
CMP #13
BEQ EXLN2 ;--> end of line
JSR EXBR ;Execute letter command
JMP EXLN1
EXLN2 JSR SETOV0 ;Reset to mode 0 (CHKA)
LDA QFL ;Q0=send modem responses
BNE EXLNQ
JSR ADDQRE ;Add response to queue
EXLNQ RTS
;Add response to queue
ADDQRE LDA RESPONS
CMP #255 ;Response 255 is no response
BEQ ADDQREQ
LDX VFL ;V0=single digit response
BNE ADDQRE1
CLC
ADC #30H
STA RTBL0
LDY RTBL0AD
LDX RTBL0AD+1
JMP RQ
ADDQREQ RTS
ADDQRE1 ASL A
ASL A
ASL A
ASL A
CLC
ADC RTBL1AD
TAY
LDA #0
ADC RTBL1AD+1
TAX
;Add string (terminating with 0) pointed to by XY to queue.
RQ STY RQADR
STX RQADR+1
LDX #0
STX RIND
RQ1 LDX RIND
.BYTE 0BDH ;LD ABS,X
RQADR .WORD RTBL0 ;Patched on entry to RQ
CMP #0
BEQ RQQ
INX
STX RIND
JSR ADDQ
JMP RQ1
RQQ RTS
;Response string table
RTBL0AD .WORD RTBL0
RTBL0 .BYTE "0",13,0
RTBL1AD .WORD RTBL1
RTBL1 .BYTE "OK",13,10,0," " ;0
.BYTE "CONNECT",13,10,0," " ;1
.BYTE "RING",13,10,0," " ;2
.BYTE "NO CARRIER",13,10,0," " ;3
.BYTE "ERROR",13,10,0," " ;4
.BYTE "CONNECT 1200",13,10,0," " ;5
.BYTE "NO DIALTONE",13,10,0," " ;6
.BYTE "BUSY",13,10,0," " ;7
.BYTE "RESPONSE 8",13,10,0," " ;8
.BYTE "RESPONSE 9",13,10,0," " ;9
.BYTE "CONNECT 2400",13,10,0," " ;10
.BYTE "RINGING",13,10,0," " ;11
;Executes a letter command and its parms
EXBR LDX #EXTBL2 - EXTBL ;Search for letter in table
EXBR1 CMP EXTBL,X
BEQ EXBR2
DEX
DEX
DEX
BPL EXBR1
RTS
EXBR2 LDA EXTBL+1,X ;Jump to addr given by table
STA EXVEC
LDA EXTBL+2,X
STA EXVEC+1
.BYTE 4CH ;JMP
EXVEC .WORD 0FF69H ;To be patched
EXTBL .BYTE 5AH ;'Z'
.WORD EXZ
.BYTE 45H ;'E'
.WORD EXE
.BYTE 51H ;'Q'
.WORD EXQ
.BYTE 56H ;'V'
.WORD EXV
.BYTE 58H ;'X'
.WORD EXX
.BYTE 44H ;'D'
.WORD EXD
.BYTE 48H ;'H'
.WORD EXH
.BYTE 53H ;'S'
.WORD EXS
EXTBL2 .BYTE 2AH ;'*'
.WORD ASTER
;Reset AT flags and modes
EXZ LDX #S18-EFL ;zero flags and regs
LDA #0
EXZ1 STA EFL,X
DEX
BPL EXZ1
LDA #1 ;Set defaults E1 V1
STA EFL
STA VFL
JSR SETOV0 ;reset vectors
LDA #0
JSR SETPVEC
LDA #0
JMP SETISV
;Echo command. E1=echo
EXE JSR GETNUM
STA EFL
RTS
;Send responses command. Q0=send responses
EXQ JSR GETNUM
STA QFL
RTS
;Send digit responses command. V1=digit responses
EXV JSR GETNUM
STA VFL
RTS
;Extended responses set command. E1=extended set
EXX JSR GETNUM
STA XFL
RTS
;Dial command
EXD JSR DIALBEG
EXD1 JSR GETCH ;get dial sub-command/digit
BCS EXD3 ;--> end of line
CMP #0DH
BEQ EXD3 ;--> end of line
JSR CHKNUM
BCC EXD2 ;--> digit
;
;Put compares here to check for dial options. Presently ignored.
;
JMP EXD1
EXD2 SEC ;eval and dial digit
SBC #30H
JSR DIALDIG
JMP EXD1 ;back to dial sub-command loop
EXD3 JSR DIALEND
LDA #255 ;no response
STA RESPONS
LDA #1 ;poll mode 1 (echo CR, pause, then wait for carrier)
JMP SETPVEC
;Set register command. Eg. S0=0
EXS JSR GETNUM
BCS EXSQ
STA REGNUM
JSR GETCH
BCS EXSQ
CMP 3DH ;'='
BNE EXSQ
JSR GETNUM
LDX REGNUM
STA S0,X
EXSQ RTS
REGNUM .BYTE 0
;Hangup/pickup handling
EXH JSR GETNUM
CMP #0
BEQ EXH0 ;H0 --> hangup
CMP #1
BEQ EXH1 ;H1 --> pickup
RTS
EXH0 JMP HANGUP
EXH1 JMP PICKUP
;Echo rest of line with CR to SEROUTX (card commands if valid)
ASTER LDX LNIND
CPX LNLEN
BCS ASTER1 ;--> past end of line
LDA LINE,X
INX
STX LNIND
JSR SEROUTX ;Echo
JMP ASTER
ASTER1 RTS
;Get next non-space char from line buffer but DON'T advance over it
;Exit: A=char, X=used (LNIND), Carry=set when past end of line
SEECH LDX LNIND
CPX LNLEN
BCS SEECHQ ;--> past end of line
LDA LINE,X
AND #7FH
CMP #20H
BNE SEECH1
INX
STX LNIND
JMP SEECH
SEECH1 CLC
SEECHQ RTS
;Get next non-space char from line buffer and advance over it
;Exit: A=char, X=used, Carry=set when past end of line
GETCH JSR SEECH
BCS GETCHQ
INX
STX LNIND
GETCHQ RTS
;Read and eval number from line buffer
;Exit: A=number or 0 if not present, Carry=set when past end of line
GETNUM LDA #0
STA NUM1
GETNUM1 JSR SEECH
BCS GETNUM3 ;--> past end of line
JSR CHKNUM
BCS GETNUM2 ;--> not a numeric char
JSR GETCH ;advance over digit
SEC
SBC #30H
STA NUM2
LDA NUM1 ;NUM1 := NUM1 * 10 + NUM2
ASL A
ASL A
CLC
ADC NUM1
ASL A
CLC
ADC NUM2
STA NUM1
JMP GETNUM1
GETNUM2 CLC
GETNUM3 LDA NUM1
RTS
NUM1 .BYTE 0
NUM2 .BYTE 0
;Checks whether ascii char in A is a numeric digit. Carry clear if so
CHKNUM CMP #30H ;'0'
BCC CHKNUM1
CMP #3AH ;'9'+1
RTS ;Return with carry clear/set
CHKNUM1 SEC
RTS
;***********************************
;ROUTINE: OTHERENTRY
;PURP: HANDLE OTHER COMMANDS
;ENTRY: A = OTHER COMMAND
; X = N0
; Y = CN
;EXIT: A = ERROR CODE
;USED: ALL
;***********************************
OTHERENTRY:
CMP #0
BEQ OUTSTAT ;BRANCH IF OUTPUT STATUS COMMAND
CMP #1
BEQ INSTAT ;BRANCH IF INTPUT STATUS COMMAND
CMP #2
BEQ VIDEOON ;BRANCH IF VIDEO ON COMMAND
CMP #3
BEQ APLEON ;BRANCH IF APPLE ON COMMAND
CMP #4
BEQ WIDTH ;BRANCH IF WIDTH COMMAND
CMP #SNDNAMECMD
BEQ SENDNAME ;BRANCH IF SEND NAME COMMAND
;ERROR BAD COMMAND
LDA #0FFH ;ELSE ERROR
RTS
OUTSTAT:
JMP SOSTATUS ;TEST IF THE DEVICE IS READY TO SEND ANOTHER CHARACTER
INSTAT: .BYTE 4CH ;JMP
ISVEC .WORD SISTATUS ;to be patched
;Set INSTAT mode [A]
SETISV ASL A
TAX
LDA ISVTBL,X
STA ISVEC
LDA ISVTBL+1,X
STA ISVEC+1
RTS
ISVTBL .WORD SISTATUS ;#0 Test for input byte avail (normal)
.WORD NOTRDY ;#1 Always return no byte avail
NOTRDY LDA #0
CLC
RTS
VIDEOON:
JMP INITENTRY ;DO SOMETHING TO TURN ON YOUR VIDEO
APLEON:
;DO SOMETHING TO TURN ON THE APPLE VIDEO ON
; THIS IS PROBABLY NOTHING UNLESS THIS IS A CONSOLE DEVICE
RTS
WIDTH:
;RETURN THE WIDTH OF THIS DEVICE
LDA #80 ;80 COLUMNS ?
RTS
SENDNAME:
;SEND THE NAME COMMAND
LDA NAME ;GET LENGTH
STA CNT ;SAVE AS COUNT
JSR WR1Z80BYTE ;SEND IT TO HOST
LDA #1
STA IDX
$LP: LDX IDX
LDA NAME,X ;GET NEXT CHARACTER
JSR WR1Z80BYTE
INC IDX
DEC CNT
BNE $LP ;CONTINUE UNTIL ALL BYTES ARE SENT
LDA #0
RTS
;***********************************
;ROUTINE: POLLENTRY
;PURP: HANDLE POLLING, THIS ENTRY POINT
; IS CALLED PERIODICALY WHILE THE APPLE IS
; WAITING FOR A COMMAND FROM THE Z-80. THIS
; CODE SHOULD BE VERY SHORT AS THE Z-80 IS
; IGNORED WHILE THIS CODE IS BEING EXECUTED
;ENTRY: NONE
;EXIT: NONE
;USED: ALL
;***********************************
POLLENTRY
.BYTE 4CH ;JMP
POLLVEC .WORD POLLSIO ;To be patched
;Set POLL vector. Entry: A=mode. Exit: AX used
SETPVEC ASL A
TAX
LDA PVECTBL,X
STA POLLVEC
LDA PVECTBL+1,X
STA POLLVEC+1
RTS
PVECTBL .WORD POLLNRM ;#0 Usual
.WORD CHKDL1 ;#1 When queue is empty, change to #2
.WORD CHKPAU ;#2 Pause 3 secs (and ignore input)
.WORD CHKDL2 ;#3 Check for carrier for 30 seconds
;Usual poll routine
POLLNRM JSR POLLSIO
LDA TIMER ;If timer > 0 then dec it
BNE POLLNR1
RTS
POLLNR1 DEC TIMER
RTS
;When queue is empty, change to poll mode #2 and instat mode #1
CHKDL1 JSR SISTATUS ;Wait till queue is empty
BEQ CHKDL1A
RTS
CHKDL1A LDA #2 ;Change to mode #2
JSR SETPVEC
LDA #1 ;set instat mode #1 (ignore input)
JSR SETISV
LDA #3 ;3 sec pause
STA CHKTM2
LDA #TM1SEC
STA CHKTM1
RTS
;Pause for 3 seconds (mode #2) then change to poll mode #3
CHKPAU DEC CHKTM1
BEQ CHKPAU1
RTS
CHKPAU1 LDA #TM1SEC
STA CHKTM1
DEC CHKTM2
BEQ CHKPAU2
RTS
CHKPAU2 LDA #3 ;Change to poll mode 3
JSR SETPVEC
LDA #30 ;30 sec timeout
STA CHKTM2
LDA #TM1SEC ;Reset 1 sec timeout
STA CHKTM1
JSR CLRQ ;Clear queue
;Check for carrier (#3). If detected, give response and reset to POLL mode #0
CHKDL2 JSR DIALST
BCS CHKD7 ;--> modem response
DEC CHKTM1
BEQ CHKD4 ;--> 1 sec timeout
CHKD3 LDA #0 ;No byte avail
RTS
CHKD4 LDA #TM1SEC ;Reset 1 sec timeout
STA CHKTM1
DEC CHKTM2
BEQ CHKD6 ;--> 30 sec timeout
LDA CHKTM2 ;send CR every 8 secs
AND #07H
BNE CHKD3
LDA #0DH
JSR SEROUT
JMP CHKD3
;Full timeout
CHKD6 LDA #3 ;NO CARRIER response
JMP CHKD8
;Modem response
CHKD7 NOP ;CONNECT or NO CARRIER response
CHKD8 STA RESPONS
LDA QFL ;Q0=send modem responses
BNE CHKD9
JSR CLRQ
JSR ADDQRE ;Add response to queue
CHKD9 LDA #0 ;Reset poll mode
JSR SETPVEC
LDA #0 ;Reset instat mode
JSR SETISV
JMP SISTATUS
CHKTM1 .BYTE TM1SEC ;11.7 msec/unit counter
CHKTM2 .BYTE 0 ;1 sec/unit counter
TIMER .BYTE TM1SEC
;AT REGS/FLAGS
EFL .BYTE 0 ;1=echo
QFL .BYTE 0 ;0=send responses
VFL .BYTE 0 ;1=send single digit responses
XFL .BYTE 0 ;1=extended response set
S0 .BYTE 0
S1 .BYTE 0
S2 .BYTE 0
S3 .BYTE 0
S4 .BYTE 0
S5 .BYTE 0
S6 .BYTE 0
S7 .BYTE 0
S8 .BYTE 0
S9 .BYTE 0
S10 .BYTE 0
S11 .BYTE 0
S12 .BYTE 0
S13 .BYTE 0
S14 .BYTE 0
S15 .BYTE 0
S16 .BYTE 0
S17 .BYTE 0
S18 .BYTE 0
;VARIABLES
RESPONS .BYTE 0
RIND .BYTE 0
LNLEN .BYTE 0
LNIND .BYTE 0
LINE .BLOCK 40
PLUSCH1 .BYTE 2CH ;Holds +++
PLUSCH2 .BYTE 2CH
PLUSCH3 .BYTE 2CH
;TEMPORARY DATA
IDX: .BLOCK 1 ;TEMPORARY
CNT: .BLOCK 1 ;TEMPORARY
MESIND: .BLOCK 1
BOTTOM:
.END
PLUSCH