home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
microcrn
/
issue_36.arc
/
REAL36.FIG
< prev
next >
Wrap
Text File
|
1987-05-21
|
4KB
|
115 lines
program dacsound;
{ Generates different tones through the DAC.
These are sine waves, but you can generate different types of
waves to see what they sound like. Turbo generates an array of
points which are passed to an assembly language program for quick,
consistent output.
Passing byte values to the assembly routine worked fine, but I
had a lot of trouble passing anything else, so I declared "time"
and "wve_adr" at absolute addresses so I could just pluck the
values out directly with assembly language. To determine where
to put the absolute addresses, I looked at the Turbo compiler
message which said "free."
Note the length of the tone is controlled by the "time" variable
(which MUST be reloaded before each waveout call) AND the length
of the wave itself, so wave2 with a time of 8 has twice the duration
of wave1 with a time of 8.
Next time I'll be using a PC. }
const
A_CONTROL: byte = $22; {PIO address for KAYPRO 84s }
A_DATA: byte = $20; {See issue #34 }
MODE : byte = $0f; {0000 1111 mode 0 = output}
INT : byte = $07; {0000 0111 ints disabled}
count1 : byte = 50; { These are arbitrary; they don't }
count2 : byte = 100; { represent any particular tones. }
count3 : byte = 200; { (All those piano lessons wasted!)}
type
wave = array[0..255] of byte;
var
wave1,wave2,wave3 : wave;
time : byte absolute $D000;
wve_adr : integer absolute $D010;
count : byte;
procedure make_waves(var wavex : wave; count: byte);
{fills the array wavex with a sine wave which is count
bytes long}
var
radians : real;
curve,i : integer;
begin
writeln('making waves ~~~~~~~~~~~');
radians := 0;
for i:= 0 to count do
begin
curve := 127 + round(127 * cos(radians));
{ 0 volts at the 8-bit DAC occurs with a byte value
of 127, so the wave needs peak values of 127 with an
offset of 127. }
if curve > 255 then curve := 255;
if curve < 0 then curve := 0;
wavex[i] := byte(curve);
radians := radians + (2 * 3.14159)/count;
end;
end; {make_waves}
procedure waveout(COUNT: byte; PRT: byte);
{Outputs bytes starting from memory location WVE_ADR to
WVE_ADR + COUNT to port PRT. Repeats process TIME cycles.
The value in DE is the number of cycles for each count in
TIME. The OTIR instruction does the outputs. }
{$A+}
begin
inline(
$3A/PRT/ { LD A,(PRT) }
$4F/ { LD C,A }
$DD/$21/$00/$D0/{ LD IX,TIME }
$11/$FF/$00/ { LOOP1:LD DE,00FFH }
$2A/$10/$D0/ { LOOP2:LD HL,(WVE_ADR) }
$3A/COUNT/ { LD A,(COUNT) }
$47/ { LD B,A }
$ED/$B3/ { OTIR }
$1B/ { DEC DE }
$7A/ { LD A,D }
$FE/$00/ { CP 0 }
$20/$F1/ { JR NZ,LOOP2 }
$7B/ { LD A,E }
$FE/$00/ { CP 0 }
$20/$EC/ { JR NZ,LOOP2 }
$DD/$35/$00/ { DEC (IX) }
$20/$E4 { JR NZ,LOOP1 }
);
end; {Waveout}
procedure tone(var wavex : wave; _time : byte; count: byte; pause: integer);
begin
{ set global variables }
wve_adr := addr(wavex[0]);
time := _time;
waveout(count,A_DATA);
delay(pause);
end; { tone }
begin
port[A_CONTROL]:= MODE; {initialize the pio}
port[A_CONTROL]:= INT;
make_waves(wave1,count1);
make_waves(wave2,count2);
make_waves(wave3,count3);
while not keypressed do
begin
tone(wave1,8,count1,1000);
tone(wave2,4,count2,1000);
tone(wave3,2,count3,1000);
end;
end. { "The Star-Spangled Banner" is left as an excercise. }