;       Title    'MEX overlay - TRS-80 MOD IV vers 3.2'
;                      Montezuma Micro CP/M 2.2
;
;******************************************************************************
;       R E V I S I O N       H I S T O R Y
;******************************************************************************
;
; VERSION 3.2 09/15/86 - Bug Fixed.  When exiting MEX to CP/M, interrupts
;                        were not shut off properly and would cause the machine to go
;                        into never-never land.
;                               Fred LaForest
;
; VERSION 3.1 08/21/86 - Bug fixed.  If the input buffer was filled before it
;                        could be emptied, the count of characters went past
;                        the configured maximum number of spaces in the buffer.
;                               Fred LaForest
;
; VERSION 3.0 08/18/86 - Major revision level change.  I removed the auto
;                        answer code, it is modem dependent and belongs in a
;                        modem overlay.  All smart modem code is gone.  The SET
;                        command code has been tightened up.
;                        At higher speeds, the Mod 4 loses characters during
;                        screen scrolling.  Configurable code has been added to
;                        use interrupts to process UART input.  This eliminates
;                        almost all character dropouts during screen processing.
;                               Fred LaForest
;                               3235 Edgeworth
;                               Ferndale, MI 48220
;                               GENIE: FALAFOREST
;
;******************************************************************************
;
; VERSION 2.1 08/06/86 - Correct modem control to properly handle changes
;                        in word length, parity, and stop bits.  Changes
;                        to these parameters by the SET command were never
;                        communicated to the UART.
;                               Fred LaForest
;
; VERSION 2.0 10/06/85 - Change to the printer status routine.  Now
;                        checks all four possible printer states.
;                        Ver.114 changed ^C address from AUTO ANSWER.
;                        Added code at STANS to find the correct
;                        address.
;                                               Ed Richter
;                                               71455,1133
; VERSION 1.9 09/12/85 - Minor change to eliminate some un-necessay
;                        code when using the AUTO ANSWER mode. See
;                        NOMXOSM.
;                                               Ed Richter
; VERSION 1.8 05/05/85 - Included the changes from the file
;                        MXO-RS17.FIX. The baud rate detect now works.
;                                               Ed Richter
; VERSION 1.7 01/25/85 - ^C in "auto-answer now aborts to CPM, not
;                        MEX.(sorry bout that one) Added code to
;                        determine baud rate in "auto-answer".
;                        Changed "NITMOD" to default  to the baud
;                        rate selected by "MSPEED"
;                                               Ed Richter
; VERSION 1.6 01/21/85 - A system reset seems a little drastic
;                        so added code for a ^C abort to auto
;                        answer. Also added "number of rings"
;                        equate.
;                                                Ed Richter
; VERSION 1.5 11/17/84 - Added SET ANSWER ON command
;                        (For Hayes-compatible modems
;                         only...see NOTE below.)
;                                               Thom Foulks
; VERSION 1.3 10/10/84 - Fixed bug in the Printer ready test
;                                                 Ed Richter
; VERSION 1.2 09/18/84 - Added the comments to 1.1 and changed the
;                        configuration of the SET message that is
;                        output to the console
;                                                  Ed Richter
; VERSION 1.1 09/16/84 - Added code to fully control the SIO USART
;                        via the SET command. This overlay now
;                        supports-- SET BAUD -- SET PARITY --
;                        SET STOP BITS -- SET WORD LENGTH --
;                                                   Ed Richter
;
; MEX TRS-80 MOD IV OVERLAY VERSION 1.0: Written 09/10/84 by Ed Richter
;
; This file was derived from the MDM7xx overlay M7R4-5.ASM, and the
; file MXOPM10.ASM. It is a MEX overlay for use with the TRS-80 MOD
; IV, and an external modem. It has a SET command that supports 300
; though 9600 baud.
;
;******************************************************************************

REV:    EQU     32              ;MEX Overlay revision number
;
CR:     EQU     0DH             ;carriage return
LF:     EQU     0AH             ;linefeed
ONV:    EQU     0FH             ;reverse video on
INV:    EQU     0EH             ;reverse video off
TPA:    EQU     0100H           ;start of program
TAB:    EQU     09H
YES:    EQU     0FFH            ;true
NO:     EQU     0               ;not true

;******************************************************************************
;
;       UART equates and port equates
;
;******************************************************************************
;
;       ***********  Important NOTICE  ***********
;
;       The following equate, MMINTR, is set to YES if you want input
;       characters from the UART to be captured by the TRS-80 Mod 4 interrupt
;       circuitry.  This virtually eliminates all lost characters during
;       screen scrolling.  This means you can tell any RCPM or BBS that you
;       don't need ANY nulls (0).
;
;       A BIG assumption is that you are a MOD 4 using Montezuma Micro CP/M
;       implementation.  The initialization code searchs through the BIOS for
;       the TWO places which disable interrupts and really don't need this type
;       of protection.  They are th keyboard handler and the video screen memory
;       handler.  They only switch out RAM between F800h and FFFFh.  This does
;       NOT overlap any user program in TPA.
;
;       The technique used to find the two BIOS locations can be modified for
;       other machines or CP/M implementations.
;
;       NOTE!!!;  If you DO NOT want to use interrupt processing, set MMINTR to
;       NO.  This will revert this overlay to the older port polling method
;       which is used in older overlays for the Mod 4.
;
;
MMINTR          EQU     YES     ;Set YES if you are using Montezuma Micro CP/M
;                               ;AND you wish to use interrupt input processing
;                               ;Set NO if you DO NOT want interrupt processing
;                               ;and want the older port polling method
;
;       TRS 80 Communications port information
;
PORT:           EQU     0E8H    ;master reset port
MODCT1:         EQU     PORT+2  ;modem control port
MODDAT:         EQU     PORT+3  ;modem data in port
MODCT2:         EQU     PORT+2  ;not used mod iv
BAUDRP:         EQU     PORT+1  ;baud rate port
MDRCVB:         EQU     080H    ;bit to test for receive
MDRCVR:         EQU     080H    ;value when ready
MDSNDB:         EQU     040H    ;bit to test for send
MDSNDR:         EQU     040H    ;value when ready

;
;       UART Control Bit Configuration
;
U$WORD:         EQU     060h    ;Word length mask
U$WRD5:         EQU     000H    ;Word length of 5 bits
U$WRD6:         EQU     040H    ;Word length of 6 bits
U$WRD7:         EQU     020H    ;Word length of 7 bits
U$WRD8:         EQU     060H    ;Word length of 8 bits
U$PART:         EQU     088H    ;Parity control mask
U$PREV:         EQU     080H    ;Parity EVEN
U$PROD:         EQU     000H    ;Parity ODD
U$PROF:         EQU     008H    ;Parity OFF
U$PRON:         EQU     000h    ;Parity ON
U$STOP:         EQU     010H    ;Stop bits mask
U$STP1:         EQU     000H    ;Stop bits 1
U$STP2:         EQU     010H    ;Stop bits 2
U$XMIT:         EQU     004H    ;Set to enable transmit
U$RTS:          EQU     002H    ;Set for RTS
U$RTSO:         EQU     000H    ;Clear to turn on RTS
U$DTR:          EQU     001H    ;Set for DTR off
U$DTRO:         EQU     000H    ;Clear to turn on DTR
;
;       Default UART configurations and bit masks
;
DEFCTB:         EQU     U$PROF+U$WRD8+U$STP1+U$DTRO+U$XMIT+U$RTSO
DFBAUD:         EQU     6       ;0=110 1=300 2=450 3=600 4=710 5=1200
                               ;6=2400 7=4800 8=9600 9=19200 default
CTSMSK:         EQU     020H            ;carrier detect mask
ISOCD:          EQU     0DFH            ;port ready mask
PRPORT:         EQU     0F8H            ;printer port
PRSTAT:         EQU     0F0H            ;printer ready mask
BRKMSK:         EQU     0FFH-U$XMIT     ;send break
DTRMSK:         EQU     0FFH-U$DTR-U$RTS ;drop dtr

;******************************************************************************
;
;       MEX SERVICE PROCESSOR STUFF
;
;******************************************************************************
MEX:            EQU     0D00H   ;address of the service processor
INMDM:          EQU     255     ;get char from port,CY=no more in 100ms
TIMER:          EQU     254     ;delay 100 ms * reg b
TMDINP:         EQU     253     ;b=# secs to wait for char,CY=no char
CHEKCC:         EQU     252     ;check for ^C from kbd, Z=present
SNDRDY:         EQU     251     ;test for modem-send ready
RCVRDY:         EQU     250     ;test for modem-receive ready
SNDCHR:         EQU     249     ;send to modem (after SNDRDY)
RCVCHR:         EQU     248     ;recv a char from modem after (RCVRDY)
LOOKUP:         EQU     247     ;table search: see CMDTBL for info
PARSFN:         EQU     246     ;parse filename from input stream
BDPARS:         EQU     245     ;parse baud-rate from input stream
SBLANK:         EQU     244     ;scan input stream to next non-blank
EVALA:          EQU     243     ;evaluate numeric from input stream
LKAHED:         EQU     242     ;get nxt char w/o removing from input
GNC:            EQU     241     ;get char from input, CY=1 if none
ILP:            EQU     240     ;inline print
DECOUT:         EQU     239     ;decimal output
PRBAUD:         EQU     238     ;print baud rate
CONOUT:         EQU     2       ;simulated BDOS funct 2:CONSOLE OUT
PRINT:          EQU     9       ;simulated BDOS funct 9: PRINT STRING
INBUF:          EQU     10      ;input buffer, same as BDOS FUNCT 10

;******************************************************************************
;
;       Place the printer test routine address here
;
;******************************************************************************

               ORG     0D11H   ;install printer ready test
               DW      PRTSTS

;******************************************************************************
;
;       Low address MEX flags and configuration constants go here
;
;******************************************************************************

               ORG     TPA
;
               DS      3       ;(for  "JMP   START" instruction)
PMODEM:         DS      1       ;Not used by MEX                        103H
SMODEM:         DS      1       ;Not used by MEX
TPULSE:         DS      1       ;Not used by MEX                        105H
CLOCK:          DB      40      ;clock speed in MHz x10, 25.5 MHz max.  106H
                               ;20=2 MHh, 37=3.68 MHz, 40=4 MHz, etc.
MSPEED:         DB      DFBAUD  ;0=110 1=300 2=450 3=600 4=710 5=1200   107H
                               ;6=2400 7=4800 8=9600 9=19200 default
BYTDLY:         DB      0       ;0=0 delay  1=10ms  5=50 ms - 9=90 ms   108H
                               ;default time to send character in ter-
                               ;minal mode file transfer for slow BBS.
CRDLY:          DB      0       ;0=0 delay 1=100 ms 5=500 ms - 9=900 ms 109H
                               ;default time for extra wait after CRLF
                               ;in terminal mode file transfer
COLUMS:         DB      4       ;number of DIR columns shown            10AH
SETFL:          DB      YES     ;yes=user-added Setup routine           10BH
SCRTST:         DB      YES     ;Cursor control routine                 10CH
               DS      1       ;reserved (old ACKNAK flag)             10DH
BAKFLG:         DB      YES     ;yes=change any file same name to .BAK  10EH
CRCDFL:         DB      YES     ;yes=default to CRC checking            10FH
TOGCRC:         DB      YES     ;yes=allow toggling of CRC to Checksum  110H
CVTBS:          DB      NO      ;yes=convert backspace to rub           111H
TOGLBK:         DB      YES     ;yes=allow toggling of bksp to rub      112H
ADDLF:          DB      NO      ;no=no LF after CR to send file in      113H
                               ;terminal mode (added by remote echo)
TOGLF:          DB      YES     ;yes=allow toggling of LF after CR      114H
TRNLOG:         DB      NO      ;yes=allow transmission of logon        115H
                               ;write logon sequence at location LOGON
SAVCCP:         DB      YES     ;yes=do not overwrite CCP               116H
LOCNXT:         DB      NO      ;yes=local command if EXTCHR precedes   117H
                               ;no=external command if EXTCHR precedes
TOGLOC:         DB      YES     ;yes=allow toggling of LOCONEXTCHR      118H
LSTTST:         DB      YES     ;yes=allow toggling of printer on/off   119H
XOFTST:         DB      YES     ;yes=checks for XOFF from remote while  11AH
                               ;sending a file in terminal mode
XONWT:          DB      YES     ;yes=wait for XON after CR while        11BH
                               ;sending a file in terminal mode
TOGXOF:         DB      YES     ;yes=allow toggling of XOFF checking    11CH
IGNCTL:         DB      YES     ;yes=CTL-chars above ^M not displayed   11DH
EXTRA1:         DB      0       ;for future expansion                   11EH
EXTRA2:         DB      0       ;for future expansion                   11FH
BRKCHR:         DB      'K'-40H ;^K = Send 300 ms. break tone           120H
NOCONN:         DB      'N'-40H ;^N = Disconnect from the phone line    121H
LOGCHR:         DB      'L'-40H ;^L = Send logon                        122H
LSTCHR:         DB      'P'-40H ;^P = Toggle printer                    123H
UNSVCH:         DB      'R'-40H ;^R = Close input text buffer           124H
TRANCHR:        DB      'T'-40H ;^T = Transmit file to remote           125H
SAVECHR:        DB      'Y'-40H ;^Y = Open input text buffer            126H
EXTCHR:         DB      '^'-40h ;^^ = Send next character               127H
               DS      2
INCTL1:         JMP     STATSND ;go to "get status"                     12AH
               DS      7
OTDATA:         OUT     MODDAT  ! RET   ;out modem data port            134H
               DS      7
               IF      NOT MMINTR      ;If not interupt driven
INPORT:         IN      MODDAT  ! RET   ;in modem data port
               ENDIF
               IF      MMINTR          ;If interrupts are used
INPORT:         JMP     INT$GET         ;Get a char from buffer
               ENDIF
               DS      7
MASKR:          ANI     MDRCVB  ! RET   ;bit to test for receive ready  148H
TESTR:          CPI     MDRCVR  ! RET   ;value of rcv. bit when ready   14BH
MASKS:          ANI     MDSNDB  ! RET   ;bit to test for send ready     14EH
TESTS:          CPI     MDSNDR  ! RET   ;value of send bit when ready   151H
               DS      12              ;unused by MEX
LOGON:          DS      2               ;for user message               160H
DIALV:          DS      3               ;autodial rtn jump              162H
DISCV:          JMP     DISCON          ;disconnect rtn                 165H

               IF      NOT MMINTR
GOODBV:         DS      3               ;not needed                     168H
               ENDIF
               IF      MMINTR          ;Interrupt processing
GOODBV:         JMP     INT$BYE         ;Restore system vectors         168H
               ENDIF

INMODV:         JMP     NITMOD          ;go to user written routine     16BH
NEWBDV:         JMP     PBAUD           ;set new baud-rate              16EH
NOPARV:         DS      3               ;(by-pass PMMI routine)         171H
PARITV:         DS      3               ;(by-pass PMMI routine)         174H
SETUPV:         JMP     SETCMD          ;initialize USART and modem     177H
SPMENV:         DS      3               ;not used with MEX              17AH
VERSNV:         JMP     SYSVER          ;print header msg               17DH
BREAKV:         JMP     PBREAK          ;send header                    180H
; Do not change the following six lines.
ILPRTV:         DS      3               ;                               183H
INBUFV:         DS      3               ;                               186H
ILCMPV:         DS      3               ;                               189H
INMDMV:         DS      3               ;                               18CH
NXSCRV:         DS      3               ;                               18FH
TIMERV:         DS      3               ;                               192H

;******************************************************************************
;
; Routine to clear to end of screen.  If using CLREOS and CLRSCRN, set
; SCRNTEST to YES at 010AH (above).
;
;******************************************************************************

CLREOS:         LXI     D,EOSMSG        ;clear to end of screen         195H
               CALL    MPRINT          ;                               198H
               RET                     ;                               19DH
;
CLS:            LXI     D,CLSMSG        ;clear sreen                    19EH
               CALL    MPRINT          ;                               1A1H
               RET                     ;                               1A6H

;
SYSVER:         LXI     D,SOMESG        ;print the sys version msg      1A7H
               CALL    MPRINT
;
;       Print out a message telling of carrier status
;
CARRSH          LXI     D,NOMESG        ;no carrier present msg
               CALL    CARRCK
               CNZ     MPRINT          ;print if no carrier
               LXI     D,CARMSG        ;carrier present
               CALL    MPRINT          ;say so and continue
               RET

;******************************************************************************
;
;       UART controling and accessing routines
;
;******************************************************************************
;
;       This area resets the SIO-UART DTR reinitializes all control parameters
;
NITMOD:         MVI     A,1
               OUT     PORT            ;reset the USART to
               LDA     CURURT          ;Get the current UART parameters
               OUT     MODCT1
               LDA     MSPEED          ;Get startup baud rate
               CALL    PBAUD           ;Set up baud rate generator
               IF      MMINTR          ;Are we interrupt processing?
               CALL    INT$SET         ;Yes, Set up needed vectors
               ENDIF
               RET

;
;       Send a break tone to reset some time-share computers.
;
PBREAK:         LDA     CURURT          ;Get modem control bits
               ANI     BRKMSK          ;send break
               OUT     MODCT1
               MVI     B,3
               MVI     C,TIMER
               CALL    MEX             ;delay 300 msec
               LDA     CURURT          ;Get current bits
               OUT     MODCT1
               RET

;
;       Routine to return status of the modem port
;
STATSND:        IN      MODCT1          ;in modem contol port
               PUSH    B               ;just in case
               ANI     ISOCD           ;isolate status and clear CD bit
               IF      MMINTR
               ANI     0FFH-MDRCVB     ;Clear any receive status
               ENDIF
               MOV     B,A             ;save status
               IF      MMINTR
               CALL    INT$TST         ;Test for input
               ORA     B               ;Include other bits
               MOV     B,A             ;Save in B
               ENDIF
               IN      PORT            ;get CD bit
               ANI     CTSMSK          ;isolate CD bit
               ORA     B               ;merge CD with status
               POP     B               ;restore B
               RET

;
;       Determine the carrier detect status  0=CARRIER
;
CARRCK:         IN      PORT            ;get carrier bit
               ANI     CTSMSK
               RET

;
;       This routine will hang up the phone by dropping DTR.
;
DISCON:         LDA     CURURT          ;Get current modem bits
               ANI     BRKMSK
               ORI     U$DTR+U$RTS     ;Shut off DTR
               OUT     MODCT1          ;send cmd
               MVI     B,5
               MVI     C,TIMER
               CALL    MEX             ;delay 500 msec
               LDA     CURURT          ;Get current bits
               OUT     MODCT1
               RET

;******************************************************************************
;
;       Baud rate set routine
;
;       A = MEX baud rate code
;
;******************************************************************************
PBAUD:          PUSH    H               ;save everybody
               PUSH    B
               PUSH    D
               MOV     E,A             ;get speed
               MVI     D,0             ;zero the other half of reg pair
               LXI     H,BAUDTB        ;get baud rate table address
               DAD     D               ;add speed offset
               MOV     A,M             ;get baud rate
               ORA     A               ;0=not valid baud rate
               JZ      PBEXIT          ;not valid baud rate then exit
               OUT     BAUDRP          ;good baud rate then set it
               MOV     A,E             ;get speed
               STA     MSPEED          ;set speed
               JMP     PBEXIT1         ;return
PBEXIT:         STC
PBEXIT1:        POP     B               ;no carrier or incorrect baud rate
               POP     D
               POP     H
               RET
;
BAUDTB:         DB      0,055H,0,0,0             ;110,300,450,610,710
               DB      077H,0AAH,0CCH,0EEH,0FFH ;1200,2400,4800,9600,19200

;******************************************************************************
;
;       Test for printer ready
;
;**************
****************************************************************
PRTSTS:         IN      PRPORT          ;get printer status
               ANI     PRSTAT          ;isolate it
               XRI     030H            ;invert it
               JZ      PRTSTS1         ;return if not ready A=00
               MVI     A,01H           ;get "A" ready to zero
PRTSTS1:        DCR     A               ;A = 0 not ready
               RET                     ;A = FF ready

;******************************************************************************
;
;       Sets the communications parameters via the SET command
;
;******************************************************************************
SETCMD:         MVI     C,SBLANK        ;any arguments
               CALL    MEX
               JC      SETSHO          ;if not print out values
;
;       First determine the parameter they wish to change
;
               LXI     D,CMDTBL        ;parse commands
               CALL    TSRCH           ;from table
               JC      SETERR          ;Word was not found
               MOV     A,H             ;Get MS table address byte
               ORA     A               ;Test for zero
               JZ      SETTBL          ;Go Get next parameter
               PCHL                    ;Jump to special routine
;
;       All table look up errors come here
;
SETERR:         LXI     D,SETEMS        ;no then print error
               CALL    MPRINT
               RET

SETEMS:         DB      CR,LF,'SET command error',CR,LF,LF,'$'

;
;       This routine will field parameter changes for WORD, PARITY and STOP BITS
;
SETTBL:         LXI     D,STTABL        ;Get address of table
               DAD     D               ;HL -> next parameter input table
               XCHG                    ;DE -> the table now
               CALL    TSRCH           ;from table
               JC      SETERR          ;Word was not found
               LDA     CURURT          ;Get current UART parameters
               ANA     L               ;Mask out bit under review
               ORA     H               ;Set new bits
               STA     CURURT          ;Store new parameters
               OUT     MODCT1          ;Tell UART of the changes
               RET                     ;Return to MEX

;
;       Set the baud rate from the set command
;
STBAUD:         LXI     D,STBDTB        ;Get the legal choices table
               CALL    TSRCH           ;Search the table
               JC      SETERR          ;When in doubt, do without
               MOV     A,L             ;Get the MEX speed code
               STA     MSPEED          ;Inform MEX of speed change
               MOV     A,H             ;Get UART code
               OUT     BAUDRP          ;Tell the UART baud rate generator
               RET                     ;Return to MEX

;
;       Print out a helpful description of the SET command
;
STHELP:         LXI     D,SOMESG        ;Get Overlay version message
               CALL    MPRINT          ;Print the version
               LXI     D,HLPMSG        ;Get address of SET command
               CALL    MPRINT
               RET                     ;Return to MEX

;
;       Show the settings of the current parameters
;
SETSHO:         CALL    CLS             ;clear screen
               CALL    SYSVER          ;Print version and carrier status

               LXI     D,BAUDMSG       ;Print baud rate message
               CALL    MPRINT          ;Print it
               LDA     MSPEED          ;get MSPEED to determine present
               MVI     C,PRBAUD        ;baud rate
               CALL    MEX

               LXI     D,STOPMSG       ;Insert Stop bits message
               CALL    MPRINT
               LDA     CURURT          ;Get UART settings
               ANI     U$STP2          ;How many bits
               MVI     A,'1'           ;Assume 1 bit
               JZ      STSHS1          ;Jump if so
               MVI     A,'2'           ;Must be 2
STSHS1:         CALL    TYPE            ;Tell operator

               LXI     D,WLMSG         ;Start word length message
               CALL    MPRINT
               LDA     CURURT          ;Get UART settings
               ANI     U$WORD          ;Isolate byte length
               MVI     C,'5'           ;5 bits?
               JZ      STSHLG          ;Yes
               MVI     C,'6'
               CPI     U$WRD6          ;6 bits?
               JZ      STSHLG
               MVI     C,'7'           ;7 bits?
               CPI     U$WRD7
               JZ      STSHLG
               MVI     C,'8'           ;Must be 8 bits then
STSHLG:         MOV     A,C             ;Put char into A
               CALL    TYPE            ;Output to the screen

               LXI     D,PARMSG        ;Start parity message
               CALL    MPRINT
               LDA     CURURT          ;Get UART settings
               ANI     U$PART          ;Isolate parity info
               LXI     D,POFMSG        ;Assume off
               CPI     U$PROF          ;Off?
               JZ      STSHPT          ;Yes
               LXI     D,EVEMSG        ;Even parity?
               CPI     U$PREV
               JZ      STSHPT          ;Yes
               LXI     D,ODDMSG        ;Must be ODD
STSHPT:         CALL    MPRINT

               RET

;******************************************************************************
;
;       MEX service routine front ends
;
;******************************************************************************

TSRCH:          MVI     C,LOOKUP        ;Table lookup routine
               JMP     MEX
;
MPRINT:         MVI     C,PRINT         ;MEX print function
               JMP     MEX
;
CRLF:           MVI     A,CR            ;newline on console
               CALL    TYPE
               MVI     A,LF
TYPE:           PUSH    H               ;save em
               PUSH    D
               PUSH    B
               MOV     E,A
               MVI     C,CONOUT        ;align output char
               CALL    MEX             ;print via mex
               POP     B               ;restore em
               POP     D
               POP     H
               RET


               IF      MMINTR          ;Gen if interrupts wanted

;******************************************************************************
;
;       I N T E R R U P T       P R O C E S S I N G
;
;******************************************************************************
;
;       Search the BIOS for the interrupt disable in the video handler
;       and the keyboard handler.  Replace the DI with NOP and note their
;       addresses.  Replace the 38H vector with a jump to our interrupt
;       handling routine.
;
INT$SET:        LHLD    0001H           ;Get start address of BIOS
               LXI     B,0B00H         ;Max search size of BIOS
               LXI     D,INT$NOP       ;Table to save BIOS addresses

IS$LP1:         MVI     A,0F3H          ;Code for 'DI'
               DB      0EDH,0B1H       ;CPIR, look for DI
               JNZ     IS$SDN          ;Search is done

IS$TST:         PUSH    H               ;Save regs
               PUSH    D
               PUSH    B
               LXI     D,I$STR         ;Get remainder of code string
               MVI     B,4             ;Compare next four bytes
IS$LP2:         LDAX    D               ;Get byte from string
               INX     D               ;Bump ptr
               CMP     M               ;Compare to BIOS bytes
               INX     H
               JNZ     IS$LE2          ;Not the same
               DB      10H,(IS$LP2-$-1) AND 0FFH ;DJNZ IS$LP2
IS$LE2:         POP     B               ;Restore regs
               POP     D
               POP     H
               JNZ     IS$LP1          ;Jump if not found

               DCX     H               ;We found a DI!
               XRA     A
               MOV     M,A             ;Put NOP where DI was
               XCHG
               MOV     M,E             ;Put DI address into table
               INX     H
               MOV     M,D
               INX     H
               XCHG
               INX     H               ;Restore HL
               JMP     IS$LP1          ;Look for more 'DI's

IS$SDN:         XRA     A               ;Clear A
               STAX    D               ;Clear the last entr
               INX     D
               STAX    D
               LHLD    INT$NOP         ;Test for any 'DI's found
               MOV     A,H
               ORA     L
               JZ      IS$NONE         ;No DI strings found, error!
;
;       Set up all vectors
;
               LDA     0038H           ;Get old vector contents
               LHLD    0039H
               STA     INT$VCT         ;Save it for later
               SHLD    INT$VCT+1
               MVI     A,0C3H          ;Form a JMP instruction
               LXI     H,INT$RTN       ; to the interrupt service routine
               STA     0038H           ;Store new vector
               SHLD    0039H

               LXI     H,INT$BUF       ;HL -> start of buffer
               SHLD    INT$INP         ;Set up pointers
               SHLD    INT$OUTP        ;into the buffer
               XRA     A               ;Clear A regs
               STA     INT$CNT         ;Count of chars in buffer
;
;       Set up interrupt hardware and GO
;
               MVI     A,020H          ;Interrupt on UART data input ready
               OUT     0E0H            ;Set up interrupt mask
               RET                     ;Return to the caller

IS$NONE:        LXI     D,I$NODI        ;Print error message
               CALL    MPRINT
               JMP     0000H           ;Return to CP/M

;
;       I N T $ B Y E    ---   Restore all vectors and return
;
INT$BYE:        DI                      ;Disable interrupts
               LXI     H,INT$NOP       ;Point to DI address table
IB$LP1:         MOV     E,M             ;Load an address
               INX     H
               MOV     D,M
               INX     H
               MOV     A,D             ;Test for end of table
               ORA     E
               JZ      IB$VCT          ;Exit when DI's replaced
               LDA     INT$BYE         ;Get a DI
               STAX    D               ;Store it
               JMP     IB$LP1          ;Loop for the next one

IB$VCT:         LDA     INT$VCT         ;Get old 38H vector data
               LHLD    INT$VCT+1
               STA     0038H           ;Restore data
               SHLD    0039H

               XRA     A               ;Clear A reg
               OUT     0E0H            ;Disallow all interrupts
               RET                     ;Return to caller

;
;       I N T $ R T N    ----  Interrupt service routine
;
INT$RTN:        PUSH    PSW             ;Save flags
               IN      MODCT1          ;Get UART flags
               ANI     MDRCVR          ;Isolate data ready bit
               CPI     MDRCVB          ;Anythin' ther?
               JNZ     IR$RET          ;No, return

               IN      MODDAT          ;Get the data byte
               PUSH    H               ;Save another reg
               LHLD    INT$INP         ;Get our ptr
               MOV     M,A             ;Save the data byte
               CALL    INT$BMP         ;Bump the ptr
               SHLD    INT$INP         ;Save ptr

               LDA     INT$CNT         ;Increment count
               INR     A               ;Add one to the count
               CPI     INTSIZ+1        ;Max saved chars?
               JC      IR$SVCT         ;No, Save new count
               LHLD    INT$OUTP        ;Get the output pointer
               CALL    INT$BMP         ;Bump it ahead of the input ptr
               SHLD    INT$OUTP
               MVI     A,INTSIZ        ;Reload max size
IR$SVCT:        STA     INT$CNT         ;Save updated count
               POP     H               ;Restore H

IR$RET:         IN      0E0H            ;Read int status reg
               POP     PSW
               EI                      ;Reenable interrupts
               DB      0EDH,04DH       ;RETI

;
;       I N T $ T S T   ---     Test buffer for pending data
;
INT$TST:        DI                      ;Disable interrupts
               LDA     INT$CNT         ;Get the count
               ORA     A               ;Test for zero
               EI                      ;Enable interrupts
               RZ                      ;Return if no data
               MVI     A,MDRCVR        ;Get data ready bit
               RET                     ;Return

;
;       I N T $ G E T    ---    Get a data byte from the buffer
;
INT$GET:        DI                      ;Disable interrupts
               LDA     INT$CNT         ;Get byte count
               ORA     A               ;Test for anything
               JZ      IG$RET          ;Nothing, return
               DCR     A               ;Subtract one
               STA     INT$CNT         ;Update count
               PUSH    H               ;Save HL reg
               PUSH    B               ;And BC
               LHLD    INT$OUTP        ;Get buffer ptr
               MOV     B,M             ;Load a byte from the buffer
               CALL    INT$BMP         ;Bump the pointer
               SHLD    INT$OUTP        ;Save updated ptr
               MOV     A,B             ;Get data byte again
               POP     B               ;Restore regs
               POP     H

IG$RET:         EI                      ;Enable interupts
               RET                     ;Return to caller

;
;       Routine to bump the buffer pointer and reset it to the buffer
;       start if we overrun the end
;
INT$BMP:        INX     H               ;Bump ptr
               MOV     A,L             ;Get LS byte
               CPI     (INT$BUF+INTSIZ) AND 0FFH ;Buffer end?
               RNZ                     ;No, return with the ptr as is
               LXI     H,INT$BUF       ;Get buffer stat addr
               RET                     ;Return the reset ptr

;
;       Interrupt Routine Data, Pointer, and Buffer area
;
I$NODI:         DB      'Non standard BIOS -- Cannot continue',CR,LF,'$'

I$STR:          DB      03EH,08EH,0D3H,084H ;MVI A,8EH   OUT 84H

INT$VCT:        DS      3               ;Old 38H vector data
INT$NOP:        DS      2*5             ;Up to 5 DI's

INTSIZ:         EQU     200             ;Buffer up to 200 characters
INT$CNT:        DB      0               ;Count of bytes in buffer
INT$INP:        DW      INT$BUF         ;Interrput service rtn ptr
INT$OUTP:       DW      INT$BUF         ;MEX buffer ptr
INT$BUF:        DS      INTSIZ          ;Pending data buffer

               ENDIF



;******************************************************************************
;
;       Message and data area
;
;******************************************************************************

CURURT: DB      DEFCTB          ;Current UART configuration bits

BAUDMSG:DB      CR,LF,'Baud Rate:       $'
STOPMSG:DB      CR,LF,'Stop bits:       $'
WLMSG:  DB      CR,LF,'Word length:     $'
PARMSG: DB      CR,LF,'Parity:          $'

POFMSG: DB      'off$',CR,LF
ODDMSG: DB      'on and odd$',CR,LF
EVEMSG: DB      'on and even$',CR,LF

CLSMSG: DB      CR,LF,1AH,'$'
EOSMSG: DB      CR,LF,19H,'$'

SOMESG: DB      'TRS Mod 4 CP/M 2.2 overlay V'
       DB      REV/10+'0'
       DB      '.'
       DB      REV MOD 10+'0'
       IF      MMINTR
       DB      ' (Interrupt Driven)'
       ENDIF
       DB      CR,LF,'$'

NOMESG: DB      ONV,'no $'
CARMSG: DB      ONV,'carrier present',INV,CR,LF,'$'

;***************************************************************************
;
;       MEX legal command tables
;
;***************************************************************************

CMDTBL: DB      '?'+80H         ;"set ?"
       DW      STHELP
       DB      'BAU','D'+80H   ;"set baud ?'
       DW      STBAUD
       DB      'WOR','D'+80H   ;set word length
       DW      STWORD-STTABL
       DB      'PARIT','Y'+80H ;set parity
       DW      STPAR-STTABL
       DB      'STO','P'+80H   ;set stop bits
       DW      STSTOP-STTABL
       DB      0

;
;       UART data format parameters
;
STTABL:                         ;Start of UART control parameters

STSTOP: DB      '1'+80h         ;Legal stop bits settings
       DB      0FFH-U$STOP,U$STP1
       DB      '2'+80h         ;2 bits
       DB      0FFH-U$STOP,U$STP2
       DB      0

STPAR:  DB      'OD','D'+80h    ;Odd parity and ON
       DB      0FFH-U$PART,U$PROD+U$PRON
       DB      'EVE','N'+80h   ;Even parity and ON
       DB      0FFH-U$PART,U$PREV+U$PRON
       DB      'OF','F'+80h    ;Parity OFF
       DB      0FFH-U$PART,U$PROF
       DB      0

STWORD: DB      '5'+80h         ;5 Bits per byte
       DB      0FFH-U$WORD,U$WRD5
       DB      '6'+80h         ;6 Bits per byte
       DB      0FFH-U$WORD,U$WRD6
       DB      '7'+80h         ;7 Bits per byte
       DB      0FFH-U$WORD,U$WRD7
       DB      '8'+80h         ;8 Bits per byte
       DB      0FFH-U$WORD,U$WRD8
       DB      0

;
;       Legal baud settings table
;
STBDTB: DB      '30','0'+80H    ;300 Baud
       DB      1,055H          ;MEX speed,UART baud speed
       DB      '120','0'+80H   ;1200 Baud
       DB      5,077H
       DB      '240','0'+80H   ;2400 Baud
       DB      6,0AAH
       DB      '480','0'+80H   ;4800 Baud
       DB      7,0CCH
       DB      '960','0'+80H   ;9600 Baud
       DB      8,0EEH
       DB      '1920','0'+80H  ;19200 Baud
       DB      9,0FFH
       DB      0

;
;       Help menu for SET command
;
HLPMSG: DB      CR,LF,'SET BAUD 300 <or> 1200 <or> 2400 <or> 4800 <or> 9600'
       DB      CR,LF,'SET PARITY OFF <or> ODD <or> EVEN'
       DB      CR,LF,'SET WORD 5 <or> 6 <or> 7 <or> 8'
       DB      CR,LF,'SET STOP 1 <or> 2'
       DB      CR,LF,'$'
;
;-----------------------------------------------------------------------------
; NOTE:  MUST TERMINATE PRIOR TO 0B00H (with Smartmodem or Anchor)
;-----------------------------------------------------------------------------
; End of TRS-80 MOD IV  MEX modem overlay
;
;******************************************************************************

       END     ;
S-80 MOD IV  MEX modem overlay