/* TuneTask -- Tunes for the Felling Abaondoned speaker
 */
#include <Tunes.h>	// get extern defines
#include <pitches.h>	// get note defines

// get the prototypes for the schip-scheduler
//   accessed from default cores/arduino directory)
//#include "schip/scheduler.h"
#include <schip.h>

// posted for each Melody note,
// @param ind -- index into Melody
static void TuneTask( uint16_t ind )
{
	byte i = ind;

	// if nothing to do, don't do it
	if( (Tunes::Melody == 0) || (Tunes::Melody == ((Note*)0xffff)) )
		return;

	// check for Melody repeat
	if( Tunes::Melody[ind].pitch == REPEAT )
	{
		// rewind
		i = ind = 0;
	}

	// arg -- argument to the next call of this function (next Melody index)
	// duration -- ON ticks of this note
	// length -- ticks until next event
	// pitch -- buzzer frequency
	// play() reposts the current task if length != 0
	if( !Tunes::play( ++i, (Tunes::Melody[ind].pitch),
			   (Tunes::Melody[ind].duration << 3),
			   (Tunes::Melody[ind].length << 3) ) )
	{
		Tunes::Melody = 0;
	}

	return;
}

uint8_t Tunes::SPEAKERout; // output pin assignment
Note*   Tunes::Melody;	// currently playing note sequence

/** Execute one note play and repost current task
 *  ticks are in millisec and pitch in Hz
 *	word arg -- argument to pass to next iteration of Task
 *	word pitch -- buzzer frequency
 *	word duration -- ON ticks of this note
 *	word length -- ticks until next event
 *	return true if length > 0 (task reposted and melody should continue playing)
 */
byte Tunes::play( word arg, word pitch, word duration, word length )
{
	// turn on the current note
	if( pitch != 0 )
		tone( SPEAKERout, pitch, duration );

	if( length != 0 )
	{
		repostTask( length, arg );
		return 1;
	}
	else
	{
		return 0;
	}
}

/** constructor to set output pin number
 **/
Tunes::Tunes( uint8_t pin )
{
	SPEAKERout = pin;
	return;
}

// start playing a Melody sequence
void Tunes::startTune( Note* sequence )
{
	Melody = sequence;
	// start playing: ticks, function, argument
	postTask( 0, TuneTask, 0 );
}

// stop everything in it's tracks
void Tunes::stopTune()
{
	noTone( SPEAKERout );
	Melody = 0;
}

// end the melody but let last note play out
void Tunes::endTune()
{
	Melody = 0;
}
