psl_generate_tones.hcc
// psl_generate_tones.hcc
/* Use PSL Audio to generate tones.
*
* Left Channel gets 440 Hz sine wave.
* Right Channel gets 880 Hz sine wave.
*
* Buttons:
* 0: Cyle through intensities
* 1: Cycle through sampling rates
*
* Uses waveform intensities generated by RC200AudioSamples.java.
*
* Author C. Vickery
* Fall 2003
*/
// Cannot use PAL Virtual Console, so no simulation is provided.
#define RC200_TARGET_CLOCK_RATE 50000000
#include <rc200.hch>
#include <stdlib.hch>
#define true TRUE
#define false FALSE
#include "delays.hch"
// Bits per sample specified in RC-200 PSL Reference Manual.
macro expr bps = 20;
// Lookup tables for the waveforms. The header files were
// produced by RC200AudioSamples.java, which also defines the value
// of numSamples_xxx_yyy, where xxx is the frequency and yyy is the
// sampling rate (8000. 11025, 16000, 22050, 32000, 44100, or 48000).
// Samples for the left channel (440 Hz)
rom signed bps samples_440[7][110] =
{
#include "samples_440_8000.hch"
#include "samples_440_11025.hch"
#include "samples_440_16000.hch"
#include "samples_440_22050.hch"
#include "samples_440_32000.hch"
#include "samples_440_44100.hch"
#include "samples_440_48000.hch"
};
// Parameters copied from the samples_440_nnnn header files.
macro expr numSamples_440_8000 = 19;
macro expr numSamples_440_11025 = 26;
macro expr numSamples_440_16000 = 37;
macro expr numSamples_440_22050 = 51;
macro expr numSamples_440_32000 = 73;
macro expr numSamples_440_44100 = 101;
macro expr numSamples_440_48000 = 110; // Need 7 bits for this value
// Row Length lookup table for samples_440
rom unsigned 7 numSamples_440[7] =
{
numSamples_440_8000,
numSamples_440_11025,
numSamples_440_16000,
numSamples_440_22050,
numSamples_440_32000,
numSamples_440_44100,
numSamples_440_48000,
};
// Samples for right channel (880 Hz)
rom signed bps samples_880[7][55] =
{
#include "samples_880_8000.hch"
#include "samples_880_11025.hch"
#include "samples_880_16000.hch"
#include "samples_880_22050.hch"
#include "samples_880_32000.hch"
#include "samples_880_44100.hch"
#include "samples_880_48000.hch"
};
// Parameters copied from the samples_880_nnnn header files.
macro expr numSamples_880_8000 = 10;
macro expr numSamples_880_11025 = 13;
macro expr numSamples_880_16000 = 19;
macro expr numSamples_880_22050 = 26;
macro expr numSamples_880_32000 = 37;
macro expr numSamples_880_44100 = 51;
macro expr numSamples_880_48000 = 55; // Need 6 bits for this value
// Row Length lookup table for samples_880
rom unsigned 6 numSamples_880[8] =
{
numSamples_880_8000,
numSamples_880_11025,
numSamples_880_16000,
numSamples_880_22050,
numSamples_880_32000,
numSamples_880_44100,
numSamples_880_48000,
};
// Indices and limits into rows of samples
unsigned 7 i_440 = 0; // Index in row
unsigned 6 i_880 = 0;
unsigned 7 max_440 = 0; // End of row ...
unsigned 6 max_880 = 0; // ... depends on sample rate.
// Which sampling rate to use
unsigned 3 which_rate = 6; // Default is 48K
sema rateGuard; // For protecting above
// Volume and mute controls for RC200 AudioOut
static unsigned 5 volume = 0b00000;
static unsigned 1 mute = 1;
// main() - FSM
// ------------------------------------------------------------------
/*
* This module manages a state machine for the device. The state
* consists of two values, a volume setting and the sampling rate.
*
* Volume values range from 0 to 31, corresponding to each of
* the non-muted values for RC200AudioOutSetVolume(). The value
* increases by one for each press of the right (lower) button.
*
* Sampling rates range from 0 to 6, which serve as an index into
* the seven sampling rates possible. The value increases by 1 for
* each press of the left button.
*
* The hex displays show the current state at all times: The right
* display shows the volume, with the left decimal point on for
* values > 15. The left display shows the index of the sampling
* rate.
*
* The output is muted/unmuted every 5 sec.
* The right decimal point is off when the output is muted
*
* b0 is the left button and b1 is the right button.
*
* This FSM module also manages volume control settings for the
* audio out device.
*
*/
void main( void )
{
unsigned 1 b0_prev, b1_prev, b0, b1;
b0_prev = 0;
b1_prev = 0;
par
{
RC200AudioRun( RC200_ACTUAL_CLOCK_RATE );
seq
{
}
while ( true )
{
milli_delay( 5000 );
mute = 0; // TEMP: disable cycling value of mute every 5 sec
RC200AudioOutSetVolume( mute, ~volume, ~volume );
}
while ( true )
{
// Read buttons
par
{
b0 = RC200Button1Read();
b1 = RC200Button0Read();
}
// Check for a new button presses
par
{
// Check if Sampling Rate button was just pressed.
if ( b0 && ( b0 != b0_prev ) )
{
// Change sampling rate. Use a semaphore (with visual
// feedback) to prevent this and the generator function
// from accessing the sampling parameters at the same time.
while ( trysema(rateGuard) == 0 ) delay;
RC200LEDWrite( 0, 1 );
which_rate = ( which_rate == 6 ) ? 0 : which_rate + 1;
par
{
max_440 = numSamples_440[ which_rate ];
max_880 = numSamples_880[ which_rate ];
switch ( which_rate )
{
case 0:
RC200AudioOutSetSampleRate( RC200AudioSampleRate8000 );
break;
case 1:
RC200AudioOutSetSampleRate( RC200AudioSampleRate11025 );
break;
case 2:
RC200AudioOutSetSampleRate( RC200AudioSampleRate16000 );
break;
case 3:
RC200AudioOutSetSampleRate( RC200AudioSampleRate22050 );
break;
case 4:
RC200AudioOutSetSampleRate( RC200AudioSampleRate32000 );
break;
case 5:
RC200AudioOutSetSampleRate( RC200AudioSampleRate44100 );
break;
case 6:
RC200AudioOutSetSampleRate( RC200AudioSampleRate48000 );
break;
default:
RC200AudioOutSetSampleRate( RC200AudioSampleRate48000 );
break;
}
}
milli_delay( 100 ); // So the LED can be seen.
RC200LEDWrite( 0, 0 );
releasesema( rateGuard );
}
// Check if Volume Button was just pressed.
if ( b1 && ( b1 != b1_prev ) )
{
// Change volume
volume++;
RC200AudioOutSetVolume( mute, ~volume, ~volume );
}
}
// Update button states and 7-seg displays
par
{
b0_prev = b0;
b1_prev = b1;
RC200SevenSeg0WriteDigit( 0@which_rate, volume \\ 4 );
RC200SevenSeg1WriteDigit( volume <- 4, ~mute );
}
milli_delay( 50 ); // Debounce time for buttons
}
}
}
// main() - Generate Tones
// ------------------------------------------------------------------
/*
* This is the tone generator module.
*/
void main( void )
{
max_440 = numSamples_440[ which_rate ];
max_880 = numSamples_880[ which_rate ];
i_440 = 0; // Index in row
i_880 = 0;
// Wait for device to initialize, and set initial volume.
milli_delay( 300 ); // Ad hoc value used because it works.
RC200AudioOutSetVolume( mute, ~volume, ~volume );
// Generate a tone intensity, depending on FSM control.
while ( true )
{
// Critical section protected by semaphore so paramters won't
// be used while in an inconsistent state.
RC200LEDWrite( 1, 1 ); // Usually too fast to see.
while ( trysema( rateGuard ) == 0 ) delay;
RC200LEDWrite( 1, 0 );
// Write next sample to both audio channels
RC200AudioOutWrite( samples_440[ which_rate ][ i_440 ],
samples_880[ which_rate ][ i_880 ] );
// Update indices
par
{
i_440++;
i_880++;
}
par
{
// Increment indices modulo current row lengths.
if ( i_440 == max_440 )
{
i_440 = 0;
}
if ( i_880 == max_880 )
{
i_880 = 0;
}
}
releasesema( rateGuard );
}
}