home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
modems
/
modem7
/
m7mmp4.aqm
/
M7MM+4.ASM
Wrap
Assembly Source File
|
1985-08-25
|
38KB
|
1,355 lines
; M7MM+4.ASM v4.0 Micromodem ][ overlay file for MDM717. 1/18/84
;
; rev 4.0 - 1/18/84 - Revised and renamed to M7MM+4.ASM. Updated
; for use with MDM717.COM. Fixed bug in dial
; retry reporting present in M7MM+3. - mah
;
; *********************************************************
; * C A U T I O N *
; * *
; * This overlay will only work with MDM717.COM *
; * Use of this overlay with previous or future revisions *
; * of MDM7xx will not result in an executable file. *
; *********************************************************
;
; rev 3.0 - 1/16/84 - Revised and renamed to M7MM+3.ASM. Updated
; for use with MDM716.COM. Added alternate
; dialing capability for Micromodem ][/e.
; Also added ability to abort during carrier
; wait. - mah
;
; rev 2.0 - 1/8/84 - Renamed to M7MM+2.ASM. Added Micromodem ][/e
; support. Includes touch tone dialing. Also
; fix auto-redial connect bug. - mah
;
; rev 1.4 - 1/8/84 - Changed bank select logic to technique
; used by ALS Engineering. This allowed
; more interrupt windows, and compacted
; code. Overlay is now independent of ALS
; card and/or BIOS revision - mah
;
; rev 1.3 - 12/2/83 - Fixed premature carrier tone problem on
; originate call function. - mah
;
; rev 1.2 - 12/1/83 - Added conditional code for ALS Rev B Card - mah
; Renamed to M712MM+.ASM
;
; rev 1.1 - 11/20/83 - Corrected timing in pulse dialing for CP/M 2.2 - mah
;
; rev 1.0 - 10/12/83 - Original version (M712MM.ASM)
;
; Written by: Mark A. Howard - SYSOP
; CNY Technical RBBS-RCP/M
; 315-437-4890
; 319 Tower Ave
; Syracuse, N.Y. 13206
;
;
; This overlay is similar to most of the other overlays available
; for MDM7xx, but differs in the respect that it not only modifies
; areas intended for overlays, but also overlays portions of the
; root program. This was done to allow use of the logical and I/O
; procedures built into the program for use with the PMMI modem.
; The PMMI modem resembles the Micromodem in many respects, and
; most of the features are available on the Micromodem.
;
; It is for this reason that M7MM+4 will only work with MDM717, and
; further revisions of the root program will cause this overlay to
; be incompatible.
;
;=============================================================================
;
; TO USE: First edit this file filling in answers for your own
; equipment. Also edit the phone number library, M7NM-3.ASM
; if the phone directory is desired. Optionally, MDMNUM.COM
; may be used to change phone numbers later. Assemble these
; files with ASM.COM or MAC.COM or equivalent assembler.
;
;========================== ASSEMBLY WITH CP/M 2.2 ===========================
;
; Use DDT to overlay the the results of these program(s)
; to the original .COM file:
;
; A>DDT MDM717.COM
; DDT VERS 2.2
; NEXT PC
; 4580 0100
; -IM7MM+4.HEX (note the "I" command)
; -R ("R" loads in the .HEX file)
; NEXT PC
; 4580 0000
; * -IM7NM-3.HEX (get the optional phone library)
; * -R
; * NEXT PC
; * 4580 0000
; -G0 (return to CP/M)
; A>SAVE 69 MDM7.COM (now have a modified .COM file)
;
; * - This step is optional - however editing the number
; library and overlaying it in this manner is the only
; way to set or modify the alternate dialing strings.
;
;======================== ASSEMBLY WITH CP/M 3.0 =========================
;
; Use SID to overlay the results of these program(s)
; to the original .COM file:
;
; A>SAVE (load the CP/M 3.0 SAVE transient)
; (note no messages)
; A>SID MDM717.COM (load the original .COM file)
; CP/M 3 SID - Version 3.0
; NEXT MSZE PC END
; 4580 4580 0100 xxxx (xxxx depends on your sys)
; #RM7MM+4.HEX (load overlay, note "R" command)
; NEXT MSZE PC END
; xxxx 4580 0100 xxxx (xxxx's are insignificant)
; * #RM7NM-3.HEX (get the optional phone # overlay)
; * NEXT MSZE PC END
; * xxxx 4580 0100 xxxx
; #G0 (exit SID)
;
; CP/M 3 SAVE - Version 3.0
; Enter file (Type return to exit) : MDM7.COM (name new file)
; Beginning hex address 100 (from PC above)
; Ending hex address 457F (MSZE - 1)
;
; A> (you now have modified .COM file)
;
; * This step is optional - however see note above
;
;============================================================================
;
YES: EQU 0FFH
NO: EQU 0
;
; = = = = = = = = = = = = = = = = = =
;
; ---------------------> CUSTOMIZATION EQUATES <----------------------
;
; ---> Change the following information to match your equipment <---
;
CPM2 EQU NO ;Apple ][/][+/][/e with most CP/M cards
ALSCARD EQU YES ;Apple ][/][+/][/e with ALS CP/M Card
;
MMIIE EQU NO ;Yes if Micromodem ][/e
;
SLOT EQU 2 ;Micromodem slot (usually 2)
;
; = = = = = = = = = = = = = = = = = =
;
; System equates
;
FCB EQU 5CH ;system FCB area
PRINT EQU 9 ;print string function
BDOS EQU 5 ;BDOS jump location
;
; Ascii equates
;
BELL: EQU 07H ;bell
CR: EQU 0DH ;carriage return
ESC: EQU 1BH ;escape
LF: EQU 0AH ;linefeed
CANCEL: EQU 'X'-040H ;cancel character
;
; Performance equates
;
WAITCD EQU 250 ;secs * 10 to wait for carrier detect
; after dialing phone number
WAITRD EQU 30 ;secs * 10 to wait between continuous
; redial retries
;
SLOTNUM EQU SLOT*16 ;offset to slot base address
;
IF CPM2
;
SLOTBAS EQU 0E085H ;I/O memory for most CP/M cards
;
ENDIF ;CPM2
;
IF ALSCARD
;
SLOTBAS EQU 0C085H ;I/O memory for ALS CP/M Card
;
ENDIF ;ALSCARD
;
;
;====================== MICROMODEM SPECIFIC EQUATES ======================
;
;
; MODEM I/O EQUATES
;
MODCTL2 EQU SLOTBAS+SLOTNUM ;IN RI, OUT CR2
MODCTL1 EQU MODCTL2+1 ;IN STATUS, OUT CR1
MODDATP EQU MODCTL1+1 ;IN/OUT DATA
;
IF MMIIE
;
MODCTL3 EQU MODCTL2-2 ;SPKR, TOUCH TONE REG
;
ENDIF ;MMIIE
;
; BIT MASKS FOR MODCTL1 INPUT
;
MODSNDB EQU 2 ;bit to test for send status
MODSNDR EQU 2 ;value when ready
MODRCVB EQU 1 ;bit to test for receive status
MODRCVR EQU 1 ;value when ready
CARBIT EQU 4 ;carrier detect* bit
;
; BIT MASKS FOR MODCTL1 OUTPUT
;
INITBITS EQU 03H ;the first time
BRKBITS EQU 60H ;break signal bits
D8NP2SB EQU 11H ;8 bit data, no parity, 2 stop
D8NP1SB EQU 15H ;8 bit data, no parity, 1 stop
D8EP1SB EQU 19H ;8 bit data, even parity, 1 stop
D8OP1SB EQU 1DH ;8 bit data, odd parity, 1 stop
;
; BIT MASK FOR MODCTL2 INPUT
;
RNGBIT EQU 80H ;ring indicator* bit
;
; BIT MASKS FOR MODCTL2 OUTPUT
;
MODBIT EQU 4 ;mode bit in cr2 (1=org 0=ans)
SETBIT EQU 8 ;set bit in cr2 (always 1)
OFFBIT EQU 80H ;off hook bit in cr2 (0=hungup)
TXEBIT EQU 2 ;transmit enable bit (1=enable)
NOTTXE EQU 0FDH ;not(txebit) for and mask
BAUDBIT EQU 1 ;baud rate bit (0=110 1=300)
;
; SETUP WORDS FOR MODCTL2 OUTPUT
;
ORIGMOD EQU MODBIT+OFFBIT+SETBIT
ANSWMOD EQU OFFBIT+SETBIT
;
IF MMIIE
;
; BIT MASKS FOR MODCTL3 OUTPUT
;
SPKRBIT EQU 20H ;1=speaker on
TONEBIT EQU 10H ;1=tone on
;
ENDIF ;MMIIE
;
;
;======================== ROOT PROGRAM ADDRESSES =========================
;
; THESE ARE FIXED ADDRESSES OF ROUTINES AND VARIABLES REFERENCED
; IN THE ROOT FROM THIS OVERLAY, AND ARE ONLY VALID FOR MDM712.
;
KEYIN EQU 27A4H ;address of "keyin:" in root
CRLF EQU 278CH ;address of "crlf:" in root
TYPE EQU 27B8H ;address of "type:" in root
STAT EQU 2799H ;address of "stat:" in root
ERXIT EQU 285AH ;address of "erxit:" in root
MOVE EQU 28B2H ;address of "move:" in root
MOVER EQU 2CFEH ;address of "mover:" in root
NEWLINE EQU 4362H ;address of "newline:" in root
SPACES EQU 436BH ;address of "spaces:" in root
CLRTST EQU 43C5H ;address of "clrtst:" in root
KBDCHR EQU 27C5H ;address of "kbdchr:" on root
MENU EQU 2EF6H ;address of "menu:" in root
RETURN EQU 15E2H ;address of "return:" in root
DECOUT EQU 27D8H ;address of "decout:" in root
FIXCNT EQU 28CBH ;address of "fixcnt:" in root
;
ALTDIAL1 EQU 0CDFH ;address of alt dial string 1
ALTDIAL2 EQU 0CF7H ;address of alt dial string 2
CMDBUF EQU 4508H ;address of command line buffer
BUFFER EQU 4A00H ;address of data buffer
NUMBLIB EQU 0D0FH ;address of phone number library
LIBLEN EQU 22H ;length of a library line
RBWAIT EQU 50 ;wait 5 sec before redial
ANSWFLG EQU 44B2H ;answer mode request flag
ORIGFLG EQU 44B6H ;originate mode request flag
CRFLAG EQU 44F5H ;continuous redial flag
RINGBKFL EQU 4504H ;ringback flag
DIALCT EQU 44EAH ;no. of dials attempted
OPARITY EQU 44BEH ;odd parity flag in option table
EPARITY EQU 44BDH ;even parity flag in option table
MODCTLB EQU 44FFH ;storage byte for MODCTL1 word
UARTCTLB EQU 4506H ;storage byte for current control word
;
;============================= OVERLAY CODE ===============================
;
ORG 100H
;
DS 3 ;(for "JMP START" instruction)
;
PMMIMODEM: DB YES ;but not really, just did this to get
;correct logic decisions made in root 103H
SMARTMODEM: DB NO ;yes=HAYES Smartmodem, no=non-PMMI 104H
TOUCHPULSE: DB 'T' ;T=touch, P=pulse (Smartmodem-only) 105H
;
; ----------> Note: The clock speed for most CP/M Cards usually
; works out to be 2 mhz. Change the equate below
; to adjust timing for program.
;
CLOCK: DB 20 ;clock speed in MHz x10, as above
;
MSPEED: DB 1 ;0=110 1=300 2=450 3=600 4=710 5=1200 107H
;6=2400 7=4800 8=9600 9=19200 default
;
; ------------> Note: The following equates affect default program
; parameters. The following configuration is what
; is usually used, change any of the following if
; different operation is desired.
;
BYTDLY: DB 5 ;0=0 delay 1=10ms 5=50 ms - 9=90 ms 108H
;default time to send character in ter-
;minal mode file transfer for slow BBS.
CRDLY: DB 5 ;0=0 delay 1=100 ms 5=500 ms - 9=900 ms 109H
;default time for extra wait after CRLF
;in terminal mode file transfer
NOOFCOL: DB 5 ;number of DIR columns shown 10AH
SETUPTST: DB YES ;yes=user-added Setup routine 10BH
SCRNTEST: DB YES ;Cursor control routine 10CH
ACKNAK: DB YES ;yes=resend a record after any non-ACK 10DH
;no=resend a record after a valid-NAK
BAKUPBYTE: DB NO ;yes=change any file same name to .BAK 10EH
CRCDFLT: DB YES ;yes=default to CRC checking 10FH
TOGGLECRC: DB YES ;yes=allow toggling of CRC to Checksum 110H
CONVBKSP: DB NO ;yes=convert backspace to rub 111H
TOGGLEBK: DB YES ;yes=allow toggling of bksp to rub 112H
ADDLF: DB NO ;no=no LF after CR to send file in 113H
;terminal mode (added by remote echo)
TOGGLELF: DB YES ;yes=allow toggling of LF after CR 114H
TRANLOGON: DB YES ;yes=allow transmission of logon 115H
;write logon sequence at location LOGON
SAVCCP: DB YES ;yes=do not overwrite CCP 116H
LOCONEXTCHR: DB NO ;yes=local command if EXTCHR precedes 117H
;no=external command if EXTCHR precedes
TOGGLELOC: DB YES ;yes=allow toggling of LOCONEXTCHR 118H
LSTTST: DB YES ;yes=printer available on printer port 119H
XOFFTST: DB NO ;yes=checks for XOFF from remote while 11AH
;sending a file in terminal mode
XONWAIT: DB NO ;yes=wait for XON after CR while 11BH
;sending a file in terminal mode
TOGXOFF: DB YES ;yes=allow toggling of XOFF checking 11CH
IGNORCTL: DB YES ;yes=CTL-chars above ^M not displayed 11DH
EXTRA1: DB 0 ;for future expansion 11EH
EXTRA2: DB 0 ;for future expansion 11FH
BRKCHR: DB '@'-40H ;^@ = Send 300 ms. break tone 120H
NOCONNCT: DB 'N'-40H ;^N = Disconnect from the phone line 121H
LOGCHR: DB 'L'-40H ;^L = Send logon 122H
LSTCHR: DB 'P'-40H ;^P = Toggle printer 123H
UNSAVE: DB 'R'-40H ;^R = Close input text buffer 124H
TRANCHR: DB 'T'-40H ;^T = Transmit file to remote 125H
SAVECHR: DB 'Y'-40H ;^Y = Open input text buffer 126H
EXTCHR: DB '^'-40H ;^^ = Send next character 127H
;
;
DS 2 ; 128H
;
IN$MODCTL1: JMP LDACTLP ;in modem control port 12AH
DS 7 ;( IN STATUS )
OUT$MODDATP: JMP STADATP ;out modem data port 134H
DS 7 ;( OUT DATA )
IN$MODDATP: JMP LDADATP ;in modem data port 13EH
DS 7 ;( IN DATA )
ANI$MODRCVB: ANI MODRCVB ! RET ;bit to test for receive ready 148H
CPI$MODRCVR: CPI MODRCVR ! RET ;value of rcv. bit when ready 14BH
ANI$MODSNDB: ANI MODSNDB ! RET ;bit to test for send ready 14EH
CPI$MODSNDR: CPI MODSNDR ! RET ;value of send bit when ready 151H
IN$MODCTL2: JMP LDACTL2 ;in modem control port #2 154H
;( IN RI )
OUTDUMMY: DB 0,0,0 ;dummy old "out baudrp" 157H
OUT$MODCTL1: JMP STACTLP ;out modem control port #1 15AH
;( OUT CR1 )
OUT$MODCTL2: JMP STACTL2 ;out modem control port #2 15DH
;( OUT CR2 )
LOGONPTR: DW LOGON ;for user message. 160H
JMP$DIAL: JMP DIAL ;called from RESTART: 162H
JMP$DISCONNT: JMP DISCONNT ;called from DONETCD: after... 165H
JMP$GOODBYE: JMP GOODBYE ;called from DONETCD: 168H
JMP$INITMOD: JMP INITMOD ;jump to from INITADR: for ret 16BH
JMP$NEWBAUD: JMP NEWBAUD ;called frm NOLST: for baud chg 16EH
JMP$NOPARITY: JMP NOPARITY ;called from DONETCB: 171H
JMP$PARITY: JMP PARITY ;called from RCVFIL: & SENDFIL: 174H
JMP$SETUPR: JMP SETUPR ;if SETUPTST true & not PMMI 177H
JMP$SPCLMENU: JMP SPCLMENU ;implements Micromodem menu 17AH
JMP$SYSVER: JMP SYSVER ;version message 17DH
JMP$BREAK: JMP SENDBRK ;if PMMI not true 180H
;
;
; Do not change the following six lines. These are jumps to specific
; subroutines in root program.
;
JMP$ILPRT: DS 3 ;print inline string until 0 183H
JMP$INBUF DS 3 ;same as CP/M func 10 but no ^C 186H
JMP$INLNCOMP: DS 3 ;compare inline string to (DE) 189H
JMP$INMODEM DS 3 ;modem input, timeout = 100 ms 18CH
JMP$NXTSCRN: DS 3 ;"hit any key to continue" 18FH
JMP$TIMER DS 3 ;wait .1 sec for (B reg) 192H
;
;
; Routine to clear to end of screen. If using CLREOS and CLRSCRN, set
; SCRNTEST to YES at 010AH (above).
;
CLREOS: CALL JMP$ILPRT ; 195H
DB 'K'-040H ;for Apple ][ 80 col card 198H
DB 0,0,0,0 ;
RET ; 19DH
;
CLRSCRN: CALL JMP$ILPRT ; 19EH
DB 'L'-040H ;for Apple ][ 80 col card 1A1H
DB 0,0,0,0 ;
RET ; 1A6H
;
SYSVER: CALL JMP$ILPRT ; 1A7H
DB 'Version for '
;
IF ALSCARD
;
DB 'ALS CP/M Card '
DB CR,LF,'and '
;
ENDIF ;ALSCARD
;
DB 'Micromodem ]['
;
IF MMIIE
;
DB '/e'
;
ENDIF ;MMIIE
;
DB ' as of 1/8/84'
DB CR,LF,0
RET
;
;========================= BAUD RATE ROUTINES =============================
;
;......
;
; Change baudrate on-the-fly with CTL-B (while in terminal mode)
;
;
NEWBAUD: CALL JMP$ILPRT
DB CR,LF,'Enter new Baudrate: ',0
LXI H,FCB+9
MVI M,' '
;
NEWBAUD1: CALL KEYIN
CPI CR
CZ CRLF
JZ FIXBAUD
;.....
;
;
NEWBAUD2: CPI '0'
JC NEWBAUD1
CPI '9'+1
JNC NEWBAUD1
MOV M,A
CALL TYPE
INX H
JMP NEWBAUD1
;
ORG 024FH ;"setbaud:" is called from within
;the root, so this address is fixed
;
SETBAUD: LDA UARTCTLB ;called from "restart0:"
ORI BAUDBIT ;set for default 300 baud
STA UARTCTLB ;
CALL OUT$MODCTL2 ;
DB 00H ;to fill in old routine
;
FIXBAUD: CALL GETBAUD ;c = baud rate
LDA UARTCTLB ;get current mode word
ANI 0FEH ;strip old baud rate bit
ORA C ;setup new word
STA UARTCTLB ;update current mode word
MOV A,C ;
STA MSPEED ;update current modem speed
;
OFFHOOK: PUSH B ;save the used registers
PUSH H ;
LXI H,7500 ;
;
OFFDLY: DCR L ;delay needed for modem
JNZ OFFDLY ;
DCR H ;
JNZ OFFDLY ;
POP H ;restore hl
LDA UARTCTLB ;get the current status
MOV B,A ;save current mode word in B
LDA ANSWFLG ;answer mode?
ORA A ;
JNZ ORGCHEK ;no - originate?
MVI A,0FBH ;yes - zap the mode bit for answer
ANA B ;
JMP UPDATE ;and update the modem
ORGCHEK: LDA ORIGFLG ;check for originate mode
ORA A ;
JZ ORGMOD ;yes, set originate
MOV A,B ;otherwise retain old status
JMP UPDATE ;and tell the modem
ORGMOD: MVI A,MODBIT ;
ORA B ;set the mode bit
UPDATE: ORI OFFBIT ;set the offhook bit
STA UARTCTLB ;update storage word
CALL OUT$MODCTL2 ;go offhook in requested mode & baud
LDA MODCTLB ;update format register
CALL OUT$MODCTL1 ;just in case
XRA A ;
POP B ;restore bc
RET ;
;
GETBAUD: LDA FCB+9 ;
ORA A ;
JZ NOBAUD ;no baud rate change
CPI ' ' ;
JNZ DOBAUD ;
NOBAUD: POP D ;get rid of first ret addr
JMP OFFHOOK ;and go do offhook
;
DOBAUD: LXI D,FCB+9 ;something's there, convert it
LXI H,0 ;to binary and check validity
;
DECLP: LDAX D ;get a baud rate byte
INX D ;for the next time
CPI ' ' ;skip spaces
JZ DECLP ;
CPI '0' ;check for numiscity
JC BADRATE ;c = non-numic
CPI '9'+1 ;
JNC BADRATE ;nc = bad stuff
SUI '0' ;kill the ascii bias
MOV B,H ;put hl in bc
MOV C,L ;
DAD H ; x2
DAD H ; x4
DAD B ; x5
DAD H ; x10
ADD L ; now add value
MOV L,A ;
JNZ DIGNC ;
INR H ;
;
DIGNC: MOV A,E ;check for end of fcb
CPI FCB+12 ;
JNZ DECLP ;nope, keep converting
MVI C,0 ;now set c
PUSH H ;save binary baud rate
LXI D,-110 ;for subtract
DAD D ;do it
MOV A,H ;
ORA L ;110 baud?
POP H ;restore baud rate
RZ ;yes - with c = 0
INR C ;no, try 300
LXI D,-300 ;
DAD D ;
MOV A,H ;
ORA L ;
RZ ;yes, c = 1
;
BADRATE POP H ;(getbaud ret)
POP H ;(fixbaud/setbaud ret)
CALL ERXIT ;exit with error message
DB '++ Invalid Baud Rate ++$'
;
;======================== PARITY ROUTINES ==============================
;
;.....
;
PARITY: LDA OPARITY ;check for odd parity flag
ORA A ;
JNZ EVENPAR ;not set, check for even
MVI A,D8OP1SB ;set odd parity
JMP PARITY1 ;go do it
;
EVENPAR: LDA EPARITY ;check even parity flag
ORA A ;
RNZ ;nop if neither set
MVI A,D8EP1SB ;set even parity
;
PARITY1: STA MODCTLB ;update current format word
JMP OUT$MODCTL1 ;this will ret to caller
;
NOPARITY: MVI A,D8NP2SB ;2 stop bits for no parity
JMP PARITY1 ;
;
;
;=========================== DISCONNECT ROUTINE ============================
;
;.....
;
GOODBYE:
DISCONNT: LDA UARTCTLB ;get the current mode word
ANI 07FH ;
STA UARTCTLB ;hang up
CALL OUT$MODCTL2 ;
;
IF MMIIE
;
XRA A ;turn off the speaker
CALL STACTL3 ;
;
ENDIF ;MMIIE
;
PUSH B ;
MVI B,10 ;wait a second
CALL TIMER ;
POP B ;
RET ;
;
;=================== INITIALIZATION AND APPLE I/O ROUTINES =================
;
;.....
;
INITMOD: EQU $ ;locate the routine
;
IF ALSCARD
;
LHLD 1 ;pointer to cold boot vector in BIOS
LXI D,60H ;offset to ALS' special vectors
DAD D ;hl => APREAD vector
SHLD APREAD+1 ;store address locally so we can use
INX H ;bump hl to point to APWRITE
INX H ;
INX H ;
SHLD APWRITE+1 ;
;
ENDIF ;ALSCARD
;
MVI A,INITBITS ;initialize the ACIA
CALL OUT$MODCTL1 ;
MVI A,D8NP2SB ;set default format
STA MODCTLB ;
CALL OUT$MODCTL1 ;
RET ;from initmod:
;
; Apple I/O subroutines
;
IF CPM2
;
STADATP: STA MODDATP ;out DATA
RET ;
;
STACTLP: STA MODCTL1 ;out CR1
RET ;
;
STACTL2: STA MODCTL2 ;out CR2
RET ;
;
LDADATP: LDA MODDATP ;in DATA
RET ;
;
LDACTLP: LDA MODCTL1 ;in STATUS
RET ;
;
LDACTL2: LDA MODCTL2 ;in RI
RET ;
;
ENDIF ;CPM2
;
IF MMIIE AND CPM2
;
STACTL3: STA MODCTL3 ;out CR3
RET ;
;
ENDIF ;MMIIE AND CPM2
;
IF ALSCARD
;
; ALS bank select Apple I/O output
;
STADATP: PUSH H ;save the reg about to be used
LXI H,MODDATP ;point to desired location
JMP APWRT ;go do the action
;
STACTLP: PUSH H ;
LXI H,MODCTL1 ;out CR1
JMP APWRT ;
;
STACTL2: PUSH H ;
LXI H,MODCTL2 ;out CR2
;
ENDIF ;ALSCARD
;
IF ALSCARD AND MMIIE
;
JMP APWRT ;to give STACTL2 a place to go
STACTL3: PUSH H ;
LXI H,MODCTL3 ;out CR3
;
ENDIF ;ALSCARD AND MMIIE
;
IF ALSCARD
;
APWRT: PUSH D ;save the rest of the registers
PUSH B ;
;
APWRITE: CALL $-$ ;INITMOD inits this CALL
;
POP B ;
POP D ;
POP H ;
RET ;
;
; ALS bank select Apple I/O input
;
LDADATP: PUSH H ;
LXI H,MODDATP ;
JMP APRD ;
;
LDACTLP: PUSH H ;
LXI H,MODCTL1 ;in STATUS
JMP APRD ;
;
LDACTL2: PUSH H ;
LXI H,MODCTL2 ;
;
APRD: PUSH D ;save the rest
PUSH B ;
;
APREAD: CALL $-$ ;INITMOD inits this CALL
;
POP B ;
POP D ;
POP H ;
RET ;
;
ENDIF ;ALSCARD
;
;========================= DIAL ROUTINES =============================
;
;.....
;
DIAL: XRA A ;reset:
STA CRFLAG ;continuous redial flag
STA RINGBKFL ;ringback flag
LXI H,0 ;reset:
SHLD DIALCT ;no. of dial attempts
LXI H,CMDBUF+1 ;point to command buffer
MOV A,M ;get no. of char's
CPI 3+1 ;
JC DIAL1 ;< 4?
;
; If there were only 3 characters, the CAL<ret> was typed, the user
; obviously expecting to get a phone number (or letter) from the
; library file. If 4 or more, a number (or letter) was typed in from
; the menu command line, so move the characters down 4 to compensate.
; Needed for auto-redialing of menu command line entries.
;
MOV C,A ;
MVI B,0 ;bc = num of chars
SUI 4 ;
MOV M,A ;subtract 4 from cmdbuf+1
INX H ;point to beginning of cmd line
XCHG ;switch pointers
LXI H,CMDBUF+6 ;
CALL MOVER ;
JMP DIAL4 ;
;
; Comes here if no phone number was manually entered after "CAL" and if
; no phone library letter was entered. Displays the phone number library
; then asks for an entry.
;
DIAL1: MVI C,13 ;
LXI H,NUMBLIB ;point to library
LXI D,BUFFER ;
CALL NEWLINE ;
STAX D ;
INX D ;
;
DIAL2: MVI B,LIBLEN ;
CALL MOVE ;
CALL SPACES ;
MVI B,LIBLEN ;
CALL MOVE ;
CALL NEWLINE ;
DCR C ;
JNZ DIAL2 ;
;
DIAL3: MVI A,'$' ;terminate the buffer
STAX D ;
CALL CLRTST ;clear the screen if appropriate
MVI C,PRINT ;
LXI D,BUFFER ;readdress the buffer
CALL BDOS ;print the library
CALL JMP$ILPRT ;
DB CR,LF,'Enter library letter or phone number,',CR,LF
DB 'CTL-X quits while dialing or ringing : ',0
LXI D,CMDBUF ;point to command buffer
CALL JMP$INBUF ;go get user command
;
; You now have either a library letter or a manually entered phone number.
; These either came from the menu command line or from the library command
; line. Next we see if a letter, if so, get the corresponding line with
; phone number from the library. If a number we ignore the library look-
; up. (Ringback numbers are valid in library, but cause a caution message
; to the user, as this is not possible with Micromodem.)
;
DIAL4: LXI H,CMDBUF+1 ;point to no. of char's
MOV A,M ;
ORA A ;
JZ DIALEXIT ;if none, bomb out
INX H ;point to first char
PUSH H ;save the pointer
CALL DIALBGN ;begin the dialing sequence
POP H ;restore the pointer
MVI B,'A' ;first compare byte
MVI E,0 ;corresponding library entry
MVI C,26 ;no. of entries to check
MOV A,M ;get the first cmdbuf char
;
DIAL5: CMP B ;match?
JZ DIAL6 ;yes
INR B ;no - increment compare byte
INR E ;and offset
DCR C ;decrement tries
JZ DIAL10 ;0 means checked 'Z'
JMP DIAL5 ;try again
;
; Now have a match between the requested letter and the one in the library.
; E register has the decimal equivalent (0-25) of the letter (A-Z)
;
DIAL6: LXI H,NUMBLIB ;point to library
LXI B,LIBLEN ;
MOV A,E ;number of entries to skip
ORA A ;0?
JZ DIAL8 ;yes - hl points to selected entry
;
DIAL7: MOV A,M ;
ORA A ;null phone number?
JZ DIALBAD ;yes - do error routine
DAD B ;no - move to next entry
DCR E ;done skipping?
JNZ DIAL7 ;no - do it again
;
; Now hl points to the line containing the phone number requested, so
; store that line at CMDBUF+1
;
DIAL8: MVI B,LIBLEN ;length of the line
LXI D,CMDBUF+1 ;to pointer
XCHG ;switch pointers
MOV M,B ;put length of line in cmdbuf+1
XCHG ;switch pointers back
INX D ;de -> cmdbuf+2
CALL MOVE ;from hl to de b times
;
; Now have the full line including phone number in 'CMDBUF' area.
;
DIAL10: LXI H,CMDBUF+1 ;address the command line
MOV E,M ;put the no. of chars in e
INX H ;point to first char
;
DIAL11: MOV A,M ;get a char
ORA A ;nulls cause an error
JZ DIALBAD ;
;
; Dial a digit, check keyboard for abort
;
CALL DIALA ;dial the digit in A
CALL STAT ;keyboard hit?
JZ DIAL13 ;no - continue
CALL KEYIN ;yes - get the character
CPI CANCEL ;is it the cancel character?
JZ DIALEXIT ;yes - forget the whole idea
DIAL13: INX H ;point to the next digit
DCR E ;decrement char count
JNZ DIAL11 ;more to dial
;
; Show number of dial attempts
;
CALL JMP$ILPRT ;
DB ' -try #',0 ;
LHLD DIALCT ;get the attempt counter
INX H ;bump it first
SHLD DIALCT ;and update it
CALL DECOUT ;now type it
MVI A,' ' ;and then a space
CALL TYPE ;
;
; Dialing is done
;
MVI B,WAITCD ;secs * 10 to wait for carrier
CALL CARWT ;go wait for carrier
JC EXMENU ;cy means operator cancelled
LDA UARTCTLB ;not detected, try answer mode
XRI MODBIT ;flip modem mode...
ORI TXEBIT ;enable the transmitter
STA UARTCTLB ;
CALL OUT$MODCTL2 ;set modem
MVI B,30 ;now wait for orig tone for 3 seconds
CALL CARWT ;
JC EXMENU ;cy if cancel requested
LDA UARTCTLB ;nope, connection failed
XRI MODBIT ;flip back to originate
ANI NOTTXE ;reset the transmit enable bit
STA UARTCTLB ;
CALL OUT$MODCTL2 ;tell modem about it
;
; Connection not made, go see if a redial is desired
;
CALL DISCONNT ;disconnect the modem
DIALAGN: LDA CRFLAG ;continuous redial requested?
ORA A ;
JNZ DIALAGN1 ;yes - skip the idle chatter
CALL JMP$ILPRT ;
DB CR,LF,LF,'No answer. Redial? (Y,N,C) : ',0
CALL KBDCHR ;get a keyboard character
CALL CRLF ;for neatness
CPI 'N' ;(N)o?
JZ MENU ;nope, go back to the menu
CPI 'Y' ;(Y)es?
JZ DIALAGN1 ;yup, do it again
CPI 'C' ;(C)ontinuously redial?
JNZ DIALAGN ;none of these, try again for user
MVI A,1 ;set the continuous redial flag
STA CRFLAG ;so we won't do this again
;
DIALAGN1: MVI B,WAITRD ;secs * 10 to wait until redial
CALL TIMER ;
CALL CRLF ;for display neatness
JMP DIAL4 ;
;
EXMENU: CALL DISCONNT ;disconnect the modem
CALL CRLF ;
JMP MENU ;
;
; Come here when the connection has been made
;
CONMADE: EQU $ ;
;
IF MMIIE
;
XRA A ;turn off speaker now
CALL STACTL3 ;
;
ENDIF ;MMIIE
;
LDA UARTCTLB ;carrier detected ...
ORI TXEBIT ;enable the transmitter, if not already
STA UARTCTLB ;
CALL OUT$MODCTL2 ;
CALL SETBAUD ;set the current baud rate
CALL JMP$ILPRT ;
DB CR,LF,LF,'Connected.',BELL,0
LDA CRFLAG ;were we continuously redialing?
ORA A ;
JZ RETURN ;no - drop into terminal mode
CALL JMP$ILPRT ;yes - get the user's attention
DB ' - hit any key ... ',0
;
CONMADE2: CALL STAT ;check for user
JZ CONMADE3 ;
CALL KEYIN ;get the character typed
XRA A ;
JMP RETURN ;and drop into terminal mode
;
CONMADE3: MVI B,10 ;1 second between bells
CALL TIMER ;
MVI A,BELL ;
CALL TYPE ;send the bell
CALL IN$MODCTL1 ;check to see if distant modem gave up
ANI CARBIT ;
JZ CONMADE2 ;no - keep trying to signal user
CALL DISCONNT ;disconnect the modem
CALL JMP$ILPRT ;distant modem gave up waiting
DB CR,LF,LF,BELL,'++ Carrier lost, hit any key ++ ',0
CONMADE4: CALL STAT ;check for keyboard
JZ CONMADE4 ;
CALL KEYIN ;get the character
XRA A ;
JMP MENU ;go back to menu
;
; Automatic dialing routine, prints the number being dialed
;
DIALA: CALL TYPE ;get that out of the way
CPI 'R' ;ringback request?
JNZ DIALA0 ;no - continue checking
PUSH PSW ;yes - is it really?
MOV A,E ;check character count
CPI 1 ;last one?
JZ RINGBK ;
POP PSW ;not really, keep checking
DIALA0: MOV B,A ;save char in B
CALL DIALAD ;check for alternate dialing request
MOV A,B ;restore char
DIALADC: CPI ',' ;pause request?
JNZ DIALA1 ;no - keep going
MVI B,20 ;yes - wait 2 seconds and return
JMP TIMER ;this will return
;
DIALA1: CPI '0' ;check for dialability
RC ;less than, so return
CPI '9'+1 ;
RNC ;greater than, so return
SUI '0' ;kill ascii bias
JNZ DIALA2 ;if 1-9, go on
MVI A,10 ;convert 0 to 10
;
; Dial the digit in the AC, determine the dialing method
;
DIALA2: MOV C,A ;put digit to be dialed in C
;
IF MMIIE
;
LDA TOUCHPULSE ;get touch tone flag
CPI 'T' ;
JNZ DIALA2P ;not a T, pulse dial
;
; Touch tone dialing routine, wait 100 ms, tone for 100 ms
;
MVI B,10 ;wait 100 ms
CALL MS10 ;
MOV A,C ;get the digit to dial (0-10)
ORI TONEBIT+SPKRBIT ;add speaker and tone bits
CALL STACTL3 ;output to modem
MVI B,10 ;for 100 ms
CALL MS10 ;
MVI A,SPKRBIT ;turn off tone now
JMP STACTL3 ;digit dialed, STACTL3 will RET
;
DIALA2P: EQU $ ;
;
ENDIF ;MMIIE
;
MVI B,60 ;wait 600 ms
CALL MS10 ;uses the local timing routine
DIALNXT: LDA UARTCTLB ;get the current make word
PUSH PSW ;put on the stack
ANI 07FH ;make the break word
CALL OUT$MODCTL2 ;* break *
MVI B,5 ;* for 56 ms *
CALL MS10 ;
POP PSW ;get the make word
CALL OUT$MODCTL2 ;* make *
MVI B,4 ;* for 44 ms *
CALL MS10 ;
DCR C ;done with digit?
JNZ DIALNXT ;
RET ;digit dialed
;
MS10: PUSH B ;wait 10 ms * b register
PUSH H ;save used registers
;
IF ALSCARD ;
;
LXI H,064H ;constant to wait
;
ENDIF ;ALSCARD
;
IF CPM2 ;
;
LXI H,032H ;because I/O faster
;
ENDIF ;CPM2
;
CALL FIXCNT ;adjust for clock speed
MOV B,H ;put in bc
MOV C,L ;
POP H ;restore one register
;
MSLP: DCX B ;decrement timeout count
MOV A,B ;
ORA C ;done yet?
JNZ MSLP ;no - keep timing
POP B ;restore the other register
DCR B ;debump count
JNZ MS10 ;do it again
RET ;
;
TIMER: PUSH B ;wait 100ms * b register
PUSH H ;
;
IF ALSCARD ;
;
LXI H,03E8H ;constant to wait
;
ENDIF ;ALSCARD
;
IF CPM2
;
LXI H,01F4H ;because clock slower
;
ENDIF ;
;
CALL FIXCNT ;adjust for clock speed
MOV B,H ;put in bc
MOV C,L ;
POP H ;restore one register
;
MSLP2: DCX B ;decrement timeout count
MOV A,B ;
ORA C ;done yet?
JNZ MSLP2 ;no - keep timing
POP B ;restore the other register
DCR B ;debump count
JNZ TIMER ;do it again
RET ;
;
; Bad library number
;
DIALBAD: CALL JMP$ILPRT ;
DB CR,LF,'++ Bad library number called ++',CR,LF,0
;
DIALEXIT: CALL DISCONNT ;disconnect the modem
CALL CRLF ;
XRA A ;clear:
STA CRFLAG ;the continuous redial flag
CALL JMP$INMODEM ;clear any garbage
JMP MENU ;
;
DIALEXT2: CALL JMP$INMODEM ;wait for a clear line
JNC DIALEXT2 ;
CALL JMP$GOODBYE ;redundancy
JMP MENU ;
;
; Disconnect from the line, wait 3 seconds, then pick up again
;
DIALBGN: CALL DISCONNT ;disconnect
PUSH B ;
MVI B,20 ;because disconnt waits 1
CALL TIMER ;
POP B ;
;
IF MMIIE
;
MVI A,SPKRBIT ;turn on MM][/e's speaker
CALL STACTL3 ;
;
ENDIF ;MMIIE
;
CALL OFFHOOK ;go offhook again
PUSH B ;
MVI B,20 ;
CALL TIMER ;wait 2 seconds
POP B ;
RET ;and return
;
; If Micromodem ][:
;
; Check for aternate dialing characters, message the user if detected
;
; If Micromodem ][/e:
;
; Does the alternate dialing request, allowing dialing mode switch
; with T or P in alternate dialing string. When done, leaves the modem
; in touch tone mode, as all long distance services require touch tone.
;
DIALAD: MOV A,B ;get the char
CPI '<' ;altdial1?
JZ DIALAD2 ;
CPI '>' ;altdial2?
RNZ ;
;
IF MMIIE ;
;
DIALAD2: LDA TOUCHPULSE ;alternate dialing requested
CPI 'T' ;check for touch tone
JZ DIALAD3 ;
MVI A,'T' ;we're pulse dialing, switch for ad
DIALAD3: STA TOUCHPULSE ;
MOV A,B ;restore the char
CPI '>' ;altdial1?
JNZ ALT2 ;no, must be altdial2
;
PUSH H ;save the used register
LXI H,ALTDIAL1 ;
JMP DIALAD4 ;
;
ALT2: PUSH H ;
LXI H,ALTDIAL2 ;
;
DIALAD4: CALL TYPE ;get that out of the way
DIALAD5: MOV A,M ;get an alternate dialing char
CPI '$' ;end of string?
JZ DIALAD6 ;
CPI 'P' ;dialing mode change?
JZ SETIT ;
CPI 'T' ;
JZ SETIT ;
CALL DIALADC ;dial the character, if you can
JMP ADNEXT ;
;
SETIT: STA TOUCHPULSE ;update the dialing method
ADNEXT: INX H ;point to the next char
JMP DIALAD5 ;and do it all again
;
DIALAD6: MVI A,' ' ;for display neatness
CALL TYPE ;
POP H ;remember?
RET ;
;
ENDIF ;MMIIE
;
IF NOT MMIIE
;
DIALAD2: CALL JMP$ILPRT ;
DB CR,LF,BELL,'++ Alternate dialing not available for'
DB ' Micromodem ++',CR,LF,LF
DB ' Do you wish to continue ? (Y,N) : ',0
CALL KBDCHR ;
CALL CRLF ;
CALL CRLF ;
CPI 'N' ;
JNZ DIALAD3 ;
POP H ;justify stack
JMP MENU ;
;
DIALAD3: CPI 'Y' ;
JNZ DIALAD2 ;
RET ;
;
ENDIF ;NOT MMIIE
;
; Ringback not possible, also messages user, but doesn't need ack
;
RINGBK: POP PSW ;justify stack
CALL JMP$ILPRT ;just message the user
DB BELL,' - (Ringback not available)',0
RET ;from DIALA
;
; Waits for carrier, performs direct jump to "conmade:" if detected
;
CARWT: PUSH B ;save the count
CALL IN$MODDATP ;updates status register
CALL IN$MODCTL1 ;check the modem status
ANI CARBIT ;carrier detected?
JNZ CARWT1 ;no, time out
POP B ;restore BC
POP PSW ;get rid of return address
JMP CONMADE ;and go do connect options
CARWT1: CALL STAT ;check for keyboard cancel
JZ CARWT2 ;z = no char hit
CALL KEYIN ;char hit, is it cancel?
CPI CANCEL ;
JNZ CARWT2 ;no, ignore it
STC ;set cancel flag
RET ;
;
CARWT2: MVI B,10 ;wait .1 seconds
CALL MS10 ;
POP B ;restore the count
DCR B ;
JNZ CARWT ;keep waiting
XRA A ;reset the cy
RET ;
;
;====================== MICROMODEM SPECIAL MENU ========================
;
SPCLMENU: CALL JMP$NXTSCRN ;
CALL JMP$ILPRT ;
DB ' Additional commands for Micromodem'
DB CR,LF,LF
DB ' Modem control :',CR,LF,LF
DB ' A - Answer tone for S or R',CR,LF
DB ' O - Originate tone for S or R',CR,LF,LF
DB ' Parity options :',CR,LF,LF
DB ' 1 - Set odd parity',CR,LF
DB ' 0 - Set even parity',CR,LF,LF
DB ' Both ends must be capable of parity. Only',CR,LF
DB ' available in R and S modes. Parity check',CR,LF
DB ' will be part of transfer protocol.',CR,LF,LF
DB ' Note : Data format will be forced to 1 stop',CR,LF
DB ' bit as the Micromodem only supports parity',CR,LF
DB ' in this format. Data format will be 2 stop',CR,LF
DB ' bits when parity is disabled (default).',CR,LF,LF,0
CALL JMP$NXTSCRN ;
CALL JMP$ILPRT ;
DB ' Additional commands for Micromodem'
DB CR,LF,LF
DB ' Speed options :',CR,LF,LF
DB ' Follow primary and secondary options with',CR,LF
DB ' baud rate as ".XXX".',CR,LF,LF
DB ' Speed option example :',CR,LF,LF
DB ' SBOT.110 will set modem for batch mode',CR,LF
DB ' send transfer at 110 baud, then drops',CR,LF
DB ' into terminal mode.',CR,LF,LF
DB ' 110 and 300 baud are only rates available,',CR,LF
DB ' default is 300 baud.'
DB CR,LF,LF
;
IF MMIIE
;
DB ' SET command selects touch-tone or pulse dialing'
DB CR,LF,LF
;
ENDIF ;MMIIE
;
DB 0 ;
RET ;
;
;=============================================================================
;
SENDBRK: RET ;These functions disabled for PMMI
SETUPR: EQU $
;
IF MMIIE
;
CALL JMP$ILPRT ;
DB CR,LF,'(T)ouch tone, or (P)ulse dialing ? : ',0
CALL KBDCHR ;get the response
CALL CRLF ;for neatness
CALL CRLF ;
CPI 'T' ;touch tone?
JZ SETMD ;
CPI 'P' ;pulse?
JNZ SETUPR ;no, try again
SETMD: STA TOUCHPULSE ;update flag
;
ENDIF ;MMIIE
;
RET ;
;
;-----------------------------------------------------------------------
;
;.....
;
; You can put in a message at this location which can be called up with
; CTL-O if TRANLOGON has been set TRUE. You can use several lines if
; desired, as long as IGNORE$ERROR evaluates to less than 0B80H
; Terminate message with a null.
;
LOGON: DB CR,LF,0
;
;=============================================================================
;
IGNORE$ERROR EQU $+1 ;! MUST BE <= 0B80H
;
ORG 117EH ;in "optck:"
;
DB 0,0,0,0,0,0,0,0 ;disable uartctlb modification
DB 0,0,0,0,0,0,0,0 ;at this level
DB 0,0,0 ;
;
ORG 1CE9H ;in "break:"
;
ORI BRKBITS ;
;
ORG 2733H ;in "donetcd:"
;
DB 0,0,0,0,0,0,0 ;zap the multiple goodbye
DB 0,0,0,0,0,0,0 ;for pmmi
;
ORG 3B70H ;in "nxtopt0:"
;
JMP PATCH ;go do patch
;
ORG 3BABH ;in "byebye:"
;
JMP 3BB9H ;disable multiple goodbye
;
PATCH STA CMDBUF+3 ;disable setting answflg during call
JMP 3B7FH ;now "doopt:"
;
DB 0,0,0,0,0 ;rest of byebye:
;
ORG MODCTLB ;
;
DB D8NP2SB ;default modem format
;
ORG UARTCTLB ;
;
DB ORIGMOD ;default modem mode word
;
END