[Back to SOUND SWAG index] [Back to Main SWAG index] [Original]
{
From: Gerhard Dalenoort Read: Yes Replied: No
}
Program DigiTal; { Real-Mode Only }
{ Timer routines tnx to Unit digital
InterruptVector : Array [0..255] of Pointer Absolute $0000 : $0000;
My Question is this: In DPMI mode were do I have to look
for the Interrupt Table ???
and How to program DMA ???
GreetZ,
Gerhard.
}
Uses Crt;
Const
fname = 'c:\modplay\sounds\hcaprince.911'; { Can be any raw data File }
SAMPLERATE = 16000; { about: 3Khz - 44Khz }
HexTable : Array[0..15] of Char =
('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
Counter : Word = 1;
{ SB-DSP Constants }
BASE = $220; { Change this to your card base adres }
resetport = Base + $6;
readport = Base + $A;
Writeport = Base + $C;
statusport = Base + $E;
dac_Write = $10;
adc_read = $20;
speakeron = $D1;
speakeroff = $D3;
{ Timer Constants}
C8253ModeControl = $43;
C8253Channel : Array [0..2] of Byte = ($40, $41, $42);
C8253OperatingFreq = 1193180;
C8259Command = $20;
TimerInterrupt = $08;
Var
OldTimerInterrupt : Pointer;
InterruptVector : Array [0..255] of Pointer Absolute $0000 : $0000;
OK,DonePlaying : Boolean;
Sound : Pointer;
Size,
SegSound, OfsSound: Word;
Mbyte : byte;
Procedure spk_on;
begin
Repeat Until port[Writeport] < $80;
port[Writeport] := $D1;
end;
Procedure spk_off;
begin
Repeat Until port[Writeport] < $80;
port[Writeport] := $D3;
end;
Function resetDSP : Boolean;
(*----------------------------------------------------------
Not Mine...
The Book says:
- Write a 1 to ResetPort $2x6,
- Wait 3 MicroSec. (æs)
- Write a 0 to ResetPort $2x6
- Wait until ready byte $0AA at DataPort $2xA
(it is advisable to check first for a data avaible: Port $22E bit 7 set)
Typically the DSP takes about 100 microsecs. to reset.
Mine looks like this in pseudo code:
Port[$226]:=1;
Asm nop; nop; nop; End; { Consume time }
Port[$226]:=0;
I:=0; { Longint }
Repeat Inc(I) until (I>123000) or (Port[$22A]=$0AA);
ResetDSP:=(I<32000);
-------------------------------------------------------------- *)
Var
count, bdum : Byte;
begin
resetDSP := False;
port[resetport] := 1;
For count := 1 to 6 do bdum := port[statusport];
port[resetport] := 0;
For count := 1 to 6 do bdum := port[statusport];
Repeat Until port[statusport] > $80;
if port[readport] = $AA then resetDSP := True;
end;
Procedure generic(reg,cmd:Integer; data:Byte);
{ ?? not used here, what does it do ?? }
begin
Repeat Until port[Writeport] < $80;
port[reg] := cmd;
Repeat Until port[Writeport] < $80;
port[reg] := data;
end;
fUNCtION hEX( tHEvAR:wORD):sTRING; { See what the it looks like in HEX }
vAR
bUF : sTRING;
w : wORD;
bEGIN
w := tHEvAR;
bUF:= hEXtABLE[ hI(w) sHR 4];
bUF:=bUF + hEXtABLE[ hI(w) mOD 16];
bUF:=bUF + hEXtABLE[ lO(w) sHR 4];
bUF:=bUF + hEXtABLE[ lO(w) mOD 16];;
hEX:=bUF;
eND;
{=[ 8253 Timer Programming Routines ]=====================================}
Procedure Set8253Channel(ChannelNumber : Byte; ProgramValue : Word);
begin
Port[C8253ModeControl] := 54 or (ChannelNumber SHL 6); { XX110110 }
Port[C8253Channel[ChannelNumber]] := Lo(ProgramValue);
Port[C8253Channel[ChannelNumber]] := Hi(ProgramValue);
end;
{-[ Set Timer Interupt Vector To Default Handler ]------------------------}
Procedure SetTimerInterruptVectorDefault;
begin
aSM cli END;
InterruptVector[TimerInterrupt] := OldTimerInterrupt;
aSM sti END;
end;
{-[ Set Clock Channel 0 Back To 18.2 Default Value ]----------------------}
Procedure SetDefaultTimerSpeed;
begin
Set8253Channel (0, 0);
end;
{=[ MUST CALL BEFORE ExitING Program!!! ]=================================}
Procedure CleanUp;
begin
SetDefaultTimerSpeed;
SetTimerInterruptVectorDefault;
end;
{-[ Set Clock Channel 0 (INT 8, IRQ 0) To Input Speed ]-------------------}
Procedure SetPlaySpeed(Speed : LongInt);
Var ProgramValue : Word;
begin
if Speed > 33000 then Speed:=33000;
ProgramValue := C8253OperatingFreq div Speed;
Set8253Channel(0, ProgramValue);
end;
Procedure PlayData; Interrupt;
var DATA : Byte;
begin
if Not(DonePlaying) Then
begin
if Counter <= Size Then
begin
Data:=(Mem[SegSound:OfsSound+Counter] {SHR 2} ); { SHR = Volume down }
Inc(Counter);
{ Port[$22C]:=$10; NextByte is realtime sample Data
Port[$22C]:=Data; Sample Data
The next ASM is the same as these
two port Writes to the DSP, Maybe just faster.
} Asm
mov dx,$22C
in al,dx
mov al,10h
out dx,al
in al,dx
mov al,data
out dx,al
end;
end else { Counter > Size }
begin
DonePlaying := True;
Counter := 1;
end;
end;
Port[C8259Command] := $20; { Enable Interupts }
end;
{---------------------- LoadRawSampleData --------------------}
Function loadFile(Var buffer:Pointer; Filename:String) : Word;
Var
fromf : File;
size : LongInt;
errcode : Integer;
begin
assign(fromf,Filename);
reset(fromf,1);
errcode := ioresult;
if errcode = 0 then
begin
size := Filesize(fromf);
{Writeln(size);}
getmem(buffer,size);
blockread(fromf,buffer^,size);
end
else size := 0;
loadFile := size;
close(fromf);
end;
Procedure unload(buffer:Pointer; size:Word);
begin freemem(buffer,size); end;
Var I : Integer;
Ch : Char;
Begin
Clrscr;
DonePlaying:=True;
Size := LoadFile(Sound,Fname);
SegSound:=Seg(Sound^); { Get SegMent and Ofset of sample }
OfsSound:=Ofs(Sound^);
OK:=ResetDSP; { Reset DSP (soundCard) }
if Not OK then begin Write(#7,'No card ?');Halt(1);end; { NO CARD DETECTED }
Spk_on;
SetPlaySpeed(SAMPLERATE); { Set Herz Timer for Interrupt $8 }
ASM cli END; { Point Interrupt $8 to My procedure }
OldTimerInterrupt := InterruptVector[TimerInterrupt];
InterruptVector[TimerInterrupt] := @PlayData;
ASM sti END;
GotoXY(10,10);
Writeln('Testin: ',Counter:5);
WriteLn(#13#10,' We Still got: ',MaxAvail,' Memory, load more samples,');
WriteLn(' That would be ',MaxAvail div 64000,' samples of 64000 bytes
(MaxSampleSize) '); WriteLn(' and ',MaxAvail mod 64000,' bytes of memory,
enough ? ...nah.'); WriteLn(' Sample loaded is ',Size,' Bytes already');
WriteLn(#13#10' O jeah, press space to play the sample, <Esc> to Quit ');
repeat
IF Port[$60]=57 then { SpaceBar is pressed ? }
begin
Delay(1); { Won't slow the playing }
GotoXY(10,10); { Won't slow the playing }
Write('Testin: ',Counter:5); { Won't slow the playing }
if DonEplaying then { it means the sample is played }
Begin { Loop Mode }
Counter:=1; { First set the counter to 1, the interrupt }
DonePlaying:=False; { plays as soon as DonePlaying = false }
end;
end else { if not spacebar is down }
begin { Stop playing and reset the counter }
DonePlaying:=True;
counter:=1;
end;
if Keypressed Then Ch:=ReaDkEY; { The port doesn't read the key }
Until Ch=#27;
CleanUp; { Set the interrupt to original etc. }
Unload(Sound,Size); { Free Sample Memory }
Spk_off; { DAC to output off }
ClrScr;
end.
[Back to SOUND SWAG index] [Back to Main SWAG index] [Original]