home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
hamradio
/
rtty3.lbr
/
RTTY3.AZM
/
RTTY3.ASM
Wrap
Assembly Source File
|
1987-02-21
|
32KB
|
1,365 lines
; RTTY.ASM Version 2.0 By G.F.Reding 02/13/86
;
; --------------------------------------------------------------
;
; Ascii to Baudot to Ascii program with buffer to disk and disk
; to buffer routines (taken frop 'PLINK.ASM' by L.E.Hughs
; Randy Suess 12/20/78
;
; --------------------------------------------------------------
;
; 02/13/86 Program and version upgrade
; v 3.1 by G.F.Reding [72436,45]
;
; Capture to memory may be toggled on or off as desired.
;
; Transmit text file and write to disk options prompt for the
; drive in addition to the filename.
;
; Baudot or ascii receive/transmit modes may be selected, with
; the program initially starting in baudot mode. Upon change of
; mode, the bits/parity are changed, speed is set to the lowest
; rate for the appropriate mode, and a flag is appropriately set
; which determines if ascii/baudot or ascii/baudot conversion is
; to be performed and it's also used in the speed display/change
; routines.
;
; The speed may be viewed and/or changed. If change is desired,
; the speed is stepped up to the next higher rate available for
; the (ascii or baudot) mode. Once the highest rate is reached,
; the next rate will be the lowest rate for the current mode.
;
; The program has been cleaned up and improved. It is comparable
; to version 6.7 of PLINK from which a lot of the routines came.
; Messages are given at most times, making the program fairly
; user-friendly.
;
; Note: Console and serial port i/o is shown for a Zilog SIO.
;
; G.F.Reding [72436,45]
; 02/13/86
;
; Future upgrades could include a buffered send routine, possibly
; split screen mode of operation for send/receive, 25th line for
; status of the program and/or command options, AMTOR mode, etc.
; Any helpers out there?
;
; --------------------------------------------------------------
;
; System and program equates
;
BASE EQU 0 ; Standard = 0, Alternate 4200H
BDOS EQU BASE+5
DBUF EQU BASE+80H ; Default disk buffer address
FCB EQU BASE+5CH ; File control block
FN EQU 1 ; File name field (rel)
FT EQU 9 ; File type field (rel)
NR EQU 32 ; Next record field (rel)
;
RESDSK EQU 13 ; Reset disk
OFFC EQU 15 ; Open file
CFFC EQU 16 ; Close file
DFFC EQU 19 ; Delete file
RRFC EQU 20 ; Read record
WRFC EQU 21 ; Write record
MFFC EQU 22 ; Make file
;
BEL EQU 07H ; Bell
LF EQU 0AH ; Line feed
CR EQU 0DH ; Carriage return
DEL EQU 7FH ; Delete
;
; I/O Port addresses and masks
;
COND EQU 60H ; Console data port
CONS EQU 61H ; Console status port
CRBF EQU 01H ; Receive buffer full (ready)
CTBE EQU 04H ; Transmit buffer empty (ready)
;
MODD EQU 62H ; Modem data port
MODS EQU 63H ; Modem status port
MRBF EQU 01H ; Receive buffer full (ready)
MTBE EQU 04H ; Transmit buffer empty (ready)
;
BRPORT EQU 053H
BAUDS EQU 051H
MODEW EQU 07EH ; Value for BRPORT
;
EV1: EQU 046H ; Reg 4 - even parity, 1 stop
NO1: EQU 044H ; Reg 4 - no parity, 1 stop
NO5: EQU 048H ; Reg 4 - no parity, 1.5 stop
RX5: EQU 001H ; Reg 3 - 5 bit, rx enable
RX7: EQU 041H ; Reg 3 - 7 bit, rx enable
RX8: EQU 0C1H ; Reg 3 - 8 bit, rx enable
TX5: EQU 08AH ; Reg 5 - dtr, rts, tx on, 5 bit
TX7: EQU 0AAH ; Reg 5 - dtr, rts, tx on, 7 bit
TX8: EQU 0EAH ; Reg 5 - dtr, rts, tx on, 8 bit
;
;
; Command control characters
;
KYEXIT EQU 'E'-40H ; Exit program to CPM
KYMODE EQU 'A'-40H ; Mode (baudot/ascii) toggle
KYABRT EQU 'C'-40H ; Abort file transmit
KYSPED EQU 'R'-40H ; Speed display/change (steps)
KYTRAN EQU 'T'-40H ; Transmit text file from disk
KYCAPT EQU 'Y'-40H ; Ascii capture (yank) toggle
KYWRIT EQU 'W'-40H ; Write to disk (disables capture)
;
;
; EQUATES FOR THE BAUDOT SEND/RECEIVE ROUTINES
;
ALTM: EQU 7DH ; Alternate mode key
;
FIGS: EQU 1BH ; Baudot 'figs'
LTRS: EQU 1FH ; Baudot 'ltrs'
SPACE: EQU 04H ; Baudot 'space'
;
CNTA: EQU 01H ; Control a
CNTB: EQU 02H ; Control b
CNTC: EQU 03H ; Control c
CNTE: EQU 05H ; Control e
CNTH: EQU 08H ; Control h
CNTI: EQU 09H ; Control i
CNTO: EQU 0FH ; Control o
CNTV: EQU 16H ; Control v
CNTX: EQU 18H ; Control x
CNTZ: EQU 1AH ; Control z
;
ASPC: EQU 20H ; Ascii space
APOS: EQU 27H ; Apostrophe
ATSN: EQU 40H ; "at" SIGN
EQL: EQU 3DH ; Equals sign
ESCP: EQU 1BH ; Escape key
GRTH: EQU 3EH ; Greater-than sign
LARW: EQU 5FH ; Left arrow
LBKT: EQU 5BH ; Left bracket
LETH: EQU 3CH ; Less-than sign
PCT: EQU 25H ; Percent sign
PLUS: EQU 2BH ; Plus sign
RBKT: EQU 5DH ; Right bracket
RESL: EQU 5CH ; Reverse slant
STAR: EQU 2AH ; Asterisk
UARW: EQU 5EH ; Up-arrow
;
CRX: EQU 48H
LFX: EQU 42H
;
;
; MAIN PROGRAM
;
ORG BASE+100H
;
LINK: LXI H,0 ; Save old stack ptr
DAD SP
SHLD OLDSP
LXI SP,STACK+64 ; Create local stack
;
LINK2: LXI H,TBUF ; Set ptr to tbuf
SHLD PTR
LXI H,0 ; Size = 0
SHLD SIZE
LXI H,LINK1M ; Signon and help message
CALL WCS ; Print it
CALL MDIN5N ; 5 bit no parity 1.5 stop
CALL MDSTB1 ; Set low baudot rate
LXI H,MODEBM ; Baudot mode message
CALL WCS ; Print it
;
;
; MAIN LOOP
;
LINK3: IN CONS ; Get console status
ANI CRBF
JZ LINK4 ; Jump if no data
IN COND ; Else read console data
OUT COND ; Echo to terminal
ANI 7FH ; Call pcc if control char
CPI 20H
CC PCC1
JC LINK4 ; Jump if pcc handled char
ORI 80H ; Else set valid data bit
STA INCH ; Store in input char buffer
;
LINK4: LDA OUTCH ; Get data for console
ORA A
JP LINK5 ; Jump if no data for console
ANI 7FH ; Else discard valid data bit
OUT COND ; And output char to console
XRA A ; Then clear output char buffer
STA OUTCH
;
LINK5: IN MODS ; Get status
ANI MRBF
JZ LINK6 ; Jump if no data from rtty
CALL RMC ; Call rtty read routine
CALL SAVE ; Save char in text buffer if flag on
ORI 80H ; Set data valid bit
STA OUTCH ; Store in output char buffer
;
LINK6: IN MODS ; Get status
ANI MTBE
JZ LINK3 ; Jump if rtty xmit buffer busy
LDA INCH ; Jump if no data for rtty
ORA A
JP LINK3
ANI 7FH ; Else discard valid data bit
;
CPI CR ; For each cr to send
JNZ LINK7
MVI A,CR ; Added code
CALL WMC ; To send two cr
CALL WMC
MVI A,LF ; And one lf
OUT COND ; Echo lf to console
;
LINK7: CALL WMC
XRA A ; Then clear input char buffer
STA INCH
JMP LINK3 ; End of main loop
;
;
; PCC - PROCESS CONTROL CHARACTER
;
PCC1: CPI KYEXIT ; Exit program?
JNZ PCC2 ; No, check more
PUSH H
LXI H,EXIT1M ; Exit confirm message
CALL WCS ; Print it
POP H
CALL RCC ; Get answer
CALL WCC ; Echo it
ANI 5FH ; Make upper case
CPI 'Y' ; If yes
JZ PCC1A ; Then continue exit
CALL WCCR ; Else cr/lf
LXI H,EXITNM ; No exit message
CALL WCS ; Print it
STC ; Ignore the char
RET
;
PCC1A: PUSH H
LHLD SIZE ; Get capture buffer size
MOV A,L ; Check
ORA H ; If anything there
JZ PCC1B ; No, exit simply
LXI H,EXIT2M ; Save buffer message
CALL WCS ; Print it
POP H
CALL RCC ; Get save answer
CALL WCC ; Echo it
ANI 5FH ; Make upper case
CPI 'Y' ; If yes
CZ WTB ; Then save the buffer
JMP PCC1C ; And exit
;
PCC1B: POP H
PCC1C: LXI H,EXITYM ; Exit to cp/m message
CALL WCS ; Print it
CALL MDIN8N ; Reset to 8 bit no parity 1 stop
CALL MDSTA6 ; 1200 baud
LHLD OLDSP ; Clean up act, exit to cp/m
SPHL
RET
;
PCC2: CPI KYTRAN ; Transmit a file?
JNZ PCC3
CALL STF ; Send ascii file to rtty
STC ; Ignore the char
RET
;
PCC3: CPI KYMODE ; Change mode?
JNZ PCC4 ; No, check more
LDA FLAGM
DCR A ; Was the flag zero
JNZ PCC3A ; Yes, so go set to 1
STA FLAGM ; No, was 1, now zero
CALL MDIN5N ; 5 bit no parity 1.5 stop
CALL MDSTB1 ; Set low baudot rate
LXI H,MODEBM ; Baudot mode message
JMP PCC3B
;
PCC3A: MVI A,1 ; Turn on capture flag
STA FLAGM
CALL MDIN7E ; 7 bit even parity 1 stop
CALL MDSTA1 ; Set low ascii rate
LXI H,MODEAM ; Ascii mode message
PCC3B: CALL WCS ; Print it
STC ; Ignore the char
RET
;
PCC4: CPI KYCAPT ; Yank (capture)?
JNZ PCC5 ; No, check more
LDA FLAGC
DCR A ; Was the flag zero
JNZ PCC4A ; Yes, so go set to 1
STA FLAGC ; No, was 1, now zero
LXI H,CAPTNM ; Capture off message
JMP PCC4B
;
PCC4A: MVI A,1 ; Turn on capture flag
STA FLAGC
LXI H,CAPTYM ; Capture on message
PCC4B: CALL WCS ; Print it
STC ; Ignore the char
RET
;
PCC5: CPI KYWRIT ; Write buffer?
JNZ PCC6 ; No, check more
XRA A ; Turn off capture flag
STA FLAGC
CALL WTB ; Write text buffer to disk
STC ; Ignore the char
RET
;
PCC6: CPI KYSPED ; Speed change?
JNZ PCC7 ; No, invalid command
CALL MDTELL ; Display and/or change speed
STC ; Ignore the char
RET
;
PCC7: STC ; Link handle all other ctrl chars
CMC
RET
;
; STF - SEND TEXT FILE (TO RTTY)
;
STF: CALL GFN ; Get file name to send
JC STF6 ; Jump if file name error
CALL OPEN ; Try to open specified file
CPI 255 ; Jump if file not found
JZ STF7
XRA A ; Else rewind file and continue
STA FCB+NR
;
STF1: CALL READ ; Read next record into dbuf
CPI 1 ; Jump if end-of-file
JZ STF5
LXI H,DBUF ; Point to disk buffer
MVI C,128
;
STF2: MOV A,M ; Fetch next char from dbuf
INX H
CPI 'Z'-40H ; Jump if end-of-file char
JZ STF5
CALL WMC ; Write char to rtty
CALL WCC ; Write char to console
IN CONS ; Get console status
ANI CRBF ; Anything there
JZ STF4 ; No, skip over
IN COND ; Else get the char
ANI 7FH ; Strip parity
CPI KYABRT ; Check for ctrl c abort
JZ STF8
;
STF4: DCR C ; Loop thru rest of dbuf
JNZ STF2
JMP STF1 ; Go get next record from disk
;
STF5: CALL CLOSE ; Clean up act
LXI H,STFS1M ; Transfer complete message
CALL WCS ; Print it
RET
;
STF6: LXI H,STFS2M ; File name error message
CALL WCS ; Print it
RET
;
STF7: LXI H,STFS3M ; File not found message
CALL WCS ; Print it
RET
;
STF8: CALL CLOSE ; Clean up act
LXI H,STFS4M ; Transfer aborted message
CALL WCS ; Print it
RET
;
;
; SAVE - SAVE CHAR IN TEXT BUFFER IF FLAG ON
;
; ENTRY: A - CHARACTER TO SAVE
;
SAVE: PUSH PSW
LDA FLAGC
ORA A
JNZ SAVE1
POP PSW
RET
;
SAVE1: POP PSW
ANI 7FH ; Discard parity bit
RZ ; Return if char is a null
;
SAVE2: PUSH H
LHLD SIZE ; Get the size
INX H ; Increment it
SHLD SIZE ; Size = size + 1
LHLD PTR ; Get capture buffer ptr
MOV M,A ; Put char into buffer
INX H ; Point to next addr
SHLD PTR ; Store it
PUSH PSW
LDA BASE+7 ; Get system size
SUI 1 ; So we don't crash cp/m
CMP H ; Are we out of room?
JZ SAVE3 ; Yes, abort
SUI 4 ; Leave some room (1k)
CMP H ; Are we low on memory
LXI H,SAVE1M ; Memory low message
CC WCS ; Print it
POP PSW
POP H
RET
;
SAVE3: LXI SP,STACK+64 ; Reinitialize the stack
LXI H,SAVE2M ; Aborted - no memory message
CALL WCS ; Print it
LXI H,LINK ; Set up return address
PUSH H ; Leave it on stack
;
;
; WTB - WRITE TEXT BUFFER TO DISK
;
WTB: LHLD SIZE ; Jump if text buffer empty
MOV A,L
ORA H
JZ WTB5
CALL GFN ; Get file name
JC WTB6 ; Jump if file name error
MVI C,RESDSK ; Reset disk in case r/o
CALL BDOS ; Or error recovery
CALL DELT ; Delete old file, if any
CALL MAKE ; Make new file
XRA A ; Rewind file
STA FCB+NR
LHLD SIZE ; De = tbuf size
XCHG
LXI H,DBUF ; Top of stack points to dbuf
PUSH H
LXI H,TBUF ; Hl points to tbuf
;
WTB1: MVI C,128 ; Disk buffer size
;
WTB2: MOV A,M ; Fetch next byte of tbuf
INX H
XTHL
MOV M,A ; Store in dbuf
INX H
XTHL
DCX D ; Size = size - 1
MOV A,D ; Exit loop if size = 0
ORA E
JZ WTB3
DCR C ; Loop until dbuf full
JNZ WTB2
CALL WRITE ; Write full dbuf to disk
CPI 0 ; Did we have an error?
JNZ WTB4B ; If so, bail out
XTHL ; Top of stack points to dbuf
LXI H,DBUF
XTHL
JMP WTB1 ; Loop until end of tbuf
;
WTB3: POP H ; Hl points to current place in dbuf
;
WTB4: MVI M,'Z'-40H ; Store eof code
INX H
DCR C ; Loop thru rest of dbuf
JNZ WTB4
CALL WRITE ; Write last sector to disk
CPI 0 ; Error?
JNZ WTB4B ; If so handle it
CALL CLOSE ; Else clean up act
LXI H,TBUF ; Clear text buffer
SHLD PTR
LXI H,0 ; Set the size to zero
SHLD SIZE
LXI H,WTBS1M ; Saved, capture off message
CALL WCS ; Print it
RET
;
WTB4B: LXI H,WTBS2M ; Error writing - disk full msg
CALL WCS ; Print it
JMP WTB ; And try again
;
WTB5: LXI H,WTBS3M ; Buffer empty message
CALL WCS ; Print it
RET
;
WTB6: LXI H,WTBS4M ; File name error message
CALL WCS ; Print it
RET
;
;
; WCS - WRITE CONSOLE STRING
;
; ENTRY: HL - POINTS TO NUL TERMINATED STRING
;
WCS: MOV A,M
INX H
ORA A
RZ
CALL WCC
JMP WCS
;
; WCCR - WRITE CONSOLE CARRIAGE RETURN (AND LINE FEED)
;
WCCR: MVI A,CR
CALL WCC
MVI A,LF
;
;
; WCC - WRITE CONSOLE CHARACTER
;
; ENTRY: A - CHARACTER TO WRITE
;
WCC: PUSH PSW
WCC1: IN CONS
ANI CTBE
JZ WCC1
POP PSW
OUT COND
RET
;
;
; RCS - READ CONSOLE STRING (WITH ECHO)
;
; EXIT: B - NUMBER OF CHARS READ (<255)
; HL - POINTS TO LAST CHAR STORED (CR)
;
RCS: LXI H,IBUF
MVI B,0
;
RCS1: CALL RCC ; Read next char from console
CPI DEL ; Jump if not del
JNZ RCS2
INR B ; Ignore del if ibuf already empty
DCR B
JZ RCS1
DCX H ; Else discard last char
MOV A,M
CALL WCC ; Echo it
DCR B ; Decrement count
JMP RCS1 ; And loop
;
RCS2: CPI 'U'-40H ; Jump if not control-u
JNZ RCS3
CALL WCCR ; Else abort current line
JMP RCS ; And start over
;
RCS3: CALL WCC ; Echo it
MOV M,A ; Store char in ibuf
INR B ; Increment count
CPI CR ; Jump if carriage return
JZ RCS4
INX H ; Else advance ptr
JMP RCS1 ; And loop
;
RCS4: MVI A,LF ; Issue line feed
CALL WCC ; Echo it
RET
;
;
; RCC - READ CONSOLE CHARACTER
;
; EXIT: A - CHARACTER READ
;
RCC: IN CONS
ANI CRBF
JZ RCC
IN COND
ANI 7FH
RET
;
;
; WMC - WRITE RTTY CHARACTER
;
; ENTRY: A - CHARACTER TO WRITE
;
WMC: PUSH B ; Save registers
PUSH H
PUSH PSW
LDA FLAGM ; Get mode flag
CPI 1 ; Is it 1
JZ WMC1 ; Yes, ascii mode
JMP STTY1 ; No, baudot mode
;
WMC1: IN MODS ; Get status
ANI MTBE ; Transmit buffer empty?
JZ WMC1 ; If not, loop and wait
POP PSW ; Get char
PUSH PSW ; Resave
ANI 7FH
OUT MODD ; Send the char
POP PSW ; Restore registers
POP H
POP B
RET
;
; ASCXMT(4) REV. 2 BY KEITH PETERSEN, W8SDZ. 10/29/78.
;
; This program is for transmitting ascii through a baudot medium
; use a special format of figures blank (X) - where (X) is a
; special baudot character used to convey the ascii equivalent
; character to the receiving end where it is then converted back
; to ascii again. Lower case alpha characters are transmitted
; via a 4th case, ltrs blank (X).
;
; Call with ascii character in accumulator.
;
STTY1: POP PSW ; Get char
PUSH PSW ; Resave
;
MVI C,0 ; Set up counter
ANI 7FH ; Strip parity bit
CPI ALTM ; Alternate mode key?
JNZ STTY2 ; No, ignore next routine
MVI A,09H ; Baudot '$'
JMP STTY3
;
STTY2: CPI 7BH ; Above l.c. 'z' ?
JNC STTY7 ; If so, ignore it
LXI H,BTABLE ; Point to table start
ADD L ; Add char value
MOV L,A ; L points to baudot char.
MOV A,H ; Get h for correction
ACI 0 ; Correct if necessary
MOV H,A ; H is now correct
MOV A,M ; Get baudot char
ORA A ; Is it a non-printing char?
JZ STTY7 ; If so ignore it
CPI CRX ; Is it a carriage return?
JZ STTY5 ; Yes, handle without case test
CPI LFX ; Is it a line feed?
JNZ STTY3 ; No, ignore next routine
MVI A,LTRS
PUSH PSW ; Save it on stack
MVI A,LFX
LXI H,SCASE ; Point to present case reg.
MVI M,40H ; Set it to lower case
JMP STTY4 ; Send lf and ltrs
;
STTY3: PUSH PSW ; Save char
ANI 0C0H ; Strip all but case bits
LXI H,SCASE ; Point to present case reg.
CMP M ; Same case as previous char?
JZ STTY6 ; Yes no change necessary
MOV M,A ; Update case register
ORA A
JZ STTYTC
CPI 80H
JZ STTYUC
CPI 0C0H
JNZ STTYLC
;
STTYFC: XRA A ; Get a baudot 'blank'
PUSH PSW ; Save it on the stack
INR C ; Increment char count
;
STTYLC: MVI A,LTRS
JMP STTY4
;
STTYTC: XRA A ; Get a baudot 'blank'
PUSH PSW ; Save it on the stack
INR C ; Increment char count
;
STTYUC: MVI A,FIGS
STTY4: INR C ; Increment char count
STTY5: PUSH PSW ; Save it on the stack
;
STTY6: IN MODS ; Baudot uart status
ANI MTBE ; Trans. buffer empty?
JZ STTY6 ; If not, loop and wait
POP PSW ; Get char
;
ORI 0E0H ; Make upper 3 bits marking
OUT MODD ; Send to baudot port
DCR C ; More to send?
JP STTY6 ; Yes, continue sending
;
STTY7: POP PSW ; Restore registers
POP H
POP B
RET
;
;
; RMC - READ RTTY CHARACTER
;
; EXIT: A - CHARACTER READ
;
RMC: PUSH H ; Save hl
LDA FLAGM ; Get mode flag
CPI 1 ; Is it 1
JZ RMC1 ; Yes, ascii mode
JMP RTTY1 ; No, baudot mode
;
RMC1: IN MODD ; Get char
ANI 7FH
POP H ; Restore hl
RET
;
; ASCRCV(4), VER. 2 BY KEITH PETERSEN, W8SDZ. 10/30/78.
;
; This is a program to change ascii-coded-baudot to ascii.
; The routine returns with a 0FFH in the 'A' register if
; character it to be ignored. Otherwise it returns with
; the ascii character in the 'A' register. It is assumed
; that a status test has been done before calling this
; routine to determine that a baudot character is available.
;
RTTY1: LHLD CASAVE ; Get present case
;
IN MODD ; Get baudot char
ANI 1FH ; Baudot chars only
CPI FIGS
JZ RTTYUC
CPI LTRS
JZ RTTYLC
ORA A ; Baudot 'blank' ?
JZ RTTYTC
CPI SPACE
JNZ RTTY2
LXI H,LTABLE ; Space gives lower case
;
RTTY2: SHLD CASAVE ; Save present case
ADD L ; Add char. to table adrs.
MOV L,A ; L points to ascii char.
MOV A,H ; Get h for correction
ACI 0 ; See if correction needed
MOV H,A ; H is correct now
XRA A ; Put zero in a reg.
STA FLAGR ; Clear ltrs-figs last flag
MOV A,M ; Get ascii equivalent
POP H ; Restore hl registers
ORA A ; Is it printable?
RNZ ; Yes, valid char. return
CMA ; Make 0ffh 'ignore flag'
RET ; Return to calling program
;
RTTYLC: LXI H,LTABLE ; Lower case table address
JMP SETFLG ; Set ltrs last flag, exit
;
RTTYUC: LXI H,UTABLE ; Upper case table address
JMP SETFLG ; Set figs last flag, exit
;
RTTYTC: LDA FLAGR ; Get shift reminder flag
CPI FIGS
JNZ RTTYFC
LXI H,TTABLE ; Third case table address
JMP CLRFLG
;
RTTYFC: CPI LTRS ; Check for ltrs last
JNZ CLRFLG
LXI H,FTABLE ; Fourth case table address
;
CLRFLG: XRA A ; Ready to clear flag
;
SETFLG: STA FLAGR ; Ltrs-figs last flag
SHLD CASAVE ; Save present case
MVI A,0FFH ; 'ignore flag'
POP H ; Restore hl regs.
RET ; Return to program
;
;
; Get drive and filename
;
GFN: XRA A ; Initialize the fcb
STA FCB
LXI H,FCB+12 ; Zero the fcb to its end
MVI C,21
CALL ZEROM
;
LXI H,GFNS1M ; Which drive message
CALL WCS ; Print it
CALL RCC ; Get answer from console
CALL WCC ; Echo it
ANI 5FH ; Make upper case
CPI 'C'-40H ; Control c abort
JZ GFN6
SUI 'A'-1
JC GFN ; Require alphabetic
JZ GFN
CPI 6 ; Allow 5 drives (cp/m 2.x max 16)
JNC GFN
STA FCB ; Store it
;
LXI H,GFNS2M ; Filename message
CALL WCS ; Print it
CALL RCS ; Read response into ibuf
LXI H,FCB+FN ; Blank fill fn and ft fields
MVI C,11
;
GFN1: MVI M,' '
INX H
DCR C
JNZ GFN1
LXI H,IBUF ; Point to input buffer
LXI D,FCB+FN ; Scan off fn field
MVI C,9
;
GFN2: MOV A,M ; Fetch next char from ibuf
INX H
CPI 61H ; If lc, convert to uc
JC GFN2A
SUI 20H
;
GFN2A: CPI CR ; Jump if end of line
JZ GFN5
CPI '.' ; Jump if end of name
JZ GFN3
STAX D ; Else store char in fn field
INX D
DCR C ; Loop if 8 or less chars so far
JNZ GFN2
JMP GFN6 ; Else take error exit
;
GFN3: LXI D,FCB+FT ; Scan off ft field
MVI C,4
;
GFN4: MOV A,M ; Fetch next char from ibuf
INX H
CPI 61H ; If lc, convert to uc
JC GFN4A
SUI 20H
;
GFN4A: CPI CR ; Jump if end of line
JZ GFN5
STAX D ; Else store char in ft field
INX D
DCR C ; Loop if 3 or less chars so far
JNZ GFN4
JMP GFN6 ; Else take error exit
;
GFN5: STC ; Clear error flag and return
CMC
RET
;
GFN6: STC ; Set error flag and return
RET
;
;
ZEROM: MVI M,0 ; Zero memory, length in c
INX H
DCR C
JNZ ZEROM
RET
;
; OPEN - OPEN DISK FILE
;
OPEN: PUSH H
PUSH D
PUSH B
LXI D,FCB
MVI C,OFFC
CALL BDOS
POP B
POP D
POP H
RET
;
; READ - READ RECORD FROM DISK FILE
;
READ: PUSH H
PUSH D
PUSH B
LXI D,FCB
MVI C,RRFC
CALL BDOS
POP B
POP D
POP H
RET
;
; CLOSE - CLOSE DISK FILE
;
CLOSE: PUSH H
PUSH D
PUSH B
LXI D,FCB
MVI C,CFFC
CALL BDOS
POP B
POP D
POP H
RET
;
; DELT - DELETE DISK FILE
;
DELT: PUSH H
PUSH D
PUSH B
LXI D,FCB
MVI C,DFFC
CALL BDOS
POP B
POP D
POP H
RET
;
; WRITE - WRITE RECORD TO DISK
;
WRITE: PUSH H
PUSH D
PUSH B
LXI D,FCB
MVI C,WRFC
CALL BDOS
POP B
POP D
POP H
RET
;
; MAKE - MAKE NEW DISK FILE
;
MAKE: PUSH H
PUSH D
PUSH B
LXI D,FCB
MVI C,MFFC
CALL BDOS
POP B
POP D
POP H
RET
;
;
; Show the modem speed, prompt for change
;
MDTELL: LDA FLAGM ; Get mode flag
CPI 1 ; Is it 1
JZ MDTLA1 ; Yes, ascii mode
JMP MDTLB1 ; No, baudot mode
;
; Check and tell the ascii rate
;
MDTLA1: LDA MDRATE ; Get the rate flag
CPI 1 ; Is it 1
JNZ MDTLA2 ; No, check others
LXI H,MDTA1M ; 1st speed message
JMP MDTELC
;
MDTLA2: CPI 2 ; Is it 2
JNZ MDTLA3 ; No, check others
LXI H,MDTA2M ; 2nd speed message
JMP MDTELC
;
MDTLA3: CPI 3 ; Is it 3
JNZ MDTLA4 ; No, check others
LXI H,MDTA3M ; 3rd speed message
JMP MDTELC
;
MDTLA4: CPI 4 ; Is it 4
JNZ MDTLA5 ; No, check others
LXI H,MDTA4M ; 4th speed message
JMP MDTELC
;
MDTLA5: CPI 5 ; Is it 5
JNZ MDTLA6 ; No, must be 6
LXI H,MDTA5M ; 5th speed message
JMP MDTELC
;
MDTLA6: LXI H,MDTA6M ; 6th speed message
JMP MDTELC
;
; Check and tell the baudot rate
;
MDTLB1: LDA MDRATE ; Get the rate flag
CPI 1 ; Is it 1
JNZ MDTLB2 ; No, check others
LXI H,MDTB1M ; 1st speed message
JMP MDTELC
;
MDTLB2: CPI 2 ; Is it 2
JNZ MDTLB3 ; No, check others
LXI H,MDTB2M ; 2nd speed message
JMP MDTELC
;
MDTLB3: CPI 3 ; Is it 3
JNZ MDTLB4 ; No, check others
LXI H,MDTB3M ; 3rd speed message
JMP MDTELC
;
MDTLB4: CPI 4 ; Is it 4
JNZ MDTLB5 ; No, must be 5
LXI H,MDTB4M ; 4th speed message
JMP MDTELC
;
MDTLB5: LXI H,MDTB5M ; 5th speed message
JMP MDTELC
;
;
MDTELC: CALL WCS ; Print it
LXI H,MDCH1M ; Change it (Y) message
CALL WCS ; Print it
CALL RCC ; Get answer
CALL WCC ; Echo it
ANI 5FH ; Make upper case
CPI 'Y'
JNZ MDTELD
CALL MDSET0
JMP MDTELL ; Loop, another change?
;
MDTELD: CALL WCCR ; Print cr/lf
RET
;
;
;
MDSET0: LDA FLAGM ; Get mode flag
CPI 1 ; Is it 1
JZ MDSETA ; Yes, ascii mode
JMP MDSETB ; No, baudot mode
;
; For ascii, check existing rate and step to next
;
MDSETA: LDA MDRATE ; Get the rate flag
CPI 1 ; Is it 1
JZ MDSTA2 ; If yes, set to next rate
CPI 2 ; Else is it 2
JZ MDSTA3 ; If yes, set to next rate
CPI 3 ; Else is it 3
JZ MDSTA4 ; Yes, set to next rate
CPI 4 ; Else is it 4
JZ MDSTA5 ; Yes, set to next rate
CPI 5 ; Else is it 5
JZ MDSTA6 ; Yes, set to next rate
JMP MDSTA1 ; No, must be 6, so set low rate
;
; For baudot, check existing rate and step to next
;
MDSETB: LDA MDRATE ; Get the rate flag
CPI 1 ; Is it 1
JZ MDSTB2 ; If yes, set to next rate
CPI 2 ; Else is it 2
JZ MDSTB3 ; If yes, set to next rate
CPI 3 ; Else is it 3
JZ MDSTB4 ; If yes, set to next rate
CPI 4 ; Else is it 4
JZ MDSTB5 ; If yes, set to next rate
JMP MDSTB1 ; No, must be 5, so set low rate
;
; Baud rate for ascii mode
;
MDSTA1: XRA A ; Set flag to zero
STA MDRATE ; As set bumps it
LXI H,BD110 ; 110 baud
JMP MDSETX
;
MDSTA2: LXI H,BD300 ; 300 baud
JMP MDSETX
;
MDSTA3: LXI H,BD450 ; 450 baud
JMP MDSETX
;
MDSTA4: LXI H,BD600 ; 600 baud
JMP MDSETX
;
MDSTA5: LXI H,BD710 ; 710 baud
JMP MDSETX
;
MDSTA6: LXI H,BD1200 ; 1200 baud
JMP MDSETX
;
; Baud rates for baudot mode
;
MDSTB1: XRA A ; Set flag to zero
STA MDRATE ; As set bumps it
LXI H,BD045 ; 60 wpm = 45.45 baud
JMP MDSETX
;
MDSTB2: LXI H,BD050 ; 66 wpm = 50 baud
JMP MDSETX
;
MDSTB3: LXI H,BD057 ; 75 wpm = 57 baud
JMP MDSETX
;
MDSTB4: LXI H,BD074 ; 100 wpm = 74 baud
JMP MDSETX
;
MDSTB5: LXI H,BD100 ; 132 wpm = 100 baud
JMP MDSETX
;
; Modem speed setup
;
MDSETX: MVI A,MODEW
OUT BRPORT
MOV A,M
OUT BAUDS
INX H
MOV A,M
OUT BAUDS
;
LDA MDRATE ; Get rate
INR A ; And bump it to next higher
STA MDRATE ; Store the new value
RET
;
;
MDIN5N: MVI A,NO5 ; No parity 1.5 stop
STA MDINI1 ; Store for reg 4
MVI A,RX5 ; 5 bits, rx enable
STA MDINI3 ; Store for reg 3
MVI A,TX5 ; Dtr, rts, tx on, 5 bits
STA MDINI4 ; Store for reg 5
JMP MDINI0 ; Do the setup
;
MDIN7E: MVI A,EV1 ; Even parity 1 stop
STA MDINI1 ; Store for reg 4
MVI A,RX7 ; 7 bits, rx enable
STA MDINI3 ; Store for reg 3
MVI A,TX7 ; Dtr, rts, tx on, 7 bits
STA MDINI4 ; Store for reg 5
JMP MDINI0 ; Do the setup
;
MDIN8N: MVI A,NO1 ; No parity 1 stop
STA MDINI1 ; Store for reg 4
MVI A,RX8 ; 8 bits, rx enable
STA MDINI3 ; Store for reg 3
MVI A,TX8 ; Dtr, rts, tx on, 8 bits
STA MDINI4 ; Store for reg 5
;
; Main initialization routine used by those above
;
MDINI0: MVI A,4 ; Write reg 4
OUT MODS
MVI A,NO5 ; No parity, 1.5 stop, 16x
MDINI1: EQU $-1
OUT MODS
MVI A,1 ; Write reg 1
OUT MODS
MVI A,0
OUT MODS
MVI A,5 ; Write reg 5
OUT MODS
MVI A,0 ; DTR, RTS both off
OUT MODS
PUSH B ; Save in case used elsewhere
MVI B,5 ; 1/2 second delay (10 = 1 sec)
MDINI2: CALL DELAY ; 1/10 second delay
DCR B
JNZ MDINI2 ; Keep looping until finished
POP B ; Restore bc
MVI A,3 ; Write reg 3
OUT MODS
MVI A,RX5 ; 5 bits, enable receive
MDINI3: EQU $-1
OUT MODS
MVI A,5 ; Write reg 5
OUT MODS
MVI A,TX5 ; DTR, RTS, TX on, 5 bits
MDINI4: EQU $-1
OUT MODS
RET ; Return
;
; 1/10 second delay routine
;
DELAY: PUSH B
LXI B,4167*4 ; 4167 * system clock mhz
DELAY1: DCX B
MOV A,B
ORA C
JNZ DELAY1
POP B
RET
;
;
; MESSAGES
;
CAPTNM: DB CR,LF,'[Capture OFF]',CR,LF,0
CAPTYM: DB CR,LF,'[Capture ON]',CR,LF,0
;
EXIT1M: DB CR,LF,'Exit to CP/M -- Confirm (Y/N)? ',0
EXIT2M: DB CR,LF,'Save buffer before exit? ',BEL,0
EXITNM: DB CR,LF,'[Exit aborted]',CR,LF,0
EXITYM: DB CR,LF,LF,'[Exit to CP/M]',CR,LF,0
;
LINK1M: DB CR,LF,'RTTY v 3.1'
LINK2M: DB CR,LF
DB '^',KYTRAN+40H
DB ' Transmit '
DB '^',KYWRIT+40H
DB ' Write '
DB '^',KYCAPT+40H
DB ' Capture '
DB '^',KYSPED+40H
DB ' Speed'
DB CR,LF
DB '^',KYMODE+40H
DB ' Mode '
DB '^',KYABRT+40H
DB ' Cancel '
DB '^',KYEXIT+40H
DB ' Exit'
DB CR,LF,LF,0
;
GFNS1M: DB CR,LF,'Which drive? ',0
GFNS2M: DB CR,LF,'Filename? ',0
;
STFS1M: DB CR,LF,'[Transfer complete]',BEL,CR,LF,0
STFS2M: DB CR,LF,'[File name error]',CR,LF,0
STFS3M: DB CR,LF,'[File not found]',CR,LF,0
STFS4M: DB CR,LF,'[Transfer aborted]',CR,LF,0
;
WTBS1M: DB CR,LF,'[Buffer saved - Capture OFF]',CR,LF,0
WTBS2M: DB CR,LF,'[Write error - Disk may be full]'
DB CR,LF,'[Change disks - Use other drive]',BEL,CR,LF,0
WTBS3M: DB CR,LF,'[Buffer empty]',CR,LF,0
WTBS4M: DB CR,LF,'[File name error]',CR,LF,0
;
SAVE1M: DB CR,LF,'[Memory LOW]',BEL,CR,LF,0
SAVE2M: DB CR,LF,'[Aborted - NO memory]',BEL,CR,LF,0
;
MODEAM: DB CR,LF,'[Ascii Mode]',CR,LF,0
MODEBM: DB CR,LF,'[Baudot Mode]',CR,LF,0
;
MDTA1M: DB CR,LF,'[ 110 baud]',0
MDTA2M: DB CR,LF,'[ 300 baud]',0
MDTA3M: DB CR,LF,'[ 450 baud]',0
MDTA4M: DB CR,LF,'[ 600 baud]',0
MDTA5M: DB CR,LF,'[ 710 baud]',0
MDTA6M: DB CR,LF,'[1200 baud]',0
;
MDTB1M: DB CR,LF,'[ 60 wpm]',0
MDTB2M: DB CR,LF,'[ 66 wpm]',0
MDTB3M: DB CR,LF,'[ 75 wpm]',0
MDTB4M: DB CR,LF,'[100 wpm]',0
MDTB5M: DB CR,LF,'[132 wpm]',0
MDCH1M: DB ' Change it? ',0
;
;
; LOWER-CASE TABLE FOR RECEIVE
;
LTABLE: DB 0,'E',LF,'A SIU',CR,'DRJNFCK'
DB 'TZLWHYPQOBG',FIGS,'MXV'
;
; UPPER-CASE TABLE FOR RECEIVE
;
UTABLE: DB 0,'3',LF,'- ',BEL,'87',CR,'$4'
DB APOS,',!:(5")2#6019?&',FIGS,'./;'
;
; THIRD-CASE TABLE FOR RECEIVE. USED FOR SPECIAL CHARACTERS.
; THE FIRST COLUMN IN THE TABLE THE ASCII CHARACTER EQUIVALENT.
; THE SECOND COLUMN IS THE SPECIAL CASE BAUDOT CHARACTER
; FROM WHICH THE CONVERSION IS MADE.
;
TTABLE: DB 0,CNTC,LF ; BL 3 LF
DB LARW,ASPC,ATSN ; - SP BEL
DB CNTV,CNTO,CR ; 8 7 CR
DB ALTM,CNTE,PCT ; $ 4 '
DB DEL,EQL,ESCP ; , ! :
DB LETH,CNTH,LBKT ; ( 5 "
DB GRTH,CNTB,STAR ; ) 2 #
DB CNTI,CNTZ,CNTA ; 6 0 1
DB CNTX,UARW,PLUS ; 9 ? &
DB 0,RBKT,RESL ; FIG . /
DB 0 ; ;
;
; FOURTH-CASE TABLE FOR RECEIVE. FOR LOWER-CASE ALPHA CHARS.
;
FTABLE: DB 0,65H,LF,61H,ASPC,73H
DB 69H,75H,CR,64H,72H,6AH
DB 6EH,66H,63H,6BH,74H,7AH
DB 6CH,77H,68H,79H,70H,71H
DB 6FH,62H,67H,FIGS,6DH,78H
DB 76H
;
;
; TABLE FOR SENDING
;
BTABLE: DB 5FH,17H,13H ; NUL SOH STX
DB 1,0,0AH ; ETX EOT ENQ
DB 0,85H,10H ; ACK BEL BS
DB 15H,42H,0C2H ; HT LF VT
DB 2,48H,0 ; FF CR SO
DB 7,0,0 ; SI DLE DC1
DB 0,0,0 ; DC2 DC3 DC4
DB 0,6,0 ; NAK SYN ETB
DB 18H,0,16H ; CAN EM SUB
DB 0EH,0,0 ; ESC FS GS
DB 0,0,44H ; RS US SPACE
DB 8DH,91H,94H ; ! " #
DB 89H,0BH,9AH ; $ PCT &
DB 8BH,8FH,92H ; ' ( )
DB 14H,1AH,8CH ; AS PL ,
DB 83H,9CH,9DH ; - . /
DB 96H,97H,93H ; 0 1 2
DB 81H,8AH,90H ; 3 4 5
DB 95H,87H,86H ; 6 7 8
DB 98H,8EH,9EH ; 9 : ;
DB 0FH,0DH,12H ; LT EQ GT
DB 99H,5,43H ; ? AT A
DB 59H,4EH,49H ; B C D
DB 41H,4DH,5AH ; E F G
DB 54H,46H,4BH ; H I J
DB 4FH,52H,5CH ; K L M
DB 4CH,58H,56H ; N O P
DB 57H,4AH,45H ; Q R S
DB 50H,47H,5EH ; T U V
DB 53H,5DH,55H ; W X Y
DB 51H,11H,1DH ; Z LB LS
DB 1CH,19H,3 ; RB UA LA
;
; THESE ARE THE LOWER CASE ALPHA CHARACTERS
;
DB 0,0C3H,0D9H ; ' a b
DB 0CEH,0C9H,0C1H ; c d e
DB 0CDH,0DAH,0D4H ; f g h
DB 0C6H,0CBH,0CFH ; i j k
DB 0D2H,0DCH,0CCH ; l m n
DB 0D8H,0D6H,0D7H ; o p q
DB 0CAH,0C5H,0D0H ; r s t
DB 0C7H,0DEH,0D3H ; u v w
DB 0DDH,0D5H,0D1H ; x y z
;
;
; Following are baud rates values -- (19200 x 13)/ baud = divisor
;
BD045: DW 5492 ; 60 wpm = 45.45 baud
BD050: DW 4992 ; 66 wpm = 50.00 baud
BD057: DW 4385 ; 75 wpm = 56.92 baud
BD074: DW 3364 ; 100 wpm = 74.20 baud
BD100: DW 2496 ; 132 wpm = 100.00 baud
;
BD110: DW 2272 ; 08E0H
BD300: DW 832 ; 0342H
BD450: DW 554 ; 022AH
BD600: DW 416 ; 01A0H
BD710: DW 351 ; 015FH
BD1200: DW 208 ; 00D0H
BD2400: DW 104 ; 0068H
BD4800: DW 52 ; 0034H
BD9600: DW 26 ; 001AH
BD1920: DW 0 ; 19200 baud
;
;
; TEMPORARY STORAGE AREAS
;
CASAVE: DW LTABLE ; Recv present case reminder
FLAGR: DB 0 ; Recv figs/ltrs last flag
SCASE: DB 40H ; Send present case reg
FLAGM: DB 0 ; Mode flag, initial 0=baudot (1=ascii)
MDRATE: DS 1 ; Modem baud rate flag
;
; DATA AREA
;
MCB: DS 1 ; Rtty control byte
INCH: DB 0 ; Input char buffer, initial 0
OUTCH: DB 0 ; Output char buffer, initial 0
;
OLDSP: DS 2 ; Old stack pointer
STACK: DS 128 ; Local stack
;
IBUF: DS 256
;
; TEXT BUFFER
;
FLAGC: DB 0 ; Text capture flag, initial 0=off
PTR: DS 2 ; Text buffer pointer
SIZE: DS 2 ; Text buffer size
TBUF EQU $ ; Start of text buffer
;
END