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
/
CPM
/
22RSX
/
RXMD.ARK
/
RXMD09.MAC
< prev
next >
Wrap
Text File
|
1985-12-07
|
14KB
|
539 lines
;
; Receive a record - returns with carry bit set if EOT received
;
rcvrecd:
xra a; Clear error count
sta errct
rcvrpt: call funchk; Check function keys
mvi b,10; 10-seconds to get 1st byte
lda frstim
ora a
jnz rcvr1; If started, skip next line
mvi b,3+1; Check every 4 seconds until started
rcvr1: call recv; Get any char received
jc rcvstot; Timeout error if no char received
cpi soh; See if it is SOH
jz rcvsoh; Got SOH, get record
cpi stx; See if it is STX for 1k blocks
jz rcvstx; Got STR, get record
cpi cancel; Was it a CTL-X to abort?
jz ckcan; If yes, check for aborting
ora a; Get another char, if a null
jz rcvrpt
cpi '{'; V.22 synch char, ignore
jz rcvrpt
cpi '{' + 80h; V.22 synch char with high bit set
jz rcvrpt
cpi eot
stc
rz; with carry on end of transmission
cpi crc; Ignore our own char coming back
jz rcvrpt
cpi ksnd; Ignore our own char coming back
jz rcvrpt
cpi nak; Ignore our own char coming back
jz rcvrpt
mvi a,1; Prevents going to modem
sta remoff
call crlf
mov a,b
call hexo
call ilprt
db 'H received not SOH ',0
; " "
; Didn't get SOH or EOT or did not get valid header so purge the line,
; then send NAK.
;
rcvsr: call wait1; Flush incoming
call ckabort; Want to quit now?
lda frstim; Get first time switch
ora a; Has first 'SOH' been received?
mvi a,nak
jnz rcvsr1; Yes, then send 'NAK'
lda crcflg
ora a
mvi a,nak
jz rcvsr1; Not CRC, signal checksum with NAK
mvi a,crc; Else tell sender we have 'CRC'
call send
lda kflg
ora a
jz rcvsr1; not requesting 1k transmissions
mvi a,ksnd; Signal we also have 1k capability
rcvsr1: call send
lda errct
inr a; Increment error count
sta errct
mov b,a; Keep error count for now
lda frstim; Have we gotten under way yet?
ora a
mov a,b; get error count back
jz rcvsr2; Not started yet, exit
cpi 10; 10 errors the limit, once under way
jnc rcvsabt; Abort if over the limit
call rdcount; Display record count before repeating
jmp rcvrpt; Less than 10, keep going
;
rcvsr2: cpi 10; 10 times for 1k/CRC yet? (40 seconds)
jc rcvrpt; Keep trying if less
xra a; Else flip to checksum mode
sta crcflg
mov a,b; Get the count back
cpi 15; Another 5 times for checksum?
jc rcvrpt; If less, try again, quit at 60 seconds
; " "
; Error limit exceeded, so abort
rcvsabt:
xra a
sta remoff; Allow console output to remote
lxi sp,stack; Clear the stack just in case
call closfil; Keep whatever we got
call ilprt
db cr,lf,cr,lf,'++ RECEIVED FILE CANCELLED ++',0
call delfile; Delete received file
call erxit; Print 2nd half of message
db '++ UNFINISHED FILE DELETED ++','$'
;
; Deletes the received file (used if receive aborts)
;
delfile:
mvi a,delet
call fileop; Delete it
inr a
rnz; Success, return
call erxit
db cr,lf,'++ Can''t delete received file ++','$'
;
; Aborts with 1 CTL-X if first time flag is not set, two otherwise
;
ckcan: lda frstim; 1st time flag set yet?
ora a
jz rcvsabt; If not, Abort and close file
mvi b,2; Max 2 seconds for extra CTL-X
call recv
jc rcvrpt; No additional char, ignore CTL-X
cpi cancel; If a 2nd CTL-X, abort and close file
jz rcvsabt
jmp rcvrpt; Else wait for a STX, SOH or timeout
;
; Timed out on receive
;
rcvstot:
lda frstim; 1st time flag set yet?
ora a
jz rcvsr; If not, don't show an error
sta remoff
call ilprt
db '++ Timeout waiting for character ++',cr,lf,0
jmp rcvsr; Bump error count, etc.
;
; Got a STX - set KFLG for 1k
;
rcvstx: sta kflg; Set 1k flag
sta crcflg; Ensure in CRC mode for 1k blocks
jmp rcvs1
;
; Got SOH - get block number, block number complemented
;
rcvsoh: xra a
sta kflg; If SOH, clear the 1k flag
rcvs1: mvi b,5; Timeout = 5 seconds
mov a,b; Get something to store
sta remoff; Error messages only shown locally
sta frstim; Indicate first 'SOH' or 'STX' recvd.
call recv; Get block number
jc rcvstot; timeout
mov d,a; Save block number
mvi b,5; Timeout = 5 seconds
call recv; Get complement of rcd no.
jc rcvstot; Timeout
cma
cmp d; Same as original block number?
jz rcvdata; Yes, get data
; " "
; Got bad record number in header
call ilprt
db '++ Error in header ++',cr,lf,0
jmp rcvsr; Go check error limit and send NAK
;
rcvdata:
mov a,d
sta rcvcnt; get and save record num.
mvi c,0; Init checksum
lxi h,0; Init CRC
shld crcval; Clear CRC counter
call grcdsz; 128/1024 on kflg
lhld recptr; Get buffer address
; " "
rcvchr: mvi b,5; 5 sec timeout
call recv; Get the character
jc rcvstot; Timeout
mov m,a; Store char
inx h; Point to next char
dcx d; One less to go
mov a,d
ora e
jnz rcvchr; Not done, get next char
lda crcflg; Using 'CRC'?
ora a
jnz rcvcrc; If yes go get 'CRC'
; " "
; Verify checksum
mov d,c; Save checksum
mvi b,5; Timeout length
call recv; Get checksum
jc rcvstot; Timeout
cmp d; Checksum ok?
jz chksnum; Yes, exit
call ilprt
db '++ Checksum error ++',cr,lf,0
jmp rcvsr; Go check the error limit and send NAK
;
; Got a record, it's a duplicate if equal to the previous number,
; it's OK if previous + 1 record
chksnum:
lda rcvcnt; Get received record number
mov b,a
lda rcdcnt; previous record number
cmp b; Previous record repeated?
jz rcvack; If yes 'ACK' to catch up
inr a; Increment by 1 for 128 char block
cmp b; Match this one we just got?
jnz abort; No match, stop the sender, exit
ret; Else return with carry not set, was ok
;
; Receive the Cyclic Redundancy Check characters (2 bytes) and see if
; the CRC received matches the one calculated. If they match, get next
; record, else send a NAK requesting the record be sent again.
;
rcvcrc: mvi e,2; Number of bytes to receive
rcvcrc2:
mvi b,5; 5 second timeout
call recv; Get CRC byte
jc rcvstot; Timeout
dcr e; Decrement the number of bytes
jnz rcvcrc2; Get both bytes
call crcchk; Check received CRC against calc'd CRC
ora a
jz chksnum; CRC ok, go check record numbers
call ilprt
db '++ CRC error ++',cr,lf,0
jmp rcvsr; Go check error limit and send NAK
;
; Previous record repeated, due to the last ACK being garbaged.
; ACK it so sender will catch up
rcvack: call sndack
jmp rcvrecd
;
; Send an ACK for the record
;
sndack: mvi a,ack
jmp send
;
; ---------------------------------
;
; Send the record header
; Send SOH, block number and complemented block number (3 bytes total)
;
sndhdr: lda kflg; Sending 1k blocks?
ora a
mvi a,stx; If yes, send a STX rather than SOH
jnz sndhd1
mvi a,soh; Send start of header
sndhd1: call send
sndhnm: lda rcdcnt; Send the current record number
call send
lda rcdcnt; Get the record number again
cma; Complemented
jmp send
;
; Send the data record
;
sndrec: mvi c,0; Init checksum
lxi h,0; Init CRC
shld crcval
call grcdsz; 128/1024 on kflg
lhld recptr; Get buffer address
sendc: mov a,m; Get a char
call send; Send it
inx h; next char
dcx d
mov a,e
ora d
jnz sendc; More
ret
;
; Send the CRC or checksum value, whichever appropriate
;
sndchk: lda crcflg; See if sending 'CRC' or 'checksum'
ora a
mov a,c; checksum value
jz send; If chksum send it
; " "
; Send the two Cyclic Redundancy Check characters. Call FINCRC to
; calculate the CRC which will be in 'DE' upon return.
;
sndcrc: call fincrc; Calculate the 'CRC' for this record
mov a,d; Put first 'CRC' byte in accumulator
call send; Send it
mov a,e; Put second 'CRC' byte in accumulator
call send; Send it
xra a; Set zero return code
ret
;
; After a record has been sent, and accepted, move the pointers
; forward 128 or 1024 characters for the next record.
;
setptr: call grcdsz; 128/1024 on kflg
lhld recptr; Get the buffer pointer
dad d; Increment for the record just sent
shld recptr; New buffer address for next block
ret
;
; Get current protocol record size (128 or 1024, on KFLG)
; a,f,d,e
grcdsz: lxi d,128
lda kflg
ora a
rz
lxi d,1024
ret
;
; After a library transmission has been made, decrement the remaining
; records in that library file, then reset the 1k flag if less than 8
; remaining.
;
setlbr: lda kflg
lxi d,-1
ora a
jz setl1
lxi d,-8
setl1: lhld rcnt; Alter the records-sent count
dad d
shld rcnt; One less transmission to go
ora a; 'K' flag already zero?
rz; If yes, skip the rest
; " "
; See if enough records left to use 1k protocol if requested
;
setflg: lhld rcnt
mov a,h
ora a
rnz; 256 or more left
mov a,l; Get number of records in 'L' register
cpi 8
rnc; If 8 or more, keep going
xra a; Reset the 'K' flag
sta kflg
ret
;
; After a record is sent, a character is returned telling if it was
; received properly or not. An ACK allows the next record to be sent.
; A NAK causes the current record to be resent. If no character (or
; any character other than ACK or NAK) is received after a short wait
; (10 to 12 seconds), a timeout error message is shown and the record
; will be resent.
;
gtack: call mdinst
jz gtack1; No char ready now
call mdinp; Get the char
cpi ack
rz; ACK, return
cpi nak
jz gtack2; NAK, print error, then resend
cpi cancel; CTL-X to cancel attempt?
jz gtcan
gtack1: mvi b,1; 1 second for an ACK or NAK
call recv; Go wait for a char
jc gtack2; timed out
cpi ack
rz; ACK, return
cpi nak
jz gtack3; NAK, error
cpi cancel; CTL-X to cancel attempt?
jz gtcan
gtack2: mvi b,12; 12-seconds more for an ACK or NAK
call recv; Go wait for a char
jc gtatot; timeout
cpi ack
rz; ACK, return
cpi '{'
jz gtack2; ignore V.22 sync char
cpi '{' + 080h
jz gtack2; ignore V.22 sync char w/hi bit
cpi cancel; CTL-X to cancel attempt?
jnz gtack3
; " "
; Two or more CTL-X will cancel the file transfer
gtcan: mvi b,2; Up to 2 secs. for another CTL-X
call recv
mvi a,cancel; Get original char back
jc gtack3; If no more CTL-X, display the first
cpi cancel; Was it a second one?
jz ackmsg; If yes, abort the file transfer
gtack3: mov b,a; Save the char
sta remoff; Send to console only
lda chkeot; Sending EOT?
ora a
jnz ackerr; If yes, don't show error (for KMD)
call ilprt
db '++ ',0
mov a,b
cpi nak
jz gtack4
call hexo
call ilprt
db 'H',0
jmp gtack5
;
gtack4: call ilprt
db 'NAK',0
; " "
gtack5: call ilprt
db ' received not ACK ++',cr,lf,0
; " "
; Timeout or error on ACK - bump error count then resend the record
; if error limit is not exceeded
;
ackerr: lda accerr; Count accumulated errors on ACK
inr a
sta accerr
lda errct
inr a; Bump error count
sta errct
cpi 10
jnc ackmsg; At limit, send error msg and abort
call rdcount; Else show the record count for repeat
stc; Make sure carry is set for repeat
ret; And go back
;
;
; Reached error limit
;
ackmsg: call wait1; Flush input
call send3can; Tell remote we are quitting
mvi b,1; Wait for remote to perhaps quit too
call recv
mvi a,bs
call send3x; Clear any CTL-X from buffer
xra a
sta remoff; Show message on remote and local
call erxit
db cr,lf,'++ FILE TRANSFER ABORTED ++','$'
;
;
; Timed out, with no character - set the carry bit and return
;
gtatot: call ilprt
db '++ Timeout - no character received ++',cr,lf,0
jmp ackerr
;
; Check the total error count vs. records sent, switch from 1k to 128
; character transmissions if higher than operator selected value.
;
gtratio:
lda kflg
ora a
rz; Not 1k blocks, skip this
lda errct; See if we got any errors last record
cpi 4
jnc gtratio1; If 4 or more, switch to 128 size
lda accerr; See if up to minimum errors yet
cpi 3; Had as many as three errors yet?
rc; If not, don't get excited too quickly
lhld recdno; Get current record number increment
lxi d,-8; Have not successfully sent this 1k yet
dad d; Subtract the current increment
xchg
lhld accerr; Number of non-'ACK' errors in HL
xchg
call dvhlde; Get ratio in BC of records/hit
call mspeed; get current speed
cpi 5; 1200 baud?
mvi a,71-1; for 1200 bps
jz gtr1; If 1200, skip next line
mvi a,43-1; for 2400 bps
gtr1: cmp c; Compare with actual ratio
rc; return if less hits than allowed
; " "
gtratio1:
xra a; Else reset the system to 128
sta kflg
call ilprt
db cr,lf,'Aborting 1k blocks, too many hits',cr,lf,0
ret
;
ckabort:
call constat
ora a
rz
call conin
cpi cancel
rnz
; " "
; Aborts send or receive routines and returns to command line
;
abort: lxi sp,stack
call wait1; 1- sec delay to clear input
call send3can; Show cancelling, remote may quit also
call wait1; 1-second delay to clear input
mvi a,bs
call send3x
abortx: xra a; Reset the batch flag
sta bchflg
call catch
call erxit; Exit with abort message
db cr,lf,'++ RXMD ABORTED ++','$'
;
; Send 3 cancels
send3can:
mvi a,cancel
; " "
; Send 3 copies of (a)
send3x: call send
call send
jmp send
;
; Increment record number
; a,f
incrno: push h
push d
lhld rcdcnt; Incr transmission count
inx h
shld rcdcnt
lxi d,1
lda kflg
ora a
jz incrn1; not 1k blocks, incr by 1
mvi e,8; If 1k blocks incr. by 8
incrn1: lhld recdno; Get current record count
dad d; Increment that count properly
shld recdno
call rdcount
pop d
pop h
ret
;
; Display the record count on the local CRT
; a,f,h,l
rdcount:
lhld recdno; Get the record number for display
mvi a,1
sta remoff; Set local only
lda optsav; See if receive or send mode
cpi 'R'
jz rmsg
call ilprt
db cr,'Sending # ',0
jmp rest
rmsg: call ilprt
db cr,'Received # ',0
rest: lhld recdno
call decout
call ilprt
db ' (',0
call t4hex
call ilprt
db 'h) ',0
jmp funchk; Check for function keys
%