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