pal_generate_tones.hcc
// pal_generate_tones.hcc
/* Use Pal Audio to generate tones.
*
* Switch (button) 0: 440 Hz sine wave
* Switch (button) 1: 880 Hz sine wave
* Both switches: Sum of 440 and 880.
*
* Uses waveform intensities generated by
* Generate_PAL_Samples.java.
*
* For visualization with Waveform Analyzer,
* set the trace parameters to 50,000 points
* with a 1,000 nsec period.
*
* Author: C. Vickery
* Fall, 2003
*
*/
#ifdef USE_SIM
#define PAL_ACTUAL_CLOCK_RATE 1000000
set clock = external "P1"
with
{
extlib = "DKSync.dll",
extinst = "1000", // Period of 1MHz simulated clock
extfunc = "DKSyncGetSet"
};
// Use switches instead of buttons when simulating so that
// both can be on at the same time.
#define SW0 8
#define SW1 9
#define NUM_SWITCHES 10
#endif
#if (defined USE_RC200 || USE_RC200E)
#define PAL_TARGET_CLOCK_RATE 50000000
#define SW0 0
#define SW1 1
#define NUM_SWITCHES 2
#endif
#include <pal_master.hch>
#include <stdlib.hch>
#define true TRUE
#define false FALSE
// Bits per sample.
/* Notes:
* 1. The macro expr bps must be defined before #including header
* files produceded by Generate_PAL_Samples.java.
* 2. The value of bps will vary depending on the target platform.
* For example, when USE_SIM is defined, it is 16, but when
* USE_RC200 is defined it is 20.
*/
macro expr bps = ( PalAudioOutGetMaxDataWidthCT() );
// Lookup tables for the two waveforms. The header files were
// produced by Generate_PAL_Samples.java, which also defines values
// for sampleRate_xxx and numSamples_xxx.
rom signed bps a_440[] =
#include "a-440.hch"
rom signed bps a_880[] =
#include "a-880.hch"
signed bps left; // Value output to both channels, actually.
#ifdef USE_SIM
// A "feature" of the DKConnect DLL is that it can handle unsigned
// values of any width, but signed values only of 32 bits. So we
// sign extend the values being output to 32 bits and output the 32
// bit values after scaling them up to make the amplitude of the
// waveform big enough to see.
// (Celoxica service call 00011469; November 18, 2003.)
interface bus_out() left_channel( signed 32 out =
(adjs(left, 32) << (32 - bps)) )
with
{
extlib = "DKConnect.dll",
extinst = "t(32)",
extfunc = "DKConnectGetSet"
};
#endif
// micro_delay()
// ------------------------------------------------------------------
/*
*/
macro proc micro_delay( microsec )
{
macro expr clocks = PAL_ACTUAL_CLOCK_RATE / 1000000 * microsec;
unsigned (log2ceil( clocks )) counter;
counter = clocks;
while ( counter )
counter--;
}
// main()
// ------------------------------------------------------------------
/*
* Generates sine waves from rom lookup tables.
*/
void main( void )
{
unsigned 1 b0, b1; // Switches
unsigned (log2ceil( numSamples_440 )) i_440; // Samples index
unsigned (log2ceil( numSamples_880 )) i_880; // Samples index
PalVersionRequire( 1, 2 );
PalSwitchRequire( NUM_SWITCHES );
PalAudioOutRequire( 1 );
i_440 = 0;
i_880 = 0;
par
{
PalAudioOutEnable(PalAudioOutCT( 0 ) );
seq
{
PalAudioOutRun(PalAudioOutCT( 0 ), PAL_ACTUAL_CLOCK_RATE );
PalAudioOutSetSampleRate( PalAudioOutCT( 0 ),
assert( sampleRate_440 == sampleRate_880, sampleRate_440,
"440 and 880 Hz sampling rates are not the same (%d - %d)",
sampleRate_440, sampleRate_880 ) );
}
// Generate a tone intensity, depending on states of switches
while ( true )
{
switch ( b1@b0 )
{
// No tone
case 0b00:
left = 0;
break;
// 440 Hz
case 0b01:
left = a_440[i_440];
break;
// 880 Hz
case 0b10:
left = a_880[i_880];
break;
// 440 mixed with 880
/*
* Halve each intenstity before summing to avoid overflow.
*/
case 0b11:
left = (a_440[i_440] >> 1) + (a_880[i_880] >> 1);
break;
}
par
{
PalAudioOutWrite( PalAudioOutCT( 0 ), left, left );
i_440++;
i_880++;
}
// Wrap indices if necessary
par
{
if ( i_440 == numSamples_440 )
{
i_440 = 0;
}
if ( i_880 == numSamples_880 )
{
i_880 = 0;
}
}
}
// Switch handler
while ( true )
{
PalSwitchRead( PalSwitchCT( SW0 ), &b0 );
PalSwitchRead( PalSwitchCT( SW1 ), &b1 );
}
}
}