code.src



( Stuff below is predefined words from compiler examples - LRE )

( These three utility words: BEGIN-MOD, END-MOD, FORGET-MOD ) 
( are commonly used to load the assembler as a transient, create )
( some code definitions, then discard the assembler while )
( retaining the code definitions (so that the large amount )
( of dictionary required by the assembler is not wasted in )
( the final application program.   You would follow a sequence )
( something like this: )

( 15000 BEGIN-MOD )  ( reserve transient area for the assembler )
( ASM86  )           ( load the assembler )
( END-MOD )          ( signal end of the transient module )
( X LOAD   )         ( load your code definitions )
( FORGET-MOD )       ( throw away the assembler )
-->
( Transient modules, continued                       07/19/84 )
FORTH DEFINITIONS DECIMAL

VARIABLE LINKS  2 ALLOT         ( DP, NFA )
VARIABLE X      VARIABLE V

( voc-links fixup contributed by John Clark )
: FIX-VOC-LINKS
        VOC-LINK DUP  X !   @ V !
        BEGIN   V @
        WHILE   V @ HERE U<
                IF    V @ X @ !  V @ X !  X @ @ V !
                ELSE  V @ @ V !  THEN
        REPEAT ;
-->

( Transient modules, continued                 13:01 10/23/84 )

( length --- )
: BEGIN-MOD    HERE LINKS !                 ( save the old DP )
        LATEST LINKS 2+ !            ( and NFA of latest word )
        LIMIT 500 - SWAP - DP ! ;   ( space for PAD and STACK )

( --- )
: END-MOD  LINKS @ DP ! ;                ( restore the old DP )

( --- )
: FORGET-MOD    LINKS 2+ @         ( NFA of "old" latest word )
        LINKS @ DUP C@ 0=      ( watch out for word alignment )
        IF 1+
        THEN N>LINK !  FIX-VOC-LINKS ;   ( LFA most recent wd )


( Start of LRE code.  Real time reentrant interrupt handler ) 
(  for a home brew MIDI interface. )

 ( MAIN INTERRRUPT HANDLER - INT_HNDLR )
 HEX
  3A98 BEGIN-MOD  ASM86 END-MOD
       ( INTR TIME 61 + 28 = 89 CLKS )
  CODE INT_HNDLR

  ( START OF CODE FOR INT_HNDLR )

        AX PUSH DX PUSH BX PUSH DS PUSH ( SAVE ENVIRONMENT 60 )
    CS: DX, TIMER_LATCH MOV ( TIMER LATCH ADDRESS 4 )
    CS: BX, BUFF_SEG MOV ( BUFFER SEG GOES HERE 4 )
        DS, BX MOV ( BUFFER SEG INTO DATA SEG REG 2 )
        BX, # 100 MOV ( TIME LSB ADDRESS 4 )
        AL, # 80 MOV DX, AL OUT ( LATCH COUNT 4, 12 )
        DX DEC AL, DX IN  ( GET CNT 2, 12 )
        AL, # 0FF XOR ( MAKE CNT POSITIVE ASCENDING 4 )
        AL, [BX] SUB ( ABSOLUTE DIFF WITH LAST 18 )
        9$ JZ ( SAME - DON'T DO ANYTHING WITH CNT 4, [16] )
        [BX], AL ADD ( INC TIME LO BY DIFFERENCE 30 )
        9$ JNC ( DONT'T HAVE TO INC HI CNT 4, [16] )
 -->

  ( CONT. OF INT_HNDLR )
        BX INC WORD [BX] INC ( ADD ONE TO HI CNT 2, 29 )
  9$:   CS: DX, IIR_REG MOV ( IIR REGISTER ADDRESS 4 )
        AL, DX IN ( GET IIR )
        AL, # 1 TEST ( SEE IF INT PENDING )
        10$ JZ ( WILL BE 0 IF INT PENDING )
	AL, 122 MOV
  	AL, AL OR 
	16$ JNZ
	AL, 21 IN
   CS:	INT_MASK , AL MOV
	AL, # F8 OR
	21 , AL OUT
	AL, # 20 MOV
	20 , AL OUT ( EOI TO PIC )
	14$ JMP
   16$: AL, # 20 MOV
	20 , AL OUT ( EOI TO PIC )
	DS POP ( RESTORE ENVIRONMENT )
        BX POP
        DX POP
        AX POP
        IRET ( ALL DONE - GO FOR NEXT )

 -->
  ( CONT. OF INT_HNDLR )

  10$:  AL, # 4 CMP ( CHECK FOR RX INT )
        11$ JNZ ( WILL BE 0 IF RX )
   CS:  DX, RX_TX_REG MOV
	AL, DX IN
	AL, # 0FE CMP
	9$ JZ
	BX, 125 MOV
	[BX], AL MOV
	BL INC
	125 , BX MOV
        9$ JMP ( GO SEE IF ANOTHER INT PENDING )
  11$:  AL, # 2 CMP ( CHK FOR TX INT )
        12$ JNZ ( WILL BE 0 IF TX )
    CS: BX, TX_VECTOR MOV ( SET UP TO CALL TX )
        CS: BX CALL ( GO SVC TX )
        9$ JMP ( GO SEE IF ANOTHER INT PENDING )

  -->

 ( CONT. OF INT_HNDLR )

  12$:  CS: DX, MOD_STAT_REG MOV ( LOAD I/O_BASE + 6 FOR MOD )
        AL, DX IN ( GET MODEM STATUS )
        AL, # 4 TEST ( SEE IF TIMER INT )
        13$ JZ ( NOT TIMER IF ZERO )
        AH, 10B MOV ( GET TX ENABLED FLAG )
	AH, AH OR ( SEE IF BUSY )
        13$ JZ ( WILL BE 0 IF NOT ENABLED )
        AH, 10C MOV ( GET TX BUSY FLAG )
	AH, AH OR
        13$ JNZ ( WILL BE NON 0 IF BUSY )
    CS: BX, TX_VECTOR MOV ( SET UP TO GO TX )
	AX PUSH
        CS: BX CALL ( GO CHECK FOR CHAR TO TX )
  -->
 ( END OF INT_HNDLR )

        AX POP ( GET MODEM STATUS BACK )
  13$:  AL, # 0B TEST ( SEE IF OTHER THAN TIMER PENDING )
        20$ JNZ ( WILL BE ZERO IF NO OTHER PENDING )
	9$ JMP
  20$:  AL, # 08 TEST ( CHK FOR SYNC INT )
	17$ JZ 
	AX PUSH
   CS:  BX, SYNC_VECTOR MOV ( ELSE GO CHK SYNC )
        CS: BX CALL
	AX POP
  17$:  AL, # 2 TEST ( SEE IF SW1 INT )
	18$ JZ
   CS:  BX, SW1_VECTOR MOV ( GO DO SW1 )
	CS: BX CALL
  18$:  AL, # 1 TEST ( SEE IF SW2 INT )
        19$ JNZ ( GO DO IF IS )
	9$ JMP ( ELSE GO SEE IF MORE )
  19$:	CS: BX, SW2_VECTOR MOV
	CS: BX CALL
	9$ JMP



   14$: CLI
	BX, 123 MOV
	AX, 125 MOV
	AX, BX CMP
	15$ JNZ
   CS:	AL, INT_MASK MOV
	21 , AL OUT
	AL, AL XOR
	122 , AL MOV
	DS POP
	BX POP
	DX POP
	AX POP
	IRET

   15$: AL, # 0FF MOV
	122 , AL MOV
	STI
	AL, [BX] MOV
	BL INC
	123 , BX MOV
   CS:  BX, RX_VECTOR MOV
   CS:  BX CALL
	14$ JMP


        NEXT, END-CODE


  -->

  ( SPURIOUS OR UNUSED INTERRUPT HANDLER - NUL_INT_HNDLR )
        HEX

  CODE NUL_INT_HNDLR

        RET

  NEXT, END-CODE

 -->

  ( RCV CHAR INTERRUPT HANDLER - RX_INT_HNDLR )
        HEX
 CODE RX_INT_HNDLR
        ( INTERRUPT STARTS HERE )
	( AL HAS RECEIVED CHARACTER )
        AL, # 80 CMP ( CHK FOR DATA )
        19$ JC ( CARRY MEANS GO PROCESS DATA )
        AL, # 0F8 CMP  ( CHK FOR REAL TIME )
        18$ JNC ( => F8 MEANS SYSTEM REAL TIME )
        AL, # F0 CMP ( CHK FOR SYS EX OR SYS COM )
        14$ JNC ( < F8 AND => F0 MEANS SYS EX OR COM )
          ( FALL THRU MEANS CHANNEL BYTE )
        107 , AL MOV ( SET RUNNING STATUS ) -->
  ( CONT. OF RX_INT_HNDLR )

        AH, # 02 MOV ( SET UP FOR NUMBER OF DATA BYTES )
        AL, # 0C0 CMP
        1$ JC ( MUST BE < 0C0 - MEANS 2 DATA )
        AL, # 0E0 CMP
        1$ JNC ( > 0DF MEANS 2 DATA )
        AH DEC ( ELSE 1 DATA BYTE )
   1$:  ( NOW SET NUMBER OF BYTES EXPECTED )
        0108 , AH MOV
        0109 , AH MOV ( AND BYTE COUNT )
        AH, AH XOR ( CLR SYS EX FLAG )
        010A , AH MOV
   -->

  ( CONT. OF RX_INT_HNDLR )

   2$:  ( TIME TAG AND PUT AH INTO BUFFER )
  18$:  BX, 0105 MOV ( GET RX BUFFER PTR 15 )
        BX, # 0FFFC CMP ( SEE IF WILL ROLL OVER PTR 4 )
        [BX], AL MOV ( PUT BYTE IN BUFFER )
        5$ JNC ( GO ROLLOVER CHK IF => 0FFFC 4, [16] )
        ( FALL THRU MEANS FAST MOVE TIME TAG )
        BX INC ( NEXT BUFFER BYTE 2 )
	CLI
        AX, 0100 MOV ( GET LO AND NEXT TT 14 )
        [BX], AX MOV ( PUT IN BUFFER 19 )
        BX INC BX INC ( NEXT BYTE 2, 2 )

    -->
  ( CONT. OF RX_INT_HNDLR )
        AL, 102 MOV ( GET TT HI 10 )
        [BX], AL MOV ( PUT IN BUFFER 19 )
        BX INC ( SET UP FOR NEXT 2 )
   3$:  STI
	0105 , BX MOV ( SAVE FOR NEXT 14 )
   4$:  ( RETURN AND RESTORE )
        RET
  19$:  11$ JMP ( BRIDGE TO PROCESS DATA )
  -->
 ( CONT. OF RX_INT_HNDLR )

   5$:  ( TT & PUT IN BUFFER WITH PTR ROLLOVER CHK )
        BX INC
        6$ JNZ ( NO ROLLOVER JMP )
        BX, # 8200 MOV ( ELSE RESET TO START OF BUFFER )
   6$:  CLI
	AL, 100 MOV ( GET TT LO )
        [BX], AL MOV ( PUT IN BUFFER )
        BX INC
        7$ JNZ
        BX, # 8200 MOV
   7$:  AL, 101 MOV
        [BX], AL MOV
  -->
  ( CONT. OF RX_INT_HNDLR )

        BX INC
        8$ JNZ
        BX, # 8200 MOV
   8$:  AL, 102 MOV
        [BX], AL MOV
        BX INC
        3$ JNZ
        BX, # 8200 MOV
        3$ JMP

  14$: 15$ JMP ( BRIDGE TO SYS EX OR SYS COMMON )
  -->
  ( CONT. OF RX_INT_HNDLR )

  11$: ( PROCESS DATA )
        AH, 10A MOV ( GET SYS EX FLAG )
        AH, AH OR
        12$ JNZ ( SYS EX IN PROGRESS - DON'T MESS WITH CNT )
        AH, 109 MOV ( GET BYTES EXPECTED )
        AH, AH OR ( CHK FOR NOT ZERO )
        13$ JZ ( GO CHK RUNNING STATUS IF NONE EXPECTED )
        AH DEC ( ELSE DEC EXPECTED )
        109 , AH MOV ( & SAVE )

  -->
  ( CONT. OF RX_INT_HNDLR )

  12$:  BX, 105 MOV ( GET BUFFER PTR )
        [BX], AL MOV ( PUT DATA IN BUFFER )
        BX INC ( SET UP FOR NEXT )
        3$ JNZ ( DON'T RESET PTR IF NO ROLLOVER )
        BX, # 8200 MOV ( ELSE RESET PTR TO START OF BUFFER )
        3$ JMP
  17$:  1$ JMP ( BRIDGE TO R&R WITH SYS EX CLEAR )
  13$:  ( CHK RUNNING STATUS )
        BX, 107 MOV ( GET RUNNING STATUS )
        BL, BL OR ( SEE IF SET )
        4$ JZ ( DISCARD & RESTORE & RETURN IF NOT RUNNING )

  -->
  ( CONT. OF RX_INT_HNDLR )

   ( ELSE FALL THRU )
        BH DEC ( ALREADY HAVE BYTE CNT IN BH )
        109 , BH MOV ( NEW BYTES EXPECTED )
        18$ JMP ( GO TT & PUT IN BUFFER )

  -->

  ( CONT. OF RX_INT_HNDLR )

  16$:  ( SYS EX BYTE )
        10A , AL MOV ( SET SYS EX FLAG )
        AH, AH XOR
        109 , AH MOV ( CLEAR BYTES EXPECTED )
        2$ JMP ( GO TT & PUT IN BUFFER )
  -->

  ( CONT. OF RX_INT_HNDLR )

  15$: ( SYS EX OR SYS COMMON HANDLER )
        AH, AH XOR ( SET AH TO ZERO )
        107 , AH MOV ( CLEAR RUNNING STATUS )
        AL, # 0F0 CMP ( CHK FOR SYS EX )
        16$ JZ ( GO SYS EX IF IS )
        AH, # 2 MOV ( NO. OF DATA )
        AL, # 0F2 CMP ( CHK FOR SONG POS. )
        17$ JZ ( GO CLR SYS EX, TT, & PUT IN BUFFER )
        AH DEC

  -->

  ( END OF RX_INT_HNDLR )

        AL, # 0F3 CMP ( CHK FOR SONG SELECT )
        17$ JZ ( GO ONE DATA IF IS )
        AH DEC ( ELSE 0 DATA )
        17$ JMP

  NEXT, END-CODE


   -->

  ( START OF TX INTERRUPT HANDLER - TX_INT_HNDLR )

         HEX

  CODE TX_INT_HNDLR

    CS: DX, RX_TX_REG MOV ( TX LOAD REGISTER ADDRESS )
	AL, 12B MOV ( SEE IF TO INSERT CLK )
	AL, AL OR
	3$ JZ
	AL, AL XOR
	12B , AL MOV ( CLR INSERT FLAG )
	AL, # F8 MOV ( CLK BYTE )
	10C , AL MOV ( SET BUSY FLAG )
	DX, AL OUT ( SEND BYTE )
	RET ( ALL DONE )

  3$:   AL, 118 MOV ( CHK IF STATUS IS SYS EX )
        AL, # 0F0 CMP ( SEE IF SYS EX IN PROGRESS )
        1$ JZ ( GO TRANSMIT IF IS IN PROGRESS )
        AL, 11A MOV ( GET NUMBER OF DATA BYTES LEFT )
        AL, AL OR ( CHK FOR ANY DATA TO SEND )
        4$ JZ ( GO SEE IF READY TO SEND OTHER IF NO )
          ( FALL THRU MEANS SEND NEXT DATA )
  -->

  ( CONT. OF TX_INT_HNDLR )

        ( AL DEC ) ( SET BYTE COUNT FOR NEXT )
        ( 11A , AL MOV )
   1$:  BX, 103 MOV ( GET BUFFER POINTER  )
        AL, [BX] MOV ( GET BYTE TO SEND )
        AL, # 80 CMP ( MAKE SURE IS DATA )
        4$ JNC ( IF ISN'T GO PROCESS STATUS BYTE )
        DX, AL OUT ( ELSE SEND IT )
	AL, 11A MOV
	AL DEC
	11A , AL MOV
        BX INC ( FOR NEXT )
        2$ JNS ( DON'T RESET IF NO ROLLOVER )
        BX, # 0200 MOV ( ELSE RESET TO BEGINNING OF BUFF )
 -->

  ( CONT. OF TX_INT_HNDLR )

   2$:  103 , BX MOV ( SAVE NEW PTR )
        AL, # 0FF MOV ( MAKE SURE NOT ZERO )
        10C , AL MOV ( SET TX BUSY FLAG )
        RET ( ALL DONE )
 -->

  ( CONT. OF TX_INT HNDLR )
        ( NO BYTES EXPECTED )
   4$:  AL, # 0F7 CMP 20$ JNC ( DON'T CHK INSERT FOR EOX )
	( OR REAL TIME )
        AL, 10D MOV ( CHK INSERT BUFFER )
        AL, AL OR ( SEE IF FLAG SET )
        20$ JZ ( DON'T DO INSRT IF NOT SET )
        BX, 114 MOV ( LO INSüRT PTR IN BX )
        AX, 116 MOV ( GET HI PTR )
        AX, BX CMP ( SEE IF ANYTHING IN BUFFER )
        19$ JZ ( NOPE - CLR FLAG & CONTINUE )
        AL, [BX] MOV DX, AL OUT ( ELSE GET BYTE & SEND )
        AL, # 0FF MOV 10C , AL MOV ( SET TX BSY )
        BL INC ( SET PTR FOR NEXT )
        114 , BX MOV ( & SAVE )
        RET ( RETURN & RESTORE )
 -->
  ( CONT. OF TX_INT HNDLR )

  19$:  AL, AL XOR ( CLEAR INSERT BUFFER FLAG )
        10D , AL MOV
         ( FALL THRU TO REGULAR CHAR CHK )

  20$:  BX, 103 MOV ( GET TX BUFF PTR )
        AL, [BX] MOV ( GET BYTE )
        AL, # 80 CMP ( CHK FOR DATA BYTE )
        9$ JNC  ( IF NOT DATA DON'T CHK RUNNING STATUS )
          ( FALL THRU TO CHK RUNNING STATUS )

  -->
  ( CONT. OF TX_INT_HNDLR )

        ( CHECK RUNNING STATUS )
        AL, AL OR  ( MAY BE END OF FILE IF ZER0 )
        BX PUSH ( NEED TO CONSERVE LABELS )
        7$ JNZ ( DON'T CHECK FOR END IF NOT ZERO )
        ( CHECK FOR 5 ZEROES MEANS END OF FILE )
        AH, # 4 MOV ( SET UP LOOP CNT )
   5$:  BX INC ( PT TO NEXT BYTE )
        6$ JNS ( SEE IF OVERFLOW )
        BX, # 200 MOV
   6$:  AL, [BX] MOV ( GET NEXT CHAR )
        AL, AL OR ( CHECK IF IT'S 0 TOO )
        7$ JNZ ( GET OUT OF LOOP IF NOT ZERO )
 -->

  ( CONT. OF TX_INT_HNDLR )

         AH DEC ( CHK LOOP CNT )
        5$ JNZ ( CONTINUE IF NOT COUNTED DOWN )
        BX POP ( CLEAN UP STACK )
        AL, # 0FF MOV 121 , AL MOV ( SET DONE FLAG )
        AL, AL XOR 10C , AL MOV ( CLR TX BSY )
        RET ( FALL THRU MEANS CLR TX BUSY & R&R )
   7$:  BX POP ( ELSE CONTINUE ON )
        AL, [BX] MOV ( GET ORIGINAL BYTE BACK )
        AH, 118 MOV ( GET RUNNING STATUS )
        AH, AH OR ( SEE IF SET )
        9$ JNZ ( IF RUNNING STAT CHK TT ETC. )
 -->
  ( CONT. OF TX_INT_HNDLR )

        ( ELSE SET UP TO TRY NEXT )
        BX INC
        8$ JNS
        BX, # 200 MOV
   8$:  103 , BX MOV ( NEW PTR )
        AL, AL XOR 10C , AL MOV
        RET ( BSY CLR & R&R SO GARBAGE WON'T HANG )
  -->
  ( CONT. OF TX_INT HNDLR )
           ( CHK TT ETC )
   9$:  AX PUSH ( SAVE BYTE )
        BX INC
        10$ JNS
        BX, # 200 MOV
  10$:  AL, [BX] MOV ( GET LO TT )
        11C , AL MOV ( CACHE LO TT )
        BX INC
        11$ JNS
        BX, # 200 MOV
  11$:  AL, [BX] MOV ( GET NEXT TT )
        11D , AL MOV ( CACHE NEXT TT )

 -->

  ( CONT. OF TX_INT_HNDLR )

        BX INC
        12$ JNS
        BX, # 200 MOV
  12$:  AL, [BX] MOV ( GET HI TT )
        11E , AL MOV ( CACHE HI TT )
        BX INC
        13$ JNS
        BX, # 200 MOV
  13$:  BX PUSH ( WAIT AND SEE )
        ( NOW CHK TT - IF NOW - TT = NC DONT SEND )
        BX, 11C MOV ( HAVE TT LO & NEXT IN BX )
 -->

  ( CONT. OF TX_INT_HNDLR )

        AX, 100 MOV ( GET NOW LO & NEXT )
        AX, BX CMP ( NOW - TT )
        BL, 11E MOV ( GET TT HI )
        AL, 102 MOV ( GET HI NOW )
        AL, BL  SBB ( SEE IF TIME YET )
        BX POP  ( DONE WITH TESTING )
        AL, # 0 MOV 10C , AL MOV ( CLR TX BUSY )
        AX POP 14$ JC ( IF NOT TIME GO R&R )
	103 , BX MOV ( SET NEW PTR )
	AH, # 0FF MOV
	10C , AH MOV ( TX BUSY )
        DX, AL OUT ( SEND BYTE )  
  ( CONT. OF TX_INT_HNDLR )

        AL, # 80 CMP ( CHK FOR DATA )
        15$ JNC ( IF DATA GETS HERE USE OLD IF NOT JMP )
                ( TO NEW CNTS )
        AL, 119 MOV
        AL DEC ( ALREADY ONE GONE )
        11A , AL MOV
  14$:  RET
  -->
  ( CONT. OF TX_INT_HNDLR )

  15$:  ( SEE HOW MANY DATA BYTES GO AFTER STATUS )
        AL, # 0F8 CMP ( CHK FOR REAL TIME )
        14$ JNC ( GO R&R - NOTHING CHGS FOR REAL TIME )
        AL, # 0F1 CMP ( CHK FOR OVER SYS EX )
	AH, AL MOV
        16$ JC ( JMP IF NOT OVER )
        AH, AH XOR  ( CLEAR RUNNING IF OVER )
  16$:  118 , AH MOV ( SET RUNNING STATUS ) -->

  ( CONT. OF TX_INT_HNDLR )

    ( NOW FIGURE DATA BYTES )
        AH, # 0 MOV ( CNT IN AH )
        AL, # 0F4 CMP ( MEANS 2 DATA )
        17$ JNC ( GO SET 0 )
        AL, # 0F1 CMP ( IF IS MEANS 0 DATA )
        17$ JZ ( GO SET 0 )
        AH INC ( SET TO 1 DATA )
        AL, # 0F3 CMP ( MEANS 1 )
        17$ JZ ( GO SET 1 )
        -->

  ( END OF TX_INT_HNDLR )

        AL, # 0E0 CMP ( FOR 2 DATA )
        18$ JNC ( 2 DATA IF IS )
        AL, # 0CF CMP
        17$ JNC
  18$:  AH INC

  17$:  AL, AH MOV ( GET NO OF DATA )
        119 , AX MOV ( SET BOTH EXPECTED AND CNT )
        14$ JMP ( ALL DONE )

  NEXT, END-CODE
 -->

  ( START OF INSERT )
    HEX 
  CODE INSERT
        AL, 10E MOV AL, AL OR ( CHECK FRAME XFR FLAG )
        3$ JZ ( RETURN IF NOT SET - ELSE TRNSFR FRAME )
  1$:   BX, 110 MOV ( GET LO MARKER )
        AX, 11F MOV ( GET HI PTR )
        AX, BX CMP ( IF SAME THEN ALL DONE )
        2$ JZ ( KICK OUT IF DONE )
        AL, [BX] MOV ( GET BYTE TO TRNSFR )
        BL INC 110 , BX MOV ( NEW PTR )
        BX, 116 MOV ( GET INSERT PTR )
        [BX], AL MOV ( PUT BYTE IN INSERT )
        BL INC 116 , BX MOV ( NEW INSERT PTR )
        1$ JMP ( CHK FOR NEXT )
  -->
  ( END OF INSERT )

  2$:   ( COMES HERE WHEN DONE WITH A TRANSFER )
        AL, AL XOR
        10E , AL MOV ( CLEAR FRAME TRANSFER FLAG )
        AL, # 0FF MOV
        10D , AL MOV ( SET INSERT FRAME )
  3$:   RET ( ALL DONE )

  NEXT, END-CODE
  -->

  ( RCV CHAR INTERRUPT HANDLER W/RE-TX - RE_RX_INT_HNDLR )
        HEX
 CODE RE_RX_INT_HNDLR
        AL, # 80 CMP ( SEE IF DATA )
        14$ JNC 11$ JMP ( NO CARRY MEANS GO PROCESS DATA )
  14$:  AL, # 0F8 CMP ( CHK FOR REAL TIME )
        10$ JC ( JMP IF NOT REAL TIME )
        AH, 10E MOV AH, AH OR
        16$ JZ ( PUT IN TRNSFR BUFF IF TRNSFR IN PROG )
        BX, 112 MOV ( GET BUFFER POINTER )
        [BX], AL MOV ( PUT IN BUFF )
        BL INC ( NEW PTR )
        112 , BX MOV
   -->
  ( RCV CHAR INTERRUPT HANDLER W/RE-TX - RE_RX_INT_HNDLR )

        18$ JMP ( )

  16$:  BX, 116 MOV ( GET INSERT BUFFER HI )
        [BX], AL MOV ( PUT BYTE IN INSERT BUFFER )
        BL INC 

  ( CONT. OF RE_RX_INT_HNDLR )
        116 , BX MOV ( SAVE NEXT )
        10D , AL MOV ( SET INSERT FLAG )
        18$ JMP ( GO TT & PUT IN BUFFER )
  10$:  AL, # F1 CMP ( CHK FOR SYS COM )
        15$ JC ( JMP IF NOT SYS COM )
        AH, AH XOR ( CLR RUNNING IF SYS COM )
  15$:  107 , AH MOV ( SET RUNNING STATUS )
        ( NOW FIGURE DATA BYTES )
        AH, AH XOR ( DATA IN AL - 0 IN AH )
        AL, # 0F4 CMP (  => MEANS 0 DATA )
        1$ JNC ( GO SET 0 DATA )
        AL, # 0F1 CMP ( IF IS MEANS 0 DATA )
        1$ JZ ( GO SET 0 ) -->
  ( CONT. OF RE_RX_INT_HNDLR )

        AH INC ( SET TO 1 DATA )
        AL, # 0F3 CMP ( MEANS 1 )
        1$ JZ AH INC ( GO SET 1 )
        AL, # 0E0 CMP ( FOR 2 DATA )
        1$ JNC AH DEC ( 2 DATA IF IS )
        AL, # 0CF CMP ( FOR 1 DATA )
        1$ JNC
        AH INC ( ELSE 2 DATA )
   1$:  ( NOW SET NUMBER OF BYTES EXPECTED )
        0108 , AH MOV
        0109 , AH MOV ( AND BYTE COUNT )
        AH, AH OR 2$ JNZ ( DON'T SET XFR FLAG IF NOT 0 )
  -->
  ( CONT. OF RE_RX_INT_HNDLR )
        AH, # 0FF MOV 10E , AH MOV ( SET XFR FLAG )
        BX, 112 MOV BL INC
        11F , BX MOV ( SET XFR PTR )
   2$:  ( TIME TAG AND PUT AH INTO BUFFER )
        BX, 112 MOV ( GET RE TX FRAME BUFF PTR HI )
        [BX], AL MOV ( PUT BYTE IN BUFFER )
        BL INC
        112 , BX MOV ( SAVE FOR NEXT )
 -->
  ( CONT. OF RE_RX_INT_HNDLR )

   18$: BX, 0105 MOV ( GET RX BUFFER PTR 15 )
        BX, # 0FFFC CMP ( SEE IF WILL ROLL OVER PTR 4 )
        [BX], AL MOV ( PUT BYTE IN BUFFER )
        5$ JNC ( GO ROLLOVER CHK IF => 0FFFC 4, [16] )
        ( FALL THRU MEANS FAST MOVE TIME TAG )
        BX INC ( NEXT BUFFER BYTE 2 )
	CLI
        AX, 0100 MOV ( GET LO AND NEXT TT 14 )
        [BX], AX MOV ( PUT IN BUFFER 19 )
        BX INC BX INC ( NEXT BYTE 2, 2 )
        AL, 102 MOV ( GET TT HI 10 )
    -->
  ( CONT. OF RE_RX_INT_HNDLR )
        [BX], AL MOV ( PUT IN BUFFER 19 )
        BX INC ( SET UP FOR NEXT 2 )
   3$:  STI
	0105 , BX MOV ( SAVE FOR NEXT 14 )
   4$:  
    CS: AX, INSERT_VECTOR MOV
        CS: AX JMP
 -->
 ( CONT. OF RE_RX_INT_HNDLR )

   5$:  ( TT & PUT IN BUFFER WITH PTR ROLLOVER CHK )
        BX INC
        6$ JNZ ( NO ROLLOVER JMP )
        BX, # 8200 MOV ( ELSE RESET TO START OF BUFFER )
   6$:  CLI
	AL, 100 MOV ( GET TT LO )
        [BX], AL MOV ( PUT IN BUFFER )
        BX INC
        7$ JNZ
        BX, # 8200 MOV
   7$:  AL, 101 MOV
        [BX], AL MOV

  -->

  ( CONT. OF RE_RX_INT_HNDLR )

        BX INC
        8$ JNZ
        BX, # 8200 MOV
   8$:  AL, 102 MOV
        [BX], AL MOV
        BX INC
        9$ JNZ
        BX, # 8200 MOV
   9$:  3$ JMP

  -->
  ( CONT. OF RX_INT_HNDLR )
  11$: ( PROCESS DATA )
        AH, 107 MOV ( GET STATUS )
        AH, # 0F0 CMP ( CHK FOR SYS EX STATUS )
        12$ JZ ( SYS EX IN PROGRESS - DON'T MESS WITH CNT )
        AH, 109 MOV ( GET BYTES EXPECTED )
        AH, AH OR ( CHK FOR NOT ZERO )
        13$ JZ ( GO CHK RUNNING STATUS IF NONE EXPECTED )
        AH DEC ( ELSE DEC EXPECTED )
        109 , AH MOV ( & SAVE )
        12$ JNZ ( JMP IF NOT FRAME END )
        AH, # 0FF MOV 10E , AH MOV ( ELSE SET FRAME XFR FLAG )
        BX, 112 MOV BL INC ( & SET PTR )
        11F , BX MOV
    -->
  ( CONT. OF RE_RX_INT_HNDLR )
  12$:  BX, 112 MOV [BX], AL MOV ( RE TX )
        BL INC  112 , BX MOV
        BX, 105 MOV ( GET BUFFER PTR )
        [BX], AL MOV ( PUT DATA IN BUFFER )
  17$:  BX INC ( SET UP FOR NEXT )
        9$ JNZ ( DON'T RESET PTR IF NO ROLLOVER )
        BX, # 8200 MOV ( ELSE RESET PTR TO START OF BUFFER )
        9$ JMP
  13$:  AH, 107 MOV ( GET RUNNING STATUS )
        AH, AH OR ( SEE IF SET )
        BX, 105 MOV
    -->

  ( CONT. OF RE_RX_INT_HNDLR )

        17$ JZ
        BX, 107 MOV
   ( ELSE FALL THRU )
        BH DEC ( ALREADY HAVE BYTE CNT IN BH )
        107 , BH MOV ( NEW BYTES EXPECTED )
        20$ JNZ ( NOT END OF FRAME IF 0 )
        BL, # 0FF MOV 10E , BL MOV ( ELSE SET FRAME XFR FLAG )
        BX, 112 MOV BL INC ( & POINTER )
        11F , BX MOV
  20$:  2$ JMP ( GO TT & PUT IN BUFFER )
  -->
  ( END OF RE_RX_INT_HNDLR )

  NEXT, END-CODE

  -->

  ( RE TX FRAME TO INSERT BUFFER TRNSFR_RX_TO_INSERT )
              HEX

   CODE TRNSFR_RX_TO_INSERT
        DS PUSH
    CS: BX, BUFF_SEG MOV
        DS, BX MOV
        AL, 10E MOV ( CHK FRAME TRANSFER FLAG )
        AL, AL OR ( SEE IF SET )
        3$ JZ ( RETURN IF NOT SET )
        ( ELSE TRANSFER FRAME BUFFER INTO INSERT BUFF )
   1$:  AX, 110 MOV BX, AX MOV ( GET LO MARKER )
        AX, 11F MOV ( GET HI PTR )
        AX, BX CMP ( IF SAME THEN ALL DONE )
        2$ JZ ( KICK OUT IF DONE )
  -->
  ( CONT. OF TRNSFR_RX_TO_INSERT )

        AL, [BX] MOV ( GET BYTE TO TRANSFER )
        AX, BX XCHG ( SET UP NEW POINTER )
        AL INC
        110 , AX MOV ( SAVE FOR NEXT )
        AX, 116 MOV ( GET INSERT POINTER )
        AX, BX XCHG
        [BX], AL MOV ( PUT BYTE IN INSERT )
        AX, BX MOV ( NOW SET NEW INSERT PTR )
        AL INC
        116 , AX MOV ( SAVE )
        1$ JMP ( CHK FOR NEXT )
 -->
  ( CONT. OF TRNSFR_RX_TO_INSERT )

   2$: ( COMES HERE WHEN DONE WITH A TRANSFER )
        CLI ( DISABLE INTS )
        AL, AL XOR
        10E , AL MOV ( CLEAR FRAME TRANSFER FLAG )
        AL, # 0FF MOV
        10D , AL MOV ( SET INSERT FLAG )
        STI ( ENABLE INTS )

   3$:  DS POP

        NEXT, END-CODE

   -->

  ( GET_CUR & SET_CUR )

  HEX 

  CODE GET_CUR
        BH, # 0 MOV AH, # 3 MOV
        10 INT  DX PUSH
    NEXT, END-CODE

  CODE SET_CUR
        DX POP BH, # 0 MOV AH, # 2 MOV 10 INT
    NEXT, END-CODE

  -->


  ( ENABLE_MIDI_INT, EN_UART_TIME_INT )
    HEX 
  CODE ENABLE_MIDI_INT
        CLI  ( STOP INTS )
        AL, 21 IN ( GET PIC MASK )
        AL, # 0FB AND ( SET BIT 2 TO ZERO )
        21 , AL OUT ( NEW MASK WITH PIC 2 ENABLED )
        STI ( ENABLE INTS )
     NEXT,
        END-CODE  ( ALL DONE )

  -->
  ( DIS_MIDI_INT )

  CODE  DIS_MIDI_INT
     CLI
        AL, 21 IN
        AL, # 04 OR
        21 , AL OUT
        STI
   NEXT, END-CODE

  -->
 ( CODE CLR_BUFFER )
         HEX

  CODE CLR_BUFFER  ( OFFSET REP# -- )
        AX, BUFF_SEG MOV ( BUFF_SEG INTO AX )
        CX POP ( NUMBER OF REP TIMES )
        BX POP ( OFFSET )
        ES PUSH
        DI PUSH
        ES, AX MOV ( BUFF_SEG INTO ES )
        PUSHF ( SAVE FORTH DIRECTION FLAG )
        CLD ( SET POSITIVE DI INCREMENT )
        DI, BX MOV ( SET DI TO OFFSET )

 -->

 ( CONT. OF CODE CLR_BUFFER )

        AX, AX XOR ( CLEAR AX  )
        REP WORD STOS ( CLEAR THE BUFFER )
        POPF ( RESTORE REGS FOR FORTH )
        DI POP
        ES POP
   NEXT, END-CODE  ( ALL DONE - GO BACK TO FORTH )
  -->

  HEX ( SCREEN DRAW n CHARS )

  CODE DRAW_N
        BH, # 0 MOV ( PAGE 0 )
        AH, # 3 MOV ( GET CURSOR SERVICE )
        10 INT  ( ROM BIOS INT )
        CX, DX MOV ( SAVE CURSOR )
        DX POP ( COL INTO DL )
        AX POP ( GET ROW )
        DH, AL MOV ( ROW INTO DH )
        BH, # 0 MOV ( PAGE 0 )
        AH, # 2 MOV ( SET CURSOR )
        10 INT ( BIOS INT )

  -->

  ( END SCRN DRAW N CHARS - COLOR CHAR N ROW COL ---   )

        DX, CX MOV ( OLD CURSOR BACK INTO DX )
        CX POP ( GET NUMBER OF TIMES TO WRITE )
        AX POP ( GET CHAR )
        BX POP ( GET COLOR )
        AH, # 9 MOV ( WRITE INT SVC )
        10 INT
        AH, # 2 MOV ( SET CURSOR SVC )
        10 INT ( RESTORE CURSOR  )
   NEXT,  END-CODE


 -->
 ( WRITE 80 BUFFER )
   HEX  

  CODE WRITE_80_BUFF
        AX POP ( BUFF SEG INTO AX )
        BX POP ( RCV_FILE HANDLE INTO BX )
        CX POP ( NO OF BYTES TO WRITE INTO CX )
        DX POP ( CURRENT FILE WRITE POSITION INTO DX )
        DS PUSH ( SAVE DATA SSEGMENT )
        AX PUSH DS POP ( BUFF_SEG INTO DS )
        AH, # 40 MOV ( WRITE SERVICE )
        SI PUSH BP PUSH PUSHF ( SAVE FOR FORTH )
        21 INT ( GO DOS WRITE )
        POPF  BP POP SI POP DS POP ( RESTORE FORTH )
        AX PUSH ( RETURN AX )
   NEXT, END-CODE  -->
  ( READ_80_BUFF )
   HEX 
  CODE READ_80_BUFF
        AX POP BX POP CX POP DX POP
        DS PUSH AX PUSH DS POP
        AH, # 3F MOV
        SI PUSH BP PUSH PUSHF
        21 INT
        POPF BP POP SI POP DS POP
        AX PUSH
   NEXT, END-CODE

   CODE DOS_STI
	STI
	  NOP NOP NOP NOP
	NEXT, END-CODE


  CODE CHANGE_RX_CHANNEL
   (   CS: DX, RX_TX_REG MOV )
     (  AL, DX IN )
	AL, # 0F0 CMP
	2$ JNC ( NOT CHANNEL BYTE IF NO CARRY )
	AL, # 80 CMP
	2$ JC ( NOT CHANNEL BYTE IF CARRY )
	AH, AL MOV ( SAVE CHANNEL BYTE )
	AL, # 0F AND ( GET CHANNEL NO. )
	BL, AL MOV
  CS:	AL, TRACK_FROM MOV
	BL, AL CMP
	1$ JNZ 
  CS:   AL, TRACK_TO MOV
	AH, # F0 AND
	AL, AH OR
  CS:	BX, CHNG_CHAN_NEXT MOV
  CS:	BX  JMP

  1$:	AL, AH MOV
  2$:	CS:  BX, CHNG_CHAN_NEXT MOV
	CS:  BX  JMP

	NEXT, END-CODE

  CODE TRANSPOSE_RX
    ( CS: DX, RX_TX_REG MOV  )
     (  AL, DX IN )
	AL, # 80 CMP
	4$ JNC ( NO CARRY MEANS NOT DATA )
	AH, 107 MOV ( GET RUNNING STATUS )
	AH, # A0 CMP
	4$ JNC ( NO CARRY MEANS NOT NOTE EVENT )
	AH, # 80 CMP 
	4$ JC ( CARRY MEANS NO RUNNING STATUS )
	AH, 109 MOV ( GET BYTES EXPECTED )
	AH, AH OR 
	2$ JZ ( ZERO MEANS RUNNING STATUS NOTE )
	AH, # 2 CMP ( SEE IF NOTE BYTE )
	4$ JNZ ( NOT NOTE BYTE IF NOT ZERO )
   2$:	( PROCESS NOTE BYTE )
   CS:	AH, LO_SPLIT MOV
	AH, AL CMP 
	3$ JC ( IS ABOVE LO SPLIT IF CARRY )
	AH, AH XOR 
   CS:	BX, LO_DELTA MOV
	AX, BX ADD
	AL, # 7F AND
   4$:	CS: BX, RX_TRANSP_NEXT MOV
	CS: BX JMP

   3$:	CS: AH, HI_SPLIT MOV
	AH, AL CMP
	4$ JNC ( NOTE IS BELOW HI SPLIT IF NO CARRY )
	AH, AH XOR
   CS:	BX, HI_DELTA MOV
	AX, BX ADD
	AL, # 7F AND
   CS:  BX, RX_TRANSP_NEXT MOV
   CS:	BX JMP

	NEXT, END-CODE