home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sound Sensations!
/
sound_sensations.iso
/
miditool
/
tmpu_pas
/
tpmpu.pas
< prev
Wrap
Pascal/Delphi Source File
|
1987-06-05
|
5KB
|
104 lines
{ The following is an example and discussion of an interrupt routine routine
written in turbo pascal for use with midi applications on an ibmpcxt with
a roland mpu401 interface.
Prior to utilizing the interrupt routines one must
1.change the vector address to the offset and code segment of your
interrupt routine.The address is 4 bytes beginning at 040(decimal)
-see below routine irq2_on.
2.enable irq2 (turn the 2nd byte of port hex 21 to 0 -see irq2_on)
The routine 'never_call_stop_mode_herc' is an example of
an irq2 routine which is never called by the program directly -
rather it is called when an irq2 occurs .The mpu401 sends a irq2
whenever it wants to send a single byte of information so the routine
is set up to handle one byte at a time only .
(This particular routine plays a piano keyboard on the screen in real time
while also printing notes(no time values) on a piano staff on the screen.
Other procedures are called which handle these functions.
The mpu401 has been set to stop mode(command hex 8a)prior to activation
of these routines,but the shell(inline statements) work the same with
any mode of the mpu401(ie.record,play,overdub).
The interrupt routine
must begin with the inline statement (which saves the current registers)
and end with the port statement (eoi to irq controller) and another inline
statement (restore registers).
In between can be turbo pascal code with the following restrictions
-as outlined in the turbo manual
1.no access to input/output commands such as write or read -
though can write directly to screen memory.
2.only typed constants are allowed -ie variables which have been
defined initialized to some value.(eg. const mididata :byte=0;
This is because these variables are stored in the code segment (CS)
rather than the data segment (DS) which is usually unavailable in
the interrupt mode.If you really want to access global variables
you can -according to the turbo manual - store the value of Dseg
in a constant variable and then use it in the interrupt handler to
set the ds properly.I have yet to implement this and am not quite
sure how to (let me know if you have implemented this).
When finsished with the interrupt mode it is neccessary to disable the
irq2 (via port hex 21) and restore the old vector for irq2.This is done
in the routine irq2_off. }
{****************************************************************************}
procedure never_call_stop_mode_herc;
begin
inline ($50/$53/$51/$52/$56/$57/$1E/$06/$fb); {fb=enable further interrupts}
mididata:=port[dataport];
if mididata<$80 then begin
c:=c+1;
if c=3 then begin curr_velocity[user_record_trnum]:=mididata;
play_herc_lead_sheet
(curr_running_status[user_record_trnum],
curr_notenum[user_record_trnum],
curr_velocity[user_record_trnum]);
c:=1;end{IF}
else curr_notenum[user_record_trnum]:=mididata ;end;
{COULD REDUCE THE IF STATEMENTS }
if mididata >=$80 then begin
curr_running_status[user_record_trnum]:=mididata;
c:=1;end;
port[$20]:=$20;
inline($07/$1f/$5f/$5e/$5a/$59/$5b/$58/$8b/$e5/$5d/$cf); {cf=interrupt return}
END;
{****************************************************************************}
{****************************************************************************}
procedure init_interrupt(ii:integer);
{this procedure changes the offset of irq2(=interrupt 10(dec.)) to
the cseg and offset of the desired interrupt handler }
begin
old_ofs:=memw[$0000:ii*4];
old_seg:=memw[$0000:ii*4+2];
new_ofs:=ofs(never_call_stop_mode_herc); {was mono}
new_seg:=cseg;
memw[$0000:ii*4]:=new_ofs; {change vector address}
memw[$0000:ii*4+2]:=new_seg;
writeln('prior vector irq',ii:2,' = $',integerhex(old_seg),
':',integerhex(old_ofs));
write('new vector irq',ii:2,' = $',integerhex(new_seg),
':',integerhex(new_ofs));
end;
{****************************************************************************}
procedure restore_interrupt(ii:integer);
begin
memw[$0000:ii*4]:=old_ofs; {change vector address}
memw[$0000:ii*4+2]:=old_seg;
end;
{****************************************************************************}
procedure irq2_on;
begin
write('enabling irq2');
write(' port $21 was ',port[$21]);
init_interrupt(10);
port[$21]:=($fb and port[$21]); {turns 2nd byte to 0,thus enabling irq2}
end;
{****************************************************************************}
procedure irq2_off;
begin
write(' disabling irq2,port $21 was= ',port[$21]);
port[$21]:= (4 or port[$21]);{turns 2nd byte to 1,thus disabling irq2 }
restore_interrupt(10);
end;
{******************************************}. ... ...-.... 1200 N81N