; I2RY-1.ASM - Royal Alphatronic PC IMP overlay (low speed) - 07/10/87
;
;               USES 8251A I/O and no baudrate generator
;
; You will want to look this file over carefully. There are a number of
; options that you can use to configure the program to suit your taste.
; This file adapts the Royal computer to the IMP modem program.  This
; model has no baudrate generator and changes the 8251 from "x16" for
; 1200 bps to "x64" for 300 bps.  The Royal must be jumpered for 1200
; bps for this method to work. (J101 4th from left)
;
; Edit this file for your preferences then follow the "TO USE:" example
; shown below.
;
; Many terminals will clear the screen with a CTL-Z.  If yours does, put
; a 1AH at CLEAR: (010AH).  Many terminals use two characters, the first
; normally an ESC.  For example, ESC *.  In this case put '*' at CLEAR:
; (The ESC will automatically be typed with no CTL-character present.)
; If you don't know what your terminal uses, put a 0 at CLEAR: and IMP
; will scroll up 24 blank lines to clear the CRT for things like MENU,
; looking at the function key table, typing CTL-Z in command mode, etc.
;
; Use the "SET" command to change the baudrate when desired.  The value
; at MSPEED controls the baudrate when the program is first called up.
;
;       TO USE: First edit this file filling in answers for your own
;               equipment.  Then assemble with ASM.COM or equivalent
;               assembler.  Then use MLOAD to merge into the main file:
;
;               MLOAD IMP.COM=IMP.COM,I2RY-x.HEX
;
; =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =
;
; 07/11/87  Adapted from I2SY-2.ASM for Royal Alphatronic PC
;                                               - Paul Carmichael
;
; 06/01/87  Improved the GOODBYE routine, added BREAK routine, needs
;           IMP245 to use it.                   - Irv Hoff
;
; 10/27/85  Initial IMP version                 - Irv Hoff
;
; =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =   =
;
;
; ROYAL EQUATES
;
EOICMD  EQU     20H     ; Non-spec EIO for PIC
RXINTV  EQU     0EF04H  ; Receive ready interruptvector
LSTSTV  EQU     0D92DH  ; Lstst vector (bug in monitor)
PICPRT0 EQU     70H     ; PIC base port
PICPRT1 EQU     71H
PICMSK0 EQU     0FDH    ; Enable receive ready interrupt
PICMSK1 EQU     0FFH    ; Mask all interrupts
RXBFSIZ EQU     32      ; Receive buffer size
XOFF    EQU     'S'-40H
XON     EQU     'Q'-40H
;
;
NO      EQU     0
YES     EQU     NOT NO  ; (Some assemblers cannot use 0FFh)
;
;
; Valeus shown are for an 8251A
;
PORT    EQU     40H     ; Your base port (data or status)
MDCTL1  EQU     PORT+1  ; Modem control port
MDDATP  EQU     PORT    ; Modem data port
MDRCV   EQU     02H     ; Modem receive ready
MDSND   EQU     01H     ; Modem send ready bit
MDTXE   EQU     05H     ; Modem send buffer empty, holding buffer empty
;
MDMODE  EQU     82H     ; Insures 8251 is out of mode with DTR high
MDRSET  EQU     42H     ; Resets USERT for additional commands
MDSET0  EQU     4FH     ; 1 stop bit, no parity, 8 bits, x64
MDSET1  EQU     4EH     ; 1 stop bit, no parity, 8 bits, x16
MDSET2  EQU     4CH     ; 2 stop bits, no parity, 8 bits, x16
RDCOM   EQU     37H     ; Reset RTS, error flags, RCV, DRT, TX ready
;
;
;-----------------------------------------------------------------------
;
ESC     EQU     '['-40H ; ^[ = escape
BELL    EQU     'G'-40H ; ^G = bell character
LF      EQU     'J'-40H ; ^J = linefeed
NEXTRY  EQU     'K'-40H ; ^K = try next phone number, abort this try
CR      EQU     'M'-40H ; ^M = carriage return
CLEARSC EQU     'Z'-40H ; ^Z = clears screen, command mode only
EOFCHAR EQU     'Z'-40H ; ^Z = end of file
;
;
;-----------------------------------------------------------------------
;
;
       ORG     103H
;
MSPEED:  DB     5       ; 0=110 1=300 2=450 3=600 4=710 5=1200          103h
                       ; 6=2400 7=4800 8=9600 9=19200 default
HS2400:  DB     NO      ; Yes=2400 bps highest speed                    104h
HS1200:  DB     YES     ; Yes=1200 bps highest speed                    105h
RACAL:   DB     NO      ; Yes=Racal-Vadic 1200v or 2400v or 2400pa      106h
PROMODM: DB     NO      ; Yes=Prometheus ProModem 1200 bps              107h
RESVD1:  DB     NO      ; Reserved for special modems                   108h
RESVD2:  DB     NO      ; Reserved for special modems                   109h
;
;
CLEAR:   DB     'E'     ; Clear screen character (ESC not needed)       10Ah
CLOCK:   DB     40      ; Clock speed in mhz x10, 25.5 MHz max.         10Bh
                       ; 20=2 MHz, 37=3.68 MHz, 40=4 MHz, etc.
BYTDLY:  DB     2       ; 0=0 delay  1=10ms  5=50 ms - 9=90 ms          10Ch
                       ; Default time to send character in ter-
                       ; Minal mode file transfer for slow bbs
CRDLY:   DB     2       ; 0=0 delay 1=100 ms 5=500 ms - 9=900 ms        10Dh
                       ; Default time for extra wait after crlf
                       ; In terminal mode file transfer
NOFCOL:  DB     5       ; Number of directory columns shown             10Fh
TCHPUL:  DB     'T'     ; T=tone, P=pulse (Hayes 2400 modems)           10Fh
;.....
;
ADDLFD:  DB     NO      ; Yes=add LF after cr to send file in terminal  110h
                       ; Mode (normally added by remote echo)
CONVRUB: DB     YES     ; Yes=convert RUB to backspace                  111h
CRCDFLT: DB     YES     ; Yes=default to CRC checking                   112h
IGNRCTL: DB     YES     ; Yes=CTL-characters above ^M not displayed     113h
;.....
;
EXTCHR:  DB     '['-40H ; ESC = preceeds local control character        114h
EXITCHR: DB     'E'     ; Exit character                                115h
FILESND: DB     'F'     ; Send file when in terminal mode               116h
NOCONCT: DB     'N'     ; Disconnect from phone line                    117h
LOGCHR:  DB     'L'     ; Send logon                                    118h
LSTCHR:  DB     'P'     ; Toggle printer                                119h
UNSAVCH: DB     'R'     ; Close input text buffer                       11Ah
SAVECHR: DB     'Y'     ; Open input text buffer                        11Bh
CLEARS:  DB     'Z'     ; Clears screen, terminal mode                  11Ch
BRKCHR:  DB     'Q'     ; Send a break tone                             11Dh
NODTR:   DB     NO      ; Yes if no DTR and need ATH0 to disconnect     11Eh
;.....
;
; Handles in/out ports for data and status
;
         ORG   11FH
I$MDCTL1: IN    MDCTL1
         RET
;
         ORG   129H
I$MDTXE:  IN    MDCTL1
         RET
;
         ORG   133H
I$MDDATP: JMP   GETRX
;
         ORG   13DH
O$MDDATP: OUT   MDDATP
         RET
;
         ORG   147H
A$MDRCV:  RET
;
         ORG   14AH
C$MDRCV:  JMP   RXRDY
;
         ORG   14DH
A$MDSND:  ANI   MDSND
         RET
;
C$MDSND:  CPI   MDSND
         RET
;
A$MDTXE:  ANI   MDTXE
         RET
;
C$MDTXE:  CPI   MDTXE
         RET
;.....
;
       ORG     159H
;
; Special exit vector, used by some computers to reset interrupt vectors
;
J$EXITVEC:JMP   REXIT           ;                                       159h
;.....
;
; JUMP VECTORS NEEDED BY EACH OVERLAY
;
J$GOODBYE:JMP   GOODBYE         ; Disconnects modem by dropping DTR     15Ch
J$INITMOD:JMP   INITMOD         ; Initializes modem, autosets baudrate  15Fh
J$STUPR:  JMP   STUPR           ; Set routine to change baudrate        162h
J$SYSVR:  JMP   SYSVR           ; Signon message                        165h
;.....
;
; "AT" command strings, can be replaced in individual overlay if needed
;
J$STRNGA: DS    3               ; 1200 bps "AT" string                  168h
J$STRNG1: DS    3               ; 2400 bps "AT" string                  16Bh
;
;
; Next fourteen lines should not be changed by user overlay as these go
; to specific locations in the main program, not in the overlay.
;
;
J$CMDSPL: DS    3               ; Allows entry of baudrate on CMD line  16Eh
J$CRLF:   DS    3               ; Turns up one new line on display      171h
JR$DIAL:   DS   3               ; Start of dialing routine              174h
J$DSCONT: DS    3               ; Terminates modem use                  177h
J$GOLST:  DS    3               ; Printer routine, needed by APPLE //e  17Ah
J$ILPRT:  DS    3               ; Prints an inline string, 0 to end     17Dh
J$INBUF:  DS    3               ; Stores a keybd string for comparison  180h
J$INLNCP: DS    3               ; Inline "compare strings" routine      183h
J$INMDM:  DS    3               ; Max .1 sec wait for modem character   186h
J$RCVRSP: DS    3               ; For 3801 I/O use (TV-803)             189h
J$SNDCHR: DS    3               ; Sends a character to the modem        18Ch
J$SNDSTR: DS    3               ; Sends a string to the modem, $ to end 18Fh
J$TIMER:  DS    3               ; 1 second timer (amount in 'B' reg.)   192h
J$BREAK:  JMP   SENDBRK         ; Break routine                         195h
J$NEW2:   DB    0,0,0           ; For future needs                      198h
;.....
;
;
; For 2400 bps auto-stepdown units
;
MANUAL:   DB    0               ; For manual selection flag             19Bh
J$300:    JMP   OK300           ;                                       19Ch
J$1200:   JMP   OK1200          ;                                       19Fh
J$2400:   JMP   OK2400          ; Sets baudrate to 2400 bps             1A2h
;.....
;
;
LOGPTR:   DW    LOGON           ; Pointer to display logon message      1A5h
;
SYSVR:    CALL  J$ILPRT         ; Display the following line            1A7h
         DB    'Version for Royal Alphatronic PC'
         DB    CR,LF,0
         RET
;.....
;
;
;-----------------------------------------------------------------------
;
; NOTE:  You can change the SYSVER message to be longer or shorter.  The
;        end of your last routine should terminate by 0400h (601 bytes
;        available after start of SYSVER).
;
;-----------------------------------------------------------------------
;
; You can put in a message at this location which can be called up with
; (special character-L).  You can put in several lines.  End with a 0.
;
LOGON:  DB      'Hello!',CR,LF,0
;
;-----------------------------------------------------------------------
;
; This routine sets a 300 ms break tone
;
SENDBRK:
       MVI     A,3FH           ; DTR normal, send break tone
       JMP     GOODBYE+2
;.....
;
;
; This routine sets DTR low for 300 ms to disonnect the phone
;
GOODBYE:
       MVI     A,3DH           ; Send break, turn off DTR
       DI
       OUT     MDCTL1          ; Send to status port
       MVI     B,3             ; Delay 300 ms to hang up phone
       CALL    J$TIMER
       MVI     A,37H           ; Normal send/receive with DTR
       OUT     MDCTL1          ; Send to status port
       LXI     H,RXBUF
;
R:      SHLD    RXPTR           ; Reset pointer
       XRA     A
       STA     RXCNT           ; Clear count
       EI
       RET
;.....
;
;
; Sets 8251 to 8 bits, DTR, RCV and TX ready
;
INITMOD:
       DI
       CALL    INIT0           ; Go initialize the modem
       LHLD    LSTSTV+1
       SHLD    OLDVEC          ; Save old LsTst vector
       LXI     H,LSTST
       SHLD    LSTSTV+1        ; Insert new
       XRA     A
       STA     RXCNT           ; Clear buffer counter
       LXI     H,RXBUF
       SHLD    RXPTR           ; Preset pointer
       LXI     H,RXISR
       SHLD    RXINTV+1        ; Rxrdy service vector into table
       MVI     B,8
       MVI     A,EOICMD
;
INITL1: OUT     PICPRT0         ; EOI to PIC
       DCR     B
       JNZ     INITL1          ; 8 times
       MVI     A,0C3H
       STA     RXINTV
       MVI     A,PICMSK0
       OUT     PICPRT1         ; Enable rxrdy interrupt
       EI
       RET
;.....
;
;
INIT0:  LDA     MSPEED          ; Get the selected value
       CPI     1               ; 300 baud
       JZ      OK300
       CPI     5               ; 1200 bps
       JZ      OK1200
       JMP     STUPR1          ; Else ask what is wanted
;.....
;
;
;
STUPR:  CALL    J$CMDSPL        ; Gives us CMDBUF+6
       JNC     STUPR2
;
STUPR1: CALL    J$ILPRT
       DB      'INPUT BAUD RATE (300, 1200): ',0
       LXI     D,BAUDBUF       ; Point to new input buffer
       CALL    J$INBUF
       CALL    J$CRLF
       LXI     D,BAUDBUF+2
;
STUPR2: CALL    J$INLNCP        ; Compare BAUDBUF+2 with chars. below
       DB      '300',0
       JNC     OK300           ; Go if got match
       CALL    J$INLNCP
       DB      '1200',0
       JNC     OK1200
       CALL    J$ILPRT         ; All matches failed, tell operator
       DB      '++ INCORRECT ENTRY ++',CR,LF,BELL,CR,LF,0
       JMP     STUPR1          ; Try again
;
OK300:  MVI     A,1             ; MSPEED 300 baud value
       MVI     B,MDSET0        ; Divide by 64 for 300 baud
       JMP     LOADBD          ; Go set the baudrate
;
OK1200: MVI     A,5
       MVI     B,MDSET1        ; Divide by 16 for 1200 bps
       JMP     LOADBD          ; Go set the baudrate
;
OK2400: JMP     OK1200
;
LOADBD: STA     MSPEED          ; Change time-to-send to match baudrate
       MVI     A,MDMODE        ; Insure 8251 is out of mode
       OUT     MDCTL1
       XTHL                    ; Small delay to complete command
       XTHL
       MVI     A,MDRSET        ; Reset the 8251a for new command
       OUT     MDCTL1
       XTHL                    ; Small delay to complete command
       XTHL
       MOV     A,B             ; Set speed
       OUT     MDCTL1
       XTHL                    ; Small delay to complete command
       XTHL
       MVI     A,MDCOM         ; Error reset, RCV, DTR, TX ready
       OUT     MDCTL1
       XTHL                    ; Small delay to complete command
       XTHL
       RET
;.....
;
;
REXIT:  DI
       MVI     A,0C9H          ; Put return code into vector
       STA     RXINTV
       MVI     A,PICMSK1
       OUT     PICPRT1         ; Mask all interrupts
       LHLD    OLDVEC
       SHLD    LSTSTV+1
       XRA     A
       STA     RXCNT
       LXI     H,RXBUF
       SHLD    RXPTR
       EI
       RET
;.....
;
;
; Receive ready service routine
;
RXISR:  PUSH    PSW
       PUSH    B
       PUSH    D
       PUSH    H               ; Save registers
       IN      MDDATP
       LHLD    RXPTR           ; Get buffer pointer
       MOV     M,A             ; Put RX data to buffer
       INX     H
       SHLD    RXPTR
       LDA     RXCNT
       INR     A
       CPI     RXBFSIZ         ; ? buffer full
       STA     RXCNT
       JC      RXISX           ; Skip next if not
       MVI     A,0FFH
       STA     XOFFL
       MVI     A,XOFF
       CALL    J$SNDCHR
;
RXISX:  MVI     A,EOICMD
       OUT     PICPRT0         ; EOI to PIC
       POP     H
       POP     D
       POP     B
       POP     PSW             ; Restore registers
       EI
       RET
;.....
;
;
; Get a character from RX buffer
;
GETRX:  PUSH    B
       PUSH    D
       PUSH    H
;
GETRX0: DI
       LDA     RXCNT
       DCR     A               ; Decrement counter
       STA     RXCNT           ; Store new value
       LXI     H,RXBUF
       MOV     C,A
       MOV     A,M
       STA     CHAR            ; Save character
       JZ      GETRX1          ; Skip next if last character
       MVI     B,0
       XCHG
       LXI     H,RXBUF+1
       DB      0EDH
       DB      0B0H            ; Move buffer down a byte
;
GETRX1: LDA     XOFFL
       ORA     A
       JZ      GETRXX          ; If XOFF flag not set leave
       MVI     A,XON
       CALL    J$SNDCHR
       XRA     A
       STA     XOFFL           ; Turn XON and clear flag
;
GETRXX: LHLD    RXPTR
       DCX     H
       SHLD    RXPTR           ; Adjust buffer pointer
       LDA     CHAR            ; Recover character
       POP     H
       POP     D
       POP     B
       EI
       RET
;.....
;
;
RXRDY:  LDA     RXCNT           ; Get RX buffer counter
       ORA     A               ; Anything there?
       JZ      RXNRDY          ; Go not ready if not
       XRA     A               ; Indicate ready
       RET
;
RXNRDY: MVI     A,0FFH
       ORA     A               ; Indicate not ready
       RET
;.....
;
;
LSTST:
       IN      30H
       IN      30H             ; For hardware
       ANI     40H             ; ? busy
       JZ      LSTRDY          ;
       XRA     A
       RET                     ; Lister busy
;
LSTRDY: DCR     A
       ORA     A
       RET                     ; Lister not busy
;.....
;
;
XOFFL:  DB      0               ; Xoff flag
CHAR:   DB      0               ; Temp character register
RXPTR:  DW      0               ; Buffer pointer
OLDVEC: DW      0               ; Old LsTst vector
BAUDBUF:DB      10,0,0,0,0,0    ; CONINP buffer
       DB      0,0,0,0,0,0
RXCNT:  DB      0               ; RX buffer counter
RXBUF:  DS      RXBFSIZ         ; RX input buffer
;
;                              end
;-----------------------------------------------------------------------
       END