home *** CD-ROM | disk | FTP | other *** search
- ;MODEM ROUTINE - SEND, RECV, COMPUTER, TERMINAL
- ; * * * * * * * * * * * * * * * * * * * *
- ;SENSE SWITCH CONTROLS: *
- ; *
- ; A12 UP TO DISPLAY INCOMING DATA *
- ; A13 UP TO DISPLAY OUTGOING DATA *
- ; * * * * * * * * * * * * * * * * * * * *
- ;
- ;09/23/77 FIRST WRITTEN BY WARD CHRISTENSEN
- ;09/25/77 FIRST TESTING COMPLETE
- ;09/26/77 ADD ERROR$LIMIT EQU
- ;10/01/77 CHANGE EXIT$CHAR FROM CTL-C TO
- ; CTL-E FOR USE W/TIMESHARING COMPUTERS
- ;10/10/77 CORRECT TO SEND ANY LENGTH FILE
- ;
- MODEM$CTL$PORT EQU 4
- MODEM$SEND$MASK EQU 2
- SEND$READY EQU 2 ;VALUE WHEN READY
- MODEM$RECV$MASK EQU 1
- RECV$READY EQU 1 ;BIT ON WHEN READY
- MODEM$DATA$PORT EQU 5
- KEY$CTL$PORT EQU 0 ;KEYBOARD STATUS
- KEY$READY$MASK EQU 2
- KEY$READY EQU 2 ;VALUE WHEN KEYBOARD READY
- KEY$DATA$PORT EQU 1
- INIT$REQD EQU 1 ;MODEM INIT. REQ'D?
- INIT$CHAR$1 EQU 3 ;FIRST INIT CHAR TO CTL PORT
- INIT$CHAR$2 EQU 15H ;2ND INIT CHAR TO CTL PORT
- ERROR$LIMIT EQU 10 ;MAX ALLOWABLE ERRORS
- EXIT$CHAR EQU 'E'-40H ;CHAR TO EXIT FROM T OR C
- ORG 100H
- CALL START ;GO PRINT ID
- DB 'MODEM PROGRAM AS OF '
- DB '10/10/77',13,10,'$'
- ;FLAG FOR GENERATING TEST CODE TO USE KEYBOARD
- ;TO ECHO ACK/NAK WHILE TESTING:
- TEST EQU 0 ;GENERATE TEST CODE
- ;
- ;DEFINE ASCII CHARACTERS USED
- SOH EQU 1
- EOT EQU 4
- ACK EQU 6
- NAK EQU 15H
- LF EQU 10
- CR EQU 13
- ;
- START POP D ;GET ID MESSAGE
- MVI C,PRINT
- CALL BDOS ;PRINT ID MESSAGE
- ;INIT PRIVATE STACK
- LXI H,0 ;HL=0
- DAD SP ;HL=STACK FROM CP/M
- SHLD STACK ;..SAVE IT
- LXI SP,STACK ;SP=MY STACK
- ;
- CALL INIT$PORT
- ;GOBBLE UP GARBAGE CHARS FROM THE LINE
- MVI B,1 ;TIMEOUT DELAY
- CALL RECV
- MVI B,1
- CALL RECV
- ;
- LDA FCB+1 ;GET OPTION (S R C T)
- PUSH PSW ;SAVE OPTION
- CALL MOVE$FCB ;MOVE FROM 6C TO 5C
- POP PSW ;GET OPTION
- CPI 'S'
- JZ SEND$FILE
- CPI 'R'
- JZ RECV$FILE
- CPI 'C'
- JZ COMPUTER
- CPI 'T'
- JZ TERMINAL
- ;INVALID OPTION
- CALL ERXIT ;EXIT W/ERROR
- DB '++INVALID OPTION ON MODEM COMMAND - ',CR,LF
- DB 'MUST BE ONE OF THE FOLLOWING:',CR,LF
- DB 'MODEM SEND FILENAME',CR,LF
- DB 'MODEM RECV FILENAME',CR,LF
- DB 'MODEM COMPUTER',CR,LF
- DB 'MODEM TERMINAL',CR,LF
- DB ' ABBREV. ALLOWED: S R C T$'
- ;
- ;****************COMPUTER****************
- ;
- ;TERMINAL-TERMINAL W/ECHO SENT BY THIS PROGRAM
- ;'EXIT$CHAR' TYPED TO RE-BOOT
- ;IF ONE COMPUTER IS IN COMPUTER MODE,
- ;THE OTHER SHOULD BE IN TERMINAL MODE.
- ;AT NO TIME SHOULD BOTH BE IN COMPUTER
- ;MODE BECAUSE LINE ERRORS WILL BE PING-PONGED
- ;BACK AND FORTH AD INFINITUM.
- COMPUTER:
- IN MODEM$CTL$PORT
- ANI MODEM$RECV$MASK
- CPI RECV$READY
- JZ LINE$CHAR
- ;NOTHING FROM LINE, CHECK KEYBOARD
- MVI C,CONST ;CHECK STATUS
- CALL BDOS
- ORA A ;READY?
- JZ COMPUTER ;..NO
- MVI C,RDCON
- CALL BDOS ;GET CHAR
- CPI EXIT$CHAR ;END?
- JZ EXIT ;YES, EXIT
- OUT MODEM$DATA$PORT ;SEND CHAR
- JMP COMPUTER
- ;GOT CHAR FROM LINE
- LINE$CHAR:
- IN MODEM$DATA$PORT
- OUT MODEM$DATA$PORT ;ECHO
- CALL TYPE ;TYPE IT
- JMP COMPUTER
- ;
- ;**************TERMINAL****************
- ;
- ;SEE NOTES UNDER 'COMPUTER'
- ;
- TERMINAL:
- IN KEY$CTL$PORT
- ANI KEY$READY$MASK
- CPI KEY$READY
- JNZ TRECV ;NOTHING FROM KEYBOARD
- IN KEY$DATA$PORT
- ANI 7FH
- CPI EXIT$CHAR ;TIME TO END?
- JZ EXIT
- OUT MODEM$DATA$PORT
- TRECV IN MODEM$CTL$PORT
- ANI MODEM$RECV$MASK
- CPI RECV$READY
- JNZ TERMINAL
- IN MODEM$DATA$PORT
- CALL TYPE
- JMP TERMINAL
- ;INIT SERIAL PORT
- INIT$PORT:
- LXI D,MSG$BAUD
- CALL PRINT$MESSAGE
- IF INIT$REQD
- MVI A,INIT$CHAR$1
- OUT MODEM$CTL$PORT
- MVI A,INIT$CHAR$2
- OUT MODEM$CTL$PORT
- ENDIF
- ;GET THE SPEED
- XRA A ;GET A ZERO
- CALL SEND ;SEND A CHAR
- XRA A ;GET ZERO
- CALL SEND ;SEND AGAIN
- ;WAIT, TIMING TO DETERMINE BAUD RATE
- LXI B,0 ;INIT COUNT
- INIT$WAIT:
- IN MODEM$CTL$PORT
- ANI MODEM$SEND$MASK
- CPI SEND$READY
- JZ INIT$WAIT$END
- DCR C
- JNZ INIT$WAIT
- DCR B
- JNZ INIT$WAIT
- CALL ERXIT
- DB '++TIME OUT DETERMINING BAUD RATE$'
- INIT$WAIT$END:
- MOV A,B ;GET COUNT
- CPI 0F5H ;110 BAUD = F0,
- JC BAUD$110 ;300 BAUD = FA
- ;BAUD RATE 300
- LXI D,MSG$300
- INIT$PRINT:
- CALL PRINT$MESSAGE
- RET ;FROM INIT$PORT
- BAUD$110:
- LXI D,MSG$110
- JMP INIT$PRINT
- MSG$BAUD DB 'BAUD RATE IS $'
- MSG$110 DB '110',CR,LF,'$'
- MSG$300 DB '300',CR,LF,'$'
- ;MOVE FCB (SECOND OPERAND ON COMMAND)
- ; TO NORMAL FCB LOCATION
- MOVE$FCB:
- LXI H,FCB
- LXI D,FCB+16
- MVI B,16
- MOVE$LOOP:
- LDAX D
- MOV M,A
- INX D
- INX H
- DCR B
- JNZ MOVE$LOOP
- XRA A ;GET 0
- STA FCB+32 ;ZERO RECORD #
- RET
- ;
- ;*****************SEND FILE***************
- ;
- SEND$FILE:
- CALL OPEN$FILE ;OPEN THE FILE
- LXI D,OPENM
- CALL PRINT$MESSAGE
- SENDB XRA A ;GET A ZERO
- STA ERRCT ;ZERO ERROR COUNT
- ;READ SECTOR, SEND IT
- CALL READ$SECTOR
- LDA SECTNO ;INCR SECT NO.
- INR A
- STA SECTNO
- ;SEND OR REPEAT SECTOR
- REPTB LXI D,SECTMSG
- CALL PRINT$MESSAGE
- LDA SECTNO
- CALL HEXO
- CALL CRLF
- MVI A,SOH
- CALL SEND
- LDA SECTNO
- CALL SEND
- LDA SECTNO
- CMA
- CALL SEND
- MVI C,0 ;INIT CKSUM
- LXI H,80H
- SENDC MOV A,M
- CALL SEND
- INX H
- MOV A,H
- CPI 1 ;DONE WITH SECTOR?
- JNZ SENDC
- ;SECTOR SENT, SEND CKSUM
- MOV A,C ;GET CKSUM
- CALL SEND
- ;GET ACK ON SECTOR
- MVI B,4 ;WAIT 4 SECONDS MAX
- CALL RECV
- JNC SNTO ;NO TIMEOUT
- ;TIMED OUT WAITING FOR ACK
- CALL TOUT ;PRINT 'TIMEOUT', ERRCT
- DATERR LDA ERRCT
- INR A
- STA ERRCT
- CPI ERROR$LIMIT
- JC REPTB ;REPEAT SECTOR
- ;SECTOR SEND NO GOOD AFTER 10 TRIES
- CALL ERXIT
- DB 'CAN''T SEND SECTOR '
- DB '- ABORTING',13,10,'$'
- SECTMSG DB 'SENDING SECTOR $'
- ;NO TIMEOUT SENDING SECTOR
- SNTO CPI ACK ;ACK RECIEVED?
- JZ SENDB ;..YES, SEND NEXT SECT
- ;ACK NOT RECIEVED
- CALL HEXO ;TYPE CHR IN HEX
- LXI D,ERR1
- CALL PRINT$MESSAGE
- JMP DATERR ;GO TO DATA ERROR
- ERR1 DB 'H RECEIVED, NOT ACK',13,10,'$'
- OPENM DB 'FILE OPEN',13,10,'$'
- ;
- ;**************RECEIVE FILE****************
- ;
- RECV$FILE:
- CALL ERASE$OLD$FILE
- CALL MAKE$NEW$FILE
- RECV$LOOP:
- XRA A ;GET 0
- STA ERRCT ;INIT ERROR COUNT
- RECV$HDR:
- LXI D,RMSG
- CALL PRINT$MESSAGE
- LDA SECTNO
- INR A
- CALL HEXO
- CALL CRLF
- MVI B,5 ;5 SEC TIMEOUT
- CALL RECV
- JNC RHNTO ;NO TIMEOUT
- RECV$HDR$TIMEOUT:
- CALL TOUT ;PRINT TIMEOUT
- RECV$SECT$ERR:
- ;PURGE THE LINE OF INPUT CHARS
- MVI B,1 ;1 SEC W/NO CHARS
- CALL RECV
- JNC RECV$SECT$ERR ;LOOP UNTIL SENDER DONE
- MVI A,NAK
- CALL SEND ;SEND NAK
- LDA ERRCT
- INR A
- STA ERRCT
- CPI ERROR$LIMIT
- JC RECV$HDR
- CALL ERXIT
- DB '++UNABLE TO GET VALID HEADER',0DH,0AH,'$'
- RMSG DB 'WAITING FOR SECTOR #$'
- ;GOT CHAR - MUST BE SOH
- RHNTO CPI SOH
- JZ GOT$SOH
- ORA A ;00 FROM SPEED CHECK?
- JZ RECV$HDR
- CPI EOT
- JZ GOT$EOT
- ;DIDN'T GET SOH -
- CALL HEXO
- LXI D,ERRSOH
- CALL PRINT$MESSAGE
- JMP RECV$SECT$ERR
- ERRSOH DB 'H RECEIVED, NOT SOH',0DH,0AH,'$'
- GOT$SOH:
- MVI B,1
- CALL RECV
- JC RECV$HDR$TIMEOUT
- MOV D,A ;D=BLK #
- MVI B,1
- CALL RECV ;GET CMA'D SECT #
- JC RECV$HDR$TIMEOUT
- CMA
- CMP D ;GOOD SECTOR #?
- IF TEST
- JMP RECV$SECTOR
- ENDIF
- JZ RECV$SECTOR
- ;GOT BAD SECTOR #
- LXI D,ERR2
- CALL PRINT$MESSAGE
- JMP RECV$SECT$ERR
- ERR2 DB '++BAD SECTOR # IN HDR',0DH,0AH,'$'
- ;
- RECV$SECTOR:
- MOV A,D ;GET SECTOR #
- STA RECVD$SECT$NO
- MVI C,0 ;INIT CKSUM
- LXI H,80H ;POINT TO BUFFER
- RECV$CHAR:
- MVI B,1 ;1 SEC TIMEOUT
- CALL RECV ;GET CHAR
- JC RECV$HDR$TIMEOUT
- MOV M,A ;STORE CHAR
- INR L ;DONE?
- JNZ RECV$CHAR
- ;VERIFY CHECKSUM
- MOV D,C ;SAVE CHECKSUM
- MVI B,1 ;TIMEOUT
- CALL RECV ;GET CHECKSUM
- JC RECV$HDR$TIMEOUT
- CMP D ;CHECK
- JNZ RECV$CKSUM$ERR
- ;
- ;GOT A SECTOR, WRITE IF = 1+PREV SECTOR
- ;
- LDA RECVD$SECT$NO
- MOV B,A ;SAVE IT
- LDA SECTNO ;GET PREV
- INR A ;CALC NEXT SECTOR #
- CMP B ;MATCH?
- JNZ DO$ACK
- ;GOT NEW SECTOR - WRITE IT
- LXI D,FCB
- MVI C,WRITE
- CALL BDOS
- ORA A
- JNZ WRITE$ERROR
- LDA RECVD$SECT$NO
- STA SECTNO ;UPDATE SECTOR #
- DO$ACK MVI A,ACK
- CALL SEND
- JMP RECV$LOOP
- ;
- WRITE$ERROR:
- CALL ERXIT
- DB '++ERROR WRITING FILE',0DH,0AH,'$'
- ;
- RECV$CKSUM$ERR:
- LXI D,ERR3
- CALL PRINT$MESSAGE
- JMP RECV$SECT$ERR
- ERR3 DB '++BAD CKSUM ON SECTOR'
- DB 0DH,0AH,'$'
- ;
- GOT$EOT:
- MVI A,ACK ;ACK THE EOT
- CALL SEND
- LXI D,FCB
- MVI C,CLOSE
- CALL BDOS
- INR A
- JNZ XFER$CPLT
- CALL ERXIT
- DB '++ERROR CLOSING FILE$'
- ;
- ERASE$OLD$FILE:
- LXI D,FCB
- MVI C,SRCHF ;SEE IF IT EXISTS
- CALL BDOS
- INR A ;FOUND?
- RZ ;NO, RETURN
- LXI D,EXIST
- CALL PRINT$MESSAGE
- MVI C,RDCON
- CALL BDOS
- CPI 'Y'
- JNZ 0 ;REBOOT IF NOT ERASE
- CALL CRLF
- ;ERASE OLD FILE
- LXI D,FCB
- MVI C,ERASE
- CALL BDOS
- RET
- EXIST DB '++FILE EXISTS, TYPE Y TO ERASE:$'
- ;
- MAKE$NEW$FILE:
- LXI D,FCB
- MVI C,MAKE
- CALL BDOS
- INR A ;FF=BAD
- RNZ ;OPEN OK
- ;DIRECTORY FULL - CAN'T MAKE FILE
- CALL ERXIT
- DB '++ERROR - CAN''T MAKE FILE',0DH,0AH
- DB '++DIRECTORY MUST BE FULL',0DH,0AH,'$'
- ;
- ; S U B R O U T I N E S
- ;
- ;OPEN FILE
- OPEN$FILE LXI D,FCB
- MVI C,OPEN
- CALL BDOS
- INR A ;OPEN OK?
- RNZ ;GOOD OPEN
- CALL ERXIT
- DB 'CAN''T OPEN FILE$'
- ; - - - - - - - - - - - - - - -
- PRINT$MESSAGE:
- MVI C,PRINT
- JMP BDOS ;PRINT MESSAGE, RETURN
- ; - - - - - - - - - - - - - - -
- ;EXIT PRINTING MESSAGE FOLLOWING 'CALL ERXIT'
- ERXIT POP D ;GET MESSAGE
- CALL PRINT$MESSAGE ;PRINT IT
- EXIT LHLD STACK ;GET ORIGINAL STACK
- SPHL ;RESTORE IT
- RET ;--EXIT-- TO CP/M
- ; - - - - - - - - - - - - - - -
- ;MODEM RECV
- RECV PUSH D ;SAVE
- MSEC LXI D,0BBBBH ;1 SEC DCR COUNT
- IF NOT TEST
- MWTI IN MODEM$CTL$PORT
- ANI MODEM$RECV$MASK
- CPI RECV$READY
- JZ MCHAR ;GOT CHAR
- ENDIF
- IF TEST
- MWTI IN KEY$CTL$PORT ;READ KEYBOARD
- ANI KEY$READY$MASK
- CPI KEY$READY
- JZ MCHAR
- ENDIF
- DCR E ;COUNT DOWN
- JNZ MWTI ;FOR TIMEOUT
- DCR D
- JNZ MWTI
- DCR B ;DCR # OF SECONDS
- JNZ MSEC
- ;MODEM TIMED OUT RECEIVING
- POP D ;RESTORE D,E
- STC ;CARRY SHOWS TIMEOUT
- RET
- ;GOT MODEM CHAR
- IF NOT TEST
- MCHAR IN MODEM$DATA$PORT
- ENDIF
- IF TEST
- MCHAR IN KEY$DATA$PORT
- ANI 7FH ;DEL PARITY FROM KEYBOAREAD
- ENDIF
- POP D ;RESTORE DE
- ;CALC CHECKSUM
- PUSH PSW
- ADD C
- MOV C,A
- ;CHECK IF MONITORING INPUT
- IN 0FFH
- ANI 10H
- JZ NO$MON$INPUT
- POP PSW
- PUSH PSW
- CALL SHOW ;CHAR RECEIVED
- NO$MON$INPUT:
- POP PSW
- ;TURN OFF CARRY TO SHOW NO TIMEOUT
- ORA A
- RET
- ; - - - - - - - - - - - - - - -
- ;MODEM SEND CHAR ROUTINE
- SEND PUSH PSW
- ;CHECK IF MONITORING OUTPUT
- IN 0FFH
- ANI 20H
- JZ NO$MON$OUTPUT
- POP PSW
- PUSH PSW
- CALL SHOW
- NO$MON$OUTPUT:
- POP PSW
- PUSH PSW
- ADD C ;CALC CKSUM
- MOV C,A
- SENDW IN MODEM$CTL$PORT
- ANI MODEM$SEND$MASK
- CPI SEND$READY
- JNZ SENDW
- POP PSW ;GET CHAR
- OUT MODEM$DATA$PORT
- RET
- ; - - - - - - - - - - - - - - -
- ;SHOW CHAR RECEIVED OR SENT
- SHOW CPI 0AH ;LF?
- JZ TYPE
- CPI 0DH
- JZ TYPE
- CPI 09 ;TAB
- JZ TYPE
- CPI ' '
- JC SHOWHEX
- CPI 7FH
- JC TYPE
- SHOWHEX PUSH PSW
- MVI A,'('
- CALL TYPE
- POP PSW
- CALL HEXO
- MVI A,')'
- JMP TYPE
- ; - - - - - - - - - - - - - - -
- ;PRINT TIMEOUT MESSAGE
- TOUTM DB 'TIMEOUT $'
- TOUT LXI D,TOUTM
- CALL PRINT$MESSAGE
- PRINT$ERRCT:
- LDA ERRCT
- CALL HEXO ;FALL INTO CR/LF
- ; - - - - - - - - - - - - - - -
- CRLF MVI A,13
- CALL TYPE
- MVI A,10
- ; - - - - - - - - - - - - - - -
- TYPE PUSH PSW
- PUSH B
- PUSH D
- PUSH H
- MOV E,A
- MVI C,WRCON
- CALL BDOS
- POP H
- POP D
- POP B
- POP PSW
- RET
- ; - - - - - - - - - - - - - - -
- ;HEX OUTPUT
- HEXO PUSH PSW
- RAR
- RAR
- RAR
- RAR
- CALL NIBBL
- POP PSW
- NIBBL ANI 0FH
- CPI 10
- JC ISNUM
- ADI 7
- ISNUM ADI '0'
- JMP TYPE
- ; - - - - - - - - - - - - - - -
- ;FILE READ ROUTINE
- READ$SECTOR:
- LXI D,FCB
- MVI C,READ
- CALL BDOS
- ORA A
- RZ
- DCR A ;EOF?
- JNZ RDERR
- ;EOF
- XRA A
- STA ERRCT
- LXI D,FSENTM ;FILE SENT MESSAGE
- CALL PRINT$MESSAGE
- SEOT MVI A,EOT
- CALL SEND
- MVI B,5 ;WAIT 5 SEC FOR TIMEOUT
- CALL RECV
- JC EOTTOT ;EOT TIMEOUT
- CPI ACK
- JZ XFER$CPLT
- ;ACK NOT RECIEVED
- CALL HEXO
- LXI D,ERR1
- CALL PRINT$MESSAGE
- EOTERR LDA ERRCT
- INR A
- STA ERRCT
- CPI ERROR$LIMIT
- JC SEOT
- CALL ERXIT
- DB 'NO ACK RECIEVED ON EOT$',10,13
- FSENTM DB 13,10,'FILE SENT, SENDING EOT''S',10,13,'$'
- ;TIMEOUT ON EOT
- EOTTOT CALL TOUT
- JMP EOTERR
- ;READ ERROR
- RDERR CALL ERXIT
- DB '++FILE READ ERROR$'
- ; - - - - - - - - - - - - - - -
- ;DONE - CLOSE UP SHOP
- XFER$CPLT:
- CALL ERXIT
- DB 13,10,'TRANSFER COMPLETE$'
- DS 40 ;STACK AREA
- STACK DS 2 ;STACK POINTER
- RECVD$SECT$NO DB 0
- SECTNO DB 0 ;CURRENT SECTOR NUMBER
- ERRCT DB 0 ;ERROR COUNT
- ;
- ; BDOS EQUATES (VERSION 2)
- ;
- RDCON EQU 1
- WRCON EQU 2
- PRINT EQU 9
- CONST EQU 11 ;CONSOLE STAT
- OPEN EQU 15 ;0FFH=NOT FOUND
- CLOSE EQU 16 ; " "
- SRCHF EQU 17 ; " "
- SRCHN EQU 18 ; " "
- ERASE EQU 19 ;NO RET CODE
- READ EQU 20 ;0=OK, 1=EOF
- WRITE EQU 21 ;0=OK, 1=ERR, 2=?, 0FFH=NO DIR SPC
- MAKE EQU 22 ;0FFH=BAD
- REN EQU 23 ;0FFH=BAD
- STDMA EQU 26
- BDOS EQU 5
- REIPL EQU 0
- FCB EQU 5CH ;SYSTEM FCB
-