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