home *** CD-ROM | disk | FTP | other *** search
-
- TITLE 'PACKET TRANSMISSION / RECEPTION PROGRAM'
- ; 11-8-80
- ; LAST MODIFIED 4-12-81
- ;
- ;WRITTEN BY DALE A. HEATHERINGTON, WA4DSY
- ; 3126 FLAMINGO DR.
- ; DECATUR, GA 30033
- ; tel: 404-292-1499
- ;
- ;***************************************************************
- ;This program has not been perfected and probably has a few bugs
- ;in it. It is for the 2.2 version of CP/M only. At this time
- ;(4-19-81) it has been used by only 2 stations in the Atlanta Ga.
- ;area so I have no idea what will happen when several stations
- ;get into a "pile up" . The program could become confused. There
- ;are several fields in the packet which have no function now and
- ;may be changed later. There are some packet types which have not
- ;been implemented ie: FS (file seperator). Also beware of comments
- ;;which don't match the code.....
-
- ;Consider this version (1.8) to be in PUBLIC DOMAIN for non-commercial
- ;use and distribution. This might not be true for future versions.
-
- ;********************************************************************
- ;THIS PROGRAM MUST BE ASSEMBLED WITH THE
- ;CP/M RELOACATING MACRO ASSEMBLER (RMAC) AND THE
- ;MACRO LIBRARY "SEQIO.LIB" MUST BE AVALABLE.
- ;NOTE: SEQIO.LIB WILL NOT WORK WITH RMAC UNLESS
- ;MODIFICATIONS ARE MADE.
-
- MACLIB SEQIO2 ;MODIFIED SEQIO.LIB
-
- VERSION EQU '1'
- PTVER EQU '8' ;VERSION 1.8
-
-
- ON EQU 1
- OFF EQU 0
- ;
- ;--------------------------------------------------------;
- ;
- ; PACKET LAYOUT
- ;
- ; BYTE # BYTES DESCRIPTION
- ; 1 4 LEADER FF,7FH,1FH,7
- ; 5 1 SOH START OF HEADER
- ; 6 2 TOTAL LENGTH OF MESSAGE (STARTING AT CRC)
- ; 8 2 CRC BYTES (LOW BYTE FIRST)
- ; 10 6 DESTINATION CALL SIGN
- ; 16 1 DESTINATION PHYSICAL LOCATION CODE
- ; 17 1 DESTINATION REPEATER # (0 = DIRECT)
- ; 18 6 SOURCE CALL SIGN
- ; 24 1 SOURCE PHYSICAL LOCATION CODE
- ; 25 1 SOURCE REPEATER # (0= DIRECT)
- ; 26 1 PACKET TYPE (ENQ,ACK,NAK,FS,DTA,FRQ,EOT)
- ; 27 12 PACKET NAME (CP/M FILE NAME)
- ; 39 2 PACKET NUMBER ( 0..65535 )
- ; 41 0..1024 DATA BYTES
- ;
- ;NOTES: CRC IS CRC-16 REVERSE X^16+X^14+X+1 (SAME AS CLINK 3.0)
- ;
- ; THE PACKET NAME CONFORMS TO CP/M FILE CONTROL BLOCK FORMAT
- ; THE FIRST CHARACTER IS THE DRIVE INDICATOR (0=DEFAULT DRIVE)
- ; THE NEXT 8 ARE THE FILE NAME PADDED WITH TRAILING BLANKS.
- ; THE LAST 3 ARE THE FILE TYPE
- ;
- ; ALL PACKETS TYPES EXCEPT DATA HAVE A PACKET NUMBER OF ZERO.
- ; DATA PACKETS START WITH PACKET NUMBER 1 AND ARE TRANSMITTED
- ; IN SEQUENCE.
- ;
- ; FOUR RETRYS ARE ALLOWED IF PACKETS ARE "NAK'ED"
- ;
- ; PACKET TYPES
- ;
- ; ENQ REQUEST TO ESTABLISH COMMUNICATION AND SEND A FILE
- ; FRQ REQUEST A FILE
- ; FNF FILE NOT FOUND
- ; DTA PACKET CONTAINS DATA
- ; EOT END OF TRANSMISSION
- ; FS FILE SEPERATOR
- ; ACK ACKNOWLEDGE RECEIVING PACKET
- ; NAK DID NOT RECEIVE PACKET
- ; NAV RECEIVED ENQ BUT NOT AVALABLE TO RECV. DATA
- ;
- ;---------------------------------------------------------------------;
-
-
-
- SYN EQU 255
- DTA EQU 0
- SOH EQU 1
-
- FRQ EQU 3
- EOT EQU 4
- ENQ EQU 5
- ACK EQU 6
- FNF EQU 7
- NAV EQU 8
- NAK EQU 15H
- FS EQU 1CH
-
-
- NULL EQU 0
- CR EQU 0DH
- LF EQU 0AH
- BDOS EQU 5
- FCB EQU 5CH
- CPMBOOT EQU 0
-
- CRCPLY EQU 8005H
- HDRLEN SET TDATA-TCRC ;HEADER LENGTH
- ; CRC TO DATA
-
- ;ENTRY LOCATIONS IN THIS MODULE
-
- PUBLIC RECVIT
- PUBLIC SENDIT
-
- ;EXTERNAL ENTRY LOCATIONS
- EXTRN CPUCLK ;CPU CLOCK RATE IN MHZ
- EXTRN INITX ;INITIALIZE FOR XMITTING
- EXTRN INIRX ;INITIALIZE FOR RECEIVING
- EXTRN SENDCHR ;SEND A BYTE (IN REG. C )
- EXTRN RECVCHR ;GET A BYTE (IN REG. A)
- EXTRN RXSTAT ;RETURN NON ZERO IF BYTE READY
- EXTRN RFON ;KEY TRANSMITTER
- EXTRN RFOFF ;UNKEY TRANSMITTER
- EXTRN CKCD ;RETURN NON ZERO IF CARRIER
- EXTRN TONEON ;AUDIO SUBCARRIER ON
- EXTRN TONEOFF ;AUDIO SUBCARRIER OFF
- EXTRN WAIT1 ;WAIT 1 MILLISECOND
- EXTRN MYCALL ;USERS CALL SIGN
- EXTRN MYLOC ;USERS LOCATION CODE
- EXTRN QUIT ;PATH BACK TO CP/M
-
- ;--------------------------------------------------------
- ;HERE ARE SOME STRING CONSTANTS
-
- WHO$R$U: DB '????????????' ;12 QUESTION MARKS
-
- NOFN: DB 0,' ' ;0+11 BLANKS (A BLANK FILE NAME)
-
- DIRFILE:DB 0,'DIR ' ;SPECIAL CASE FOR DIRECTORY
-
- SYNCS: DB 0FFH,07FH,01FH,7,SOH ;PREAMBLE FOR PACKETS
-
- ;----------------------------------------------------------
- ;CODE STARTS HERE
-
- INIBUFFR: ;INITIALIZE TX BUFFER LEADER
- LXI H,SYNCS
- LXI D,TBUFFR
- MVI B,5
- CALL MOVE
- RET
-
- CLEARBUF: ;CLEARS RECEIVE BUFFER HEADER
- MVI B,RDATA-RBUFFR ;LENGTH OF HEADER
- LXI H,RBUFFR ;RECEIVE HEADER
- LXI D,RBUFFR+1
- JMP MOVE ;CLEAR RECEIVE HEADER
-
-
- ;THIS IS THE FILE TRANSMITTING ROUTINE
-
-
- SENDIT: MVI A,0
- STA ID$INH ;DONT INHIBIT NEXT CW ID
- SENDIT2:CALL INIBUFFR
- LXI H,MYCALL
- MVI B,6
- CALL PRNMEM ;PRINT OUR CALL SIGN
- CALL PRINT
- DB ' PACKET TRANSMISSION PROGRAM VER. ',VERSION,'.',PTVER,CR
- CALL PRINT
- DB 'CPU CLOCK(MHZ) = @'
- LDA CPUCLK
- ADI 30H
- MOV C,A
- CALL CONOUT ;PRINT CPU CLOCK CONSTANT
- CALL CRLF
- LXI H,HDRLEN ;GET LENGTH OF ENQ PACKET
- SHLD TLEN ;PUT IT IN BUFFER
- MVI A,ENQ
- STA TPTYPE ;PUT PACKET TYPE IN BUFFER
- LXI H,FCB+17 ;GET DESTINATION CALL SIGN
- LXI D,TDSTCAL
- MVI B,6
- CALL MOVE
- MVI A,4 ;GET LOCATION CODE
- STA TDSTLOC
- MVI A,0 ;NON REPEATER
- STA TDSTRPT
- LXI H,MYCALL ;GET OUR CALL SIGN
- LXI D,TSRCCAL
- MVI B,6
- CALL MOVE ;PUT IT IN XMIT BUFFER
- LDA MYLOC ;GET OUR LOCATION CODE
- STA TSRCLOC ;PUT IT IN BUFFER
- MVI A,0
- STA TSRCRPT ;REPEATER # IS ZERO
-
- LXI H,FCB ;GET FILE NAME
- LXI D,TTITLE
- MVI B,12
- CALL MOVE ;PUT IT IN BUFFER
- SUB A
- STA TTITLE ;DESTINATE IT TO DEFAULT DRIVE
- LXI H,0
- SHLD TPACNUM ;ZERO THE PACKET NUMBER
-
- LXI H,TTITLE+1 ;SEE IF DIRECTORY REQUEST "DIR"
- LXI D,DIRFILE+1
- MVI B,11
- CALL COMPARE$
- JNZ REALFILE ;JUMP IF NOT DIRECTORY REQUEST
- MVI A,255
- STA DIRFLAG ;SET DIRECTORY FLAG
- CALL OPEN$DIR ;SET UP DIRECTORY ROUTINE
- JMP FIRSTID ;START SENDING
-
-
-
- REALFILE:
- MVI A,0
- STA DIRFLAG ;CLEAR DIRECTORY FLAG
-
- FILE SETFILE,CHECK,,1,,
- DIRECT CHECK ;SEE IF THE FILE IS THERE
-
- JNZ GOTIT ;JUMP IF WE FOUND IT
- CALL PRINT
- DB 'FILE NOT FOUND',CR
- MVI A,1 ;RETURN A=1 IF NOT FOUND
- ORA A
- RET
-
- GOTIT: FILE INFILE,SOURCE,,1,,1024,INBUFFER
-
- FIRSTID:
- CALL CWID ;ID IN (YUK) MORSE CODE FOR FCC
- CALL SENDPAC ;SEND THE BUFFER CONTENTS (ENQ PACKET)
- JZ OK2SEND
- CALL NORPLY ;SAY HE'S NOT HOME
- RET ;QUIT
-
- OK2SEND:LXI H,1 ;SET PACKET NUMBER TO 1
- SHLD TPACNUM
- TXLP:
- LXI H,1024 ;MAX DATA LENGTH
- SHLD DATACNT
- LXI H,TDATA ;POINTER TO XMIT DATA BUFFER
- SHLD DATAPTR
- LXI H,HDRLEN ;RESET LENGTH FIELD
- SHLD TLEN
-
- FILBUF:
- LDA DIRFLAG
- ORA A ;DIRECTORY OR FILE??
- JZ FLB1 ;JMP IF FILE
- ;ELSE...
- CALL GETABYTE ;GET A BYTE FROM DIRECTORY
- JMP FLB2
-
- FLB1: GET SOURCE ;GET A BYTE FROM SOURCE FILE
-
- FLB2: JZ DONE
- LHLD DATAPTR
- MOV M,A ;PUT IT IN BUFFER
- INX H ;ADVANCE POINTER
- SHLD DATAPTR ;SAVE IT
- LHLD TLEN
- INX H ;ADVANCE LENGTH FIELD
- SHLD TLEN
- LHLD DATACNT
- DCX H
- SHLD DATACNT
- MOV A,L
- ORA H ;SEE IF WE DID 1024 BYTES
- JNZ FILBUF
- MVI A,DTA
- STA TPTYPE ;PACKET TYPE IS DATA
- CALL SENDPAC ;NOW TRANSMIT THE PACKET
- JNZ ERRR
- LHLD TPACNUM
- INX H
- SHLD TPACNUM ;COUNT THE PACKET
- MOV A,L
- DCR A
- ANI 7 ;ID IN CW EVERY 8TH PACKET
- CZ CWID
- JMP TXLP ;GO BACK TO DO ANOTHER PACKET
-
- DONE:
- LHLD TLEN ;SEE IF LENGTH IS ZERO
- LXI D,-HDRLEN
- DAD D
- MOV A,L
- ORA H
- JZ SNDEOT ;IF ZERO LENGTH JUST DO EOT
-
- MVI A,DTA ;ELSE SEND SHORT DATA PACKET
- STA TPTYPE
- CALL SENDPAC
- JNZ ERRR ;QUIT IF BAD OR NO RESPONSE
-
- SNDEOT: MVI A,EOT
- SND2: STA TPTYPE
- LXI H,HDRLEN ;
- SHLD TLEN ;SET LENGTH
- LXI H,0 ;CONTROL PACKETS HAVE NUMBER 0
- SHLD TPACNUM
- CALL SENDPAC ;SEND LAST PACKET
- PUSH PSW
- CALL CWID ;LET FCC KNOW WHO WE ARE
- POP PSW
- JNZ ERRR
- CALL PRINT
- DB 'ALL PACKETS SENT',CR
- XRA A ;RETURN ZERO IF OK
- RET
-
-
- ERRR: CALL PRINT
- DB 'TRANSMISSION ABORTED',7,CR
- MVI A,255
- ORA A
- RET ;RETURN NON ZERO IF ERROR
-
-
-
- ;THIS IS THE FILE REQUEST ROUTINE
- ;COME HERE IF PACKET IS REQUESTING A FILE FROM US.
- ;
- FLREQ: CALL CWID ;ID IN CRUDE MORSE CODE
- MVI A,ACK
- STA TPTYPE
- CALL SENDAPAC ;ACK HIS FILE REQUEST
- LXI H,RSRCCAL ;GET HIS CALL SIGN
- LXI D,FCB+17
- MVI B,6
- CALL MOVE ;MOVE IT TO FCB
- MVI A,1
- STA ID$INH ;INHIBIT NEXT CW ID
- CALL SENDIT2 ;SEND THE FILE IF WE HAVE IT
- RZ ;QUIT NOW IF FILE WAS SENT
- CPI 1 ;SEE IF THE FILE WAS NOT IN DIR
- RNZ ;RETURN IF JUST BAD SIGNALS
- MVI A,FNF ;ELSE SEND FILE NOT FOUND PACKET
- STA TPTYPE
- LXI H,HDRLEN
- SHLD TLEN ;INIT HEADER LENGTH
- LXI H,0
- SHLD TPACNUM ;SET PACKET NUMBER TO ZERO
- CALL SENDAPAC ;SEND THE FNF PACKET
- CALL CWID
- XRA A
- RET ;ALL DONE
-
-
-
-
- ;THIS SENDS A FILE REQUEST PACKET TO THE OTHER GUY IF
- ;WE WANTED TO GET A FILE FROM HIM.
- ;
- SENDFRQ:
- LXI H,HDRLEN
- SHLD TLEN
- MVI A,FRQ
- STA TPTYPE
- LXI H,MYCALL
- LXI D,TSRCCAL
- MVI B,6 ;SET UP SOURCE CALL
- CALL MOVE
- LXI H,FCB+17 ;GET DESTINATION CALL
- LXI D,TDSTCAL
- MVI B,6
- CALL MOVE
- MVI A,0
- STA TSRCRPT
- MVI A,14H ;DEST. LOCATION CODE
- STA TDSTLOC
- LDA MYLOC
- STA TSRCLOC
- LXI H,FCB
- LXI D,TTITLE ;GET FILE NAME
- MVI B,12
- CALL MOVE
- LXI H,0
- SHLD TPACNUM ;CLEAR PACKET NUMBER
- CALL CWID
- CALL SENDPAC ;SEND FRQ PACKET AND GET REPLY
- RET ;RETURN ZERO WITH PACKET TYPE IN ACC
-
- ;-------------------------------------------------------------------
-
- ; TITLE 'DIRECTORY LISTER'
- ;THIS IS A SELF CONTAINED SUBROUTINE WHICH WILL
- ;RETURN THE CP/M DIRECTORY A BYTE AT A TIME BY
- ;CALLING "GETABYTE".
- ;THE ZERO FLAG WILL BE SET AFTER THE LAST BYTE
- ;IS RETURNED.
- ;THE SUBROUTINE MUST BE INITIALIZED BY
- ;CALLING "OPEN$DIR" FIRST.
-
- SETDMA EQU 26
- SEARCH EQU 17
- SEARCH$NEXT EQU 18
- GET$ALLOC EQU 27
- GET$DPBLK EQU 31
-
-
-
- DIRFCB: DB 0 ;DR
- DB '???????????',0
- DS 20
- PWR10: DW -1000
- DW -100
- DW -10
- DW -1
-
- DSEG ;DATA SEGMENT
-
- N1: DS 0
- SWITCH: DS 1
- KLEFT: DS 2 ;K BYTES LEFT ON DISK
- ENCNT: DS 1
- COUNTER:DS 1
- DPBADR: DS 2 ;ADDRESS OF DISK PARAMETER BLOCK
- POINTER:DS 2
- ENTBUF: DS 16 ;BUFFER FOR 1 DIR. ENTRY
-
- BUFFER: DS 128
-
- ;-------------------------------------------------------------
- CSEG ;CODE SEGMENT
-
-
-
- ;RETURNS HL POINTING TO NEXT DIRECTORY ENTRY
-
- ;A=ZERO IF OK OR 255 IF NO MORE ENTRYS
-
- GET$ENTRY:
- LDA SWITCH
- ORA A
- JZ SNXT ;DO SEARCH NEXT IF ZERO
- MVI C,SETDMA
- LXI D,BUFFER
- CALL BDOS ;SET UP DIRECTORY BUFFER
- LXI D,DIRFCB
- MVI C,SEARCH ;SEARCH FOR FIRST ENTRY
- CALL BDOS
- JMP GE2
-
- SNXT: LXI D,DIRFCB
- MVI C,SEARCH$NEXT
- CALL BDOS ;SEARCH FOR NEXT ENTRY
-
- GE2: CPI 255 ;DONE?
- RZ
- ADD A ;MPY BY 32
- ADD A
- ADD A
- ADD A
- ADD A
- MOV E,A
- MVI D,0
- LXI H,BUFFER
- DAD D
- XRA A
- STA SWITCH ;CLEAR THE SWITCH
- RET ;A=0 HL->ENTRY
-
- ;-------------------------------------------------------------
-
- OPEN$DIR: ;INITIALIZE DIRECTORY LISTER
- MVI A,255
- STA SWITCH
- MVI A,4 ;INIT ENTRY COUNTER
- STA ENCNT
- MVI A,1
- STA COUNTER
- LXI H,ENTBUF
- SHLD POINTER
-
- ;AT NO EXTRA CHARGE WE NOW GIVE YOU THE NUMBER OF K BYTES
- ;LEFT ON THE DISK... RETURNED IN HL
-
- MVI C,GET$DPBLK ;GET DISK PRAM. BLOCK ADDRESS
- CALL BDOS
- SHLD DPBADR ;SAVE IT
- LXI D,5
- DAD D ;POINT TO DISK CAPACITY
- MOV E,M ;GET IT
- INX H
- MOV D,M
- PUSH D ;SAVE IT
- MVI C,GET$ALLOC
- CALL BDOS ;GET ADDRESS OF ALLOCATION MAP
- POP B
- PUSH B ;GET AND SAVE DISK CAPACITY
- LXI D,0 ; BLOCK COUNTER
- CNTK: MOV A,M ;GET 8 ALLOCATION UNIT BITS
- PUSH H ;SAVE POINTER
- MVI L,8
- MOV H,A ;BITS OF ALLOCATION TO H
- CBITS: MOV A,H
- ADD A ;SHIFT OVER A BIT
- MOV H,A
- JNC ZEROB
- INX D ;COUNT THE ONE'S
- ZEROB: DCX B ;COUNT A BLOCK
- MOV A,C
- ORA B
- JZ NOMORE
- DCR L ;COUNT BITS
- JNZ CBITS ;LOOP 8 TIMES
- POP H ;GET POINTER BACK
- INX H
- JMP CNTK ;LOOP
-
- NOMORE: POP H
- MOV A,E ;TWOS COMPLIMENT BLOCKS USED
- CMA
- MOV E,A
- MOV A,D
- CMA
- MOV D,A
- INX D
- POP H ;GET MAX DISK CAPACITY
- DAD D ;ADD THE -KBYTES USED
- INX H ;CORRECTION
- PUSH H ;PUSH BLOCKS USED ON STACK
- LHLD DPBADR ;GET ADDRESS OF DISK PARAMETER BLOCK
- LXI D,2
- DAD D ;POINT TO BLOCK SHIFT FACTOR
- MOV A,M ;GET IT
- SUI 3 ;REMOVE BIAS
- POP H ;GET BLOCKS LEFT
- KLOOP: ORA A ;TEST FOR ZERO
- JZ KDONE
- DAD H ;SHIFT HL
- DCR A
- JMP KLOOP
- KDONE: SHLD KLEFT ;SAVE THE NUMBER
- RET
-
- ;-------------------------------------------------------------
-
- GETABYTE: ;GET 1 CHARACTER OF DIRECTORY
-
- LXI H,COUNTER
- DCR M
- JZ ANOTHER
- LHLD POINTER
- MOV A,M
- INX H
- SHLD POINTER
- ORA A ;RETURN NON ZERO IF NOT DONE
- RET
-
- ANOTHER:
- LXI H,ENTBUF ;CLEAR ENTRY BUFFER POINTER
- SHLD POINTER
- CALL GET$ENTRY
- CPI 255
- JZ PUTK ;DONE, SAY HOW MANY BYTES LEFT NOW
- MVI B,8
- LXI D,ENTBUF
- AN1: INX H
- MOV A,M ;MOVE FILE NAME TO BUFFER
- STAX D
- INX D
- DCR B
- JNZ AN1
- MVI A,' '
- MVI B,4
- AN2: STAX D
- INX D
- INX H
- MOV A,M
- DCR B
- JNZ AN2
- XCHG
- LDA ENCNT ;GET ENTRY COUNT
- DCR A
- JNZ AN3 ;END OF LINE IF ZERO
- CALL EOL
- JMP GETABYTE
- AN3: STA ENCNT
- MVI M,' ' ;ELSE PUT UP FENCE
- INX H
- MVI M,':'
- INX H
- MVI M,' '
- MVI A,16
- STA COUNTER
- JMP GETABYTE
-
- EOL: MVI M,0DH
- INX H
- MVI M,0AH
- INX H
- MVI A,15
- STA COUNTER
- MVI A,4
- STA ENCNT
- RET
-
-
- PUTK:
- LXI H,ENTBUF ;PUTS "XXXX K LEFT" IN BUFF
- CALL EOL
- SHLD POINTER
- LHLD KLEFT
- CALL DECONV ;CONVERT K TO DECIMAL & PUT IN BUFFER
- LHLD POINTER
- LXI D,KMSG
- MVI B,11
- PKLP: LDAX D ;PUT IN " K LEFT <CR> <LF>"
- MOV M,A
- INX D
- INX H
- DCR B
- JNZ PKLP
- LXI H,ENTBUF
- SHLD POINTER
- MVI A,17
- STA COUNTER
- JMP GETABYTE
-
- KMSG: DB ' K LEFT',0DH,0AH,0
-
-
-
- ;--------------------------------------------------------------
- ;CONVERT NUMBER IN HL TO DECIMAL STRING AND PUT IN BUFFER
- ;USING "POINTER"
-
- DECONV:
- SHLD N1
- LXI H,PWR10
- DECV0: MOV E,M
- INX H
- MOV D,M ;GET POWER OF 10
- INX H
- PUSH H
- LHLD N1
- MVI C,'0'
- DECV1: DAD D ;SUB POWER OF 10 FROM N1
- JNC DECV2
- INR C
- JMP DECV1 ;LOOP TIL IT GOES NEG.
- DECV2: MOV A,E
- CMA
- MOV E,A ;TWOS COMPLIMENT
- MOV A,D
- CMA
- MOV D,A
- INX D
- DAD D ;RESTORE TO +
- SHLD N1
- LHLD POINTER
- MOV M,C ;OUTPUT DIGIT TO BUFFER
- INX H
- SHLD POINTER
- POP H
- MVI A,1
- CMP E ;DONE YET?
- JNZ DECV0
- RET
-
-
-
- ;END OF DIRECTORY LISTER
-
-
- ;--------------------------------------------------------------------
- ;
- ;THIS IS THE FILE RECEIVE ROUTINE
- ;
- ;
- RECVIT:
- MVI A,0
- STA ID$INH ;DONT INHIBIT NEXT CW ID
- CALL INIBUFFR
- LXI H,MYCALL
- MVI B,6
- CALL PRNMEM ;PRINT OUR CALL SIGN
- CALL PRINT
- DB ' PACKET RECEPTION PROGRAM VER. ',VERSION,'.',PTVER,CR
- CALL PRINT
- DB 'CPU CLOCK(MHZ)= @'
- LDA CPUCLK
- ADI 30H
- MOV C,A
- CALL CONOUT
- CALL CRLF
- LDA 80H ;SEE IF FILE NAME WAS ENTERED
- ORA A
- JZ RCV0 ;JUMP IF NORMAL RECEIVE
-
- CALL SENDFRQ ;DO FILE REQUEST IF LENGTH NON ZERO
- RNZ ;RETURN IF BAD
- CPI ACK ;SEE IF HE HAD THE FILE
- RNZ ;RETURN AND QUIT IF NOT
- MVI A,1
- STA ID$INH ;ALL OK, INHIBIT NEXT CW ID
-
- RCV0: LXI H,HDRLEN ;INIT THE TRANSMIT HEADER
- SHLD TLEN
- MVI A,ACK
- STA TPTYPE ;BE OPTIMISTIC
-
- LXI H,MYCALL
- LXI D,TSRCCAL ;PUT IN OUR CALL
- MVI B,6
- CALL MOVE
-
- LDA MYLOC ;GET LOCATION CODE
- STA TSRCLOC
- MVI A,0
- STA TSRCRPT ;WE ARE NOT A REPEATER (YET)
- STA TDSTLOC ;CLEAR THE DEST. LOC. CODE
-
- LXI H,WHO$R$U ;INIT. THE DEST. CALL WITH ??????
- LXI D,TDSTCAL
- MVI B,6
- CALL MOVE
-
- LXI H,NOFN ;CLEAR THE FILE NAME FIELD
- LXI D,TTITLE
- MVI B,12
- CALL MOVE
-
- CALL PRINT
- DB 'WAITING FOR ENQ PACKET',CR
-
- LXI H,0
- SHLD 80H ;CLEAR CP/M DEFAULT BUFFER
- SHLD TPACNUM ;CLEAR PACKET NUMBER
- LXI D,0 ;ZERO TELLS IT TO WAIT FOREVER
- CALL RECVPAC ;GET A PACKET
- JNZ RECVIT ;JUMP IF BAD
- CPI FRQ ;REQUEST FOR FILE?
- JZ RCV1 ;YES, THEN JUMP
- CPI ENQ
- JNZ RECVIT ;JUMP IF NOT ENQ
- RCV1: LXI H,RSRCCAL ;POINT TO SOURCE CALL SIGN
- LXI D,TDSTCAL ;MOVE IT TO DESTINATION
- MVI B,6
- CALL MOVE
- CALL CKCALL ;SEE IF PACKET IS FOR US
- JNZ RECVIT ;NO, GO BACK
-
- LXI H,RTITLE ;GET FILE NAME TO FCB
- LXI D,FCB
- MVI B,12
- CALL MOVE
- LDA RPTYPE ;CHECK PACKET TYPE AGAIN
- CPI FRQ ;FILE REQUEST?
- JNZ RXD3 ;YUP, PROCESS THAT INSTEAD
- CALL FLREQ
- LXI H,80H ;POINT TO CP/M DEFAULT BUFFER
- MVI M,0 ;CLEAR LENGTH BYTE
- JMP RECVIT ;AND GO BACK AND WAIT FOR ENQ
-
- RXD3: FILE OUTFILE,TEMP,,1,$$$,1024,OUTBUFFER ;OPEN THE TEMP. FILE
- FILE SETFILE,DEST,,1,, ;SET UP FOR REAL FILE
-
- LXI H,1 ;INIT THE SEQUENCE NUMBER
- SHLD SEQNUM ;FOR THE FIRST PACKET
-
- RXDLP2: CALL CWID ;WASTE TIME WITH PRIMITIVE MORSE CODE
-
- RXDLP1: MVI A,ACK ;NOW DO MODERN ASCII STUFF
- STA TPTYPE
- CALL SENDAPAC ;SEND ACK PACK
-
- RECVDATA:
- LXI D,15000 ;SET FOR 15 SEC TIMEOUT
- CALL RECVPAC ;GO GET A PACKET
- JNZ BADPAC
- CPI FS ;FS NOT REALLY IMPLIMENTED YET
- JZ CLOSEIT ;BUT CLOSE FILE ANYWAY
- CPI EOT
- JZ CLOSEIT
- CPI ENQ
- JZ RXDLP1 ;ACK THE EXTRA ENQ
- CPI DTA ;DATA?
- RNZ
-
- LHLD RLEN ;CHECK FOR ZERO LENGTH
- LXI D,-HDRLEN
- DAD D
- MOV A,L
- ORA H
- JZ RXDLP1 ;DISCARD ZERO LENGTH DATA PACKET
-
- LHLD SEQNUM ;CHECK FOR DUPLICATE PACKET
- LDA RPACNUM
- CMP L
- JNZ DISCARD ;DISCARD IF OUT OF SEQUENCE
- LDA RPACNUM+1
- CMP H
- JNZ DISCARD
- INX H ;COUNT THIS PACKET
- SHLD SEQNUM ;UPDATE SEQUENCE NUMBER
- LXI D,-HDRLEN
- LHLD RLEN ;GET LENGTH
- DAD D ;DATA LENGTH=TOTAL-HEADER
- SHLD DATACNT ;SAVE DATA COUNT
- LXI H,RDATA ;DATA BUFFER POINTER
- SHLD DATAPTR ;SAVE IT
- RXDLP: LHLD DATAPTR
- MOV A,M ;PUT BUFFER CONTENTS ON DISK
- INX H
- SHLD DATAPTR
- PUT TEMP ;WRITE TO TEMPORARY FILE
- LHLD DATACNT
- DCX H
- SHLD DATACNT ;COUNT BYTES
- MOV A,L
- ORA H
- JNZ RXDLP ;LOOP TILL ZERO
- LDA SEQNUM ;GET LOW BYTE OF SEQUENCE NUMBER
- ANI 7
- JZ RXDLP2 ;DO CW ID EVERY 8TH ACK
- JMP RXDLP1 ;SEND ACK AND DO IT AGAIN
-
- DISCARD: CALL PRINT
- DB 'EXTRA PACKET DISCARDED',CR
- JMP RXDLP1
-
-
- CLOSEIT:
- FINIS TEMP
- ERASE DEST
- RENAME DEST,TEMP
- MVI A,ACK
- STA TPTYPE ;SEND FINAL ACK
- CALL SENDAPAC
- CALL CWID ;FINAL CW ID
- CALL PRINT
- DB 'FILE RECEIVED',CR
- LXI H,80H
- MVI M,0
- JMP RECVIT ;GO WAIT FOR ENQ AGAIN
-
-
- BADPAC: FINIS TEMP
- ERASE TEMP
- CALL PRINT
- DB 'TOO MANY ERRORS, RECEPTION ABORTED',7,CR
- LXI H,80H
- MVI M,0
- JMP RECVIT
-
-
-
- ;WAIT FOR A SYNC STREAM FOLOWED BY SOH
- ;"TIME" HAS TIMEOUT VALUE IN MS
- ;"TIME"= ZERO MEANS WAIT FOREVER
- ;
- WAITSOH:
- CALL RFOFF ;BE SURE WE DONT TRANSMIT
- CALL INIRX ;INIT MODEM FOR RECEIVE
- LHLD TIME
- SHLD TEMPTIME ;GET TIMEOUT VALUE
- WSOH3: CALL CKCRLC ;CHECK FOR CONTROL C
- CALL COUNTDOWN ;DO TIMEOUT TEST
- RZ ;RETURN ZERO IF TIMEOUT
- CALL RXSTAT ;CHECK FOR A CHARACTER
- ORA A
- JZ WSOH3 ;LOOP BACK IF WE DONT HAVE ONE
-
- LXI H,LEADBB+1 ;LEADIN BUFFER END POINTER
- LXI D,LEADBB ;LEADIN START POINTER
- MVI B,4 ;NUMBER OF BYTES TO SHIFT
- CALL MOVE ;SHIFT BYTES OVER
-
- LXI D,1 ;1 MS TIMEOUT (CHAR. THERE ALREADY)
- CALL RECVCHR ;GET THE CHARACTER
- STA LEADBE ;STORE AT END OF BUFFER
- LXI H,LEADBB ;ADDRESS OF UNKNOWN STRING
- LXI D,SYNCS ;THIS IS WHAT WERE LOOKING FOR
- MVI B,5 ;WE WANT TO CHECK 5 CHARACTERS
- CALL COMPARE$ ;NOW COMPARE SYNCS WITH UNKNOWN
- JNZ WSOH3 ;NO MATCH, LOOP BACK
- MVI A,SOH ;RETURN WITH SOH MEANS WE GOT IT
- RET
-
-
-
-
- COUNTDOWN:
- LHLD TEMPTIME ;GET TIMEOUT VALUE
- MOV A,L
- ORA H ;PRETEST FOR ZERO
- JZ NEVERMIND ;ZERO MEANS WAIT FOREVER
- DCX H ;COUNT 1 MS
- SHLD TEMPTIME ;SAVE NEW VALUE
- CALL WAIT1 ;WAIT 1 MS
- MOV A,L
- ORA H
- RET ;RET ZERO IF TIMED OUT
-
- NEVERMIND:
- MVI A,255
- ORA A
- RET ;PRETEND WE DIDN'T TIMEOUT
-
-
-
- ;CHECKS CONSOLE FOR CONTROL C TO ABORT
-
- CKCRLC: CALL CONST ;CHECK CONSOLE
- ORA A
- RZ
- CALL CONIN ;GET CONSOLE CHAR
- CPI 3 ;CONTROL C?
- RNZ
- JMP QUIT
- ;---------------------------------------------------------
- ;
- ;RECEIVES 1 PACKET OF ANY TYPE TO ANY DESTINATION
- ;ENTER WITH DE CONTAINING THE TIMEOUT VALUE IN MILLISECONDS.
- ;IF DE=0 THE TIMEOUT IS FOREVER
- ;IT WILL TRY 4 TIMES TO HEAR THE PACKET BEFORE GIVING UP.
- ;RETURNS WITH PACKET TYPE IN REG. A WITH ZERO FLAG SET.
- ;RETURNS NON-ZERO IF ERROR.
- ;
- RECVPAC:
- XCHG
- SHLD TIME ;SET TIMEOUT VALUE
- MVI A,4 ;SET RETRY COUNTER
- STA RETRYS
- RP1: CALL RECVAPAC ;GET 1 PACKET
- JNZ RP4 ;JUMP IF ERROR
- XRA A
- LDA RPTYPE ;A HAS PACKET TYPE
- RET ;EXIT
-
- RP4:
- LDA RETRYS ;COUNT THE RETRYS
- DCR A
- STA RETRYS
- JNZ RP3
- INR A
- RET ;RETURN NON ZERO IF ERROR
-
- RP3: CALL CKCALL ;SEE IF IT WAS FOR US
- JNZ RP1 ;DONT NAK IF NOT FOR US
- MVI A,NAK
- STA TPTYPE
- CALL SENDAPAC ;SEND NAK PAC
- JMP RP1 ;GO BACK AND TRY AGAIN
-
-
-
-
- ;GETS 1 PACKET (NO RETRYS, SEE RECVPAC ABOVE)
- ;RETURNS ZERO FLAG SET WITH PACKET TYPE IN REG. A
- ;IF NO ERRORS
- ;"TIME" HAS TIMEOUT VALUE... 0=FOREVER
-
-
- RECVAPAC:
- CALL CLEARBUF ;CLEAR RECEIVE HEADER
- CALL WAITSOH ;WAIT FOR NEW LEADER
- CPI SOH
- JNZ TOOLONG ;MUST BE TIMEOUT IF NO SOH
- LXI H,HDRLEN+2 ;TOTAL LENGTH OF HEADER
- SHLD RLEN ;INITIAL LENGTH
- LXI H,RCRC ;SET UP BUFFER POINTER
- SHLD DATAPTR
- LXI D,100 ;100 MS TIMEOUT
- CALL RECVCHR ;TRY TO GET A CHAR
- JC TOOLONG
- STA RLEN ;GET LOW LENGTH BYTE
- CALL RECVCHR
- JC TOOLONG
- STA RLEN+1 ;HIGH LENGTH BYTE
- LHLD RLEN ;GET COUNT
- SHLD DATACNT ;SAVE IT
- CPI 5 ;SEE IF LENGTH TOO BIG
- JNC TOOBIG
- RCVLP: CALL RECVCHR ;START GETTING REST OF DATA NOW
- JC TOOLONG
- LHLD DATAPTR
- MOV M,A ;PUT A BYTE IN PACKET BUFFER
- INX H
- SHLD DATAPTR
- LHLD DATACNT ;COUNT THE BYTES
- DCX H
- SHLD DATACNT
- MOV A,L
- ORA H
- JNZ RCVLP ;LOOP FOR MORE BYTES
- CALL RXCRC ;CHECK RECEIVED CRC
- JNZ CRCERR ;JUMP IF ERROR
- CALL PRNRXHEADER ;PRINT WHAT WE RECEIVED
- LDA RPTYPE ;GET PACKET TYPE
- CMP A ;SET ZERO FLAG
- RET
-
- CRCERR: CALL PRINT
- DB '** CRC ERROR **',7,CR
- XRA A
- INR A
- RET ;RETURN NON ZERO DUE TO ERROR
-
-
-
- ;COME HERE AFTER TIMEOUT ERROR
- ;
- TOOLONG:
- CALL PRINT
- DB '** TIMEOUT ERROR **',7,CR
- XRA A
- INR A ;RETURN NON ZERO
- RET
-
-
- TOOBIG:
- CALL PRINT
- DB '** PACKET TOO BIG FOR BUFFER **',7,CR
- XRA A
- INR A
- RET
-
- ;
- ;
- ;
- ;
- ;----------------------------------------------------------
- ;THIS IS THE PACKET TRANSMISSION SECTION
-
- ;SEND 1 PACKET AND WAIT FOR REPLY
- ;AND DO IT UP TO 4 TIMES IF IT GETS A NAK BACK
- ;OR A TIMEOUT
-
- SENDPAC:MVI A,4 ;RETRY COUNTER
- STA RETRYS
- AGAIN: CALL SENDAPAC ;SEND THE PACKET
- CALL INIRX ;SET UP FOR RECEIVE
- LXI H,23000 ;23 SEC TIMEOUT
- SHLD TIME
- CALL RECVAPAC ;GET REPLY PACKET
- JNZ SNDP1 ;ERROR IF NON ZERO
- CPI NAK
- JZ SNDP1 ;TRY AGAIN IF NAK
- CMP A ;SET ZERO FLAG
- RET ;RETURN PACKET TYPE IN ACC
- SNDP1: LDA RETRYS
- DCR A
- STA RETRYS
- JZ SP2
- CALL PRINT
- DB 'RETRANSMITTING',CR
- JMP AGAIN ;TRY AGAIN
-
- SP2: MVI A,1 ;1=ERROR
- ORA A
- RET
- ;
- ;
- ;THIS SENDS 1 PACKET
- ;
- SENDAPAC:
- CALL INITX ;SET UP FOR TRANSMIT
- LXI D,3000 ;3 SEC WAIT AFTER KEYDOWN
- CALL RFON ;KEY TRANSMITTER
- CALL TXCRC ;COMPUTE TRANSMIT CRC
- CALL PRNTXHEADER ;TELL USER WHAT WERE SENDING
- LHLD TLEN ;GET PACKET LENGTH
- INX H
- INX H
- INX H
- INX H
- INX H ;ADD 7 FOR LEADER AND LENGTH BYTES
- INX H
- INX H
- XCHG ;TRUE LENGTH IN DE
- LXI H,TBUFFR ;POINT TO START OF BUFFER
- SP1: MOV C,M ;GET A BYTE
- CALL SENDCHR ;SEND IT
- CALL CKCRLC ;ABORT IF CONTROL C TYPED
- INX H
- DCX D
- MOV A,E
- ORA D
- JNZ SP1 ;LOOP TIL ALL BYTES SENT
- LXI D,100
- CALL DELAY ;100 MS TRAILER
- CALL RFOFF ;KILL TRANSMITTER
- RET
-
- ;
- ;
- ;
- ;---------------------------------------------------
- ;THIS MESS PRINTS THE HEADER INFORMATION TO THE CONSOLE
- ;FOR PACKETS TO BE SENT OR PACKETS WHICH HAVE BEEN RECEIVED.
-
- PRNTXHEADER:
- LXI H,TBUFFR
- LXI D,BUFFR
- MVI B,TDATA-TBUFFR
- CALL MOVE ;GET TRANSMIT HEADER
-
- CALL PRINT
- DB 'TX-@'
- CALL PRINFO
- RET
-
- PRNRXHEADER:
- LXI H,RBUFFR
- LXI D,BUFFR
- MVI B,RDATA-RBUFFR
- CALL MOVE ;GET RECEIVER HEADER
- CALL PRINT
- DB 'RX-@'
- ;
- PRINFO:
- LHLD LEN
- CALL BXDEC ;PRINT LENGTH
- CALL PRINT
- DB ' BYTES #@'
- LHLD PACNUM
- CALL BXDEC ;PRINT PACKET NUMBER
- CALL PRINT
- DB ' @'
- LXI H,SRCCAL
- MVI B,6
- CALL PRNMEM ;PRINT SOURCE CALL
- CALL PRINT
- DB ' -> @'
- LXI H,DSTCAL
- MVI B,6
- CALL PRNMEM ;PRINT DESTINATION CALL
- CALL PRINT
- DB ', @'
- LXI H,STITLE+1
- MVI B,11
- CALL PRNMEM ;PRINT FILE NAME
- CALL PRINT
- DB ' = @'
- CALL PRTYPE
- JMP CRLF
-
-
- PRTYPE: LDA PTYPE
- CPI DTA
- JZ TPDTA
- CPI ENQ
- JZ TPENQ
- CPI ACK
- JZ TPACK
- CPI NAK
- JZ TPNAK
- CPI FS
- JZ TPFS
- CPI EOT
- JZ TPEOT
- CPI FRQ
- JZ TPFRQ
- CPI FNF
- JZ TPFNF
- CALL PRINT
- DB 'UNKNOWN @'
- RET
-
- TPDTA: CALL PRINT
- DB 'DATA @'
- RET
-
- TPENQ: CALL PRINT
- DB 'ENQ @'
- RET
-
- TPACK: CALL PRINT
- DB 'ACK @'
- RET
-
- TPNAK: CALL PRINT
- DB 'NAK @'
- RET
-
- TPFS: CALL PRINT
- DB 'FS @'
- RET
-
- TPEOT: CALL PRINT
- DB 'EOT @'
- RET
- TPFRQ: CALL PRINT
- DB 'FRQ @'
- RET
-
- TPDRQ: CALL PRINT
- DB 'DRQ @'
- RET
-
- TPFNF: CALL PRINT
- DB 'FNF @'
- RET
-
- ;-----------------------------------------------------
-
-
- CRLF: CALL PRINT
- DB CR
- RET
-
-
- ;COMPARES 2 STRINGS
- ;POINTED TO BY HL & DE (B HAS LENGTH)
- ;RETURNS ZERO FLAG SET IF EQUAL
- ;
- COMPARE$:
- LDAX D
- CMP M
- RNZ
- INX H
- INX D
- DCR B
- JNZ COMPARE$
- XRA A
- RET
-
- ;CHECKS THE RECEIVED CALL SIGN AGAINST OUR OWN
- ;RETURNS ZERO IF MATCHED.
-
- CKCALL: LXI H,MYCALL
- LXI D,RDSTCAL
- MVI B,6
- JMP COMPARE$
-
-
- ;
- ;PRINTS A STRING IN MEMORY POINTED TO BY HL
- ;B HAS LENGTH.
-
- PRNMEM: MOV C,M
- CALL CONOUT
- INX H
- DCR B
- JNZ PRNMEM
- RET
-
-
- ;
- ;SENDS A CHARACTER IN REG C TO CONSOLE
- ;
-
- CONOUT: PUSH PSW
- PUSH B
- PUSH D
- PUSH H
- MOV E,C
- MVI C,2
- CALL BDOS
- POP H
- POP D
- POP B
- POP PSW
- RET
-
- ;CHECK CONSOLE STATUS
- ;RETURN A=ZERO IF NO KEY PRESSED
- ;
- CONST: PUSH B
- PUSH D
- PUSH H
- MVI C,11 ;CP/M CONSOLE STATUS CODE
- CALL BDOS
- POP H
- POP D
- POP B
- RET ;A=FF IF KEY PRESSED
- ;
- ;
- ;GETS A CHARACTER FROM CONSOLE
- ;A=CHAR.
- ;
- CONIN: PUSH B
- PUSH D
- PUSH H
- MVI C,1 ;READ CONSOLE CPM COMMAND
- CALL BDOS
- POP H
- POP D
- POP B
- RET ;A=CHAR
- ;
- ;
- ;PRINT A STRING POINTED TO BY THE CONTENTS OF THE
- ;TOP OF STACK. <CR> OR @ TERMINATES THE STRING.
-
- PRINT: XTHL
- PUSH PSW
- PUSH B
- PRN1: MOV A,M
- INX H
- CPI '@'
- JZ PRN2
- MOV C,A
- CALL CONOUT
- CPI CR
- JNZ PRN1
- CALL PRINT
- DB LF,'@'
- PRN2: POP B
- POP PSW
- XTHL
- RET
-
-
- ;CONVERTS BINARY NUMBER IN HL TO DECIMAL ASCII
- ;AND SENDS IT TO CONSOLE
-
- BXDEC: SHLD N ;SAVE NUMBER
- LXI H,P10TAB ;POINT TO POWER OF 10 TABLE
- BX0: MOV E,M
- INX H
- MOV D,M ;POWER OF 10
- INX H
- PUSH H
- LHLD N
- MVI C,'0'
- BX1: DAD D ;SUBTRACT POWER OF TEN
- JNC BX2
- INR C
- JMP BX1 ;LOOP TILL IT GOES NEG.
- BX2: MOV A,E
- CMA ;TWOS COMPLIMENT
- MOV E,A
- MOV A,D
- CMA
- MOV D,A
- INX D
- DAD D ;RESTORE TO +
- SHLD N ;SAVE IT
- CALL CONOUT
- POP H
- MVI A,1
- CMP E ;SEE IF WE ARE DONE
- JNZ BX0 ;NO, DO AGAIN
- RET
- ;
- ;
- P10TAB: DW -10000
- DW -1000
- DW -100
- DW -10
- DW -1
-
- ;
- ;
-
-
- ;THIS TELLS THE USER THAT THERE WAS NO RESPONSE
-
- NORPLY: LXI D,NOTHOME+2
- LXI H,TDSTCAL
- MVI B,6
- CALL MOVE
- LXI D,NOTHOME
- MVI C,9
- CALL BDOS
- RET
-
- NOTHOME:
- DB CR,LF,' DOES NOT RESPOND',CR,LF,'$'
-
- ;GENERAL PURPOSE MEMORY TO MEMORY MOVE SUBROUTINE
- ;ENTER WITH HL POINTING TO SOURCE, DE POINTING TO
- ;DESTINATION AND B HAS THE LENGTH (0..255, 0=256 BYTES)
-
- MOVE: MOV A,M
- STAX D
- INX H
- INX D
- DCR B
- JNZ MOVE
- RET
- ;
- ;ENTER THIS DELAY ROUTINE WITH DE CONTAINING
- ;THE DELAY VALUE IN MILLISECONDS.
-
- DELAY: CALL WAIT1 ;WAIT 1MS * DE
- DCX D
- MOV A,E
- ORA D
- JNZ DELAY
- RET
-
-
- ;THIS COMPUTES THE CRC FOR TRANSMISSION
-
- TXCRC: LXI H,0
- SHLD CRCREG ;CLEAR CRC
- LDA TLEN
- MOV C,A
- CALL CALCRC ;COMPUTE CRC FOR LENGTH FIELD
- LDA TLEN+1
- MOV B,A ;BC HAS LENGTH NOW
- CALL CALCRC
- LXI H,TDSTCAL ;SKIP OVER CRC FIELD
- DCX B
- DCX B ;ADJUST LENGTH
- TXCRC1: MOV A,M ;GET A BYTE FROM BUFFER
- CALL CALCRC ;COMPUTE CRC ON IT
- INX H ;ADVANCE BUFFER POINTER
- DCX B ;COUNT THE BYTES
- MOV A,C
- ORA B
- JNZ TXCRC1 ;LOOP UNTIL COUNTER IS ZERO
- LHLD CRCREG ;GET COMPLETE CRC
- SHLD TCRC ;PUT IT IN THE BUFFER
- RET
-
- ;COMPUTE CRC ON RECEIVE BUFFER CONTENTS
- ;RETURNS A=0 IF OK
-
- RXCRC: LHLD RLEN ;GET LENGTH
- MOV C,L
- MOV B,H ;BC IS COUNTER
- LXI H,0
- SHLD CRCREG ;CLEAR CRC
- MOV A,C ;COMPUTE CRC ON LENGTH WORD
- CALL CALCRC
- MOV A,B
- CALL CALCRC
- LXI H,RDSTCAL ;HL POINT TO BUFFER & SKIP CRC FIELD
- DCX B
- DCX B ;ADJUST COUNT
- RXCRC1: MOV A,M ;GET A BYTE
- CALL CALCRC ;DO CRC CALC.
- INX H
- DCX B
- MOV A,C
- ORA B
- JNZ RXCRC1 ;LOOP UNTIL DONE
- LHLD CRCREG ;GET COMPLETE CRC
- XCHG ;TO DE
- LHLD RCRC ;GET RECEIVED CRC
- MOV A,E
- SUB L
- RNZ ;RETURN NON ZERO IF BAD CRC
- MOV A,D
- SUB H
- RET
-
- ;
- ;THIS COMPUTES THE CRC FROM VALUES IN REGISTER A AND
- ;MEMORY LOCATION "CRCREG".
-
- CALCRC: PUSH B
- PUSH H
- MOV B,A ;SAVE BYTE
- MVI C,8 ;BIT COUNTER
- CALC1: ANI 80H ;KEEP MSB
- LHLD CRCREG ;GET CRC
- XRA H
- MOV H,A ;XOR CRC INTO DATA
- DAD H ;SHIFT CRC LEFT
- JNC CALC2
- MOV A,H
- XRI CRCPLY SHR 8 ; HL = HL XOR CRC POLYNOMIAL
- MOV H,A
- MOV A,L
- XRI CRCPLY AND 255
- MOV L,A
- CALC2: SHLD CRCREG ;SAVE RESULT
- DCR C
- JZ CALC3
- MOV A,B ;GET DATA
- ADD A ;SHIFT IT LEFT 1 BIT
- MOV B,A
- JMP CALC1 ;DO IT AGAIN
- CALC3: POP H
- POP B
- RET
- ;
- ;------------------------------------------------------------;
- ;
- ;THIS IS A CW ID SUBROUTINE PACKAGE
-
-
- ;HERE IS THE ASCII TO CW TRANSLATE TABLE
-
- ASCII$CW:
- DB 5+10010000B ; / -..-.
- DB 5+11111000B ;ZERO
- DB 5+01111000B ;1
- DB 5+00111000B ;2
- DB 5+00011000B ;3
- DB 5+00001000B ;4
- DB 5+00000000B ;5
- DB 5+10000000B ;6
- DB 5+11000000B ;7
- DB 5+11100000B ;8
- DB 5+11110000B ;9
- DB 0 ;: NOT USED
- DB 0 ; ; NOT USED
- DB 0 ; < NOT USED
- DB 0 ; = NOT USED
- DB 0 ; > NOT USED
- DB 0 ; ? NOT USED
- DB 0 ; @ NOT USED
- DB 2+01000000B ; A .-
- DB 4+10000000B ;B -...
- DB 4+10100000B ; C -.-.
- DB 3+10000000B ; D -..
- DB 1+00000000B ; E .
- DB 4+00100000B ; F ..-.
- DB 3+11000000B ;G --.
- DB 4+00000000B ;H
- DB 2+00000000B ; I ..
- DB 4+01110000B ; J .---
- DB 3+10100000B ; K -.-
- DB 4+01000000B ; L .-..
- DB 2+11000000B ; M --
- DB 2+10000000B ; N -.
- DB 3+11100000B ; O ---
- DB 4+01100000B ; P .--.
- DB 4+11010000B ; Q --.-
- DB 3+01000000B ; R .-.
- DB 3+00000000B ; S ...
- DB 1+10000000B ; T -
- DB 3+00100000B ; U ..-
- DB 4+00010000B ; V ...-
- DB 3+01100000B ; W .--
- DB 4+10010000B ; X -..-
- DB 4+10110000B ; Y -.--
- DB 4+11000000B ; Z --..
-
-
-
- ;THIS IS THE END OF THE TABLE
-
-
- ID$STRING: DS 20 ;RESERVE 20 BYTES FOR ID STRING
- DE$STR: DB ' DE '
-
- CWID:
- LXI H,ID$INH ;ID INHIBIT FLAG
- MOV A,M
- MVI M,0 ;CLEAR IT
- ORA A ;TEST IT
- RNZ ;DONT ID THIS TIME IF TRUE
- LXI H,TDSTCAL ;GET DESTINATION CALL
- LXI D,ID$STRING
- MVI B,6
- CALL MOVE
-
- LXI H,DE$STR ;POINT TO "DE" STRING
- MVI B,4
- CALL MOVE
-
- LXI H,MYCALL ;PUT OUR CALL IN
- MVI B,6
- CALL MOVE
- XCHG
- MVI M,' ' ;TRAILING SPACE
- INX H
- MVI M,0 ;NULL TERMINATES STRING
-
- CALL INITX ;INIT. FOR TRANSMITTING
- CALL TONEOFF
- LXI D,200 ;DELAY 200 MS AFTER KEY DOWN
- CALL RFON ;KEY TRANSMITTER
-
- LXI H,ID$STRING
- CWID1: MOV A,M ;GET A ASCII CHAR.
- ORA A ;NULL?
- JZ RFOFF ;QUIT IF NULL
- CPI '0'
- JC CWID2 ;IGNORE INVALID CHAR
- PUSH H
- MOV C,A
- CALL SEND$CW$CHAR ;CONVERT TO CW AND SEND
- POP H
- CWID2: INX H
- JMP CWID1 ;LOOP TILL DONE
-
-
-
- SEND$CW$CHAR:
- PUSH B
- CALL TONEOFF
- MVI C,2
- CALL DELAYX ;WAIT 2 DOT TIMES
- POP B ;GET ASCII CHARACTER BACK
- LXI H,ASCII$CW-2FH ;POINT TO CONVERSION TABLE
- MOV A,C
- CPI 20H ;TEST FOR SPACE
- JNZ CW1
- MVI C,7 ;7 DOT TIMES FOR SPACE
- JMP DELAYX
- CW1: MVI B,0
- DAD B ;INDEX INTO TABLE
- MOV A,M ;GET CW CODE
- ANI 7 ;KEEP COUNT
- RZ ;RETURN IF ZERO COUNT
- MOV B,A ;PUT COUNT IN REG. B
- MOV A,M ;GET CODE AGAIN
- CW2: ADD A ;SHIFT MSB INTO CARRY
- MVI E,1 ;ASSUME A DOT
- JNC CW3 ;JUMP IF DOT
- MVI E,3 ;ELSE SET FOR DASH
- CW3: PUSH B ;SAVE COUNT
- PUSH PSW ;SAVE CODE
- CALL TONEON ;TURN ON TONE
- MOV C,E ;GET TIME
- CALL DELAYX
- CALL TONEOFF ; TONE OFF
- MVI C,1
- CALL DELAYX ;WAIT 1 DOT TIME
- POP PSW ;RESTORE CODE
- POP B ;RESTORE COUNT
- DCR B ;COUNT DOWN
- JNZ CW2 ;LOOP TILL FINISHED
- RET
-
- ;THIS TIMES 1 DIT.
-
- DELAYX: MOV A,C
- ORA A
- RZ
- PUSH B
- PUSH D
- DLY1: LXI D,50 ;50 MS DELAY
- CALL DELAY
- DCR C
- JNZ DLY1
- POP D
- POP B
- RET
-
- ;END OF CW ID ROUTINES
- ;--------------------------------------------------------;
- ;
- ;
- DSEG ;BEGIN DATA SEGMENT
-
- ;
- ;THIS IS THE VARIABLE STORAGE AREA
-
-
-
-
- CRCREG: DS 2 ;USED BY CRC ROUTINE
- N: DS 2 ;USED BY BXDEC ROUTINE
- DATAPTR:DS 2
- DATACNT:DS 2
- RETRYS: DS 1 ;RETRY COUNTER
- SEQNUM: DS 2 ;LOCAL COUNT OF RECEIVED PACKETS
- DIRFLAG:DS 1 ;1=DIRECTORY 0=NORMAL FILE
- ID$INH: DS 1 ;1=INHIBIT NEXT ID
- LEADBB: DS 4 ;LEADER BUFFER BEGINNING
- LEADBE: DS 1 ;LEADER BUFFER END
- TIME: DS 2 ;USED FOR TIMEOUTS
- TEMPTIME: DS 2
-
- ;SCRATCH PAD PACKET HEADER
-
- BUFFR: DS 5 ;LEADER
- LEN: DS 2 ;TOTAL LENGTH OF MESSAGE
- CRC: DS 2 ;CRC BYTES
- DSTCAL: DS 6 ;DESTINATION CALL SIGN
- DSTLOC: DS 1 ;DESTINATION LOCATION CODE
- DSTRPT: DS 1 ;DESTINATION REPEATER (0=DIRECT)
- SRCCAL: DS 6 ;SOURCE CALL SIGN
- SRCLOC: DS 1 ;SOURCE LOCATION CODE
- SRCRPT: DS 1 ;SOURCE REPEATER (0=DIRECT)
- PTYPE: DS 1 ; PACKET TYPE
- STITLE: DS 12 ;NAME OF PACKET GROUP (CP/M FILE NAME)
- PACNUM: DS 2 ;PACKET NUMBER
-
- ;TRANSMIT PACKET BUFFER
-
- TBUFFR: DS 5 ;LEADER
- TLEN: DS 2 ;TOTAL LENGTH OF MESSAGE
- TCRC: DS 2 ;CRC BYTES
- TDSTCAL:DS 6 ;DESTINATION CALL SIGN
- TDSTLOC:DS 1 ;DESTINATION LOCATION CODE
- TDSTRPT:DS 1 ;DESTINATION REPEATER (0=DIRECT)
- TSRCCAL:DS 6 ;SOURCE CALL SIGN
- TSRCLOC:DS 1 ;SOURCE LOCATION CODE
- TSRCRPT:DS 1 ;SOURCE REPEATER (0=DIRECT)
- TPTYPE: DS 1 ; PACKET TYPE
- TTITLE: DS 12 ;NAME OF PACKET GROUP (CP/M FILE NAME)
- TPACNUM:DS 2 ;PACKET NUMBER
- TDATA: DS 1024 ;THIS IS THE DATA
-
-
- ;RECEIVE PACKET BUFFER
- ;
- RBUFFR: DS 5 ;LEADER
- RLEN: DS 2 ;LENGTH OF RECEIVED PACKET
- RCRC: DS 2 ;RECEIVED CRC BYTES
- RDSTCAL:DS 6 ;DESTINATION CALL SIGN
- RDSTLOC:DS 1 ;DESTINATION LOCATION CODE
- RDSTRPT:DS 1 ;DESTINATION REPEATER (0=DIRECT)
- RSRCCAL:DS 6 ;SOURCE CALL SIGN
- RSCRLOC:DS 1 ;SOURCE LOCATION CODE
- RSCRRPT:DS 1 ;SOURCE REPEATER (0=DIRECT)
- RPTYPE: DS 1 ;PACKET TYPE
- RTITLE: DS 12 ;NAME OF PACKET GROUP (FILE NAME)
- RPACNUM:DS 2 ;PACKET NUMBER
- RDATA: DS 1024 ;RECEIVED DATA
- ;
- ;
- ;
- ;
- INBUFFER: DS 1024 ;FILE READ BUFFER
- OUTBUFFER: DS 1024 ;FILE OUTPUT BUFFER
-
- END