           ttl     Terminal I/O Routines
*
.   Polled Terminal I/O Drivers for uPD7201 in MP-S4 Configuration
.
term_io    proc

via        equ     $E890               VIA for X-12 Comm.


*
.   string display driver
.
newline    bsr     outch               dump the carriage return
           lda     #lf
putch      bsr     outch               output a single character
pdata:     lda     0,x+                get next byte of data
           beq     pexit
           cmpa    #cr                 check for carriage return
           beq     newline
           cmpa    #etx                see if end of text
           bne     putch               loop if not
pexit      rts
*
.   output spaces routines
.
outsp:     pshs    a                   save a register on stack
           lda     #" "                load a space character
           bsr     outch               output the character
           ret     a
*
.   get an extended address
.
getaddr:   bsr     getbyte             get segment number
           bcs     hexit
           pshs    a                   save segment on stack
           bsr     getoff
           tfr     d,x                 put offset into X register
           ret     a
*
.   get a 12-bit hex offset
.
getoff     bsr     gethex              get high order nybble
           bcs     hexit               exit if invalid
           tfr     a,b                 keep value in B register
           bsr     getbyte             get low order byte
           exg     b,a                 swap the two bytes
           rts
*
.   get a hex byte
.
getbyte:   bsr     gethex              get first hex digit
           bcs     hexit
           lsla; lsla; lsla; lsla      shift high order bits left
           sta     0,-s
           bsr     gethex              get next hex digit
           bcs     clrout
           ora     0,s+                or in the high order bits
           rts
clrout     leas    1,s
           sec
hexit      rts
*
.   get a hex digit
.
gethex:    bsr     inch                get input character
           cmpa    #"0"                check digits out first
           blo     nothex
           cmpa    #"9"                check uppermost digit
           bls     digit               if in range, return it
           cmpa    #"A"                check lower end of upper range
           blo     nothex
           cmpa    #"F"                check upper end of range
           bhi     nothex              if higher, not valid hex
*
.   return with the proper value or with carry set
.
           suba    #"A"-"0"-10         bias to make valid
digit      suba    #"0"                bias again to fix it
           rts
nothex     scc     c                   set carry to show it
           rts
*
.   output an offset in hex
.
hexword:   bsr     hexbyte             go do the bottom half
           bra     hexbot
hexoff:    bsr     hexdig              output msp from A register
hexbot     tfr     b,a                 get lsp into A register
*
.   output a byte in hex
.
hexbyte:   pshs    a                   save data on stack
           lsra; lsra; lsra; lsra      shift right four bits
           bsr     hexdig              output the left digit
           puls    a
*
.   output a digit in hex
.
hexdig:    anda    #$0F                strip off the high order bits
           adda    #"0"                bias to make an ascii digit
           cmpa    #"9"                see if in valid range
           bls     outch               if so, output the character
           adda    #"A"-"0"-10         re-bias to make into ascii
           bra     outch
TTYOFF     equ     4
TTYON      equ     8
*
.   test for an input character available
.
incheck:   pshs    d                   save register on stack
           lda     via+13              check for pending character
           bita    #$02                ..
           beq     chkout              ..
           ldb     via+15              get non-handshake A data
           bitb    #$80                check for first byte
           beq     clearit             if not, FROGGED CYCLES
           lsrb;lsrb                   scoot it over
           andb    #$0F                check for XON style byte
           beq     chkout1             is not some sort of control
*
.   special line control characters handled here
.
           lda     via+1               get first half of data
           cmpb    #TTYOFF             check for XOFF
           bne     notxoff
           ldb     uniscratch
           orb     #cpu_xoff           say XOFF
           stb     uniscratch
           bra     clearit
notxoff    cmpb    #TTYON              check for XON
           bne     notxon
           ldb     uniscratch
           andb    #~cpu_xoff          say XON
           stb     uniscratch
notxon                                 some other kind of control
                                       for now, forget them.
clearit
           lda     via+13              wait for second byte to come around
           bita    #$02                data?
           beq     clearit
           lda     via+1               get second half of data
           lda     #0                  EQ (no data)
chkout     ret     d                 restore and return as incheck always does
chkout1    lda     #1                   NE (data)
           ret     d
*
.   get an input character from the terminal without echo
.
rawinch:   pshs    b
raw1       bsr     incheck             get status
           beq     raw1
           ldb     via+1               get data byte from A side
raw2       lda     via+13
           bita    #$02
           beq     raw2
           lda     via+1               get second half of data
           rola                        now combine pieces
           rola
           lsrb
           rora
           lsrb
           rora
           ret     b
*
.   get an input character from the terminal with echo
.
inch:      bsr     rawinch
*
.   check for control character
.
           cmpa    #" "                check against control limit
           bhs     notctrl
           pshs    a                   save character on stack
           cmpa    #cr
           beq     inchex              don't echo carriage returns
*
.   echo as control character
.
           lda     #"^"                output a "control" indication
           bsr     outch
           lda     0,s                 get back the character
           adda    #"@"
           bsr     outch               echo converted control
inchex     ret     a
*
.   if lower case alphabetic, force it into upper case
.
notctrl    cmpa    #"a"
           blo     outch               check lower limit of range
           cmpa    #"z"
           bhi     outch               check upper limit of range
           suba    #" "                bias to make upper case
*
.   output a character to the terminal
.
outch:
           bsr     waitxon             go wait around till XON occurs
           pshs    d
           pshs    a
           clrb
           asla                        move D7 to Carry
           rolb
           asla
           rolb
           orb     #$80                make no device control
outchw     lda     via+13              get IFR
           bita    #$10                check for output busy
           beq     outchw
           stb     via                 write data to B side
outchlo    lda     via+13
           bita    #$10
           beq     outchlo
           puls    a
           anda    #%00111111
           sta     via                 put low byte on via

outout     ret     d

*
.   this routine waits until terminal allows transmission through XON
.
waitxon    pshs    b,cc
waitxon1   bsr     incheck             go check for input
           bne     waitout             any real input, skip out
           ldb     uniscratch          check for XOFF
           bitb    #cpu_xoff           ttyoff bit
           bne     waitxon1            go wait some more
waitout    ret     b,cc

*
.   initialization for terminal interface
.
tinit:     pshs    a                   save regs
           lda     uniscratch
           anda    #~cpu_xoff
           sta     uniscratch          restore saying ok to talk
           lda     #%10111111          all but PB6 output
           sta     via+2               set B side to output
           clr     via+3               set A side to input
           clr     via
           clr     via+1
           lda     #$88                handshake i/o
           sta     via+12
           lda     #$3                 latched i/o
           sta     via+11
           lda     #$12                disable ca1 and cb2
           sta     via+14
           lda     via+15
           bmi     outinit
           lda     via+1               get funny fakey
outinit    lda     #$80
           sta     via                 write starting null to wake up
outchoo    lda     via+13
           bita    #$10
           beq     outchoo
           lda     #$00
           sta     via                 put low byte on via
           ret     a

*
.   stuff a bit of delay in here
.
delay      ldd     #14286
delay1     subd    #1                  delay at least 50 mS or so
           bne     delay1
           ret

           end
