home *** CD-ROM | disk | FTP | other *** search
- ;
- ; TITLE CYBER communications uitilty
- ; FILENAME CYBER.ASM
- ; AUTHOR Robert A. Van Valzah 01/22/80
- ; LAST REVISOR R.A.V. 01/30/80
- ; REASON add sherwood light display of buffer status
- ;
- vdm equ 0 ;buffer status to vdm upper right corner
- shrwood equ 0ffffh ;buffer status to sherwood digits
- ;
- ;
- ; This code performs on-line communications with a time sharing
- ; system using a modem. Additionally, recieved characters may
- ; be printed. Buffering is provided so that the printer may
- ; run slower than the modem without loosing characters. It is
- ; assumed that the modem can keep up with input from the
- ; console.
- ;
- ;
- ; Several I/O devices are used in this program and they are
- ; refered to by three letter mnemonic names as follows:
- ; con opperators console
- ; mod modem
- ; prn physical printer
- ; prq logical printer (this is a queue)
- ; dsk disk file
- ;
- ;
- ; data flow diagrams
- ;
- ; when conist=ready conin -> modout
- ;
- ; when modist=ready modin -> conout
- ; if prnt=true modin -> prqout
- ;
- ; when prqist=ready and prnost=ready
- ; prqin -> prnout
- ;
- ; when modost=ready
- ; if trns=true dskin -> modout
- ;
- ;
- ; cp/m interface equates
- ;
- ifcb equ 5ch
- bdos equ 5
- print equ 9
- open equ 15
- readrec equ 20
- setdma equ 26
- ;
- ;
- org 100h
- entry:
- jmp main ;jump around subroutines to main line
- ;
- ; print signon message
- ;
- signon:
- call sing1
- db 'CYBER communications utility 01/25/80'
- db 13,10,'$'
- sing1:
- pop d ;get address of message
- mvi c,print
- call bdos
- ret
- ;
- ; initialize the modem for communications
- ;
- modinit:
- mvi a,3 ;magic bytes for 300 baud
- out 4
- mvi a,51h
- out 4
- ret
- ;
- ; get modem output status
- ; reg a=0h if not ready, 0ffh if ready
- ;
- modost:
- in 4
- ani 2
- rz
- mvi a,0ffh
- ret
- ;
- ; send character from reg c to modem
- ;
- modout:
- call modost
- ora a
- jz modout
- mov a,c
- out 5
- ret
- ;
- ; get modem input status
- ; reg a = 0ffh if ready, 0h if not
- ;
- modist:
- in 4
- rar
- sbb a ;hack
- ret
- ;
- ; modem input charcter from line to reg a
- ;
- modin:
- call modist
- ora a
- jz modin
- in 5
- ani 7fh
- ret
- ;
- ; printer port i/o number equates
- ;
- base equ 0f4h
- datal equ base
- datah equ base+1
- cmand equ base+2
- stats equ base
- ;
- ; print formatting equates
- ;
- ncols equ 120 ;max number of cols/line (must be <=126)
- ;
- ; command bits
- ;
- restr equ 1 ;restore carriage
- chstb equ 2 ;character strobe
- xstb equ 4 ;carriage strobe
- ystb equ 8 ;paper feed strobe
- selpr equ 10h ;select printer
- selry equ 20h ;select ready
- rblft equ 40h ;ribbon lift
- ;
- ; status bits
- ;
- chrdy equ 8 ;character ready
- xrdy equ 10h ;carriage ready
- yrdy equ 20h ;paper feed ready
- ;
- ;
- ; print character in reg c
- ;
- prnout:
- mov a,c ;get char to print to reg a
- ani 7fh ;strip parity
- mov c,a
- lhld nbufad ;and pointer to next buffer address
- cpi 13 ;test for special characters
- rz ;ignore carriage return
- cpi 10
- jz plf ;line feed
- cpi 12
- jz pff ;form feed
- inr m ;assume a space
- cpi ' '
- rz ;was a space, all done
- dcr m ;un-do assumption
- rc ;was some other control char, ignore
- ;must be a printable character
- mov a,l ;see if buffer is about overflow
- cpi low(buf+ncols-2)
- rz
- cpi low(buf) ;see if this is first character
- mov a,m ;get amt to move before printing
- jz gotamt ;jump if first character
- cpi 81h
- jz noblank ;no blanks between last & this char
- sui 80h ;subtract flag value
- gotamt: ;amount to move in reg a
- inx h ;move over number of blanks
- db 11h ;lxi trick to skip following mvi a
- noblank:
- mvi a,1 ;like one blank between character
- mov m,c ;store the character comming in
- inx h ;point to next buffer location
- mvi m,81h ;init to one blank to next char
- shld nbufad ;update buffer pointer
- lxi h,reolpos ;update right end of line position
- add m
- mov m,a
- ret
- ;
- ; print line feed
- ;
- plf:
- mov a,l ;see if nbufad = buf
- cpi low(buf) ;if = then blank line
- jz prndone ;=, so don't print anything
- lda leolpos ;get left end of line position
- mov b,a ;save it in reg b
- lda reolpos ;get right end of line position
- add b ;add leolpos to reolpos
- rar ;divide by two to find midpoint
- mov b,a ;save line center point in reg b
- lda hpos ;get current head position
- sub b ;hpos-(leolpos+reolpos)/2
- jc forward ;middle > hpos
- ;
- ; print the buffer backward
- ;
- backward:
- mvi a,80h ;put end of buffer marker at left end
- sta buf
- lda reolpos ;get absolute position of right eol
- lxi h,hpos ;compute amount to move to get there
- sub m ;reolpos-hpos
- lhld nbufad ;get rightmost char to print
- dcx h
- call movprt ;move and print rightmost
- dcx h ;point to next char to print
- shld pbufad ;store pointer to next amt or char
- mvi a,2 ;set backward printing flag
- sta dirf
- ret
- ;
- ; print buffer forwards
- ;
- forward:
- mvi m,80h ;put in eob mark (also ignores trailing blanks)
- lxi h,buf ;pointer into buffer
- mov a,m ;absolute pos of leftmost char to reg a
- inx h ;point to first printable character
- push h ;save buffer pointer
- lxi h,hpos ;compute amount to move to get to leolpos
- sub m ;leolpos-hpos
- pop h ;restore buffer pointer
- call movprt ;move to and print leftmost char
- inx h ;point to next
- shld pbufad ;store pointer to next amt or char
- mvi a,1 ;set printing forward flag
- sta dirf
- ret
- ;
- ; print a form feed
- ;
- pff:
- lda lpp ;get lines per page
- lxi h,lonp ;subtract lines printed on this page
- sub m ;leaving lines left on this page
- sta lfstodo ;which is the number of lfs to do
- ret
- ;
- ; service printer
- ;
- prnserv:
- in stats ;is printer ready for another char?
- ani chrdy+xrdy+yrdy
- rnz ;no - can't service it now
- lda dirf ;printing?
- ora a
- rz ;no - no servicing to do
- cpi 1 ;set z if printing forward
- lhld pbufad ;pointer to next amt to move
- mov a,m ;amt to move to reg a
- jz fwd1
- bkwd1:
- ;signed distance to move is now in reg a
- sui 80h ;test for eob mark
- jz prndone ;found eob
- dcx h ;assume this is a movement
- cma ;two's comp for leftward movement
- inr a
- jnc bkwd2 ;it was, reg a has amount to move
- inx h ;it wasn't, fix buffer pointer
- mvi a,0ffh ;move one space to the left
- bkwd2:
- call movprt ;print the character
- dcx h ;point to next movement or chr
- shld pbufad
- ret
- fwd1:
- sui 80h ;test for end of line
- jz prndone ;hit end of line
- inx h ;point to character
- jnc fwd2 ;was a movement, reg a has distance
- dcx h ;was a character, backup pointer
- mvi a,1 ;and set amount to move to 1
- fwd2:
- call movprt ;print character
- inx h ;point to next movement or chr
- shld pbufad
- ret
- ;
- ; common finish up routine for printer service
- ;
- prndone:
- lxi h,lfstodo ;add one to line feeds to do before
- inr m ;printing next line
- xra a ;reset printer status to not printing
- sta dirf
- jmp init1 ;reset pointers
- ;
- ; move the number of character positions in reg a (taken as a
- ; signed number, + to the right, - to the left) and
- ; print the character pointed to by reg hl.
- ;
- movprt:
- mov c,m ;get character to print
- push h ;save while printing
- mov e,a ;save amount to move in reg e
- lxi h,hpos ;update the head position byte
- mov a,e
- add m ;add amount we are moving
- mov m,a
- mvi b,xstb ;ready x strobe for movstb
- lda chwid ;load up character muliplicaton factor
- call movstb ;send necessary x movement
- lda lpp ;lines per page to reg b
- mov b,a
- lxi h,lfstodo ;number of pending line feeds
- mov a,m ;skip movement if zero
- ora a
- jz noymov ;no y movement
- mov e,a ;movement to reg e for movstb
- mvi m,0 ;there will be none to do now
- lxi h,lonp ;keep track of line on page
- add m
- mov m,a
- sub b ;see if started new page
- jc samepage ;nope
- mov m,a ;yes - take lonp mod lpp
- samepage:
- lda linhgt ;load up line multiplicaton factor
- mvi b,ystb ;ready y strobe for movstb
- call movstb ;send necessary y movement
- noymov:
- mov e,c ;send character
- mvi b,chstb ;send character strobe
- mvi a,1 ;dummy multiplication factor
- call movstb
- pop h
- ret
- ;
- ; move the signed amount in reg e using value in reg a as
- ; a mulitplication factor to get the number of increments
- ; then send strobe in reg b.
- ;
- movstb:
- push psw ;save multiplication factor
- mov a,e ;form a 16 bit amount to move in reg de
- ral ;sign of movement into carry
- sbb a ;generate sign extention
- mov d,a ;16-bit signed movement now in reg de
- pop psw ;get multiplication factor
- lxi h,0 ;initialize product
- mulbyw: ;multiply
- dad d
- dcr a
- jnz mulbyw ;keep multiplying
- mov a,h ;is this leftward movement?
- ora a
- jp posmov ;no - distance is ok
- xra a ;yes - negate distance
- sub l ;reg a = 0 - low order
- mov l,a ;which is low order compliment
- sbb h ;now subtract out high order and
- sub l ;subtract out excess low order
- ;complimented distance now in reg a and reg l
- ori 4 ;and set negative motion bit
- posmov:
- cma ;high order data is active low
- out datah ;send high order data
- mov a,l ;get low order data
- cma ;it too is active low
- out datal ;send low order data
- ;fall thru to strobe
- ;
- ; pulse strobe in reg b
- ;
- strobe:
- xra a ;delay a while for data set-up time
- dlay:
- dcr a
- jnz dlay
- mvi a,0ffh-selpr-rblft-selry
- push psw ;save bits which are allways high
- sub b ;lower appropriate strobe bit
- out cmand ;send strobe bit low
- pop psw ;and send it high
- out cmand
- ret
- ;
- ; printer output status
- ; return reg a = 0h if not ready, 0ffh if ready
- ;
- prnost:
- lda dirf ;printing from buffer now?
- ora a
- mvi a,0ffh ;prepare no
- rz ;no - therefore ready for more
- cma ;yes
- ret
- ;
- ; init for printing
- ;
- prninit:
- mvi b,restr ;pulse restore line to
- call strobe ;reset printer
- xra a ;set software head position to zero
- sta hpos
- sta lonp ;reset line counter to top of page
- sta lfstodo ;zero out number of line feeds to do
- init1: ;empty buffer entry point
- xra a ;reset right end of line position
- sta reolpos
- lxi h,buf ;next buffer address pointer
- shld nbufad
- mov m,a ;inits left end of line position
- ret
- ;
- ;
- ; initialize jump vectors to CBIOS
- ;
- initjmp:
- lhld 1
- lxi d,3 ;length of jmp inst
- dad d
- shld const+1
- dad d
- shld conin+1
- dad d
- shld conout+1
- ret
- ;
- ; initialize ram
- ;
- initram:
- xra a
- sta exitflg ;reset exit flag
- sta prntflg ;reset echo to printer flag
- sta trnsflg ;reset transmit disk file flag
- sta dirf ;set printer status to idle
- ret
- if shrwood
- ;
- ; divide reg hl by negaive amount in reg bc,
- ; remainder (8-bits) in reg a, qoutient in reg hl
- ;
- div:
- mvi a,-1 ;init remainder
- submor:
- dad b
- inr a ;inc remainder
- jc submor ;still positive
- push psw ;save remainder
- mov a,b!cma!mov b,a!mov a,c!cma!mov c,a!inx b ;two's comp
- dad b
- pop psw
- ret
- ;
- ; contents of register hl to sherwood digits
- ;
- litout:
- lxi b,-100 ;set for hundreds digit
- call div ;get most sig digit to reg a
- rlc ! rlc ;rotate into position
- mov e,a ;save it in reg e
- lxi b,-10 ;set for tens digit
- call div ;next sig digit to reg a
- push psw ;save it
- rar ! rar ! ani 3 ;get 2 ms bits
- ora e ;or in ms digit
- out 0c5h
- pop psw ;get middle digit again
- ani 3 ! rlc ! rlc ! rlc ! rlc
- mov e,a ;save 2 ls bits of middle
- lxi b,-1 ;set for units digit
- call div ;get ls digit
- ora e ;or in middle digit
- out 0c7h
- ret
- ;
- ; initialize digits on sherwood front pannel
- ;
- initlit:
- xra a ;set both pia's to control mode
- out 0c4h
- out 0c6h
- cma ;set all bits to output mode
- out 0c5h
- out 0c7h
- mvi a,4 ;set both pia's back to data mode
- out 0c4h
- out 0c6h
- ret
- endif ;end of if shrwood
- ;
- ; compare register hl to de
- ;
- cmpr:
- mov a,h
- cmp d
- rnz
- mov a,l
- cmp e
- ret
- ;
- ; initialize printer queue
- ;
- prqinit:
- lxi h,qlow
- shld qiptr
- shld qoptr
- ret
- ;
- ; get printer queue input status
- ; return reg a = 0ffh if ready, 0h if not
- ;
- prqist:
- lhld qoptr ;is next full byte
- xchg
- lhld qiptr ;equal to next empty byte?
- call cmpr
- mvi a,0
- rz ;yes - queue is empty
- cma
- ret
- ;
- ; test for queue pointer in reg hl wrapping memory and
- ; reset if so
- ;
- wrapq:
- xchg ;save new ptr
- lhld qhigh ;upper limit
- xchg
- call cmpr
- rnz ;new ptr is ok
- lxi h,qlow ;have to wrap back to start
- ret
- ;
- ; show queue fullness status
- ;
- showqst:
- lhld qoptr
- xchg
- lhld qiptr
- call cmpr
- jnc noswap ;qiptr>qoptr
- xchg
- noswap:
- ;16-bit subtract hl=hl-de
- mov a,l!sub e!mov l,a!mov a,h!sbb d!mov h,a
- ;number of character in buffer now in reg hl
- if shrwood
- call litout ;send to lights
- endif
- if vdm
- mov a,l
- sta 0cc3fh ;upper right hand corner of screen
- endif
- ret
- ;
- ; get a character from printer queue to reg a
- ; assumes that the queue is not empty
- ;
- prqin:
- lhld qoptr ;pointer to next full byte
- mov a,m ;get a character
- push psw ;and save it
- inx h ;point to next full byte
- call wrapq ;reset pointer when memory wraps
- shld qoptr ;store new pointer
- call showqst ;show queue fullness status
- pop psw ;restore charcter from queue
- ret
- ;
- ; send character from reg c to printer queue
- ;
- prqout:
- lhld qiptr ;is queue empty?
- ;******overflow test goes here
- mov m,c ;put it in place
- inx h ;point to next byte to fill
- call wrapq ;fix pointer if wrapping memory
- shld qiptr
- call showqst ;display queue fullness
- ret
- ;
- ; dskinit sets diflg to 0ffh (true) if input filename is
- ; prestent and open is successfull
- ;
- dskinit:
- lda 5dh ;first name byte of fcb1
- mvi b,0 ;prepare diflg value
- cpi ' ' ;blank means no name present
- jz set1
- cpi '?' ;? means not present too
- jz set1
- dcr b ;reg b = 0ffh
- set1:
- mov a,b ;get diflg value
- sta diflg ;store it
- ora a ;was a name provided?
- rz ;no - skip open stuff
- xra a ;zap fcbnr
- sta ifcb+32
- lxi d,ifcb
- mvi c,open
- call bdos
- inr a
- jz dskerr ;not found
- lxi h,ibuf+80h ;init input buffer pointer
- shld iptr
- ret
- dskerr:
- lxi d,errmsg
- mvi c,print
- call bdos
- jmp 0
- errmsg db 'file not found',13,10,'$'
- ;
- ; get disk input status
- ; return reg a = 0ffh if ready, 0h if not
- ;
- dskist:
- lda diflg ;was a filename present?
- ret
- ;
- ; get a character from the disk input file
- ; return char in reg a
- ;
- dskin:
- lhld iptr
- mov a,l
- cpi low(ibuf+80h)
- jnz noread ;dont have to read record
- lxi d,ibuf
- mvi c,setdma
- call bdos
- mvi c,readrec
- lxi d,ifcb
- call bdos
- ora a
- jz readok ;got good data
- cpi 1 ;read past eof?
- jnz dskerr ;no - all that leaves is error
- lxi h,ibuf ;yes - fake eof with control z
- mvi m,26
- readok:
- lxi d,80h ;restore dma address
- mvi c,setdma
- call bdos
- lxi h,ibuf
- noread:
- mov a,m ;get character
- inx h
- shld iptr ;update pointer
- cpi 26 ;was eof just read?
- rnz ;no - just return with char
- xra a ;yes - reset di flag
- sta diflg
- sta trnsflg ;and transmit file flag
- lxi d,eofmsg ;send eof message
- mvi c,9
- call bdos
- mvi a,26 ;restore eof char
- ret
- ;
- eofmsg db 13, 10, 'Transmission complete.', 13, 10, '$'
- ;
- ; service disk input
- ;
- dskserv:
- lda trnsflg ;are we transmitting a file?
- ora a
- rz ;no - no servicing to do
- call dskist ;is disk input ready?
- ora a
- rz ;return if not
- call modost ;is modem ready for another?
- ora a
- rz ;return if not
- call dskin ;is ready - go get character
- mov c,a ;pass to modout
- call modout
- ret
- ;
- ; service printer queue
- ;
- prqserv:
- call prqist ;does queue have any characters?
- ora a
- rz ;no - can't service it
- call prnost ;yes - is printer ready for more?
- ora a
- rz ;no - leave chars in queue
- call prqin ;yes - get character from queue
- mov c,a ;and send it to priner
- call prnout
- ret
- ;
- ; decode control characters entered from console
- ; return z flag set if control char was found
- ;
- decode:
- cpi 5 ! lxi h,exitflg ! jz compflg
- cpi 16! lxi h,prntflg ! jz compflg
- cpi 20! lxi h,trnsflg ! jz compflg
- ret ;none of the above
- compflg:
- mov a,m ;get present flag value
- cma ;compliment
- mov m,a ;and put back complimented
- xra a ;set z flag
- ret
- ;
- ; service console
- ;
- conserv:
- call const ;any character waiting?
- ora a
- rz ;no - no serving to do
- call conin ;yes - go get it
- mov c,a ;save charater for echo
- call decode ;set flags from control chars
- rz ;don't send if local control char
- call modout ;send char to CYBER
- ret
- ;
- ; service modem
- ;
- modserv:
- call modist ;any character waiting?
- ora a
- rz ;no - no serving to do
- call modin ;yes - go get it and . . .
- mov c,a ;send it to the console
- push b ;save it for the printer
- call conout
- pop b ;get character back
- lda prntflg ;are we echoing to printer?
- ora a
- rz ;no - all done here
- call prqout ;yes - send to the printer queue
- ret
- ;
- ; main line code
- ;
- main:
- lxi sp,stack
- call signon ;print signon message
- call initram ;initialize ram
- call initjmp ;initialize jump vectors to CBIOS
- if shrwood!call initlit!endif
- call modinit ;initialize modem
- call prqinit ;initialize printer queue to empty
- call prninit ;initialize printer
- call dskinit ;initialize disk
- work:
- call conserv ;service console
- call modserv ;service modem
- call prnserv ;service printer
- call prqserv ;service printer queue
- call dskserv ;service disk
- lda exitflg ;until exit is true
- ora a
- jz work ;keep working
- jmp 0 ;reboot CP/M
- ;
- ; initialized ram areas
- ;
- ; CBIOS jmp vectors
- ;
- const jmp $-$ ;will be filled in by initjmp
- conin jmp $-$
- conout jmp $-$
- ;
- ; ram parameter area
- ;
- linhgt db 8 ;line height in increments
- chwid db 6 ;character width in increments
- lpp db 66 ;lines per page
- ;
- qhigh dw 1000h ;pointer to start of printer queue
- ;
- ; uninitialized ram areas
- ;
- lonp ds 1 ;current line on page, 0 = first line
- lfstodo ds 1 ;line feeds to do before printing
- hpos ds 1
- reolpos ds 1
- nbufad ds 2
- buf:
- leolpos: ;address of byte containing left eol
- ds 1
- lmostch: ;address of left most character
- ds ncols
- ;
- exitflg ds 1 ;nonzero when time to return to CP/M
- prntflg ds 1 ;nonzero when echoing to printer
- trnsflg ds 1 ;nonzero when transmitting a disk file
- ;
- dirf ds 1 ;0=idle, 1=printing forward, 2=backward
- ;
- diflg ds 1 ;nonzero if disk input file present
- ;
- iptr ds 2 ;pointer to next char to read from ibuf
- ibuf ds 128 ;disk input buffer
- ;
- pbufad ds 2 ;next address to print from buffer
- ;
- qiptr ds 2 ;pointer to next empty byte in queue
- qoptr ds 2 ;pointer to oldest full byte in queue
- ;
- ds 30 ;stack space
- stack:
- ;
- qlow: ;start of printer queue
- ;
- end entry
-