; MXO-MR11.ASM -- MEX Port Overlay file for the Morrow Descision 11 03-OCT-85 ;-----------------------------------------------------------------------------; ; This overlay adapts the MEX modem program for the Morrow Micro Decision 11. ; This MEX Port overlay digresses from pure by encompassing a Hayes Smartmodem ; feature in the SET command. If this offends you in anyway, set the SMODEM ; flag to "NO" to eliminate. ; ; The SET command used in this overlay will allow the setting of the baud rate ; (speed) of the modem hardware port. As mentioned, the Smartmodem speaker is ; setable by the user to one of three setting: OFF: such that the speaker is ; always off, HALF: such that the speaker is on during the dialing sequence, ; but turns off when the carrier is detected, and FULL: the speaker stays on ; when carrier detected. This is useful when one doesn't wish the stereo to be ; drowned out by the Smartmodem dialing. ; ; A more detailed description of the calling conventions used by this overlay ; overlay can be found in the PMMI modem overlay (MXO-PMxx.ASM where the "xx" ; is the current version number). ;-----------------------------------------------------------------------------; ; History as a MEX overlay ; ; 10/02/85 - Stolen from MXO-SZ20.ASM (V1.1) - Stuart Rose ; ;-----------------------------------------------------------------------------; ; OVERSION equ 1 ; overlay version number OREVISION equ 1 ; overlay revision level ; ;=============================================================================; ; CP/M system addresses ; ;=============================================================================; ; WBOOT equ 0000H ; address of warm boot jump vector TPA equ 0100H ; address of transient program area ; ;=============================================================================; ; MEX system bytes. This overlay helps MEX remember the baud rate of the ; ; modem port and speaker volume of the Smartmodem when hopping in and out of ; ; MEX **DURING THE SAME CALL**. These values are used instead of the overlay ; ; defaults (MSPEED and VOLUME respectively) when a call-in-progress is de- ; ; tected on MEX startup. Then these values are used. To protect them, they ; ; live in the system page (0000H-00FFH), in a location not used by the OS ; ; (operating system). Generally 0040H-004FH is reserved for CBIOSes and is ; ; fine for uses, as long as your CBIOS doesn't use it. If you are really un- ; ; sure, set both values to 0000H, and this feature will be eliminated. ; ;=============================================================================; ; MEXBAUD equ 004FH ; address of system byte for MEX baud rate MEXSPKR equ 004EH ; address of system byte for MEX speaker volume ; ;=============================================================================; ; MEX service processor address and functions ; ;=============================================================================; ; MEX equ 0D00H ; address of the MEX service processor INMDM equ 255 ; A = char from modem,CARRY = no char in 100 ms TIMER equ 254 ; delay B, in 100 ms units TMDINP equ 253 ; wait B seconds for char, CARRY = no char CHEKCC equ 252 ; check for ^C from keyboard, ZERO = present SNDRDY equ 251 ; test for modem-send ready RCVRDY equ 250 ; test for modem-receive ready SNDCHR equ 249 ; send a character to the modem (after sndrdy) RCVCHR equ 248 ; receive a character from modem (after rcvrdy) LOOKUP equ 247 ; table search: see CMDTBL comments for info PARSFN equ 246 ; parse filename from input stream PARSBD equ 245 ; parse baud-rate from input stream SBLANK equ 244 ; scan input stream to next non-blank EVALA equ 243 ; evaluate numeric from input stream LKAHED equ 242 ; get next char w/o removing from input stream GNC equ 241 ; get next char from input stream, CARRY = none ILP equ 240 ; inline print DECOUT equ 239 ; decimal output PRBAUD equ 238 ; print baud rate PRNTBL equ 237 ; print command table CARRY SET for ^C abort PRID equ 236 ; print current MEX ID string on console PRINT equ 9 ; BDOS/MEX print-string function call CONOUT equ 2 ; BDOS/MEX output a character to console call ; ;=============================================================================; ; Define new MEX modes (granted in MEX V1.10 and up) ; ;=============================================================================; ; CMDMOD equ 0 ; 00 - MEX is in command mode TRMMOD equ 1 ; 01 - MEX is in terminal mode SNDMOD equ 2 ; 02 - SENDOUT active KEYMOD equ 3 ; 03 - Keystring being transmitted XMDMSND equ 4 ; 04 - File transfer: Christensen-protocol send XMDMRCV equ 5 ; 05 - File transfer: Christensen-protocol rcv CISSND equ 6 ; 06 - File transfer: CIS-protocol send CISRCV equ 7 ; 07 - File transfer: CIS-protocol receive ; ;=============================================================================; ; define some ASCII control characters ; ;=============================================================================; ; NULL equ '@'-'@' ; (^@) null BELL equ 'G'-'@' ; (^G) bell TAB equ 'I'-'@' ; (^I) tab CR equ 'M'-'@' ; (^M) carriage return LF equ 'J'-'@' ; (^J) line feed ESC equ '['-'@' ; (^[) escape CTRL$Z equ 'Z'-'@' ; (^Z) control Z DEL equ 7FH ; delete EOS equ DEL ; SNDLIN end-of-string character ; ;=============================================================================; ; define some boolean variables ; ;=============================================================================; ; YES equ 0ffH ; affirmative response NO equ 000H ; negative response TRUE equ YES ; true (affirmative) response FALSE equ NO ; false (negative) response ; ;=============================================================================; ; MEX dial subroutine return error codes ; ;=============================================================================; ; CARRIER equ 0 ; CARRIER DETECTED return code BUSY equ 1 ; FAR END BUSY return code NOANSWER equ 2 ; NO ANSWER return code ABORT equ 3 ; KEYBOARD ABORT return code ERROR equ 4 ; MODEM ERROR return code NORING equ 5 ; NO RING return code NODIALTONE equ 6 ; NO DIAL TONE return code ;=============================================================================; ; MEX system page parameters (are correct for MEX V1.1x) ; ; see MEXPATxx for current values. ; ;=============================================================================; ; PROMPT equ MEX+13H ; addr of address of id prompt CANCHR equ MEX+1CH ; addr of cancel character ERRID equ MEX+2EH ; addr of error id flag (0 = no id in err msg) ; ;=============================================================================; ; miscellaneous equates ; ;=============================================================================; ; OFF equ '0' ; Smartmodem code for speaker always off HALF equ '1' ; Smartmodem code for speaker on until CD FULL equ '2' ; Smartmodem code for speaker always on ; ;=============================================================================; ; MEX format baud rates ; ;=============================================================================; ; MEX110 equ 0 ; MEX baud rate of 110 MEX300 equ 1 ; MEX baud rate of 300 MEX450 equ 2 ; MEX baud rate of 450 MEX600 equ 3 ; MEX baud rate of 600 MEX710 equ 4 ; MEX baud rate of 710 MEX1200 equ 5 ; MEX baud rate of 1200 MEX2400 equ 6 ; MEX baud rate of 2400 MEX4800 equ 7 ; MEX baud rate of 4800 MEX9600 equ 8 ; MEX baud rate of 9600 MEX19200 equ 9 ; MEX baud rate of 19200 ; ;=============================================================================; ; Baud rate parameters for Morrow Descision 11 Zilog DART ; ;=============================================================================; ; BD300 equ 0C4H ; 300 baud BD600 equ 084H ; 600 baud BD1200 equ 044H ; 1200 baud BD19200 equ 004H ; 19200 baud ; ;=============================================================================; ; Morrow Descision 11 base port for modem serial port ; ;=============================================================================; ; BASE equ 062H ; base port of modem port for MD-11 ; ;=============================================================================; ; Morrow initialization values for modem port baud rate, and the Hayes ; ; Smartmodem speaker volume (the last two values take on values stored in ; ; the MEX scratch area of the system parameter page when re-entering MEX ; ; with a call-in-progress). ; ;=============================================================================; ; MD$BAUD equ MEX1200 ; initial baud rate (speed) for Morrow modem MD$SPKR equ OFF ; initial speaker volume, speaker always off ; ;=============================================================================; ; Port offsets (from BASE) ; ;=============================================================================; ; DPORT equ 0 ; data port SPORT equ 1 ; status port CPORT equ 1 ; control port ; ;=============================================================================; ; UAR/T status bits (for Zilog and Plymouth DART) ; ;=============================================================================; ; TBMT equ 04H ; transmit buffer empty DAV equ 01H ; data available DCDLIN equ 08H ; carrier detect (use DCD line itself) ;DCDLIN equ 20H ; carrier detect (use CTS line) ; ;=============================================================================; ; Overlay starts here ; ;=============================================================================; ; org TPA ; ;=============================================================================; ; MDM7xx/MEX parameter page ; ;=============================================================================; ; JMPMEX: DS 3 ;(for "jmp START" instruction) 100H PMODEM: DB NO ;yes=PMMI S-100 Modem 103H SMODEM: DB YES ;yes=HAYES Smartmodem, no=non-PMMI 104H TPULSE: DB 'T' ;T=touch, P=pulse (Smartmodem-only) 105H CLOCK: DB 40 ;clock speed in MHz x10, 25.5 MHz max. 106H ;20=2 MHh, 37=3.68 MHz, 40=4 MHz, etc. MSPEED: DB MD$BAUD ;0=110 1=300 2=450 3=600 4=710 5=1200 107H ;6=2400 7=4800 8=9600 9=19200 default BYTDLY: DB 0 ;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 0 ;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 COLUMS: DB 5 ;number of DIR columns shown 10AH SETFLG: DB YES ;yes=user-added Setup routine 10BH SCRTST: 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 BAKFLG: DB NO ;yes=change any file same name to .BAK 10EH CRCDFL: DB YES ;yes=default to CRC checking 10FH TOGCRC: DB YES ;yes=allow toggling of CRC to Checksum 110H CVTBS: DB NO ;yes=convert backspace to rub 111H TOGLBK: 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) TOGLF: DB YES ;yes=allow toggling of LF after CR 114H LOGOK: DB NO ;yes=allow transmission of logon 115H ;write logon sequence at location LOGON SAVCCP: DB YES ;yes=do not overwrite CCP 116H LOCXCHR:DB NO ;yes=local command if EXTCHR precedes 117H ;no=external command if EXTCHR precedes TOGEXC: DB YES ;yes=allow toggling of EXTCHR 118H LSTTST: DB YES ;yes=printer available on printer port 119H XOFTST: DB YES ;yes=checks for XOFF from remote while 11AH ;sending a file in terminal mode XONWT: DB NO ;yes=wait for XON after CR while 11BH ;sending a file in terminal mode TOGXOF: DB YES ;yes=allow toggling of XOFF checking 11CH IGNCTL: DB NO ;yes=CTL-chars above ^M not displayed 11DH EXTRA1: DB 0 ;for future expansion 11EH ; ;=============================================================================; ; Terminal mode escape character (for MDM7xx only) ; ;=============================================================================; ; EXITCHR DB 'E'-'@' ; ^E = Exit to main menu 11FH BRKCHR DB '@'-'@' ; ^@ = Send 300 ms. break tone 120H NOCONN DB 'N'-'@' ; ^N = Disconnect from the phone line 121H LOGCHR DB 'L'-'@' ; ^L = Send logon 122H LSTCHR DB 'P'-'@' ; ^P = Toggle printer 123H UNSAVE DB 'Z'-'@' ; ^Z = Close input text buffer 124H TRNCHR DB 'T'-'@' ; ^T = Transmit file to remote 125H SAVCHR DB 'A'-'@' ; ^A = Open input text buffer 126H EXTCHR DB '\'-'@' ; ^\ = Send next character 127H ; ;=============================================================================; ; Overlay parameter page (unused by MEX) ; ;=============================================================================; ; ds 2 ; ; ;=============================================================================; ; Modem I/O routines ; ;=============================================================================; ; MDMSTAT:JMP INPSP ; get modem status 12AH DS 7 ; MDMOUT: JMP OUTDP ; output a character to the modem 134H DS 7 ; MDMIN: JMP INPDP ; input a character from the modem 13EH DS 7 ; ;=============================================================================; ; Modem status register send/receive bit test routines ; ;=============================================================================; ; MASKR: ANI DAV ! RET ; bit to test for receive ready 148H TESTR: CPI DAV ! RET ; value of receive bit when ready 14BH MASKS: ANI TBMT ! RET ; bit to test for send ready 14EH TESTS: CPI TBMT ! RET ; value of send bit when ready 151H DS 14 ; 154H ; ;=============================================================================; ; MEX subroutine jump table ; ;=============================================================================; ; DIALV: ds 3 ; Smartmodem dial a number 162H DISCV: jmp DISCON ; disconnect from target system 165H GOODBV: jmp GOODBYE ; MEX un-initialization subroutine 168H INMODV: jmp HELLO ; MEX initialization subroutine 16BH NEWBDV: jmp BAUD ; new baud rate subroutine 16EH NOPARV: RET ! NOP ! NOP ; no parity subroutine 171H PARITV: RET ! NOP ! NOP ; new parity subroutine 174H SETUPV: jmp SETCMD ; Spider/Z SET command subroutine 177H SMENUV: DS 3 ; not used by MEX 17AH VERSNV: jmp OVRVER ; display overlay version subroutine 17DH BREAKV: jmp SBREAK ; send a break tone subroutine 180H ILPRTV: DS 3 ; inline print (gone by MEX V2.0) 183H INBUFV: DS 3 ; input buffer (gone by MEX V2.0) 186H ILCMPV: DS 3 ; line compare (gone by MEX V2.0) 189H INMDMV: DS 3 ; timed modem input (gone by MEX V2.0) 18CH NXTSNV: DS 3 ; next screen (gone by MEX V2.0) 18FH TIMERV: DS 3 ; timer routine (gone by MEX V2.0) 192H ; ;=============================================================================; ; CLREOS subroutine ; ; This subroutine will clear the console screen from the current cursor ; ; position, to the end of the console screen (insure that SCRTST (010AH) ; ; is set to YES if you wish to use this subroutine). ; ;=============================================================================; ; CLREOS: lxi D,CLRE ; clear to end-of-screen 195H mvi C,PRINT ; call MEX ; ret ; ; ;=============================================================================; ; CLRSCN subroutine ; ; This subroutine will clear the console screen (insure that SCRTST (010AH) ; ; is set to YES if you wish to use this subroutine). ; ;=============================================================================; ; CLRSCN: lxi D,CLRS ; clear screen 19EH mvi C,PRINT ; call MEX ; ret ; ; ;=============================================================================; ; BOLD subroutine ; ; This subroutine will turn on the bold attribute (insure that SCRTST (010AH) ; ; is set to YES if you wish to use this subroutine). ; ;=============================================================================; ; BOLD: lda SCRTST ; termcap? cpi YES ; rnz ; nope lxi D,BLD ; yep, turn bold on mvi C,PRINT ; call MEX ; ret ; ; ;=============================================================================; ; UNBOLD subroutine ; ; This subroutine will turn off the bold attribute (insure that SCRTST (010AH); ; is set to YES if you wish to use this subroutine). ; ;=============================================================================; ; UNBOLD: lda SCRTST ; termcap? cpi YES ; rnz ; nope lxi D,UNBLD ; yep, turn bold off mvi C,PRINT ; call MEX ; ret ; ; ;=============================================================================; ; Escape sequences for MD-11s ; ;=============================================================================; ; CLRE: db ESC,'Y','$' ; clear to end-of-screen CLRS: db ESC,'*','$' ; clear screen BLD: db '$' ; turn on character bold attribute UNBLD: db '$' ; turn off character bold attribute ; ;=============================================================================; ; OVRVER subroutine ; ; This subroutine will print the overlay id and version on the console. ; ;=============================================================================; ; OVRVER: mvi C,ILP ; print overlay id and version number call MEX db 'Morrow Micro Decision 11 Computer Port Overlay V' db OVERSION + '0','.',OREVISION + '0',CR,LF,0 call CIPMSG ; display "call in progress" if need be rc ; mvi C,ILP ; aestetic newline call MEX ; db CR,LF,0 ; ret ; ;=============================================================================; ; GOODBYE subroutine ; ; This subroutine is executed just prior to exiting from MEX to CP/M. All un- ; ; initialization procedures are done here. ; ;============================================================================; ; GOODBYE:call CIPMSG ; echo "call in progess" if need be ret ; ; ;=============================================================================; ; CIPMSG subroutine ; ; This subroutine will display the "call in progress" message (Spider/Z users ; ; are forgetful) if BOTH a carriet is detected AND the current MEX modem port ; ; is not the current CP/M console. ; ;=============================================================================; ; CIPMSG: call CDTEST ; gotta carrier? rnc ; nope, then don't display "call in progress" call BOLD ; use bolding if possible mvi C,ILP ; print a newline call MEX ; db CR,LF,0 ; call IDMSG ; blapp out ID prompt if need be mvi C,ILP ; print "call in progess" message call MEX ; db '[call in progress]',BELL,CR,LF,0 call UNBOLD ; undo bolding damage if need be stc ; show "call in progess" message printed ret ; ;=============================================================================; ; SBREAK subroutine ; ; This routine will mimic the function of the BREAK key by sending an ; ; interrupt to the modem (transmit line held high) for a period of 300 ms. ; ;=============================================================================; ; SBREAK: push H ; save registers push D ; push B ; push PSW ; mvi A,0FAH ; force break for 300 ms mvi B,3 ; set duration for 300 ms call TOUTCP ; do it! pop PSW ; restore registers pop B ; pop D ; pop H ; ret ; ; ;=============================================================================; ; DISCON subroutine ; ; This subroutine will disconnect the modem from the target computer. This ; ; is done by dropping the DTR line to the modem for a period of 1.5 seconds ; ; in theory, 300 ms is more than sufficient (this is what a BREAK key does), ; ; but when the Smartmodem is dialing, a 300 ms pulse is not long enough to be ; ; recognized. ; ;=============================================================================; ; DISCON: push H ; save registers push D ; push B ; push PSW ; mvi A,06AH ; turn off DTR, no break sent mvi B,15 ; set duration for 1.5 seconds call TOUTCP ; do it! pop PSW ; restore registers pop B ; pop D ; pop H ; ret ; ; ;=============================================================================; ; TOUTCP subroutine ; ; This is a timed output to command port (OUTCP) subroutine. The value in the ; ; A register is output to the command port, then a time delay equal to the ; ; value of the B register (in 100 ms units) is done. ; ;=============================================================================; ; TOUTCP: push PSW ; save UAR/T command mvi A,5 ; write to control register 5 call OUTCP ; pop PSW ; restore UAR/T command call OUTCP ; send passed byte to CPORT mvi C,TIMER ; wait alotted time call MEX ; mvi A,5 ; write to control register 5 call OUTCP ; mvi A,0EAH ; turn DTR back on, no break call OUTCP ; ret ; ; ;=============================================================================; ; HELLO subroutine ; ; This subroutine is used to initialize the modem and the modem port. This ; ; is done via using some of the system reserved bytes in the CP/M system ; ; parameter page (0000H - 00FFH). There is a 16 byte system scratch area ; ; (0040H - 004FH) that is never referenced by CP/M. For the Spizer/Z, the ; ; addresses 0040H - 0042H are reserved for the Jade Double-D Floppy Disk ; ; Controller. All others are scratch. MEX uses 004FH as the byte reserved ; ; for stating the current baud rate for the modem port, while 004EH is ; ; reserved for the current Smartmodem speaker volume. These locations can ; ; can be checked whenever re-entering MEX. Protocol used: ; ; ; ; if a call is in progress (determined by the testing for a ; ; carrier detect (CDTEST)), MEX then uses the values stored in ; ; then MEX system reserved bytes for modem baud rate (the value ; ; is stored in MEX compatible format), and the Smartmodem speaker ; ; volume. ; ; ; ; otherwise set the modem baud rate and Smartmodem speaker volume ; ; to the preset values (values set in this overlay or current values ; ; when CLONEing MEX). ; ; ; ;=============================================================================; ; HELLO: call CDTEST ; check for call in progress jnc COLDMEX ; nope, initialize the modem and port GETBAUD:lxi H,MEXBAUD ; valid MEX baud byte? mov A,H ; ora L ; jz GETSPKR ; nope lda MEXBAUD ; yep, get the system byte for MEX baud rate sta MSPEED ; save it GETSPKR:lxi H,MEXSPKR ; valid MEX speaker byte? mov A,H ; ora L ; rz ; nope lda MEXSPKR ; yep, get the system byte for MEX speaker volume sta VOLUME ; save it ret ; ; ; cold starting MEX. load the baud rate and speaker volume with those values ; specified by this overlay. ; COLDMEX:lda MSPEED ; get the initial baud rate call BAUD ; set it up lda VOLUME ; get the initial speaker volume call SPEAKER ; set it up ret ; ;=============================================================================; ; IDMSG subroutine ; ; this subroutine will check whether or not the ID prompt should be displayed ; ; prior to an error message. If so, the prompt will be displayed. ; ;=============================================================================; ; IDMSG: push H ; save registers push D ; push B ; push PSW ; lda ERRID ; ID printed in "call in progress" message? cpi NO ; jz IDRET ; nope, then don't! mvi C,PRID ; yep, then print it! call MEX ; IDRET: pop PSW ; restore registers pop B ; pop D ; pop H ; ret ; ; ;=============================================================================; ; CDTEST subroutine ; ; This routine will test for a carrier detected on the designated modem ; ; status line (eithe DCD or DSR, depending on the overlay equates). If a ; ; carrier is detect then thus subroutine returns with the CARRY set. ; ;=============================================================================; ; CDTEST: mvi A,0 ; read status register 0 call OUTCP ; call INPSP ; look at the modem port status register ani DCDLIN ; is there a carrier? rz ; nope, then return stc ; yep, set the CARRY and return ret ; ; ;=============================================================================; ; SET COMMAND: ; ; ; ; This command will allow the user to set a number of hardware dependent ; ; functions. At the moment the allowable parameters are: ; ; ; ; BAUD RATE: This will allow the baud rate of the current user ; ; port to be changed on the fly. Valid baud rates ; ; are 300, 600, 1200, 19200. ; ; ; ; SPEAKER VOLUME: This will allow the user to change the volume of ; ; the speaker of the Hayes Smartmodem. Valid volumes ; ; are OFF = speaker is always off, HALF = speaker ; ; is on until carrier is detected, FULL = speaker ; ; is always on. ; ; ; ; usage: ; ; ; ; SET BAUD 9600 ; ; SET SPEAKER OFF ; ; ; ;=============================================================================; ; SETCMD: call GETARG ; any arguments? jc SHWALL ; if not, go display set parmeters LXI D,CMDTBL MVI C,LOOKUP CALL MEX ;parse argument PUSH H ;save any parsed argument adrs on stack RNC ;if we have one, return to it POP H ;oops, input not found in table jmp SETERR ; ; ; Argument table (note last character of set parameter MUST have the MSB ; turned on. MEX uses this as a flag for the end-of-parameter). ; CMDTBL: DB '?'+80H ; help DW SETHELP DB 'BAU','D'+80H ; "set baud" DW SETBAUD DB 'SPEAKE','R'+80H ; "set speaker" DW SETSPKR DB 0 ;<<=== table terminator ; ;=============================================================================; ; "SET" command (equates to a "SHOW ALL" command) ; ;=============================================================================; ; SHWALL: call NEWLINE ; start off with a newline character call BOLD ; bold the console output call SHWBAUD ; show the current baud rate call SHWSPKR ; show the current speaker volume call UNBOLD ; unbold the console output call NEWLINE ; terminate with a newline character ret ; ; ;=============================================================================; ; "SET ?" command (output HELP message to console) ; ;=============================================================================; ; SETHELP:lda SCRTST ; cursor control ability? cpi NO ; cnz CLRSCN ; yep, then clear the screen mvi C,ILP ; print out help message to console call MEX ; db CR,LF db 'SET BAUD ',0 call BOLD mvi C,ILP call MEX db '',CR,LF,0 call UNBOLD lda SMODEM ; got a Smartmodem? cpi NO ; jz NOSM01 ; nope, then don't show "SET SPEAKER" call UNBOLD mvi C,ILP call MEX db 'SET SPEAKER ',0 call BOLD mvi C,ILP call MEX db '',CR,LF,0 NOSM01: mvi C,ILP call MEX db CR,LF db 'Baud rate is one of:',CR,LF,0 call UNBOLD mvi C,ILP call MEX db '300 600 1200 19200',CR,LF db CR,LF,0 lda SMODEM ; got a Smartmodem? cpi NO ; jz NOSM02 ; nope, then don't show volume value call BOLD mvi C,ILP call MEX db 'Volume is one of:',CR,LF,0 call UNBOLD mvi C,ILP call MEX db 'OFF : Smartmodem speaker is always off',CR,LF db 'HALF : Smartmodem speaker is on until carrier detect',CR,LF db 'FULL : Smartmodem speaker is always on',CR,LF db CR,LF,0 NOSM02: ret ; ; ;=============================================================================; ; "SET BAUD" command ; ;=============================================================================; ; SETBAUD:MVI C,PARSBD ;nope, function code: parse a baudrate CALL MEX ;let MEX look up code JC BAUDERR ;jump if invalid code CALL BAUD ;no, try to set it JC BAUDERR ;if not one of ours, bomb out call NEWLINE ;show the current baud rate call SHWBAUD ; ret ; ; ;=============================================================================; ; "SHOW BAUD" command ; ;=============================================================================; ; SHWBAUD:mvi C,ILP ; nope, then display current baud rate call MEX ; db 'Modem baud rate is set to ',0 lda MSPEED ; get current baud rate mvi C,PRBAUD ; let MEX print it call MEX call NEWLINE ; terminate with newline character ret ; ;=============================================================================; ; BAUD subroutine ; ; This subroutine will set the baud of the current modem port. The new baud ; ; rate is passed in the A register, and is also stored in the MEX parameter ; ; page (MSPEED), and the MEX system reserved byte (MEXBAUD). If the new baud ; ; rate specified is either illegal or not supported, this subroutine returns ; ; with the CARRY set. ; ;=============================================================================; ; BAUD: PUSH H ;don't alter anybody PUSH D PUSH B MOV E,A ;MSPEED code to DE MVI D,0 LXI H,BAUDTBL ; nope, then fine offset into table DAD D MOV A,M ;fetch code ORA A ;0? (means unsupported code) jz BADBAUD ;yep, show it! PUSH PSW ;no, set the rate mvi A,0 ; setup control register 0 call OUTCP ; mvi A,0 ; call OUTCP ; mvi A,1 ; setup control register 1 call OUTCP ; mvi A,0 ; call OUTCP ; mvi A,2 ; setup control register 2 call OUTCP ; mvi A,0 ; call OUTCP ; mvi A,3 ; setup control register 3 call OUTCP ; mvi A,0C1H ; Rx 8 bits, Rx enable call OUTCP ; mvi A,4 ; setup control register 4 call OUTCP ; pop PSW ; clock for baud rate, 1 stop bit, no parity call OUTCP ; mvi A,5 ; setup control register 5 call OUTCP ; mvi A,0EAH ; DTR on, Tx 8 bits, no break, Tx enable, RTS on call OUTCP ; mvi A,6 ; setup control register 6 call OUTCP ; mvi A,0 ; call OUTCP ; mvi A,7 ; setup control register 7 call OUTCP ; mvi A,0 ; call OUTCP ; MOV A,E ; get MEX format baud rate STA MSPEED ; store in MEX lxi H,MEXBAUD ; valid MEX baud byte in system page? mov A,H ; ora L ; mov A,E ; jz NOMEXB ; nope STA MEXBAUD ; store it in the system byte for MEX baud rate NOMEXB: ORA A ; return no-errors jmp BDEXIT ; BADBAUD:stc ; set CARRY to show bad baud rate specified BDEXIT: POP B POP D POP H RET ; ; this is the baud rate converstion table. The MEX format baud rate value is ; used as an offset into this table. The grabbed value is the Interfacer 4 ; mode register format containing the new baud rate. ; BAUDTBL:DB 0 ;110 (not supported) DB BD300 ;300 DB 0 ;450 (not supported) DB BD600 ;600 DB 0 ;710 (not supported) DB BD1200 ;1200 DB 0 ;2400 (not supported) DB 0 ;4800 (not supported) DB 0 ;9600 (not supported) DB BD19200 ;19200 ; ;=============================================================================; ; "SET SPEAKER" command ; ;=============================================================================; ; SETSPKR:lda SMODEM ; got a Smartmodem? cpi NO ; jz SETERR ; nope, then show a SET error mvi C,SBLANK ; yep, then scan for volume argument call MEX jc SPKRERR ; if no argument, let user know lxi D,SPKTBL ; parse the argument mvi C,LOOKUP call MEX ; parse argument jc SPKRERR ; bad volume argument mov A,L ; store the new speaker volume call SPEAKER ; set the Smartmodem speaker volume call NEWLINE ; show the new speaker volume call SHWSPKR ; ret ; ; ; speaker table for MEX table search ; SPKTBL: db 'OF','F'+80H ; turn speaker off keyword db OFF,OFF ; Smartmodem ATM code for it db 'HAL','F'+80H ; turn speaker off after carrier detect keyword db HALF,HALF ; Smartmodem ATM code for it db 'FUL','L'+80H ; turn speaker on keyword db FULL,FULL ; Smartmodem ATM code for it db 0 ; argument table terminator ; ;=============================================================================; ; "SHOW SPEAKER" command ; ;=============================================================================; ; SHWSPKR:lda SMODEM ; got a Smartmodem? cpi NO ; rz ; nope, then don't show speaker volume mvi C,ILP ; yep, then show the speaker volume call MEX ; db 'Smartmodem speaker ',0 mvi C,ILP ; lda VOLUME ; cpi OFF ; speaker always off jz SPKOFF ; cpi HALF ; speaker on until carrier detect jz SPKHALF ; cpi FULL ; speaker always on jz SPKFULL ; SPKUNKN:call MEX ; speaker volume status unknown db 'volume status not known',CR,LF,0 ret ; SPKOFF: call MEX ; speaker is turned off db 'is always turned off',CR,LF,0 ret ; SPKHALF:call MEX ; speaker is set to half db 'is turned on until carrier detected',CR,LF,0 ret ; SPKFULL:call MEX ; speaker is set to full db 'is always turned on',CR,LF,0 ret ; ; ;=============================================================================; ; SPEAKER subroutine ; ; This subroutine will set the Smartmodem speaker to the requested volume. ; ; The new volume value is passed in the A register, and is also stored in the ; ; MEX parameter page (VOLUME), and the MEX system reserved byte (MEXSPKR). ; ;=============================================================================; ; SPEAKER:push H ; save registers push D ; push B ; mov E,A ; save the new speaker volume lda SMODEM ; got a Smartmodem? cpi NO ; jz SPKRET ; nope, then don't change the speaker volume mov A,E ; restore the new speaker volume sta VOLUME ; store the current volume for MEX lxi H,MEXSPKR ; valid MEX speaker byte in system page? mov A,H ; ora L ; mov A,E ; jz NOMEXS ; nope sta MEXSPKR ; store the current volume in reserved byte NOMEXS: call SNDESC ; send the Smartmodem escape seq. if need be call SNDATM ; send the Smartmodem speaker volume code call SNDATO ; send the Smartmodem on-line code if need be SPKRET: pop B ; restore registers pop D ; pop H ; ret ; ;=============================================================================; ; xxxERR subroutines ; ; These routines blapp out error messages on the console if the user somehow ; ; screwed up the SET command line (bad syntax, or bad keyword values). ; ;=============================================================================; ; SETERR: call IDMSG ;print ID prompt if need be MVI C,ILP ;inline print CALL MEX ; DB '++ bad SET parameter specified ++',BELL,CR,LF,0 RET ; BAUDERR:call IDMSG ;print ID prompt if need be MVI C,ILP ;inline print CALL MEX ; DB '++ bad baud rate specifed ++',BELL,CR,LF,0 RET ; SPKRERR:call IDMSG ;print ID prompt if need be MVI C,ILP ;inline print CALL MEX ; DB '++ bad speaker volume specifed ++',BELL,CR,LF,0 RET ; ;=============================================================================; ; SNDSEC subroutine ; ; This subroutine will place the Smartmodem in command state. If a carrier ; ; is detected, the Smartmodem escape sequence is sent, sandwiched between ; ; two guard time delays. An initial null is sent just incase we are in the ; ; "just CONNECTed" case (IE: Smartmodem has connected to target computer, ; ; but Morrow hasn't sent anything yet). If there is no carrier, then this ; ; routine merely returns. ; ;=============================================================================; ; SNDESC: call CDTEST ; check for call in progress rnc ; nope, then return lxi H,SMNULL ; yep, send a null (just CONNECTed case) call SNDLIN ; mvi B,12 ; yep, goto command mode mvi C,TIMER ; wait 1.2 seconds call MEX ; lxi H,SMESCAP ; send '+++' call SNDLIN ; mvi B,12 ; wait 1.2 seconds mvi C,TIMER ; call MEX ; call EATCODE ; eat result code ret ; ; ;=============================================================================; ; SNDCAN subroutine ; ; This subroutine will send the CANCEL character to the target computer ; ; system. The primary use of this subroutine is to cancel the Smartmodem ; ; escape sequence sent to the target system to place the Smartmodem in ; ; command state. At the target computer end, there is an un-terminated ; ; command ("+++") that should not be executed. ; ;=============================================================================; ; SNDCAN: lda CANCHR ; get the CANCEL character sta CANMSG ; store in the CANCEL character message lxi H,CANMSG ; get the CANCEL character message address call SNDLIN ; send it ret ; ; ;=============================================================================; ; SNDATM subroutine ; ; This routine will send the Smartmodem code to set the speaker volume ; ;=============================================================================; ; SNDATM: lxi H,ATMCODE ; send 'ATM' call SNDLIN ; lxi H,VOLUME ; send the volume code call SNDLIN ; call EATCODE ; eat result code ret ; ; ;=============================================================================; ; SNDATO subroutine ; ; This subroutine will send the code to place the Smartmodem back to on-line ; ; state ONLY if a carrier is detected. If no carrier is detected, then this ; ; subroutine merely returns. ; ;=============================================================================; ; SNDATO: call CDTEST ; check for call in progess rnc ; nope, then return lxi H,ATOCODE ; yep, then send 'ATO' (goto on-line mode) call SNDLIN ; call EATCODE ; eat result code call SNDCAN ; send the cancel character (cancel SNDESC) ret ; ; ;=============================================================================; ; EATCODE subroutine ; ; This subroutine will eat all the characters recieved from the modem until ; ; a 100 ms "quiet" period is detected (used to eat Smartmodem result codes). ; ; The initial delay is for the Smartmodem result code turn-around time). ; ;=============================================================================; ; EATCODE:mvi B,2 ; wait 200 ms for Smartmodem turn-around mvi C,TIMER ; call MEX ; EATCHAR:mvi C,INMDM ; eat a character call MEX ; jnc EATCHAR ; if more, then eat another character ret ; otherwise return ; ;=============================================================================; ; GETARG subroutine ; ; This subroutine will scan the input stream for an argument. If no argument ; ; present, then this subroutine returns with the CARRY set ; ;=============================================================================; ; GETARG: mvi C,SBLANK ; scan input stream for call MEX ; ret ; and simply return ; ;=============================================================================; ; EATARG subroutine ; ; This subroutine will eat (throw away) the remaining characters in the ; ; current argument. This is an aid for other routines which do not need to ; ; (and thus do not) check the entire argument for a unique match to be made ; ; (EG: "SET PORT C" and "SET PORT CONSOLE" will do the same thing, execept ; ; the SBLANK MEX function will see the next "argument" as being "ONSOLE" ; ; opposed to the line terminator). ; ;=============================================================================; ; EATARG: mvi C,LKAHED ; look ahead to next character in command line call MEX ; rc ; return if done (burp) cpi ' ' ; is it a blank? rz ; yep, then we've finished eating the argument mvi C,GNC ; nope, eat the next character in command line call MEX ; jmp EATARG ; check the next character in command line ; ;=============================================================================; ; NEWLINE subroutine ; ; This subroutine will send a newline character (CR-LF pair) to the console ; ;=============================================================================; ; NEWLINE:mvi C,ILP ; output a newline character to console call MEX ; db CR,LF,0 ; ret ; ; ;=============================================================================; ; SNDLIN subroutine ; ; This routine will send a string to the modem port. Works similar to the ; ; BDOS 9 function. The string start address is in the HL register pair, and ; ; the end-of-string character is set to EOS. ; ;=============================================================================; ; SNDLIN: mvi C,SNDRDY ; is modem ready to read another character? call MEX ; jnz SNDLIN ; nope, wait for it mov A,M ; yep, get next character to send to modem cpi EOS ; end-of-string character? rz ; yep, then return mov B,A ; nope, get the next character to send mvi C,SNDCHR ; call MEX ; send it! inx H ; bump up the string point jmp SNDLIN ; send the next character ; ;=============================================================================; ; Smartmodem codes to do what we want it do (for "SNDATx" routines) ; ;=============================================================================; ; SMNULL: db NULL,EOS ; null for justed CONNNECTed case SMESCAP:db '+++',EOS ; Smartmodem code for goto command state CANMSG: db '?',EOS ; cancel character message string ATMCODE:db 'ATM',EOS ; Smartmodem code for speaker volume VOLUME: db MD$SPKR,CR,EOS ; initial speaker volume ATOCODE:db 'ATO',CR,EOS ; Smartmodem code for goto on-line state ; ;=============================================================================; ; Modem input (get a character or status) driver ; ;=============================================================================; ; INPSP: MVI A,SPORT ; get modem status JMP INP1 INPDP: MVI A,DPORT ; get a character from the modem JMP INP1 ; INP1: PUSH B ; save BC register pair MOV C,A ; save port offset mvi A,BASE ; get the base port ADD C ; add offset for desired port (data/status) STA INP2+1 ; store for IN command INP2: IN 0 ; input data/status POP B ; restore BC register pair RET ; and return ; ;=============================================================================; ; Modem output (put a character or command) driver ; ;=============================================================================; ; OUTDP: push B ; save the BC register pair mvi C,DPORT ; put a character to the modem jmp OUT1 ; OUTCP: push B ; save the BC register pair mvi C,CPORT ; change modem control register jmp OUT1 ; OUT1: mov B,A ; save the output character mvi A,BASE ; get the base port address ADD C ; add offset for desired port (data/ctrl) sta OUT2+1 ; store for OUT command mov A,B ; restore the output character OUT2: out 0 ; send it (or change mode/control port) pop B ; restore the BC register pair ret ; return end