;*; Updated on 25-Nov-91 at 8:34 AM by Michele Tonti; edit time: 0:00:13
;   UPDATED ON 30-NOV-93 FOR ROADRUNNER BY MP.WSOL ,ALPHA MICROSYSTEMS
;*************************** AMUS Program Label ******************************
; Filename: PI16IF.M68                                      Date: 11/25/91
; Category: TDV          Hash Code: 266-204-704-055      Version:
; Initials: GR/AM        Name: James A. Jarboe IV
; Company: Educational Video Network, Inc.         Telephone #: 4092955767
; Related Files:
; Min. Op. Sys.:                               Expertise Level:
; Special:
; Description: Modified version of Piiceon's 16 port I/O board smart driver.
; It can be conditionally assembled to work with AMOS/L 1.3C or less or AMOS/L
; 1.3D or greater (including 2.x)
;*****************************************************************************
;*; Updated on 23-Nov-91 at 4:14 AM by James A. Jarboe I V; edit time: 2:12:39
;
;
;       MODULE NAME: PI16IF.M68
;       DATE: 12/2/85
;       MODIFIED: 1/8/86 - MODIFIED BAUD RATE TABLE
;                4/15/86 - MODIFIED FOR REV F BOARD
;
;  2.0  [100] 12-Nov-91 by James A. Jarboe I V
;             Added option to assemble with PHDR and COMSER stuff for
;             2.x Systems.
;[101] 06 February 1992 05:42   Edited by InterLink Systems, Inc.
;       Changed to properly support Dimension-030
;[102] 12 February 1992 08:58   Edited by InterLink Systems, Inc.
;       Changed WZ80 to a loop without timed exit.
;[103] 26 March 1992 08:58      Edited by InterLink Systems, Inc.
;       Added delay to enhance robustness.
;[104] 14 April 1992 09:31      Edited by InterLink Systems, Inc.
;       Removed unneeded delays & added needed SVLOK's
;[105] 11 May 1992 12:52        Edited by InterLink Systems, Inc.
;       Added SSTS and LSTS to save Interrupt level
;******************************************************************************
;[106] 30 NOV 1993 12:00        Edited by Mike Wsol, ALPHA MICROSYSTEMS
;       UPDATE FOR ROADRUNNER SUPPORT, 32 bit addressing
;       Assemble with /V:0 for AMOS  2.2C(452)-3 Roadrunner Release
;   will only work with Revision F and Later Revision boards, Rev B will
;   trmdef but will not communicate. The board design is radically different.
;****************************************************************************\
;       SMART 16 PORT DRIVER
;
; This version of the PIICEON 16 Port smart driver has been modified
; so that it can be conditionally assembled to work on AMOS/L systems
; with an OS Version of 1.3C or less or 1.3D or greater.
;
; The Additions that where made:
;       Added PHDR for new style drivers.
;       Added Flag word for new style drivers.
;       Added GETPIN and SETPIN vector offsets
;
;  !**NOTE**! 13-Nov-91 12:41 AM
;
;  This current version 2.0(100) HAS BEEN tested with a PIICEON 16 port
;  board with AMOS 2.2 and it works!
;  The only problem, if any, would be the logic
;  of setting the pins at SETPIN:. This may not be compatible with
;  the PI16 port board. If not, it can be modified using the WZ80 logic
;  that is used. Let me know.
;
; Conditional Assembly:
;      /V:1  = AMOS/L 1.3C or less            - 404-313-521-455
;      /V:0  = AMOS/L 1.3D or greater         - 266-056-156-034  2.0(100)
;

       SEARCH  SYS
       SEARCH  SYSSYM
       SEARCH  TRM

       OBJNAM PI16IF.IDV

       NVALU   OPTION

       ASMMSG  "                                        "
       IF      EQ,OPTION
       ASMMSG  "Assembling PI16IF for AMOS/L 1.3D or greater "
       IFF
       ASMMSG  "Assembling PI16IF for AMOS/L 1.3C or less    "
       ENDC
       ASMMSG  "                                        "

       PAGE
;***************************************************************************
;                                                                          *
;                       C U R R E N T    V E R S I O N                     *
;                                                                          *
;***************************************************************************
;
       VMAJOR  =       2               ;
       VMINOR  =       0
       VWHO    =       0
       VSUB    =       0
       VEDIT   =       106.            ;MPWsol


       PAGE
;***************************************************************************
;                                                                          *
;                            C O N S T A N T S                             *
;                                                                          *
;***************************************************************************
;
;Define 2681 Status Register Bits

ST$RDRF =       0               ; 1 = Receive Data Register Full
ST$TRDY =       2               ; 1 = Transmit holding register empty

;Define 2681 Command Register Bits

CM$RMRP =       20              ; Reset mode register pointer
CM$RRCV =       40              ; Reset receiver
CM$RTXM =       60              ; Reset transmitter
CM$REST =       100             ; Reset error status
CM$RXEN =       1               ; Receiver enable
CM$RXDI =       2               ; Receiver disable
CM$TXEN =       4               ; Transmitter enable
CM$TXDI =       10              ; Transmitter disable

; Define 2681 Mode Register 1 bits

M1$8B   =       3               ; 8 bits per character
M1$NP   =       20              ; No parity

; Define 2681 Mode Register 2 bits

M2$1SB  =       7               ; 1 stop bit
M2$2SB  =       17              ; 2 stop bits
M2$NM   =       0               ; Normal channel mode
M2$CET  =       20              ; CTS enables transmitter

; Define 2681 Interrupt Mask Register bits

IM$TXRD =       1               ; Interrupt on transmitter ready
IM$RXRD =       2               ; Interrupt on receiver ready

; Define 2681 Interrupt Status Register bits

IS$TRA  =       1               ; Transmitter ready A
IS$RRA  =       2               ; Receiver ready A
IS$TRB  =       20              ; Transmitter ready B
IS$RRB  =       40              ; Receiver ready B

;Define I/O Port Offsets

;These are defined as offset to the base of the serial port block.

P.MDR   =       0               ; Mode Register (Input & Output)
P.SR    =       1               ; Status Register (Input)
P.CLK   =       1               ; Clock Select Register (Output)
P.CMR   =       2               ; Command Register (Output)
P.RCV   =       3               ; Receiver Holding Register (Input)
P.TXM   =       3               ; Tranmitter Holding Register (Output)
P.ACR   =       4               ; Auxiliary Control Register (Output)
P.ISR   =       5               ; Interrupt Status Register (Input)
P.IMR   =       5               ; Interrupt Mask Register (Output)
P.OCR   =       15              ; Output port configuration register(Output)
P.SOB   =       16              ; Set output port bits register(Output)
P.ROB   =       17              ; Reset output port bits register(Output)

;[106]  Update for 32 Bit Addressing for ROADRUNNER
INTADD  =       ^H0FFFFFF90     ; Interrupt port address
INTVEC  =       ^H064           ; Address of interrupt vector
;[106]  Update for 32 Bit Addressing for ROADRUNNER support
DATAPRT =       ^H0FFFFFF10     ; Data & Status Port
Z80PRT  =       ^H0FFFFFF50     ; Z80 Interrupt Port
TRDYPRT =       ^H0FFFFFF30     ; Transmit ready port
;
RS%RTS  =       ^H04                    ; Request to send.

AVLPIN  =       RS%RTS                  ; Available pins.


       PAGE
;***************************************************************************
;                                                                          *
;                         P I 1 6 I F   D R I V E R                        *
;                                                                          *
;***************************************************************************
;
;
PI16IF:
       IF      EQ,OPTION               ; AMOS/L 1.3D>
        ASMMSG  " Adding PHDR "
        PHDR   -1,0,0
        BR     CHROT                   ; Character output routine.
        BR     INIT                    ; Initialization routine.
        BR     20$                     ; GETPIN vector.
        BR     30$                     ; SETPIN vector.
        WORD   ^H0A5A5                 ; Noise word for new format.
        LWORD  AVLPIN                  ; Driver Flags.
20$:     JMP    GETPIN                  ;
30$:     JMP    SETPIN                  ;

       IFF                             ; AMOS/L 1.3C<
        BR     CHROT                   ; character output routine
        BR     INIT                    ; initialization routine
        NOP
CHROUT:
        JMP     CHROT
ENDC


;Output Character Initiation Routine

;ENTER WITH A5->TERMINAL DEFINITION BLOCK

CHROT:
       SAVE    A6,D0,D1,D2,D6          ; [105]
       SSTS    D2                      ; [105] Save Interrupt status
       SVLOK                           ; [104]

       MOV     T.IHM(A5),D0            ; GET PORT NUM
       LEA     A6,PORTS                ; PORT INITED INDICATOR
       MOVW    @A6,D6                  ; GET PREVIOUS INITED PORTS
       BTST    D0,D6                   ; HAS CHANNEL BEEN INITED
       JEQ     IGNXIT                  ; NOPE

       CALL    WZ80                    ; WAIT FOR Z80 INT TO BE SERVICED
;       JEQ     IGNXIT                  ; [104]

       MOV     #DATAPRT,A6             ;[106] DATA PORT NUM
       ORW     #^H0FF00,D0             ; XMIT ENABLE = FF,,PORT NUM
       MOVW    D0,@A6
;       SVUNLK                          ; [104]
IGNXIT: LSTS    D2                      ; [105] Restore interrupt status
       REST    A6,D0,D1,D2,D6
       RTN

;--------- WAIT FOR Z80 INT TO BE SERVICED ------

WZ80:
;       MOVW    #^H900,D6               ; DONT WAIT FOREVER [101] [102]
       MOV     #Z80PRT,A6      ;[106]  ; WAIT FOR INT ON Z80 TO BE SERVICED
SWAIT:
;       NOP                             ; [103][104]
;       NOP                             ; [103][104]
       MOVW    @A6,D1                  ; MUST BE WORD MOVE
       BTST    #0,D1                   ; 0->INT ACTIVE
       BEQ     SWAIT                   ; [102]
;       DBNE    D6,SWAIT                ; [102]
;       NOP                             ; [103][104]
       RTN                             ; RET ZF=1 IF T/O

;Initialize the PI-1016 Port

; ENTER WITH D0 = BAUD RATE INDICATOR
;            A5 -> terminal definition block.

INIT:
       CMP     D0,#18.
       JHIS    BAUDER                  ; RATES SUPPORTED = 0..17

       LEA     A0,INTRPT               ; GET ADDDRESS OF INTERRUPT ROUTINE
       MOV     A0,INTVEC               ; SAVE IN AUTOVECTOR

       LEA     A0,AMALIV               ; IF FIRST CALL, THEN INIT ALL PORTS
       TSTB    @A0
       BNE     NOTFST
       MOVB    #-1,@A0
       PUSH    D0
       CALL    PRTOFF                  ; TURN OFF ALL PORTS
       POP     D0

NOTFST:
       LEA     A0,PORTS                ; PORT INITED INDICATOR
       MOVW    @A0,D2                  ; GET PREVIOUS INITED PORTS
       MOV     T.IHM(A5),D1            ; GET PORT NUMBER
       XORB    #1,D1                   ; GET OTHER CHANNEL
       BTST    D1,D2                   ; HAS OTHER CHANNEL BEEN INITED
       JEQ     NEWINI                  ; NOPE

       LEA     A0,BVAL                 ; GET BAUD VALUE USED ON OTHER PORT
       CLR     D3
       MOVB    0(A0)[D1],D3
       BTST    #7.,D3                  ; ACR=1?
       JEQ     TRYB0

TRYB1:
       LEA     A0,BAUD1                ; index the baud rate table ACR=1
       MOVB    0(A0)[D0],D4            ; Is it a valid baud rate ?
       CMPB    D4,#-1
       BEQ     CHGB0                   ;   no - invalid baud rate
       BCLR    #7,D3
       MOVB    0(A0)[D3],D4            ; OTHER CHANNEL ALSO SUPPORTED
       CMPB    D4,#-1
       BEQ     CHGB0
       BSET    #7.,D0                  ; USE ACR=1
       JMP     SBAUD

CHGB0:                                  ; TRY TO CHANGE TO ACR=0
       LEA     A0,BAUD0
       MOVB    0(A0)[D0],D4            ; BOTH BAUD RATES DEFNED
       CMPB    D4,#-1
       JEQ     BAUDER
       BCLR    #7,D3
       MOVB    0(A0)[D3],D4
       CMPB    D4,#-1
       JEQ     BAUDER
       SAVE    D0,A5                   ; RESET BAUD RATE ON OTHER CHANEL
       MOV     D3,D0                   ; OLD BAUD RATE
       LEA     A0,TCB0
       LSL     D1,#2                   ; PORT NUM * 4 FOR LWORD OFFSET
       MOV     0(A0)[D1],A5            ; PNTR TO OTHER CHAN TRM DEF BLK
       BCLR    #7.,D0                  ; USE ACR=0
       CALL    PINIT                   ; INIT OTHER CHANNEL
       REST    D0,A5
       JMP     SBAUD

TRYB0:
       LEA     A0,BAUD0                ; INDEX BAUD RATE TABLE ACR=0
       MOVB    0(A0)[D0],D4
       CMPB    D4,#-1
       BEQ     CHGB1
       BCLR    #7,D3
       MOVB    0(A0)[D3],D4
       CMPB    D4,#-1
       JNE     SBAUD                   ; SET BAUD RATE TO ACR=0
CHGB1:                                  ; TRY TO CHANGE TO ACR=1
       LEA     A0,BAUD1
       MOVB    0(A0)[D0],D4            ; BOTH BAUD RATES DEFNED
       CMPB    D4,#-1
       JEQ     BAUDER
       BCLR    #7,D3
       MOVB    0(A0)[D3],D4
       CMPB    D4,#-1
       JEQ     BAUDER
       SAVE    D0,A5                   ; RESET BAUD RATE ON OTHER CHANEL
       MOV     D3,D0                   ; OLD BAUD RATE
       BSET    #7.,D0                  ; INDICATE THAT PORT HAS ACR=1
       LEA     A0,TCB0
       LSL     D1,#2                   ; PORT NUM * 4 FOR LWORD OFFSET
       MOV     0(A0)[D1],A5            ; PNTR TO OTHER CHAN TRM DEF BLK
       CALL    PINIT                   ; INIT OTHER CHANNEL
       REST    D0,A5
       BSET    #7.,D0                  ; USE ACR=1 ON NEW PORT
       JMP     SBAUD

BAUDER:
       TYPECR  <Invalid BAUD RATE for 16 port>
ERRXIT:
       RTN

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This is the Major addition to PI16IF driver to add COMSER compatability
; to this driver.

       IF      EQ,OPTION
        ASMMSG  " Adding GETPIN  & SETPIN "
GETPIN:
       CLR     D6                      ; Clear status on pins.
       MOV     #AVLPIN, D7             ; Set available mask.
       RTN                             ; Return

; Note if this doesn't work, try logic at ACR0: to set port status,
;  or just set to return.
;
SETPIN:
       SSTS    D6                      ; Get processor status
       PUSHW   D6                      ; Save on stack
       SVLOK                           ; Disable interupts
       MOV     T.IHW(A5), A6           ; Read hardware address.
       MOV     T.IHM(A5), D7           ; Read port number.
       MOVB    #1, D6                  ; Default to port A
       BTST    #0, D7                  ; Is this port A?
       BEQ     10$                     ; Yes..use it.
       MOVB    #2, D6                  ; Default to port B
10$:    ORB     #^H81, D7               ; Force 2nd half of DUART.
       MOVB    D7,4(A6)                ; Select duart
;       NOP                             ; [103][104]
       BTST    #RS%RTS, D0             ; Set or reset RTS
       BEQ     20$                     ; Reset it.
       MOVB    D6, P.SOB(A6)           ; Set RTS.
       BR      30$
20$:    MOVB    D6, P.ROB(A6)           ; Reset RTS
30$:    POPW    D6                      ; Restore processor status.
       LSTS    D6
       RTN

ENDC

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

NEWINI:
       LEA     A0,BAUD1                ; index the baud rate table ACR=1
       MOVB    0(A0)[D0],D4            ; Is it a valid baud rate ?
       CMPB    D4,#-1
       JEQ     NOTB0
       BSET    #7.,D0                  ; SET ACR=1
       JMP     SBAUD

NOTB0:
       LEA     A0,BAUD0                ; INDEX BAUD RATE TABLE ACR=0
       MOVB    0(A0)[D0],D4
       CMPB    D4,#-1
       JEQ     BAUDER

;--- ENTER WITH D0 BITS 0..6=BAUD RATE CODE, D0 B7 = ACR
;               A5 -> TRMDEF BLK

SBAUD:

; Get port number and base addresses of DUART and channel


PINIT:
       LEA     A0,BAUD0
       MOV     D0,D3
       CLR     D6
       BCLR    #7.,D0                  ; BAUD1?
       BEQ     ACR0
       LEA     A0,BAUD1
       MOVB    #^H80,D6                ; ACR VALUE
ACR0:
       ADD     D0,A0                   ; OFFSET TO BAUD RATE INIT VALUE

       MOV     T.IHM(A5),D2            ; use port # as displacement
       LEA     A1,BVAL                 ; SAVE BAUD RATE VALUE ON CURR PORT
       MOVB    D3,0(A1)[D2]
       MOV     D2,D4                   ; keep a copy
       CLR     D3
       BCLR    #0,D2                   ; EVEN OR ODD PORT
       BEQ     EADDR
       MOV     #8.,D3                  ; BASE ADDR OF CHANNEL
EADDR:
       LSL     D2,#3                   ; BASE ADDR OF UART = 8*PORT NUM
       ORB     #^H80,D2
       ADD     D2,D3                   ; Set D2 to base of DUART
                                       ; set D3 to base of specific channel
       LSL     D2,#8.                  ; PUT ADDR IN HI BYTE
       LSL     D3,#8.

; Set up baud rate

       MOV     #DATAPRT,A2     ;[106]  ; DATA/STATUS PORT

       MOVW    D2,D5
       ADDW    #<P.ACR_8.>,D5
       MOVB    D6,D5                   ; TABLE SELECT CODE
       MOVW    D5,@A2                  ; Send table select code
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

       MOVB    @A0,D1                  ; Get baud rate code
       ROLB    D1,#4                   ; Shift to receiver select bits
       ORB     @A0,D1                  ;  or int transmit clock select bits

       MOVW    D3,D5
       ADDW    #<P.CLK_8.>,D5
       MOVB    D1,D5
       MOVW    D5,@A2                  ; Send to proper channel
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

; Reset everything

       MOVW    D3,D5
       ADD     #<P.CMR_8.>,D5

       MOVB    #CM$RMRP,D5
       MOVW    D5,@A2
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

       MOVB    #CM$RRCV,D5
       MOVW    D5,@A2
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

       MOVB    #CM$RTXM,D5
       MOVW    D5,@A2
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

       MOVB    #CM$REST,D5
       MOVW    D5,@A2
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

       MOV     #TRDYPRT,A3             ;[106] TX RDY PORT
       MOVW    D3,D5
       ADDW    #<P.MDR_8.>,D5
       MOVB    #M1$8B!M1$NP,D5         ; Set up mode register 1
       MOVW    D5,@A2
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

       MOVB    #M2$1SB!M2$NM!M2$CET,D5 ; Set up for mode register 2
       CMPB    D0,#4                   ; Did we want 110 baud
       BNE     30$
       MOVB    #M2$2SB!M2$NM!M2$CET,D5 ; Set to two stop bits
30$:
       MOVW    D5,@A2                  ; Set up mode register 2
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

       MOVW    D3,D5
       ADDW    #<P.CMR_8.>,D5
       MOVB    #CM$RXDI!CM$TXDI,D5     ; Temporarily disable RCV AND XMIT
       MOVW    D5,@A2

       MOVW    D2,D5
       ADDW    #<P.IMR_8.>,D5

       CLRB    D5                      ; NO INTS ENABLED ON UART
       BTST    #11.,D3                  ; CHANNEL A ?
       BEQ     40$                     ; GO IF TRUE
       ROLB    D5,#4                   ; SHIFT UP FOR CHANNEL B
40$:
       LEA     A0,IMASK1               ; BASE ADDRESS OF IMR BYTE TABLE
       MOV     D4,D0                   ; SAVE CHANNEL NUM
       LSR     D4,#1                   ; INDEX CORRECT MASK REGISTER
       ADD     D4,A0
       ORB     D5,@A0                  ; ADD TO EXISTING MASK VALUE
       MOVB    @A0,D5                  ; D1 REFLECTS BOTH CHANNELS
       MOVW    D5,@A2                  ; PROGRAM DUART
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

; Now enable DTR & RTS

       MOVW    D2,D5
       ADDW    #<P.SOB_8.>,D5
       MOVB    #5,D5                   ; SET UP CHANNEL A
       BTST    #11.,D3                 ; TEST IF CHANNEL B
       BEQ     50$
       MOVB    #22,D5                  ; SET UP CHANNEL B
50$:
       LEA     A0,OPBIT1               ; BASE ADDRESS OF OUTPUT BYTE TABLE
       ADD     D4,A0
       ORB     D5,@A0                  ; ADD TO EXISTING BIT PATTERN
       MOVB    @A0,D5                  ; D1 REFLECTS BOTH CHANNELS
       MOVW    D5,@A2                  ; SET BITS ON
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

       MOVW    D2,D5
       ADDW    #<P.OCR_8.>,D5
       MOVW    D5,@A2                  ; SET UP OPR
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]

; SET LOCAL MEMORY FLAGS AND POINTERS

       LEA     A0,PORTS                ; PORT INITED INDICATOR
       MOVW    @A0,D2                  ; GET PROVIOUS INITED PORTS
       BSET    D0,D2                   ; MARK CURRENT PORT AS INITED
       MOVW    D2,@A0                  ; SAVE INDICATOR

       LSL     D0,#2                   ; INDEX LONG WORDS
       LEA     A0,TCB0
       ADD     D0,A0
       MOV     A5,@A0                  ; SAVE TRMDEF BLOCK ADDRESS
       MOV     D3,T.IHW(A5)            ; SAVE DUART ADDRESS IN TRMDEF BLOCK

       MOVW    D3,D5
       ADDW    #<P.CMR_8.>,D5
       MOVB    #CM$RXEN!CM$TXEN,D5
       MOVW    D5,@A2                  ; ENABLE RECEIVER AND XMITTER
       CALL    WZ80
;       JEQ     Z80ERR                  ; [104]
       RTN

Z80ERR:
       TYPECR  <No response from the 16 port.>
       RTN

;-------- TURN OFF  ALL PORTS -------

PRTOFF:
       MOV     #DATAPRT,A4             ; [106] PORT TO Z80
       MOV     #^H0F,D0                ; PORTS 0..F
NXTOFF:
       MOVW    D0,D1
       ORW     #^H0FC00,D1
       AND
W       #^H0FCFF,D1             ; FC -> DISABLE XMITTER INTERRUPT
       MOVW    D1,@A4                  ; DISABLE XMIT INT
       CALL    WZ80

       MOV     D0,D3
       LSL     D3,#3                   ; 8*PORT = BASE ADDR
       AND     #^H0FF,D3
       ORB     #^H80,D3                ; SET HIT BIT FOR CTRL PORT OUTPUT
       LSL     D3,#8.                  ; MOVE TO HI BYTE
       ADDW    #<P.CMR_8.>,D3          ; OFFSET TO CMD REG
       MOVB    #CM$RXDI!CM$TXDI,D3     ; disable RCV AND XMIT
       MOVW    D3,@A4

       CALL    WZ80

       DBF     D0,NXTOFF
       RTN

;--------- INTERRUPT SERVICE ROUTINE -------

; INTRPT
; Come here via INTERRUPT vector to process all PM-1016 INTERRUPTs.

INTRPT:
       SAVE    A0-A6,D0-D7
       SVLOK                           ; [105] Disable other Interrupts
       LEA     A3,PORTS
       MOV     #DATAPRT,A4             ;[106] INPUT PORT
       CLR     D1
       MOVW    @A4,D1
       MOV     D1,D0                   ; SAVE DATA BYTE
       LSR     D0,#8.                  ; MOVE PORT NUM TO LOW BYTE
       CMPB    D0,#^H0FF               ; XMIT INT?
       JNE     NOXMIT

       CLR     D2
       AND     #^H0FF,D1
       BSET    D1,D2
       LEA     A5,TCB0
       LSL     D1,#2                   ; LONG WORD OFFSET
       MOV     0(A5)[D1],D1            ; TCB PNTR, USE D0 TO SET FLAGS
       MOV     D1,A5
       JEQ     FLSINT

       ANDW    @A3,D2
       JEQ     FLSINT

       TRMOCP                          ; get next output character from TRMSER
       MOV     T.IHM(A5),D0
       TST     D1                      ; data available?
       BPL     OPRG7                   ;   yes -
       ANDW    #^C<OIP>,@A5            ;   no - clear the OIP flag

       CALL    WZ80
       ORW     #^H0FC00,D0
       ANDW    #^H0FCFF,D0             ; FC -> DISABLE XMITTER INTERRUPT
;       NOP                             ; [103][104]
       MOVW    D0,@A4                  ; DISABLE XMIT INT

;       NOP                             ; [103][104]
       JMP     FLSINT                  ; return

;Send character to transmitter
OPRG7:
       MOV     #DATAPRT,A4             ;[106]  XMIT DATA PORT
       AND     #^H0FF,D1               ; CLEAR PORT NUM
       LSL     D0,#8.                  ; PORT NUM INTO HI BYTE OF LOW WRD
       MOVB    D1,D0                   ; SET PORT NUM IN WORD TO XMIT
       CALL    WZ80                    ; MAKE SURE Z80 NOT IN INT ROUTINE
       MOVW    D0,@A4                  ; send character to 16 PORT
;       NOP                             ; [103][104]
       JMP     FLSINT

;--------- RECEIVE FROM TERMINAL ------

NOXMIT:
       CLR     D2
       AND     #^H0FF,D0               ; GET PORT NUM
       BSET    D0,D2
       LEA     A5,TCB0
       LSL     D0,#2                   ; LONG WORD OFFSET
       MOV     0(A5)[D0],D0            ; TCB PNTR, USE D0 TO SET FLAGS
       MOV     D0,A5
       BEQ     FLSINT
       ANDW    @A3,D2
       BEQ     FLSINT

;Input Character Interrupt Routine
;
;Come here whenever we get a receiver interrupt.  Read the character from
;the PM-1016 and pass on to TRMSER.
;
;ENTER WITH     D1 = INPUT BYTE
;               A5      TRMDEF BLOCK PNTR
;               All registers SAVEd on stack


INPR:
       TRMICP                          ; go process the character
FLSINT:
       REST    A0-A6,D0-D7             ; restore registers
       RTE                             ; Restore interrupts

; BAUD RATE TABLE

BAUD1:          ; ACR BIT 7 = 1
       BYTE    -1                              ; 50 baud
       BYTE    0                               ; 75 baud
       BYTE    1                               ; 110 baud
       BYTE    2                               ; 134.5 baud
       BYTE    3                               ; 150 baud
       BYTE    -1                              ; 200 baud
       BYTE    4                               ; 300 baud
       BYTE    5                               ; 600 baud
       BYTE    6                               ; 1200 baud
       BYTE    12                              ; 1800 baud
       BYTE    7                               ; 2000 baud
       BYTE    10                              ; 2400 baud
       BYTE    -1                              ; 3600 baud
       BYTE    11                              ; 4800 baud
       BYTE    -1                              ; 7200 baud
       BYTE    13                              ; 9600 baud
       BYTE    14                              ; 19200 baud
       BYTE    -1                              ; 38400 baud
       BYTE    0
BAUD0:                  ; ACR = 0
       BYTE    0                               ; 0 = 50 baud
       BYTE    -1                              ; 1 = 75 baud
       BYTE    1                               ; 2 = 110 baud
       BYTE    2                               ; 3 = 134.5 baud
       BYTE    -1                              ; 4 = 150 baud
       BYTE    3                               ; 5 = 200 baud
       BYTE    4                               ; 6 = 300 baud
       BYTE    5                               ; 7 = 600 baud
       BYTE    6                               ; 8 = 1200 baud
       BYTE    -1                              ; 9 = 1800 baud
       BYTE    -1                              ; 10 = 2000 baud
       BYTE    10                              ; 11 = 2400 baud
       BYTE    -1                              ; 12 = 3600 baud
       BYTE    11                              ; 13 = 4800 baud
       BYTE    12                              ; 14 = 7200 baud
       BYTE    13                              ; 15 = 9600 baud
       BYTE    -1                              ; 16 = 19200 baud
       BYTE    14                              ; 17 = 38400 baud
       BYTE    0                               ; 18 USED FOR UN-INITED PORTS

       EVEN

TCB0: LWORD   0                         ; POINTER TO TRMDEF BLOCKS
TCB1: LWORD   0
TCB2: LWORD   0
TCB3: LWORD   0
TCB4: LWORD   0
TCB5: LWORD   0
TCB6: LWORD   0
TCB7: LWORD   0
TCB8: LWORD   0
TCB9: LWORD   0
TCBA: LWORD   0
TCBB: LWORD   0
TCBC: LWORD   0
TCBD: LWORD   0
TCBE: LWORD   0
TCBF: LWORD   0

PORTS:  WORD    0                               ; PORT INITIALIZATION INDICATOR

IMASK1: BYTE    0                               ; INTERRUPT MASK REGISTERS
IMASK2: BYTE    0
IMASK3: BYTE    0
IMASK4: BYTE    0
IMASK5: BYTE    0
IMASK6: BYTE    0
IMASK7: BYTE    0
IMASK8: BYTE    0
IMASK9: BYTE    0
IMASKA: BYTE    0
IMASKB: BYTE    0
IMASKC: BYTE    0
IMASKD: BYTE    0
IMASKE: BYTE    0
IMASKF: BYTE    0

OPBIT1: BYTE    0                               ; OUTPUT PORT BITS
OPBIT2: BYTE    0
OPBIT3: BYTE    0
OPBIT4: BYTE    0
OPBIT5: BYTE    0
OPBIT6: BYTE    0
OPBIT7: BYTE    0
OPBIT8: BYTE    0
OPBIT9: BYTE    0
OPBITA: BYTE    0
OPBITB: BYTE    0
OPBITC: BYTE    0
OPBITD: BYTE    0
OPBITE: BYTE    0
OPBITF: BYTE    0

BVAL:   BYTE    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
AMALIV: BYTE    0

       EVEN

       END