/*******************************************************************************

	music.c
	Z-World, 2000

	This program provides an example of playing simple music through the
	Intellicom speaker.  By providing the frequency of each note and delaying
	for a certain amount of time, simple tunes can be played, such as the
	first line of the chorus to "Bicycle Built For Two (Daisy Bell)" below.

	Four octaves are available in this demo (all above middle C).  To play
	a note, simply call spkrOut() with the appropriate frequency, which can
	be found in the array

								freq[octave][note]

	where 'octave' ranges from 0-3 (starting with the note A) and 'note'
	ranges from 0-11.  Note that in this demo, one octave ranges from
	'A' note to 'A' note.

	To adjust the pace of your music, change the length definition of
	a whole note ("#define WHOLE 1000" below) to something appropriate.

	NOTE that, although the frequencies in freq[] go down as low as 440 Hz
	(A above middle C), the Intellicom cannot reliably play frequences below
	about 575 Hz (D above middle C).  Scale your octaves accordingly!

 *******************************************************************************/
#class auto					/* Change local var storage default to "auto" */

#define	NUM_NOTES	12
#define	NUM_OCTAVES	 4

// definitions for the notes in each octave
#define	_A	0
#define	_As	1		// A-sharp
#define	_B	2
#define	_C	3
#define	_Cs	4		// C-sharp
#define	_D	5
#define	_Ds	6		// D-sharp
#define	_E	7
#define	_F	8
#define	_Fs	9		// F-sharp
#define	_G	10
#define	_Gs	11		// G-sharp

// actual frequency data for four octaves
const int	freq[NUM_OCTAVES][NUM_NOTES] = {
	{ 440, 466, 494, 523, 554, 587, 622, 659, 698, 740, 784, 831 },
	{ 880, 932, 988, 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661 },
	{ 1760, 1865, 1976, 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322 },
	{ 3520, 3729, 3951, 4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645 } };

// note lengths (in milliseconds)
#define	WHOLE		 1000
#define	HALF		 (WHOLE/2)
#define	QUARTER	 (WHOLE/4)
#define	EIGHTH	 (WHOLE/8)
#define	SIXTEENTH (WHOLE/16)
#define	THREEQTR	 (HALF + QUARTER)

// note volume (0-3)
#define VOL	1

////////////////////////////////////////////////////////////////////////////////

void main()
{
	brdInit();

	spkrOut(freq[1][_D], VOL);		dispPrintf("   Dai");
	delayMS(THREEQTR);
	spkrOut(freq[1][_B], VOL);		dispPrintf("sy, ");
	delayMS(THREEQTR);
	spkrOut(freq[0][_G], VOL);		dispPrintf("Dai");
	delayMS(THREEQTR);
	spkrOut(freq[0][_D], VOL);		dispPrintf("sy,\n");
	delayMS(HALF);

	// 1/4 rest
	spkrOut(0, 0);						delayMS(QUARTER);

	spkrOut(freq[0][_E], VOL);		dispPrintf("   give ");
	delayMS(QUARTER);
	spkrOut(freq[0][_Fs], VOL);		dispPrintf("me ");
	delayMS(QUARTER);
	spkrOut(freq[0][_G], VOL);		dispPrintf("your\n");
	delayMS(QUARTER);
	spkrOut(freq[0][_E], VOL);		dispPrintf("     an");
	delayMS(HALF);
	spkrOut(freq[0][_G], VOL);		dispPrintf("swer,");
	delayMS(QUARTER);
	spkrOut(freq[0][_D], VOL);		dispPrintf("do!");
	delayMS(THREEQTR+HALF);

	spkrOut(0, 0);
}

////////////////////////////////////////////////////////////////////////////////
// a blocking delay for the number of milliseconds provided

int delayMS(int msec)
{
	static unsigned long	t0;

	t0 = MS_TIMER + msec;
	while( (int)(MS_TIMER - t0) < 0 )
		; // do nothing
}

////////////////////////////////////////////////////////////////////////////////