; 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 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