Return to Mr Belvedere's Programming Nook
Soundblaster Keyboard Piano
© 1996 by Bobby Griggs.
Program Casey_Music;
uses crt;
Const
GMPort = $331;
Send = $80;
Receive = $40;
{ AL:=Command; }
Procedure WriteGMCommand; Assembler;
ASM
MOV DX,GMPort {;DX:=GMStatusPort; }
PUSH AX {;Save AX }
XOR AX,AX {;AH:=TimeOutValue; }
@@WaitLoop:
{ ;Prevent Infinite Loop with Timeout }
DEC AH {; |If TimeOutCount=0 then }
JZ @@TimeOut {;/ TimeOut; }
{; Wait until GM is ready }
IN AL,DX {; |If Not Ready then }
AND AL,Receive {; | WaitLoop; }
JNZ @@WaitLoop {;/ }
@@TimeOut:
POP AX {;Restore AX }
OUT DX,AL {;Send Data }
End;
{ ; AL:=Data }
Procedure WriteGM; Assembler;
ASM
MOV DX,GMPort {;DX:=GMStatusPort; }
PUSH AX {;Save AX }
XOR AX,AX {;AH:=TimeOutValue; }
@@WaitLoop:
{ ; Prevent Infinite Loop with Timeout }
DEC AH {; |If TimeOutCount=0 then }
JZ @@TimeOut {;/ TimeOut; }
{ ; Wait until GM is ready }
IN AL,DX {; |If Not Ready then }
AND AL,Receive {; | WaitLoop; }
JNZ @@WaitLoop {;/ }
@@TimeOut:
POP AX {;Restore AX }
DEC DX {;DX:=DataPort }
OUT DX,AL {;Send Data }
End;
{ ;Returns Data }
Function ReadGM:Byte; Assembler;
ASM
MOV DX,GMPort {;DX:=GMStatusPort; }
PUSH AX {;Save AX }
XOR AX,AX {;AH:=TimeOutValue; }
@@WaitLoop:
{ ; Prevent Infinite Loop with Timeout }
DEC AH {; |If TimeOutCount=0 then }
JZ @@TimeOut {;/ TimeOut; }
{ ; Wait until GM is ready }
IN AL,DX {; |If Not Ready then }
AND AL,Send {; | WaitLoop; }
JNZ @@WaitLoop {;/ }
@@TimeOut:
POP AX {;Restore AX }
DEC DX {;DX:=DataPort }
IN AL,DX {;Receive Data }
End;
Procedure ResetGM; Assembler;
ASM
{ ;Reset GM }
MOV DX,GMPort
MOV AL,0FFh
OUT DX,AL
{; Get ACK }
CALL ReadGM
{; UART Mode }
MOV AL,03Fh
CALL WriteGMCommand
End;
Procedure SetNoteOn(Channel,Note,Volume:Byte); Assembler;
ASM
MOV AL,[Channel]
ADD AL,90h
Call WriteGM
MOV AL,[Note]
CALL WriteGM
MOV AL,[Volume]
CALL WriteGM
End;
Procedure SetNoteOff(Channel,Note,Volume:Byte); Assembler;
ASM
MOV AL,[Channel]
ADD AL,80h
Call WriteGM
MOV AL,[Note]
CALL WriteGM
MOV AL,[Volume]
CALL WriteGM
End;
var
note:char;
Begin
writeln ('Press esc to quit ...');
repeat
note:=readkey;
ResetGM;
SetNoteOn(0,ord(note)-64,127);
SetNoteOff(0,ord(note)-64,127);
ResetGM;
until note = #27;
End.