home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
SIMTEL
/
CPMUG
/
CPMUG025.ARK
/
88-MODEM.ASM
next >
Wrap
Assembly Source File
|
1984-04-29
|
32KB
|
1,192 lines
;**********************************************************************
;
; TITLE: 88-MODEM DRIVER ROUTINE WITH DISK FILE TRANSFER
;
; VERSION: 1.00 LAST REVISION: 7/7/78
;
; AUTHOR: TIM PUGH
; 9655-M HOMESTEAD COURT
; LAUREL, MD. 20810
; (301) 776-5253
;
;****************** SUMMARY OF CONTROL CHARACTERS *********************
;
;CONTROL CHARACTERS ARE INDICATED BY A "^" PRECEEDING THE CHARACTER.
;
; ^A ASSIGN CONSOLE DEVICE
; ^B TRANSMIT A "BREAK"
; ^D DISCONTINUE CURRENT MODE
; ^F FILE NAME SPECIFIED FOR SUBSEQUENT RX/TX
; ^R RECEIVE (RX) A DISK FILE FROM A REMOTE DEVICE
; ^T TRANSMIT (TX) A DISK FILE TO A REMOTE DEVICE
; ^W ASCII ETB -- MUST BE THE LAST CHARACTER OF A TX FILE
;
;******************* OPERATING INSTRUCTIONS **************************
;
;THIS PROGRAM IS DESIGNED TO OPERATE UNDER CP/M. IF A FILE TRANSFER
;IS TO BE PERFORMED, THE FILE NAME SHOULD BE SPECIFIED WHEN THE PROGRAM
;IS CALLED, E.G.
; 88-MODEM <FILENAME>.<FILETYPE>
;
;FOLLOWING THE PROGRAM SIGN ON MESSAGE, THE SYSTEM WAITS FOR OPERATOR
;INPUT. AT THIS POINT THE OPERATOR CAN INITIATE HANDSHAKING (AS DES-
;CRIBED UNDER "FILE TX MODE" BELOW) BY ENTERING AN "H". ALTERNATIVELY,
;THE OPERATOR CAN SELECT FROM ONE OF 6 BAUD RATES BY ENTERING A "B".
;FINALLY, HE CAN DEFAULT TO 300 BAUD AND NO HAND-SHAKE BY ENTERING
;A "CR" (CARRIAGE RETURN) AS THE INITIAL ENTRY.
;
;NEXT, THE OPERATOR IS DIRECTED TO SELECT THE MODE OF OPERATION BY ENTERING
;EITHER AN "O" FOR ORIGINATE OR AN "A" FOR ANSWER. IF ANSWER MODE IS SELECTED,
;THE PROGRAM INITIALIZES THE SYSTEM ACCORDINGLY AND WAITS FOR RING DETECT.
;THE PHONE WILL BE ANSWERED ON THE FIRST RING AND GENERATES THE 2225 HZ
;CARRIER SIGNAL. UPON DETECTION OF THE RESPONDING 1270 HZ TONE, A SIGN-ON
;MESSAGE IS TRANSMITTED TO THE REMOTE DEVICE AND A LOCAL MESSAGE DIRECTING
;THE COMMENCEMENT OF NORMAL TRANSMISSION IS DISPLAYED ON THE CONSOLE.
;IF THE REMOTE DEVICE IS A TERMINAL IT SHOUD BE IN HALF-DUPLEX MODE.
;OF THE ABOVE MENTIONED CONTROL CHARACTERS, ONLY ^T, ^R, AND ^D ARE
;SUPPORTED AT THE REMOTE DEVICE. HOWEVER, ALL ARE SUPPORTED AT THE LOCAL
;CONSOLE. IF THE LOCAL CONSOLE IS UNATTENDED, A FILE TRANSFER CAN BE
;INITIATED REMOTELY PROVIDED THE FILE NAME WAS PREVIOUSLY SPECIFIED.
;COMMUNICATIONS CAN BE TERMINATED REMOTELY SIMPLY BY HANGING UP THE PHONE.
;THIS CAUSES THE SYSTEM TO RETURN TO INITIALIZATION OF ANSWER MODE AND
;AWAIT THE NEXT REMOTE CALL. ALTERNATIVELY, A "^D" ISSUED REMOTELY WILL
;TERMINATE COMMUNICATIONS AND TAKE THE SYSTEM OUT OF ANSWER MODE. THIS
;MEANS THAT THE NEXT CALLER WON'T BE GREETED BY A PERHAPS UNEXPECTED
;2225HZ TONE.
;
;IF ORIGINATE MODE IS SELECTED, THE SYSTEM WAITS FOR DIAL TONE DETECTION.
;ONCE THE DIAL TONE HAS BEEN DETECTED - ANNOUNCED ON THE CONSOLE - DIALING
;CAN BEGIN. CONVENTIONAL DIALING IS PERFORMED BY SIMPLY ENTERING THE
;NUMBER TO BE DIALED AT THE CONSOLE KEYBOARD. AS EACH NUMBER IS DIALED
;A DASH IS DISPLAYED. IT IS POSSIBLE TO EXCEED THE DIALING SPEED OF THE
;DEVICE. THIS IS INDICATED BY THE ABSENCE OF A DASH BETWEEN DIGITS.
;
;BOTH AUTODIALING AND ROTARY DIALING ARE SUPPORTED. AUTODIALING IS INIT-
;IATED BY ENTERING ONE OF 4 ALPHA CHARACTERS AS THE FIRST "DIGIT" DIALED.
;THE CHARACTERS SUPPORTED ARE "H,M,Z,W". OTHER CHARACTERS MAY BE SELECTED
;PROVIDED THE 2 LSB'S OF THE ASCII CODE FOR THE SET SELECTED COVER THE
;RANGE OF 00,01,10,11. THE PHONE NUMBERS ASSIGNED TO THESE CHARACTERS
;CAN BE FOUND IN THE LISTING JUST PRIOR THE THE "MESSAGES" SECTION.
;ROTARY DIALING IS SUPPORTED FOR THE CHARACTER "M" WHEREBY UP TO 4
;NUMBERS WILL BE DIALED IN SEQUENCE IF EACH PRECEEDING NUMBER IS FOUND
;BUSY. THE SIZE OF THE ROTARY GROUP IS NOT RESTRICTED TO 4. ANY NUMBER
;GREATER THAN OR EQUAL TO 2 CAN BE SUPPORTED.
;
;AFTER DIALING IS COMPLETED AND THE REMOTE CARRIER HAS BEEN DETECTED,
;THE SYSTEM IS PLACED IN THE "CHARACTER TX/RX MODE". THIS IS THE MODE
;USED FOR KEYBOARD COMMUNICATIONS WITH THE REMOTE DEVICE. WHILE IN
;THIS MODE, A BREAK MAY BE TRANSMITTED BY ENTERING A "^B". IF
;MORE THAN ONE FILE IS TO BE TRANSFERRED, THE NEW FILE NAME CAN BE
;SPECIFIED BY ENTERING A "^F". CONSOLE MESSAGES WILL PROMPT THE
;OPERATOR FOR APPROPRIATE ENTRIES. IT IS POSSIBLE TO REASSIGN THE
;CONSOLE DEVICE BY ENTERING A "^A". HERE TOO, CONSOLE MESSAGES WILL
;PROMPT THE OPERATOR FOR APPROPRIATE ENTRIES. THIS FEATURE IS ONLY
;SUPPORTED ON SYSTEMS HAVING A TDL "ZAPPLE" MONITOR.
;
;IN ORDER TO INITIATE THE "FILE TX MODE" THE USER SHOULD ENTER A "^T".
;THE DATA IS DISPLAYED ON THE CONSOLE DEVICE AS IT IS TRANSMITTED. UPON
;COMPLETION OF FILE TRANSMISSION, THE SYSTEM REVERTS TO THE CHARACTER
;MODE. RETURN TO CHARACTER MODE PRIOR TO COMPLETION CAN BE FORCED BY
;ENTERING "^D". "HAND-SHAKING" AS REQUIRED BY SOME UNIVAC 1100 SERIES
;COMPUTERS HAS BEEN INCLUDED. TO ENABLE THIS, ENTER A "H" AS THE
;DIALING INITIATION CHARACTER (AS THE CONSOLE MESSAGE DIRECTS).
;THE END OF FILE IN THIS MODE IS "^W". THUS, THE FILE TO BE TRANS-
;MITTED MUST HAVE A "^W" WRITTEN AS THE LAST CHARACTER ON THE FILE.
;
;TO INITIATE THE "FILE RX MODE" THE USER ENTERS A "^R". OPERATION IS
;SIMILAR TO FILE TX MODE DESCRIBED ABOVE. SINCE CHARACTER TRANSMISSION
;IS SUPPORTED IN THIS MODE, THE USER SHOULD SET UP FOR FILE TRANSFER
;BY ISSUEING A COMMAND TO THE REMOTE DEVICE EXCEPT FOR THE CARRIAGE
;RETURN. TYPE "^R" AND AFTER THE READY MESSAGE IS GIVEN, TYPE "CR".
;THE CR WILL GO TO THE REMOTE DEVICE AND INITIATE TRANSMISSION.
;THIS MODE DOES NOT TERMINATE AUTOMATICALLY. A "^D" MUST BE TYPED
;IN ORDER TO RETURN TO THE CHARACTER MODE.
;
;ESCAPE FROM THE CHARACTER MODE TO THE INITIAL DIALING SEQUENCE IS
;MADE BY ENTERING A "^D".
;
;RETURN TO CP/M IS EFFECTED BY ENTERING A "^D" WHILE IN THE "INITIAL
;DIALING SEQUENCE MODE".
;
;********************* MODEM CONTROL EQUATES **************************
;
;--I/O ADDRESSES
;
MODEM0 EQU 0C0H ;UART STATUS/CONTROL
MODEM1 EQU 0C1H ;DATA IN/OUT
MODEM2 EQU 0C2H ;FILTER & CONTROL WORD SELECT
MODEM3 EQU 0C3H ;(MODEM,DIALER,BAUD-RATE) CONTROL
;
;--UART/MODEM STATUS (IN MODEM0)
;
TBE EQU 001H ;TRANSMIT BUFFER EMPTY
RDA EQU 002H ;RECEIVE DATA AVAILABLE
DBY EQU 004H ;DIALER BUSY
PER EQU 008H ;PARITY ERROR
OVR EQU 010H ;DATA OVERRUN
BRK EQU 020H ;BREAK RECEIVED
CTS EQU 040H ;CLEAR TO SEND
DTD EQU 080H ;DIAL TONE DETECT
;
;--UART MODES (OUT MODEM0)
;
ASCII1 EQU 024H ;7 DATA BITS, EVEN PARITY, 1 STOP BIT
ASCII2 EQU 004H ;7 DATA BITS, ODD PARITY, 1 STOP BIT
BIN1 EQU 02CH ;8 DATA BITS, EVEN PARITY, 1 STOP BIT
BIN2 EQU 00CH ;8 DATA BITS, ODD PARITY, 1 STOP BIT
;
;--FILTER & CONTROL WORD SELECT CODES (OUT MODEM2)
;
MMSELO EQU 001H ;MODEM MODE CONTROL SELECT - ORIGINATE
MMSELA EQU 031H ;MODEM MODE CONTROL SELECT - ANSWER
DLSEL EQU 002H ;DIALER DIGIT CONTROL SELECT
BDSEL EQU 004H ;BAUD/DIAL RATE CONTROL SELECT
INTEN EQU 008H ;INTERRUPT ENABLE
;
;--MODEM MODES (OUT MODEM3)
;
MMORIG EQU 0C0H ;ORIGINATE: OH,DTR
MMLOW EQU 043H ;DTR,<=300,ESD,ELS
MMLREL EQU 04BH ;DTR,<=300,BRK-REL,ESD,ELS
MMHIGH EQU 063H ;DTR,>300,ESD,ELS
MMHREL EQU 06BH ;DTR,>300,BRK-REL,ESD,ELS
MMTERM EQU 00EH ;TERMINATE: BRK-REL,TX-BRK,ESD,ESS
MMBRK EQU 004H ;TX-BREAK
;
;--DIAL & BAUD RATE CONSTANTS (OUT MODEM3)
;
DRATE1 EQU 068H ;DIAL RATE 10 PPS
DRATE2 EQU 034H ;DIAL RATE 20 PPS
BAUD10 EQU 08EH ;110 BAUD
BAUD15 EQU 068H ;150 BAUD
BAUD30 EQU 034H ;300 BAUD
BAUD45 EQU 022H ;450 BAUD
BAUD50 EQU 01FH ;500 BAUD
BAUD60 EQU 01AH ;600 BAUD
;
;********************** CP/M EQUATES ******************************
;
; CP/M FUNCTIONS ARE EXECUTED BY PASSING THE FUNCTION NUMBER IN
; REGISTER C AND THE INFORMATION (ADDRESS OR DATA) IN REGISTERS
; D,E (REGISTER E IF SINGLE BYTE DATA). THE RESULT (IF APPLICABLE)
; IS RETURNED IN REGISTER A. IF DOUBLE BYTE RESULT, THE MSB IS IN
; REGISTER B.
;
;--FDOS FUNCTIONS
;
RESET EQU 0 ;SYSTEM RESET
RDCON EQU 1 ;READ CONSOLE CHARACTER
WRCON EQU 2 ;WRITE CONSOLE CHARACTER
RDRDR EQU 3 ;READ CHARACTER FROM READER DEVICE
WRPCH EQU 4 ;WRITE CHARACTER TO PUNCH DEVICE
WRLST EQU 5 ;WRITE CHARACTER TO LIST DEVICE
IOCHK EQU 7 ;READ I/O CONFIGURATION BYTE
IOSET EQU 8 ;WRITE I/O CONFIGURATION BYTE
WRCBUF EQU 9 ;WRITE BUFFER CONTENTS TO CONSOLE
RDCBUF EQU 10 ;READ BUFFER CONTENTS FROM CONSOLE
CONST EQU 11 ;CONSOLE (DATA AVAILABLE) STATUS
;
UNLOAD EQU 12 ;UNLOAD DISK R/W HEAD
DSKRES EQU 13 ;DISK SYSTEM RESET
DSKSEL EQU 14 ;DISK SELECT (0,1,2,3)
OPEN EQU 15 ;OPEN DISK FILE (FCB ADDRESS)
CLOSE EQU 16 ;CLOSE DISK FILE " "
SRCH EQU 17 ;SEARCH FOR FILE " "
SRCHN EQU 18 ;SEARCH FOR NEXT FILE
DELETE EQU 19 ;DELETE DISK FILE (FCB ADDRESS)
RDDISK EQU 20 ;READ NEXT RECORD " "
WRDISK EQU 21 ;WRITE NEXT RECORD " "
CREATE EQU 22 ;CREATE DISK FILE " "
RENAME EQU 23 ;RENAME DISK FILE " "
LOGALL EQU 24 ;IDENTIFY ALL ON-LINE DISKS
LOGSEL EQU 25 ;IDENTIFY SELECTED DISK
SETDMA EQU 26 ;SET DMA ADDRESS VALUE
;
;--CP/M ADDRESS CONSTANTS
;
BOOT EQU 0 ;WARM START
FDOS EQU 0005H ;ENTRY TO FDOS
TFCB EQU 005CH ;TRANSIENT FILE CONTROL BLOCK
TBUFF EQU 0080H ;TRANSIENT BUFFER
;
;--FCB (FILE CONTROL BLOCK) CONSTANTS
;
FCB EQU TFCB
FCBDN EQU FCB+0 ;DISK NUMBER (0,1,2,3)
FCBFN EQU FCB+1 ;FILE NAME (8 BYTES)
FCBFT EQU FCB+9 ;FILE TYPE (3 BYTES)
FCBEX EQU FCB+12 ;EXTENT (0 TO 15)
FCBRC EQU FCB+15 ;REC COUNT (0 TO 128) - SIZE OF CURRENT EXTENT
FCBNR EQU FCB+32 ;NEXT RECORD POINTER (0 TO RC)
;
;****************** MISCELLANEOUS EQUATES **************************
;
;--ASCII CONTROL CODES
;
NHUL EQU 000H ;(^@) NULL (TIME FILL)
SOH EQU 001H ;(^A) START OF HEADING
STX EQU 002H ;(^B) START TEXT
ETX EQU 003H ;(^C) END TEXT
EOT EQU 004H ;(^D) END OF TRANSMISSION
ENQ EQU 005H ;(^E) ENQUIRY - "WHO ARE YOU"
ACK EQU 006H ;(^F) ACKNOWLEDGE - "YES"
BEL EQU 007H ;(^G) BELL - HUMAN ATTENTION REQUIRED
BS EQU 008H ;(^H) BACKSPACE
HT EQU 009H ;(^I) HORIZONTAL TABULATION
LF EQU 00AH ;(^J) LINE FEED
VT EQU 00BH ;(^K) VERTICAL TABULATION
FF EQU 00CH ;(^L) FORM FEED
CR EQU 00DH ;(^M) CARRIAGE RETURN
SO EQU 00EH ;(^N) SHIFT OUT - NONSTANDARD CODE FOLLOWS
SI EQU 00FH ;(^O) SHIFT IN - RETURN TO STANDARD CODE
;
DLE EQU 010H ;(^P) DATA LINK EXCAPE - CHANGE DATA COM CNTRL
DC1 EQU 011H ;(^Q) DEVICE CONTROL 1
DC2 EQU 012H ;(^R) " " 2
DC3 EQU 013H ;(^S) " " 3
DC4 EQU 014H ;(^T) DEVICE CONTROL 4
NAK EQU 015H ;(^U) NEGATIVE ACKNOWLEDGE - "NO"
SYN EQU 016H ;(^V) SYNCHRONOUS IDLE - ENABLES RESYNC
ETB EQU 017H ;(^W) END TRANSMISSION BLOCK
CAN EQU 018H ;(^X) CANCEL PREVIOUS DATA
EM EQU 019H ;(^Y) END MEDIUM
CLR EQU 01AH ;(^Z) CLEAR SCREEN ON LS-TERMINAL (ASCII: SUB)
ESC EQU 01BH ;(^[) ESCAPE - FOR CODE EXTENSION
FS EQU 01CH ;(^\) FILE SEPARATOR
GS EQU 01DH ;(^]) GROUP "
RS EQU 01EH ;(^^) RECORD "
US EQU 01FH ;(^_) UNIT "
;
DEL EQU 07FH ;DELETE (RUBOUTS)
;
;--ZAPPLE I/O CONFIGURATION
;
ZIOCHK EQU 0F015H
ZIOSET EQU 0F018H
;
;################## PROGRAM STATEMENTS ##########################
;
ORG 100H
JMP START
DS 40 ;STACK AREA
STACK: DS 2 ;STACK POINTER
MMSEL: DS A ;MODEM MODE SELECT (ORIGINATE OR ANSWER)
MMODE: DS 1 ;MODEM MODE
CHCNT: DS 1 ;CHARACTER POSITION COUNT
BUFPTR: DS 1 ;DATA BUFFER POINTER
HSHAKE: DS 1 ;HAND-SHAKE FLAG
AUTOD: DS 2 ;AUTO-DIAL FLAG
ROTFLG: DS 1 ;ROTARY DIALING FLAG
ANSFLG: DB 1 ;ANSWER MODE FLAG
LFDFLG DB 1 ;LINE FEED FLAG
BLANKS: DB ' ' ;16 BLANKS
;
;--CONSOLE DATA BUFFER
CBUFF DB 16 ;BUFFER SIZE
CBCNT DS 1 ;COUNT OF CHARACTERS READ
CBTXT DS 16 ;CONSOLE DATA
;
BDTBL: ;BAUD RATE VALUE TABLE
DB BAUD10 ;110 BAUD
DB BAUD15 ;150 BAUD
DB BAUD30 ;300 BAUD
DB BAUD45 ;450 BAUD
DB BAUD50 ;500 BAUD
DB BAUD60 ;600 BAUD
BDVAL: DS 1 ;SELECTED BAUD RATE VALUE
;
;************************ PHONE NUMBERS ******************************
;
ADRTBL: ;PHONE NUMBER ADDRESS TABLE
DW PHONEH
DW PHONEM
DW PHONEZ
DW PHONEW
;
PHONEM: ;UNIV. OF MD.
DB '4544821$'
DB '4545201$'
DB '4545401$'
DB '4545405$'
DB GS ;GROUP SEPERATOR
PHONEH: DB '7765253$';HOME PHONE
PHONEZ: DB '8441212$';TIME SERVICE
PHONEW: DB '9361212$';WEATHER SERVICE
;
;*********************** MESSAGES **********************************
;
MSG1 DB CLR,' 88-MODEM DRIVER ROUTINE'
DB CR,LF,LF,LF
DB 'TO INITIALIZE THE SYSTEM, TYPE ONE OF THE FOLLOWING '
DB 'CHARACTERS:',CR,LF,LF
DB 'H (HAND-SHAKE INIT.), B (BAUD-RATE SEL.), '
DB 'CR (DEFAULT TO 300 BAUD)',CR,LF,LF,LF,BEL,'$'
MSG1A DB 'SPECIFY THE MODE BY TYPING THE APPROPRIATE CHARACTER '
DB CR,LF,LF,'A --> ANSWER-MODE O --> ORIGINATE-MODE'
DB CR,LF,LF,'$'
MSG1B DB CLR,' ORIGINATE MODE -- WAITING FOR DIALTONE'
DB CR,LF,LF,'$'
MSG2 DB BEL,'DIAL TONE RECEIVED: COMMENSE DIALING - '
DB 'TERMINATED BY A CR',CR,LF,LF,'$'
MSG2A DB LF,'WAITING FOR CARRIER DETECT',CR,LF,'$'
MSG3 DB LF,LF,'CONNECTION HAS BEEN BROKEN',CR,LF,'$'
MSG4 DB CLR,BEL,'CONNECTION HAS BEEN ESTABLISHED, BEGIN '
DB 'NORMAL TRANSMISSION',CR,LF,LF,LF,'$'
MSG5 DB CLR,BEL,' RETURN TO CP/M EXECUTION'
DB CR,LF,LF,LF,'$'
MSG6 DB BEL,'UNABLE TO OPEN FILE FOR TRANSMISSION',CR,LF,'$'
MSG7 DB BEL,'DISK READ ERROR',CR,LF,'$'
MSG8 DB BEL,'UNABLE TO CREATE FILE DUE TO INSUFFICIENT'
DB ' DIRECTORY SPACE',CR,LF,'$'
MSG9 DB BEL,'FILE TRANSMISSION COMPLETED',CR,LF,LF,LF,'$'
MSG10 DB CR,LF,LF,LF,'READY TO RECEIVE FILE',CR,LF,LF,LF,'$'
MSG11 DB BEL,'UNABLE TO CLOSE FILE',CR,LF,'$'
MSG12 DB BEL,'ERROR IN EXTENDING FILE',CR,LF,'$'
MSG13 DB BEL,'DISK IS FULL',CR,LF,'$'
MSG14 DB BEL,'DISK DIRECTORY IS FULL',CR,LF,'$'
MSG15 DB ' HAND-SHAKE FLAG IS SET',CR,LF,LF,'$'
MSG16 DB ' BAUD-RATE SELECTION',CR,LF,LF
DB 'SELECT A BAUD RATE BY ENTERING APPROPRIATE DIGIT '
DB 'FROM THE FOLLOWING LIST:',CR,LF
DB '1 (110 BAUD), 2 (150 BAUD), 3 (300 BAUD)',CR,LF
DB '4 (450 BAUD), 5 (500 BAUD), 6 (600 BAUD)',CR,LF,LF,'$'
MSG17 DB CLR,' ANSWER MODE',CR,LF,LF,'$'
MSG18 DB 'WAITING FOR RING-INDICATOR AND CARRIER-DETECT'
DB CR,LF,LF,'$'
MSG19 DB CR,LF,LF,' HELLO THERE',CR,LF,LF
DB ' PLEASE BEGIN YOUR TRANSMISSION',CR,LF,LF,'$'
MSG20 DB CR,LF,LF,'ENTER FILE NAME IN 2 PARTS AS FOLLOWS:',CR,LF
DB '<FILENAME> CR',CR,LF
DB '<FILETYPE> CR',CR,LF,LF,'>$'
MSG21 DB CR,LF,LF,'SELECT THE CONSOLE DEVICE FROM THE '
DB 'FOLLOWING LIST:',CR,LF
DB '0 (TTY), 1 (CRT), 2 (BATCH), 3 (MODEM)',CR,LF,LF,'$'
;
;************************* SUBROUTINES *******************************
;
;++++++++++++++++++++++ COMMON SUBROUTINES ++++++++++++++++++++++++++
;
EXIT: ;RETURN TO CP/M
MVI C,WRCBUF
LXI D,MSG5
CALL FDOS ;TYPE EXIT MESSAGE
XRA A ;CLEAR A & CARRY
LHLD STACK
SPHL ;RESTORE CP/M STACK POINTER
RET
;
CSTAT: ;READ CONSOLE STATUS
MVI C,CONST
CALL FDOS
ORA A
RET
;
CRD$ST: ;CONSOLE READ - GO TO "STOP" IF "^D"
MVI C,RDCON
CALL FDOS
CPI EOT
RNZ ;"^D" ?
POP PSW ; YES, CORRECT STACK FOR NON-RETURN
XRA A
STA ROTFLG ;RESET ROTARY FLAG
JMP STOP
;
MSTAT: ;READ MODEM STATUS AND DISPLAY ON PORT 0FFH
IN MODEM0
CMA
OUT 0FFH
CMA
RET
;
MTBE: ;MODEM TX BUFFER EMPTY TEST
CALL MSTAT
ANI TBE
JZ MTBE
RET
;
TCHAR: ;TYPE A CHARACTER ON CONSOLE DEVICE
MVI C,WRCON
MOV E,A
CALL FDOS
RET
;
DCHAR: ;DELETE A CHARACTER ON THE CONSOLE
MVI A,BS
CALL TCHAR
MVI A,' '
CALL TCHAR
MVI A,BS
CALL TCHAR
MVI A,BEL
CALL TCHAR
JMP DIAL
;
CRLF: MVI A,CR
CALL TCHAR
MVI A,LF
CALL TCHAR
RET
;
THEX: ;TYPE THE PAIR OF HEX CHARACTERS IN REG A
PUSH PSW
RAR
RAR
RAR
RAR
CALL TNIB
POP PSW
TNIB: ANI 0FH
CPI 10
JC ISNUM
ADI 7
ISNUM: ADI '0'
JMP TCHAR
;
DIALIT: ;DIAL THE DIGIT IN REG A
ANI 00FH
OUT MODEM3 ;SEND DIGIT TO DIALER
DBUSY: CALL CSTAT ;GET CONSOLE STATUS
JZ D2 ;DATA AVAILABLE?
CALL CRD$ST ; YES, TEST FOR "^D"
D2: CALL MSTAT
ANI DBY
JNZ DBUSY ;BUSY?
MVI A,'-' ; NO
CALL TCHAR ;PROMPT FOR NEXT DIGIT
RET
;
UART: ;SET UP UART CONFIGURATION
MVI A,ASCII1
OUT MODEM0 ;SELECT THE NO. OF DATA BITS & PARITY TYPE
MVI A,BDSEL
OUT MODEM2
LDA BDVAL
OUT MODEM3 ;SET THE BAUD-RATE VALUE
RET
;
MDM: ;SET UP MODEM CONFIGURATION
LDA MMSEL
OUT MODEM2
LDA MMODE
OUT MODEM3
NOP! NOP! NOP
NOP! NOP! NOP
ANI 0F7H ;RESET THE "BREAK-RLS." BIT
OUT MODEM3
RET
;
;++++++++++++++++++ CHARACTER TX/RX SUBROUTINES +++++++++++++++++++++++
;
BREAK: ;TRANSMIT A BREAK TO REMOTE DEVICE
LDA MMSEL
OUT MODEM2
LDA MMODE
ORA MMBRK
OUT MODEM3 ;TRANSMIT A BREAK
MVI A,5
CALL DELAY ;INSERT 0.5 SEC DELAY
LDA MMODE
ANI 0F3H
OUT MODEM3 ;RESET BREAK & BREAK.RLS BITS
JMP TRCHAR
;
DELAY: ;INSERT DELAY IN 100MS INCREMENTS (A.REG = INCREMENT.VAL)
MVI B,100
DEL1: MVI C,182 ;1MS = 182*(5.5 MICRO-SEC)
DEL2: DCR C
JNZ DEL2
DCR B
JNZ DEL1
DCR A
JNZ DELAY
RET
;
MOVE: ;SOURCE.ADDR=H,L DEST.ADDR=D,E BYTE.COUNT=A
ORA A
RZ ;BYTE.COUNT=0 ?
MOV B,A ; NO
MLOOP: MOV A,M
XCHG
MOV M,A
XCHG
INX D
INX H
DCR B
JNZ MLOOP
RET
;
FILE: ;SET UP FCB (FILE.CONTROL.BLOCK) AS SPECIFIED BY OPERATOR
MVI A,11
LXI H,BLANKS
LXI D,FCBFN
CALL MOVE ;BLANK FILL FCB <FILENAME> <FILETYPE>
MVI C,WRCBUF
LXI D,MSG20
CALL FDOS ;REQUEST <FILENAME> & <FILETYPE> FROM OPERATOR
MVI C,RDCBUF
LXI D,CBUFF
CALL FDOS ;GET <FILENAME> FROM CONSOLE
LDA CBCNT
LXI H,CBTXT
LXI D,FCBFN
CALL MOVE ;WRITE FCB <FILENAME>
CALL CRLF
MVI A,'>'
CALL TCHAR ;PROMPT OPERATOR FOR <FILETYPE>
MVI C,RDCBUF
LXI D,CBUFF
CALL FDOS ;GET <FILETYPE> FROM CONSOLE
LDA CBCNT
LXI H,CBTXT
LXI D,FCBFT
CALL MOVE ;WRITE FCB <FILETYPE>
CALL CRLF
JMP TRCHAR
;
ASSIGN: ;MAKE CONSOLE ASSIGNMENT (TEMPORARILY LIMITED TO TTY & CRT)
MVI C,WRCBUF
LXI D,MSG21
CALL FDOS ;PROMPT FOR CONSOLE SELECTION
MVI C,RDCON
CALL FDOS ;READ SELECTION
PUSH PSW
CALL CRLF
POP PSW
ANI 01H ;TEMPORARILY ALLOWS FOR TTY & CRT ONLY
PUSH PSW ;SAVE THE SELECTION
CALL ZIOCHK
ANI 0FCH ;MASK OUT THE 2 LSBS'
MOV B,A
POP PSW ;GET THE SELECTION
ORA B
MOV C,A
CALL ZIOSET
JMP TRCHAR
;
;+++++++++++++++++++++ FILE TX SUBROUTINES +++++++++++++++++++++++++
;
OPENF: ;OPEN DISK FILE FOR READING
MVI C,OPEN
LXI D,FCB
CALL FDOS
CPI 255
JNZ OPNOK ;IS FILE IN DIRECTORY?
MVI C,WRCBUF ; NO
LXI D,MSG6
CALL FDOS ;TYPE ERROR MESSAGE
POP PSW ;CORRECT STACK PTR FOR NON-RETURN
JMP TRCHAR ;REVERT TO CHARACTER MODE
OPNOK: XRA A
STA FCBNR ;NEXT-RECORD = 0
RET
;
DISKR: ;READ A DISK SECTOR (RECORD)
MVI C,RDDISK
LXI D,FCB
CALL FDOS
CPI 0
RZ ;NORMAL READ?
CPI 1 ; NO
JNZ DRERR ;END OF FILE?
MVI C,WRCBUF ; YES
LXI D,MSG9
CALL FDOS ;TYPE "END FILE" MSG
JMP DRERRX
DRERR: MVI C,WRCBUF
LXI D,MSG7
CALL FDOS ;TYPE "READ ERR" MSG
DRERRX: POP PSW ;CORRECT STACK FOR NON-RETURN
JMP TRCHAR ;REVERT TO CHARACTER MODE
;
SHOW: ;SHOW CHAR TRANSMITTED OR RECEIVED
CPI LF
JZ TCHAR
CPI CR
JZ TCHAR
CPI ' '
JC SHEX ;ASCII CONTROL CHARACTER?
CPI 07FH ; NO
JC TCHAR ;ASCII PRINTABLE CHARACTER?
SHEX: ;SHOW HEX VALUE FOR NON-PRINTABLE CHARACTER
PUSH PSW ; NO
MVI A,'('
CALL TCHAR
POP PSW
CALL THEX
MVI A,')'
CALL TCHAR
RET
;
;++++++++++++++++++++++ FILE RX SUBROUTINES +++++++++++++++++++++++++
;
MAKEF: ;CREATE A FILE FOR SUBSEQUENT WRITING
MVI C,CREATE
LXI D,FCB
CALL FDOS
CPI 255
JNZ MAKEOK ;IS SUFFICIENT DIRECTORY SPACE AVAILABLE?
MVI C,WRCBUF ; NO
LXI D,MSG8
CALL FDOS ;TYPE ERROR MSG.
POP PSW ;CORRECT STACK FOR NON-RETURN
JMP TRCHAR ;REVERT TO CHARACTER MODE
MAKEOK: XRA A
STA FCBNR ;NEXT-RECORD = 0
RET
;
ST$BUF: ;STORE CONTENTS OF REG A IN DISK BUFFER
PUSH PSW
LDA BUFPTR
MOV E,A ;D,E = DATA BYTE ADDRESS
MVI D,0
INR A
STA BUFPTR ;INCREMENTED BUFFER POINTER
;--STORE A BYTE A ADDRESS: TBUFF+(D,E)
LXI H,TBUFF
DAD D
POP PSW
MOV M,A
;--TEST FOR BUFFER FULL
LDA BUFPTR
CPI 080H
RNZ ;IS BUFFER FULL?
POP PSW ;YES, CORRECT STACK FOR NON-RETURN
JMP RFULL
;
DISKW: ;WRITE A DISK SECTOR (RECORD)
MVI C,WRDISK
LXI D,FCB
CALL FDOS
CPI 0
RZ ;NORMAL WRITE?
CPI 1 ; NO
JNZ DR1 ;ERROR IN EXTENDING FILE?
MVI C,WRCBUF ; YES
LXI D,MSG12
CALL FDOS ;TYPE "EXTEND ERROR" MSG
JMP DWERRX
DR1: CPI 2
JNZ DR2 ;IS DISK FULL?
MVI C,WRCBUF ; YES
LXI D,MSG13
CALL FDOS ;TYPE "DISK FULL" MSG
JMP DWERRX
DR2: MVI C,WRCBUF
LXI D,MSG14
CALL FDOS ;TYPE "DIRECTORY FULL" MSG
DWERRX: POP PSW ;CORRECT STACK FOR NON-RETURN
JMP TRCHAR ;REVERT TO CHARACTER MODE
;
CLOSEF: ;CLOSE DISK FILE (WRITING COMPLETED)
MVI C,CLOSE
LXI D,FCB
CALL FDOS
CPI 255
RNZ ;SUCESSFUL CLOSE?
MVI C,WRCBUF ; NO
LXI D,MSG11
CALL FDOS ;TYPE ERROR MESSAGE
RET
;
;*********************** MAIN PROGRAM ***************************
;
START: ;INITIALIZE OUR STACK
LXI H,0
DAD SP ;HL=STACK FROM CP/M
SHLD STACK ;SAVE CP/M STACK POINTER
LXI SP,STACK ;LOAD OUR STACK PIONTER
RESTRT: XRA A
STA HSHAKE ;RESET HAND-SHAKE FLAG
STA AUTOD ;RESET AUTO-DIAL FLAG
STA ROTFLG ;RESET ROTARY DIALING FLAG
STA ANSFLG ;RESET ANSWER MODE FLAG
STA LFDFLG ;RESET LINE FEED FLAG
MVI A,BAUD30
STA BDVAL ;DEFAULT BAUD RATE VALUE = 300
MVI A,MMLREL
STA MMODE ;DEFAULT MODEM MODE = MMLREL
MVI C,WRCBUF
LXI D,MSG1
CALL FDOS ;TYPE SIGN-ON MESSAGE
;--WAIT FOR CONSOLE INPUT
MVI C,RDCON
CALL FDOS ;READ CONSOLE DATA
CPI EOT
JZ EXIT ;"^D"?
ANI 05FH ; NO, SHIFT LC ALPLH TO UC
CPI 'H'
JNZ BAUD ;HAND-SHAKE REQUEST?
MVI A,0FFH ; YES
STA HSHAKE ;SET THE HAND-SHAKE FLAG TO ON
MVI C,WRCBUF
LXI D,MSG15
CALL FDOS ;TYPE "HAND-SHAKE" MSG.
JMP D0
;--BAUD RATE MODIFICATION
BAUD: CPI 'B'
JNZ D0 ;BAUD-RATE CHANGE REQUEST?
MVI C,WRCBUF; YES
LXI D,MSG16
CALL FDOS ;PROMPT FOR BAUD SELECTION
BA1: CALL CSTAT
JZ BA1 ;HAS OPERATOR RESPONDED?
MVI C,RDCON ; YES, GET THE CHARACTER
CALL FDOS
PUSH PSW
CPI '4'
JC BA2 ;BAUD-RATE > 300 ?
MVI A,MMHREL ; YES, CHANGE MODEM MODE ACCORDINGLY
STA MMODE
BA2: CALL CRLF
POP PSW
ANI 07H
DCR A
MOV E,A
MVI D,00H ;D,E = TBL INDEX
LXI H,BDTBL
DAD D
MOV A,M
STA BDVAL ;NEW TRANSMISSION BAUD-RATE VALUE
;--DETERMINE MODEM MODE (ORIGINATE/ANSWER)
D0: MVI C,WRCBUF
LXI D,MSG1A
CALL FDOS ;TYPE "MODE" MESSAGE
MVI C,RDCON
CALL FDOS ;READ CONSOLE DATA
CPI EOT
JZ RESTRT ;"^D"?
ANI 05FH ; NO, SHIFT LC ALPHA TO UC
CPI 'O'
JZ ORIG ;ORIGINATE-MODE SELECTED?
CPI 'A' ; NO
JNZ D0 ;ANSWER-MODE SELEDTED?
MVI A,0FFH ; YES
STA ANSFLG
JMP ANSWER
;
;++++++++++++++++++++++++ ORIGINATE MODE ++++++++++++++++++++++++++++++
;
;--SET UP DIALER BAUD RATE
ORIG: MVI A,BDSEL ; NO
OUT MODEM2
MVI A,DRATE2
OUT MODEM3
;--GO OFF-HOOK & SET BREAK RELEASE
MVI A,MMSELO
OUT MODEM2
MVI A,MMORIG
OUT MODEM3
MVI C,WRCBUF
LXI D,MSG1B
CALL FDOS ;TYPE "WAITING" MESSAGE
;--WAIT FOR DIAL TONE OR "^D"
DTONE: CALL CSTAT ;GET CONSOLE STATUS
JZ D1 ;CONSOLE DATA AVAILABLE?
CALL CRD$ST ; YES, TEST FOR "^D"
D1: CALL MSTAT ;GET MODEM STATUS
ANI DTD
JNZ DTONE ;DIAL TONE PRESENT?
MVI C,WRCBUF ; YES, INFORM OPERATOR
LXI D,MSG2
CALL FDOS
;--BEGIN DIALING SEQUENCE
MVI A,DLSEL
OUT MODEM2
LDA ROTFLG
ORA A
JZ DIAL ;ROTARY DIALING IN PROGRESS?
POP PSW ; YES, GET ROTARY CHARACTER
JMP AUTODL
DIAL: CALL CRD$ST ;CONSOLE READ
CPI CR
JZ UARTO ;CARRIAGE RETURN?
;--SCREEN OUT NON-DECIMAL "DIALED" CHARACTERS
CPI '0' ; NO
JC DCHAR ;CONTROL CHAR. OR SYMBOL?
CPI ':' ; NO
JC DIGIT ;NON-DECIMAL CHARACTER?
JMP AUTODL ; YES, PERFORM AUTO-DIALING
DIGIT: CALL DIALIT ;DIAL A DIGIT
JMP DIAL
;--AUTOMATIC DIALING ROUTINE
AUTODL: LXI H,0FFFFH
SHLD AUTOD ;SET AUTO-DIAL FLAG
PUSH PSW ;SAVE CHARACTER FOR ROTARY DIALING TEST
ANI 03H
RLC
MOV E,A
MVI D,0
LXI H,ADRTBL
DAD D ;H,L=INDIRECT ADDRESS OF PHONE NUMBER
MOV E,M
INX H
MOV D,M
XCHG ;H,L=ADDRESS OF PHONE NUMBER
AU1: MOV A,M
CPI GS
JZ ROTEND ;END OF ROTARY GROUP?
CPI '$' ; NO
JZ UARTO-1 ;DIALING COMPLETE?
PUSH H ; NO
PUSH PSW
CALL TCHAR ;TYPE DIGIT TO BE DIALED
POP PSW
CALL DIALIT
POP H
INX H
JMP AU1
;--SET UP UART CONFIGURATION
PUSH H ;SAVE ADDRESS POINTER FOR ROTARY DIALING
UARTO: MVI C,WRCON
MVI E,LF
CALL FDOS ;SEND "LINE-FEED" TO CONSOLE
CALL UART ;ESTABLISH UART CONFIGURATION
;--WAIT FOR CTS (CARRIER DETECT)
MVI C,WRCBUF
LXI D,MSG2A
CALL FDOS ;TYPE "WAITING" MESSAGE
LXI B,0FFFFH ;INITIALIZE TIME-OUT
PUSH B
CTS1: POP B
DCX B
MOV A,B
ORA C
JZ ROTARY ;TIME-OUT EXPIRED?
PUSH B ; NO
CALL CSTAT ;GET CONSOLE STATUS
JZ C1 ;CONSOLE DATA AVAILABLE?
CALL CRD$ST ; YES, TEST FOR "^D"
C1: CALL MSTAT
ANI CTS
JZ CTS1 ;CLEAR TO SEND?
JMP MDMO ; YES, SET UP MODEM CONFIGURATION
;--ROTARY DIALING SEQUENCE
ROTARY: LDA AUTOD
ORA A
JZ STOP ;AUTO-DIAL MODE?
POP H ; YES, GET PH# ADDRESS
INX H
POP PSW ;GET CHARACTER WHICH INITIATED AUTO-DIAL
CPI 'M'
JNZ STOP ;ROTARY CHARACTER?
PUSH PSW ; YES, SAVE FOR NEXT ITERATION
MVI A,0FFH
STA ROTFLG ;SET ROTARY DIALING FLAG
SHLD ADRTBL+2;STORE INCREMENTED POINTER
JMP STOP ;TRY THE NEXT PHONE NUMBER
ROTEND: LXI H,PHONEM
SHLD ADRTBL+2;RESTORE ORIGINAL POINTER
XRA A
STA ROTFLG ;RESET ROTARY DIALING FLAG
POP PSW ;RESTORE STACK TO NORMAL
JMP STOP
;--SET UP MODEM CONFIGURATION
MDMO: MVI A,MMSELO
STA MMSEL
CALL MDM
;--PROMPT OPERATOR TO BEGIN COMMUNICATIONS
MVI C,WRCBUF
LXI D,MSG4
CALL FDOS ;TYPE START TX MESSAGE
XRA A
STA ROTFLG ;RESET ROTARY DIALING FLAG
JMP TRCHAR
;
;++++++++++++++++++++++++ ANSWER MODE +++++++++++++++++++++++++++++++++
;
ANSWER: MVI C,WRCBUF
LXI D,MSG17
CALL FDOS ;TYPE "ANSWER MODE" MSG
MVI A,0FFH
STA LFDFLG ;SET LINE.FEED FLAG
CALL UART ;SET UP UART CONFIGURATION
MVI A,MMSELA
STA MMSEL
CALL MDM ;SET UP MODEM CONFIGURATION
MVI C,WRCBUF
LXI D,MSG18
CALL FDOS ;TYPE "WAITING" MESSAGE
;--WAIT FOR CTS (RING INDICATOR & CARRIER DETECT)
AN0: CALL CSTAT
JZ AN1 ;CONSOLE DATA AVAILABLE?
MVI C,RDCON ; YES
CALL FDOS ;READ CONSOLE DATA
CPI EOT
JNZ AN1 ;"^D"?
XRA A ; YES
STA ANSFLG ;RESET ANSWER MODE FLAG
JMP STOP
AN1: IN MODEM0 ; NO
ANI CTS
JZ AN0 ;HAS CONNECTION BEEN ESTABLISHED?
MVI C,WRCBUF; YES, INFORM CONSOLE OPERATOR
LXI D,MSG4
CALL FDOS
;--TRANSMIT SIGN-ON MESSAGE TO REMOTE DEVICE
LXI H,MSG19 ;H,L = MESSAGE ADDRESS
SIGNON: CALL MSTAT
ANI TBE
JZ SIGNON ;TX BUFFER EMPTY?
MOV A,M ; YES, GET NEXT CHARACTER
CPI '$'
JZ TRCHAR ;MESSAGE COMPLETE?
OUT MODEM1 ; NO, TRANSMIT THE CHARACTER
INX H
JMP SIGNON
;
;+++++++++++++++++ CHARACTER TX/RX ROUTINE +++++++++++++++++++++++++++
;
;--TEST FOR LOSS OF "CTS"
TRCHAR: IN MODEM0
ANI CTS
JZ STOP ;LOSS OF CTS?
;--TEST FOR "LINE CHARACTER" AVAILABILITY
IN MODEM0 ; NO
ANI RDA
JZ NOCHAR ;RECEIVE DATA AVAILABLE?
IN MODEM1 ; YES, READ DATA
PUSH PSW
CALL TCHAR ;TYPE RECEIVED CHARACTER
LDA LFDFLG
ORA A
JZ TR1 ;LINE FEED FLAG SET?
POP PSW ; YES
CPI CR
JNZ TR1+1 ;CHARRIAGE RETURN?
TRLF: MVI A,LF ; YES, SEND A LINE FEED
CALL TCHAR
TR0: IN MODEM0
ANI TBE
JZ TR0 ;TX BUFFER EMPTY?
MVI A,LF ; YES
OUT MODEM1 ;TRANSMIT LINE FEED TO LINE
JMP NOCHAR
TR1: POP PSW
CPI DC4
JZ TXFILE ;"^T"?
CPI DC2 ; NO
JZ RXFILE ;"^R"?
CPI EOT ; NO
JNZ NOCHAR ;"^D"?
XRA A ; YES
STA ANSFLG ;RESET THE ANSER.MODE FLAG
JMP STOP ;TERMINATE ANSWER MODE
;--TEST FOR "LOCAL CHARACTER" AVAILABILITY
NOCHAR: CALL CSTAT ;GET CONSOLE STATUS
JZ TRCHAR ;CONSOLE DATA AVAILABLE?
CALL CRD$ST ; YES, READ DATA & TEST FOR "^D"
CPI DC4
JZ TXFILE ;"^T"?
CPI DC2 ; NO
JZ RXFILE ;"^R"?
CPI SOH
JZ ASSIGN ;IF "^A" THEN CHANGE CONSOLE ASSIGNMENT
CPI STX
JZ BREAK ;IF "^B" THEN TRANSMIT A "BREAK"
CPI ACK
JZ FILE ;IF "^F" THEN SET UP NEW FILE NAME
OUT MODEM1 ;TRANSMIT DATA TO "LINE"
CPI CR
JNZ TRCHAR ;CARRIAGE RETURN?
LDA LFDFLG ; YES
ORA A
JNZ TRLF ;LINE FEED FLAG SET?
JMP TRCHAR ; NO
;
;+++++++++++++++++++++ FILE TX ROUTINE ++++++++++++++++++++++++++
;
TXFILE: CALL OPENF ;OPEN DISK FILE FOR READING
MVI A,80H
STA BUFPTR ;INITIALIZE THE BUFFER POINTER
XRA A
STA CHCNT ;INITIALIZE CHARACTER POSITION COUNT
;--START OF BYTE TRANSMIT LOOP
TXBYTE: CALL CSTAT ;GET CONSOLE STATUS
JZ TF0 ;DATA AVAILABLE?
MVI C,RDCON ; YES
CALL FDOS
CPI EOT
JZ TRCHAR ;"^D" ?
TF0: IN MODEM0 ; NO
ANI RDA
JZ TF1A ;RX DATA AVAILABLE?
IN MODEM1 ; YES
CPI EOT
JZ TRCHAR ;"^D"?
TF1A: LDA BUFPTR ; NO
CPI 80H
JNZ TF1 ;BUFFER EMPTY?
;--READ A SECTOR & EXIT IF END OF FILE
CALL DISKR ; YES
XRA A
TF1: MOV E,A ;D,E = DATA BYTE ADDRESS
MVI D,0
INR A
STA BUFPTR ;INCREMENTED BUFFER POINTER
;--READ A BYTE AT ADDRESS: TBUFF+(D,E)
LXI H,TBUFF
DAD D
MOV A,M
PUSH PSW
;--WAIT FOR UART TX BUFFER EMPTY
TF2: CALL MSTAT
ANI TBE
JZ TF2 ;UART TX BUFFER EMPTY?
POP PSW ; YES
CPI ETB
JZ TFEND ;(^W) END TRANSMISSION BLOCK?
CPI HT ; NO
JNZ TF3 ;HORIZONTAL TAB?
;--TRANSLATE HT INTO APPROPRIATE NUMBER OF SPACES
LDA CHCNT ; YES
SPACES: MOV B,A
CALL MTBE ;INSURE MODEM TX BUFFER EMPTY
MVI A,' '
OUT MODEM1
PUSH B
CALL TCHAR
POP B
INR B
MOV A,B
ANI 07H ;MOD 8 COUNT VALUE
JNZ SPACES ;FINAL SPACE SENT?
STA CHCNT
JMP TXBYTE
;--SEND DATA BYTE & UPDATE CHCNT (CHARACTER POSITION COUNT)
TF3: PUSH PSW
CALL SHOW ;DISPLAY BYTE ON CONSOLE
POP PSW
OUT MODEM1
CPI LF
JZ TFEOL ;"LF" SIGNALS END OF TEXT LINE
LDA CHCNT
INR A
STA CHCNT ;INCREMENTED CHAR POSITION COUNT
JMP TXBYTE
;--PERFORM END OF LINE PROCESSING
TFEOL: XRA A
STA CHCNT ;RESET CHAR POSITION COUNT
LDA HSHAKE
ORA A
JNZ TF4 ;HAND-SHAKE REQUIRED?
MVI A,5 ; NO, GENERATE 0.5 SEC DELAY
CALL DELAY
JMP TXBYTE ;BEGIN NEXT LINE
;--PERFORM END OF TEXT LINE "HANDSHAKING"
TF4: CALL CSTAT
JZ TF4A ;CONSOLE CHAR RECEIVED?
JMP TFEND ; YES, TERMINATE FILE TX
TF4A: CALL MSTAT ;
ANI RDA
JZ TF4 ;RECEIVE DATA AVAILABLE?
IN MODEM1 ; YES
CPI LF
JNZ TF4 ;"LINE FEED" RECEIVED FROM LINE?
MVI A,1 ; YES, INSERT 100MS DELAY
CALL DELAY
JMP TXBYTE ;BEGIN NEXT LINE
TFEND: CALL CRLF
JMP TRCHAR ;REVERT TO CHARACTER MODE
;
;+++++++++++++++++++++ FILE RX ROUTINE +++++++++++++++++++++++++++
;
RXFILE: MVI C,DELETE
LXI D,FCB
CALL FDOS ;DELETE NAMED FILE (IF IT EXISTS)
CALL MAKEF ;CREATE FILE FOR RX DATA
XRA A
STA BUFPTR ;INITIALIZE THE BUFFER POINTER
MVI C,WRCBUF
LXI D,MSG10
CALL FDOS ;TYPE "READY" MSG
;--RECEIVE A CHARACTER FROM THE REMOTE DEVICE
RCV: IN MODEM0
ANI RDA
JNZ GOTONE ;RECEIVED DATA AVAILABLE?
;--SUPPORT CHARACTER TX FROM CONSOLE
CALL CSTAT ; YES, GET CONSOLE STATUS
JZ RCV ;DATA AVAILABLE?
MVI C,RDCON ; YES
CALL FDOS
CPI EOT
JZ RFEND ;"^D" ?
OUT MODEM1 ; NO, TRANSMIT CHARACTER
JMP RCV
;--READ CHARACTER FROM EXTERNAL DEVICE
GOTONE: IN MODEM1
CPI ETB
JZ RF0 ;"^W"?
CPI EOT ; NO
JZ RFEND ;"^D"?
CPI CR ; NO
JZ RFCR ;CARRIAGE RETURN?
CPI DEL ; NO
JZ RCV ;DO NOT RECORD RUBOUTS
CPI ' '
JC RCV ;ASCII CONTROL CHARACTER?
PUSH PSW ; NO
CALL TCHAR ;DISPLAY CHARACTER ON CONSOLE
POP PSW
RF0: CALL ST$BUF ;STORE CHARACTER IN DISK BUFFER
JMP RCV
;--CARRIAGE RETURN PROCESSING
RFCR: PUSH PSW
CALL TCHAR ;TYPE "CR"
POP PSW
CALL ST$BUF ;PUT IT IN BUFFER
MVI A,LF
PUSH PSW
CALL TCHAR ;TYPE "LF"
POP PSW
CALL ST$BUF ;PUT IT IN BUFFER
LDA LFDFLG
ORA A
JZ RCV ;LINE.FEED FLAG SET?
RF1: IN MODEM0 ; YES
ANI TBE
JZ RF1 ;TX BUFFER EMPTY?
MVI A,LF ; YES
OUT MODEM1 ;SEND LINE.FEED TO REMOTE DEVICE
JMP RCV
;--BUFFER IS FULL - WRITE A DISK SECTOR
RFULL: CALL DISKW ; YES
XRA A
STA BUFPTR
JMP RCV
;--WRITE FINAL SECTOR & CLOSE FILE
RFEND: LDA BUFPTR
MOV E,A
MVI D,0
LXI H,TBUFF
DAD D
MVI A,01AH ;"^Z" INDICATES END OF FILE
MOV M,A
CALL DISKW ;WRITE THE LAST RECORD
CALL CLOSEF
JMP TRCHAR ;REVERT TO CHARACTER MODE
;
;+++++++++++++++++ TERMINATE COMMUNICATIONS +++++++++++++++++++++++
;
;--SEND A BREAK, HANG UP THE PHONE, INFORM THE OPERATOR
STOP: MVI A,MMSELO
OUT MODEM2
MVI A,MMTERM
OUT MODEM3
MVI C,WRCBUF
LXI D,MSG3
CALL FDOS ;TYPE TERMINATION MESSAGE
;--CONTINUE TO LOOP TILL LOSS OF CTS (CARRIER DETECT)
CTS2: CALL MSTAT
ANI CTS
JNZ CTS2 ;HAS CTS BEEN RESET?
MVI A,30 ; YES
CALL DELAY ;3 SECOND DELAY
LDA ROTFLG
ORA A
JNZ ORIG ;ROTARY DIALING IN PROGRESS?
LDA ANSFLG ; NO
ORA A
JNZ ANSWER ;ANSWER MODE?
JMP RESTRT ; NO
END START