TITLE  'MEX Overlay for Apple ][ / SSC / Smartmodem'
;
;  MXH-AP55.ASM
;
REV     EQU     55              ; 3 May 1987
;
; This overlay is specific for the following hardware:
;
;       Apple ][ +/e  with PCPI Applicard
;       Apple Super Serial Card
;
; Important Note:
;       Rev 5.5 introduces the Interrupt/Buffer concept.  This requires
; the use of an Applicard driver, in this case RINGBUF.DVR.  Operation
; in this mode eliminates the infamous character loss on scroll problem
; up to 2400 baud. SET INTerrupt control has been added to this official
; release to allow bypassing the INT mode if the INT/Buffer is found to
; be buggy or as I found, I had two SuperSerial cards in, 1 with and 1 w/0
; interrupts and this was a problem. (By the way I used the 2nd card for
; a network I/O). In any event, it's handy have the set feature and the
; default can be CLONEed in.                       -Jim
;------------------------------------------------------------------
; REVISION HISTORY:
;------+---------+----------------+--------------------------------
; Rev. |  Date   |     Author     |       Description
;------+---------+----------------+--------------------------------
; 5.5  | 3 May 87| Bob Sass/      | - added support for RINGBUF.DVR
;      |         |      Jim Lill  |   See note above, Tested with //e
;------+---------+----------------+--------------------------------
; 5.4  |16 Apr 87| Jim Lill       | -speeded up calls to the Modem
;      |         |                |  Port by recoding PEEK and POKE and
;      |         |                |  changing CALLs to JMPs. Picked
;      |         |                |  up 19 bytes.
;------------------------------------------------------------------
; 5.3  |13 Dec 86| Jim Lill       | -added SET WAIT code for use with
;      |         |                |  MXO-SM14 and cleaned up SET displays
;------+---------+----------------+--------------------------------
; 5.2  | 1 Nov 86| Jim Lill       | -eliminated Modem specific section
;      |         |                |  requires use of Modem overlay
;      |         |                |  such as MXO-SM14 or MXM-2413
;      |         |                |  This seems to solve a timing problem
;      |         |                |  that occurred when loading 2413
;      |         |                |  over AP51
;------+---------+----------------+--------------------------------
; 5.1  | 5 Apr 86| Jim Lill       | -changed CLSMSG and EOSMSG
;      |         |                | -added INITBAUD equate for setting
;      |         |                |  MSPEED and baud in INITPORT
;------+---------+----------------+--------------------------------
; 5.0  |1 Apr 86 | Jim Lill       | created adaption, includes DCD
;      |         |                | and a spot for RNG detect.
;------+---------+----------------+--------------------------------
; IMPORTANT NOTE:
;    This overlay is based on MXO-AP50.ASM by Henry Middlebrook
;    Refer to it for additional info. The changes in this overlay
;    could be easily adapted to other Middlebrook work like AP34
;    To find changes, search for "MEXplus"
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

YES             EQU     0FFH
NO              EQU     0

;---------------------------------------------------------------------
; Options....

INITBAUD        EQU     5       ;Initial Baud Rate
                               ; 0=110   5=1200
                               ; 1=300   6=2400
                               ;   450   7=4800
                               ; 3=610   8=9600
                               ; 4=710   9=19200
Z80XTAL         EQU     73      ;set to Z80 CPU crystal MHz
                               ;times correction factor
                               ;e.g: 6Mhz * 12.16666= 73
WAIT            EQU     YES     ;set to YES if you use the
                               ;SET WAIT command and MXO-SM14 etc
WAITSEC         EQU     45      ;default wait time
;---------------------------------------------------------------------
BELL            EQU     07H     ;bell
CR              EQU     0DH     ;carriage return
ESC             EQU     1BH     ;escape
LF              EQU     0AH     ;linefeed
TAB             EQU     09H     ;tab
;
;----------------------------------------------------------------------
;       Apple Super Serial Card equates
;       -------------------------------
;
SSCSLOT         EQU     2                       ;Slot of Super Serial Card
MODDATP         EQU     0C088H + (SSCSLOT*10H)  ;data port of ACIA
MODSTAP         EQU     0C089H + (SSCSLOT*10H)  ;status port of ACIA
MODCTLP         EQU     0C08BH + (SSCSLOT*10H)  ;control port of ACIA
MODCMDP         EQU     0C08AH + (SSCSLOT*10H)  ;command port of ACIA
;
;
RDBYTE          EQU     0FFE0H  ;Read a Byte from Apple (A = BYTE)
WRBYTE          EQU     0FFE3H  ;Write a Byte to Apple (C = BYTE)
RDWORD          EQU     0FFE6H  ;Read 2 Bytes from Apple (DE = BYTES)
WRWORD          EQU     0FFE9H  ;Write 2 Bytes to Apple (DE = BYTES)
RDNBYTS         EQU     0FFECH  ;Read N Bytes (DE = COUNT, HL = BUFFER)
WRNBYTS         EQU     0FFEFH  ;Write N Bytes (DE = COUNT, HL = BUFFER)
;
PEEK1BYTE       EQU     6       ;Command to Peek 1 Byte in the Apple
POKE1BYTE       EQU     7       ;Command to Poke 1 Byte to the Apple
;
; New DCD routine equate MEXplus
;
CTSMSK          EQU     00100000B       ;mask to test for carrier
;
; Status bit equates for SSC serial port
;
MDSNDB          EQU     10H
MDSNDR          EQU     10H
MDRCVB          EQU     08H
MDRCVR          EQU     08H
;
; Equates for PSW (Parity, Stop Bit, Word Length) used by SSC ACIA
;  In these bytes the high nibble is the Word Length mask, the low
;  nibble is the Parity mask for the ACIA PSWFIX routine.
;
P8N1            EQU     010H    ;8 NONE 1
P7E1            EQU     036H    ;7 EVEN 1
P7O1            EQU     032H    ;7 ODD 1
P7N1            EQU     030H    ;7 NONE 1
;
BRKMSK          EQU     0CH     ;mask byte for BREAK function
DISCB           EQU     0AH     ;command byte for ACIA to drop DTR
;
;----------------------------------------------------------------------
;
;       MEX Service Processor Calls
;
MEX     EQU     0D00H   ;address of the service processor
INMDM   EQU     255     ;get char from port to A, CY=no more in 100 ms
TIMER   EQU     254     ;delay 100ms * 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 a character to the modem (after sndrdy)
RCVCHR  EQU     248     ;recv a char from modem (after rcvrdy)
LOOKUP  EQU     247     ;table search: see CMDTBL comments 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
PRNTBL  EQU     237     ;print command table in columns (HL=addr)
PRID    EQU     236     ;print MEX ID string on console
;
CONOUT  EQU     2       ;simulated BDOS function 2: console char out
PRINT   EQU     9       ;simulated BDOS function 9: print string
INBUF   EQU     10      ;input buffer, same structure as BDOS 10
;
;
;======================================================================
;
       ORG     100H    ;we begin
;
; changed jumps for MEXplus
;
       DB      0C3H    ;flags a LOADable file (for 8080)
       DS      2       ;MEX has a JMP START here
;
; The following variables are located at the beginning of the program
; to facilitate modification without the need of re-assembly. They will
; be moved in MEX 2.0.
;
PMODEM: DB      YES     ;\ / These two locations are                    103H
SMODEM: DB      NO      ;/ \ not referenced by MEX.                     104H
TPULSE: DB      'T'     ;Tone/Pulse (used only in Smodem overlay)       105H
CLOCK:  DB      Z80XTAL ;CPU speed                                      106H
MSPEED: DB      INITBAUD;sets display time for sending a file           107H
                       ;uses INITBAUD equate, changes during
                       ;use via PBAUD routine
BYTDLY: DB      1       ;default time to send character in              108H
                       ;terminal mode file transfer (0-9)
                       ;0=0 delay, 1=10 ms, 5=50 ms, 9=90 ms
CRDLY:  DB      1       ;end-of-line delay in terminal                  109H
                       ;mode file transfer for slow BBS systems
                       ;0=0 delay, 1=100 ms, 5=500 ms, 9=900 ms
COLUMS: DB      5       ;number of directory columns                    10AH
SETFL:  DB      YES     ;yes=user-defined SET command                   10BH
SCRTST: DB      YES     ;yes=if home cursor and clear screen            10CH
                       ;routine at CLRSCRN
       DB      0       ;was once ACKNAK, now spare                     10DH
BAKFLG: DB      NO      ;yes=make .BAK file                             10EH
CRCDFL: DB      YES     ;yes=default to CRC checking                    10FH
                       ;no=default to Checksum checking
TOGCRC: DB      YES     ;yes=allow toggling of Checksum to CRC          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 cmd if EXTCHR precedes               117H
                       ;no=not local cmd if EXTCHR precedes
TOGLOC: DB      YES     ;yes=allow toggling of LOCNXTCHR                118H
LSTTST: DB      YES     ;yes=allow toggling of printer on/off           119H
                       ;in terminal mode. Set to no if using
                       ;the printer port for the modem
XOFTST: DB      YES     ;yes=allow testing of XOFF from remote          11AH
                       ;while sending a file in terminal mode
XONWT:  DB      NO      ;yes=wait for XON after sending CR while        11BH
                       ;transmitting a file in terminal mode
TOGXOF: DB      YES     ;yes=allow toggling of XOFF testing             11CH
IGNCTL: DB      NO      ;yes=do not send control characters             11DH
                       ;above CTL-M to CRT in terminal mode
                       ;no=send any incoming CTL-char to CRT
EXTRA1: DB      WAITSEC ;passes wait time to modem overlay
EXTRA2: DB      0       ;for future expansion                           11FH
BRKCHR: DB      '@'-40H ;^@ = Send a 300 ms. break tone                 120H
NOCONN: DB      'N'-40H ;^N = Disconnect from 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
TRNCHR: DB      'T'-40H ;^T = Transmit file to remote                   125H
SAVCHR: DB      'Y'-40H ;^Y = Open input text buffer                    126H
EXTCHR: DB      '^'-40H ;^^ = Send next character                       127H
;
       DS      2       ;unused in this overlay
;
; Jump table accessed by MEX to write/read serial port
;
IN$MODSTAP:     JMP     RD$MODSTAP      ;read ACIA status port          12AH
               DS      7
OUT$MODDATP:    JMP     WR$MODDATP      ;send character to ACIA         134H
               DS      7
IN$MODDATP:     JMP     RD$MODDATP      ;read character from ACIA       13EH
               DS      7
;
; Bit-test routines.  These will be merged with the above
; routines in MEX 2.0 to provide a more reasonable format
;
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
;---------------------------------------------------------------------------
; MEXplus changes:
;  - was unused area. >>> MUST total 12bytes <<<
;  - now used for the Ringing and Carrier Detect jumps
;
DCDTEST:        JMP     DCDVEC          ;jump to carrier-detect routine 154H
RNGTEST:        JMP     RNGVEC          ;jump to ring detect routine    157H
                                       ;
               DS      6               ;remainder of space
;
;---------------------------------------------------------------------------
;
LOGON:          DS      2               ;not used by MEX                160H
DIALV:          DS      3               ;used by Modem overlay          162H
DISCV:          JMP     DISCON          ;drops DTR to hang-up fast!     165H
GOODBV:         JMP     GOODBYE         ;called before exit to CPM      168H
INMODV:         JMP     INITPORT        ;go to user written routine     16BH
NEWBDV:         JMP     PBAUD           ;changes baud with phone #      16EH
NOPARV:         RET  !  NOP  !  NOP     ;set modem for no-parity        171H
PARITV:         RET  !  NOP  !  NOP     ;set modem parity               174H
SETUPV:         JMP     SETCMD          ;                               177H
SPMENV:         DS      3               ;not used by MEX                17AH
VERSNV:         JMP     SYSVER          ;                               17DH
BREAKV:         JMP     SENDBRK         ;                               180H
;
; The following jump vector provides the overlay with access to special
; routines in the main program (retained and supported in the main pro-
; gram for MDM overlay compatibility). These should not be modified by
; the overlay.
;
; Note that for MEX 2.0 compatibility, you should not try to use these
; routines, since this table will go away with MEX 2.0 (use the MEX
; service call processor instead).
;
ILPRTV:         DS      3       ;replace with MEX function 9            183H
INBUFV:         DS      3       ;replace with MEX functin 10            186H
ILCMPV:         DS      3       ;replace with table lookup funct 247    189H
INMDMV:         DS      3       ;replace with MEX function 255          18CH
NXSCRV:         DS      3       ;not supported by MEX                   18FH
TIMERV:         DS      3       ;replace with MEX function 254          192H
;
; Clear/screen and clear/end-of-screen. Each routine must use the
; full 9 bytes alloted (may be padded with nulls).
;
;
CLREOS:         LXI     D,EOSMSG        ;                               195H
               MVI     C,PRINT
               CALL    MEX
               RET
;
CLS:            LXI     D,CLSMSG        ;                               19EH
               MVI     C,PRINT
               CALL    MEX
               RET
;
;               *** END OF FIXED FORMAT AREA ***
;--------------------------------------------------------------------------
; Make sure MEXplus has all of its' reserved area..
;
               ORG     0200H

;--------------------------------------------------------------------------
;               Overlay  Fixed  Messages  Area
;
; these codes changed to match PCPI CONFIGSV values for Televideo 950
;
;
EOSMSG: DB      ESC,89,0,0,'$'          ;clear to end of screen message
;
CLSMSG: DB      ESC,42,0,0,'$'          ;clear screen message
;
VERMSG: DB      CR,LF,'MEX for Apple ][ / PCPI / SSC',CR,LF
       DB      ' Version: ',REV/10+'0','.'
       DB      REV MOD 10+'0'
       DB      CR,LF,LF,'$'
       DB      0,'Overlay by Middlebrook/Lill',0,'$'
;
;----------------------------------------------------------------------
; These routines are specific to the Apple ][+ with Applicard.  The
; routines read modem hardware (Apple Super Serial Card ACIA) directly
; from the Applicard.
;
; Read the Command Port of ACIA
;
RD$MODCMDP:     PUSH    D
               LXI     D,MODCMDP
               JMP     PEEK
;
; Write to the Command Port of ACIA
;
WR$MODCMDP:     PUSH    D
               LXI     D,MODCMDP
               JMP     POKE
;
; Write to the Control Port of the ACIA
;
WR$MODCTLP:     PUSH    D
               LXI     D,MODCTLP
               JMP     POKE
;
; Read the Control Port of the ACIA
;
RD$MODCTLP:     PUSH    D
               LXI     D,MODCTLP
               JMP     PEEK

;.................................
;
; Read Data Port of ACIA
;

RD$MODDATP:
               LDA     INTFLG          ;get the INT flag
               ORA     A               ;test it
               JZ      NONINTDATP      ;it not set jump to non-irq read
INTDATP:        PUSH    B               ;
               MVI     C,0F1H          ;Device 28 (read)
               CALL    WRBYTE
               CALL    RDBYTE
               POP     B
               RET

NONINTDATP:     PUSH    D               ;non-irq read
               LXI     D,MODDATP
               JMP     PEEK
;.................................
;
; Read the Status Port of the ACIA
;
RD$MODSTAP:
               LDA     INTFLG          ;see if in INT mode
               ORA     A               ;
               JZ      NONINTSTAP      ;if not use non-INT

INTSTAP:        PUSH    B               ;INT method
               MVI     C,0F3H          ;Device 28 (other)
               CALL    WRBYTE
               MVI     C,1
               CALL    WRBYTE
               CALL    RDBYTE
               POP     B
               RET

NONINTSTAP:     PUSH    D               ;non-INT method
               LXI     D,MODSTAP
               JMP     PEEK
;...............................
;
; Write to the Serial Data Port of the ACIA
;
WR$MODDATP:     PUSH    D
               LXI     D,MODDATP
               JMP     POKE
;.............................
;
; Peek at 1 byte from Apple 6502 address space
; ENTRY: DE = Address in Apple
; EXIT: A = Data
;
PEEK:   PUSH    B
       MVI     C,PEEK1BYTE
       CALL    WRBYTE
       CALL    WRWORD
       CALL    RDBYTE
       POP     B
       POP     D
       RET
;
; Poke 1 byte to Apple 6502 address space
; ENTRY: DE = Address in Apple
; EXIT: A = Data
;
POKE:   PUSH    B
       MOV     B,A
       MVI     C,POKE1BYTE
       CALL    WRBYTE
       CALL    WRWORD
       MOV     C,B
       CALL    WRBYTE
       POP     B
       POP     D
       RET
;
;----------------------------------------------------------------------
; The new stuff for MEXplus
;
; Data Carrier Detect Routine
;
DCDVEC:         CALL    RD$MODSTAP      ;read SSC status port
               ANI     CTSMSK          ;isolate carrier bit
               JNZ     NOCARR          ;0=carrier detected
               CMA                     ;make it 0ffh
               RET                     ;
NOCARR:         XRA     A               ;make it 0
               RET                     ;
;
; Ring Detect Routine
;
RNGVEC:         JMP     DCDVEC          ;overlay doesn't know
;
;----------------------------------------------------------------------
;
; This routine sends a timed Break to modem from SSC card.
;
SENDBRK:CALL    RD$MODCMDP      ;get current command status
       STA     CMDSV
       ORI     BRKMSK          ;mask to make ACIA send BREAK
       CALL    WR$MODCMDP      ;send command
       MVI     B,5
       MVI     C,TIMER         ;wait 500 msecs
       CALL    MEX
       LDA     CMDSV           ;get old command state
       JMP     WR$MODCMDP      ;put it back
;
;.....

; You can add your own routine here to set DTR low and/or send a break
; tone to disconnect when exiting to CPM.
;
GOODBYE:
       LDA     INTFLG          ;get the INT flag
       ORA     A               ;is it set?
       JZ      BYE             ;jump if not
       CALL    INTOFF
BYE:    RET
;................................
;
;  Turn off 6502 interrupts.
;
INTOFF: MVI     C,0F3H          ;Device 28 (other)
       CALL    WRBYTE
       MVI     C,20
       CALL    WRBYTE
       CALL    RDBYTE
       RET
;.................................
;
;  Turn On 6502 Interrupts
;
INTON:  MVI     C,0F3H          ;Device 28 (other)
       CALL    WRBYTE
       MVI     C,21
       CALL    WRBYTE
       CALL    RDBYTE
       RET
;.....
;
INITPORT:                       ;set up the default port conditions

; The following is used to initialize memory locations to eight data bits,
; no parity, one stop bit, and baud=INITBAUD

       LDA     INTFLG          ;get the INT flag
       ORA     A               ;test it
       JZ      SETIT           ;go set-up for non-INT

       MVI     A,09H           ;no parity, w/INT
       JMP     SETIT
;go do it

NONINT: MVI     A,0BH           ;no parity, w/o INT

SETIT:  STA     PARSV           ;save it
       MVI     A,10H           ;default 8 Data, 1 Stop Bits for ACIA
       STA     WRDSV           ;save it
       MVI     A,INITBAUD      ;set to initial baud equate
       JMP     PBAUD           ;let PBAUD setup ACIA (PBAUD will call
                               ;CHNGPORT below to actually setup ACIA)
;..............................
;
; This is the secondary entry used by the overlay to set baud,
; parity, and stop bit parameters of ACIA.
;
CHNGPORT:
       LDA     INTFLG          ;get the INT flag
       ORA     A               ;test it
       JZ      NOTINT          ;go do non-INT stuff
       CALL    INTON           ;turn int on
       LDA     PARSV           ;get current parity byte
       ORI     09H             ;req'd for int
       JMP     DOIT            ;go set up w/int
NOTINT: CALL    INTOFF          ;turn int off
       LDA     PARSV           ;get current parity byte
       ORI     0BH             ;w/o int
DOIT:   STA     CMDSV           ;save byte for other uses
       CALL    WR$MODCMDP      ;send to command port
       PUSH    H
       LXI     H,BAUDSV
       LDA     WRDSV
       ORA     M
       STA     CTLSV           ;...and save for other uses
       POP     H
       JMP     WR$MODCTLP      ;now send to control port
;
CMDSV:  DB      0               ;temporary storage
CTLSV:  DB      0               ;temporary storage
;
;.....
;
; This routine drops DTR to force modem to disconnect.  Does NOT do
; any initialization.
;
DISCON: CALL    RD$MODCMDP      ;get current command status
       STA     CMDSV           ;save it
       MVI     A,DISCB         ;get disconnect byte (drops DTR)
       CALL    WR$MODCMDP      ;send to ACIA
       MVI     B,10
       MVI     C,TIMER         ;wait 1 second
       CALL    MEX
       LDA     CMDSV           ;get back command status
       CALL    WR$MODCMDP      ;put it back in ACIA register
       MVI     B,10
       MVI     C,TIMER         ;wait another second
       JMP     MEX
;.....
;
; This routine changes the modem baud rate with phone list entry
;
; Set baud-rate code in A (if supported by your modem overlay).  PMMI
; supports only five rates, which are validated here. NOTE: this routine
; (ie, the one vectored through NEWBDV) should update MSPEED with the
; passed code, but ONLY if that rate is supported by the hardware.
;
PBAUD:  PUSH    H               ;don't alter anybody
       PUSH    D
       PUSH    B
       MOV     E,A             ;code to DE
       MVI     D,0
       LXI     H,BAUDTB        ;offset into table
       DAD     D
       MOV     A,M             ;fetch code
       ORA     A               ;0 means unsupported code
       JZ      PBEXIT          ;exit if so
       STA     BAUDSV          ;good rate, save it for CHNGPORT
       CALL    CHNGPORT        ;set baud (and PSW)
       MOV     A,E             ;get speed code back
       STA     MSPEED          ;make it current
       JMP     PBEXIT + 1      ;jump error flag set
PBEXIT: STC                     ;set return error for STBAUD caller
       POP     B               ;all done
       POP     D
       POP     H
       RET
;
; Table of baud rate parameters for supported rates
;
BAUDSV: DB      0                       ;current baud byte
BAUDTB: DB      03H,06H,0,07H,0         ;110,300,450,610,710
       DB      08H,0AH,0CH,0EH,0FH     ;1200,2400,4800,9600,19200
;.....
;
; Sign-on message
;
SYSVER: LXI     D,VERMSG
       MVI     C,PRINT
       JMP     MEX
;.....
;
; Newline on console
;
CRLF:   MVI     A,CR
       CALL    TYPE
       MVI     A,LF            ;fall into TYPE
;
; type char in A on console
;
TYPE:   PUSH    H               ;save 'em
       PUSH    D
       PUSH    B
       MOV     E,A             ;align output character
       MVI     C,CONOUT        ;print via MEX
       CALL    MEX
       POP     B
       POP     D
       POP     H
       RET
;
;----------------------------------------------------------------------
;
; The remainder of this overlay implements a very versatile SET command
; -- if you prefer not to write a SET for your modem, you may delete the
; code from here to the END statement. Control is passed here after
; MEX parses a SET command.
;
;
SETCMD: MVI     C,SBLANK        ;any arguments?
       CALL    MEX
       JC      SETSHO          ;if not, go print out values
       LXI     D,CMDTBL        ;parse command
       CALL    TSRCH           ;from table
       PUSH    H               ;any address on stack
       RNC                     ;if we have one, execute it
       POP     H               ;nope, fix stack
SETERR: LXI     D,SETEMS        ;print error
       MVI     C,PRINT
       JMP     MEX
;
SETEMS: DB      CR,LF,'SET command error',CR,LF,'$'
;
; SET command table ... note that tables are constructed of command-
; name (terminated by high bit=1) followed by word-data-value returned
; in HL by MEX service processor LOOKUP.  Table must be terminated by
; a binary zero.
;
; Note that LOOKUP attempts to find the next item in the input stream
; in the table passed to it in HL ... if found, the table data item is
; returned in HL; if not found, LOOKUP returns carry set.
;
CMDTBL: DB      '?'+80H                 ;"set ?"
       DW      STHELP
       DB      'BAU','D'+80H           ;"set baud"
       DW      STBAUD
       DB      'WP','S'+80H            ;"set PSW"
       DW      STPSW
       DB      'TON','E'+80H           ;'set TONE/PULSE byte to 'T'
       DW      STTONE
       DB      'PULS','E'+80H          ;'set TONE/PULSE byte to 'P'
       DW      STPULSE
       DB      'WAI','T'+80H           ;'set WAIT'
       DW      SETDLY
       DB      'IN','T'+80H            ;'set INT'
       DW      SETINT
       DB      0                       ;<<=== table terminator
;
; SET <no-args>: print current statistics
;
SETSHO: LXI     H,SHOTBL        ;get table of SHOW subroutines
SETSLP: MOV     E,M             ;get table address
       INX     H
       MOV     D,M
       INX     H
       MOV     A,D             ;end of table?
       ORA     E
       RZ                      ;exit if so
       PUSH    H               ;save table pointer
       XCHG                    ;adrs to HL
       CALL    GOHL            ;do it
       CALL    CRLF            ;print newline
       MVI     C,CHEKCC        ;check for console abort
       CALL    MEX
       POP     H               ;it's done
       JNZ     SETSLP          ;continue if no abort
       RET
;
GOHL:   PCHL
;
; Table of SHOW subroutines
;
SHOTBL:
       DW      BDSHOW          ;displays current baud
       DW      PSWSHOW         ;displays current PSW
       DW      TPSHOW          ;displays current TPULSE byte (0105H)
       DW      DLYSHO          ;displays current wait time
       DW      INTSHO          ;displays current INT status
       DW      CRLF
       DW      0               ;<<== table terminator
;
; SET ?  processor
;
STHELP: CALL    CLS                     ;clear screen
       LXI     D,HLPMSG
       MVI     C,PRINT
       JMP     MEX
;
; The help message
;
HLPMSG: DB      CR,LF,'SET Commands available are:',CR,LF,LF
       DB      'SET BAUD  <110, 300, 600, 1200, 2400, 4800,'
       DB      ' 9600, or 19200>',CR,LF
       DB      'SET WPS   <8N1, 7E1, 7O1, or 7N1> -- Word Length,'
       DB      ' Parity, Stop Bits',CR,LF
       DB      'SET TONE  (Sets flag for TONE  dialing)',CR,LF
       DB      'SET PULSE (Sets flag for PULSE dialing)',CR,LF
IF WAIT
       DB      'SET WAIT "n" Seconds for Modem Result',CR,LF
ENDIF

       DB      'SET INTerrupts <ON> or <OFF>',CR,LF
       DB      CR,LF,LF,'$'
;
; SET BAUD processor
;
STBAUD: MVI     C,BDPARS        ;function code
       CALL    MEX
       JC      SETERR          ;invalid code
       CALL    PBAUD           ;try to set it
       JC      SETERR          ;unsupported code
BDSHOW: CALL    ILPRT           ;display baud
       DB      'BAUD:',TAB,TAB,TAB,0
       LDA     MSPEED
       MVI     C,PRBAUD        ;use MEX routine
       JMP     MEX
;
; SET PSW processor
;
STPSW:  MVI     C,SBLANK
       CALL    MEX
       JC      SETERR          ;SET PSW should have had argument
       LXI     D,PSWTBL        ;look for PSW match in table
       CALL    TSRCH
       JC      SETERR          ;not there, so report error
       CALL    FIXPSW          ;routine to set PARSV and WRDSV
       CALL    CHNGPORT        ;now fix ACIA registers
;
PSWSHOW:
       CALL    ILPRT
       DB      '(W)ord(P)arity(S)top:',TAB,0
       LDA     PSWSET
       CPI     P8N1
       JNZ     PSW1
       CALL    ILPRT
       DB      '8N1',0
       RET
PSW1:   CPI     P7E1
       JNZ     PSW2
       CALL    ILPRT
       DB      '7E1',0
       RET
PSW2:   CPI     P7O1
       JNZ     PSW3
       CALL    ILPRT
       DB      '7O1',0
       RET
PSW3:   CPI     P7N1
       JNZ     PSW4
       CALL    ILPRT
       DB      '7N1',0
       RET
PSW4:   CALL    ILPRT
       DB      '<< ERROR >>',0
       RET
;
;
PSWSET: DB      010H            ;storage and default (8N1)
PARSV:  DB      0BH             ;storage and default (no parity)
WRDSV:  DB      010H            ;storage and default (8 data, 1 stop bits)
;
FIXPSW: MOV     A,L             ;PSW byte from table
       STA     PSWSET          ;save it
       ANI     0F0H            ;mask for word length bits
       STA     WRDSV           ;put in storage
       LDA     PSWSET          ;get back PSW byte
       ANI     0FH             ;mask for parity bits
       RLC                     ;first shift into upper nibble..
       RLC                     ;...away we go...
       RLC                     ;.....and go...
       RLC                     ;......and done
       ORI     0BH             ;mask needed for ACIA command register
       STA     PARSV           ;put in storage
       RET
;
PSWTBL: DB      '8N','1'+80H
       DW      P8N1            ;filled in with equ's
       DB      '7E','1'+80H
       DW      P7E1            ; - ditto -
       DB      '7O','1'+80H
       DW      P7O1            ; - ditto -
       DB      '7N','1'+80H
       DW      P7N1            ; - ditto -
       DB      0               ;<<==== table terminator
;
;.....
;
; These routines set TPULSE flag at 0105H to either 'T' or 'P' so that
; MODEM (specifically MXO-SM13.ASM) overlay will dial in TONE or PULSE
; mode.  The settings are mutually exclusive.
;
STTONE: MVI     A,'T'           ;get T flag
       STA     TPULSE          ;put into proper place
       JMP     TPSHOW          ;display dial mode
;
STPULSE:
       MVI     A,'P'           ;get P flag
       STA     TPULSE
;
TPSHOW: CALL    ILPRT
       DB      'DIAL:',TAB,TAB,TAB,0
       LDA     TPULSE
       CPI     'T'
       JNZ     TP1
       CALL    ILPRT
       DB      'Tone',0
       RET
TP1:    CPI     'P'
       JNZ     TP2
       CALL    ILPRT
       DB      'Pulse',0
       RET
TP2:    CALL    ILPRT
       DB      '<< ERROR >>',0
       RET
;
;-------------------------------------------------
; SET WAIT processor

IF WAIT

SETDLY: MVI     C,EVALA
       CALL    MEX
       MOV     A,H
       ORA     A
       JNZ     SETERR
       MOV     A,L
       STA     EXTRA1

DLYSHO: CALL    ILPRT
       DB      'WAIT:',TAB,TAB,TAB,0
       LDA     EXTRA1
       MOV     L,A
       MVI     H,0
       MVI     C,DECOUT
       CALL    MEX
       CALL    ILPRT
       DB      ' Seconds',0
       RET

ENDIF
;......
;
; SET INT Processor controls interrupt mode
;
SETINT:
       LXI     D,INTTBL        ;point to argument table
       CALL    TSRCH           ;look for match with allowed arguments
       JC      SETERR          ;process error if found
       MOV     A,L             ;
       STA     INTFLG          ;

INTSHO:
       CALL    ILPRT           ;show current status
       DB      'INTerrupt:',TAB,TAB,0
       LDA     INTFLG          ;get current mode word
       ORA     A               ;
       JNZ     INT             ;skip if it is
       CALL    ILPRT           ;
       DB      'OFF',0         ;
       JMP     CHNGPORT        ;
                               ;
INT:    CALL    ILPRT           ;print it
       DB      'ON',0          ;
       JMP     CHNGPORT        ;
;
;INT argument table
;
INTTBL: DB      'OF','F'+80H
       DB      0,0
       DB      'O','N'+80H
       DB      0FFH,0
       DB      0
;
INTFLG: DB      no

;..............................
;
; Compare next input-stream item in table @DE; CY=1 if not found,
; else HL = matched data item
;
TSRCH:  MVI     C,LOOKUP        ;get function code
       JMP     MEX             ;pass to MEX processor
;
; Print in-line message ... blows away C register
;
ILPRT:  MVI     C,ILP           ;get function code
       JMP     MEX             ;go do it
;
;
;       >>>>   End of MXH-APnn   <<<<