/********************************************************************
* FileName:        example buzzer.c
* Processor:       18F4520
* Compiler:        MPLAB C18 v.3.06 
*
* This file plays with the buzzer.  It plays a few songs:
*		Mary Had a Little Lamb
*		The Mexican Hat Dance	- Coding done by Megan O'Brien
*		Mario Theme				- Coding done by Dan Soledad
*
*  See if you can add a song (to the start) to play something else.
* 
* Try to figure out what you can about the included code.
*
* Author               Date        Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// David Fisher		09/9/07
// David Fisher		12/6/08		Added 2 additional songs

/** Processor Header Files *****************************************/
#include <p18f4520.h> 
#include <pwm.h>
#include <timers.h>
#include <delays.h>

/** Define Constants Here ******************************************/
//  Formula from the library function:
//  PWM period =[period + 1] x 4 x TOSC x TMR2 prescaler
//
// We have setup:
// Fosc = 1 MHz
// Tosc = 1/1 000 000
// TMR2 = 4
//
//  Want a frequency for Middle A (440Hz)
//  1/440 = (period + 1) * 4 * 1/1000000 * 4
//  period = 141.0454545
//   Therefore A_mid = 141
//
//  It's 1 equation and 1 unknown.  It's not that hard.
//   I used excel and setup the period for basic notes:
#define a_up1 70
#define g_up1 78
#define f_up1 88
#define e_up1 93
#define d_up1 105
#define c_sharp_up 112
#define c_up1 118
#define b_mid 125
#define b_flat_mid 130
#define a_mid 141
#define g_sharp_mid 150
#define g_mid 158
#define f_sharp_mid 168
#define f_mid 177
#define e_mid 188
#define d_sharp_mid 200
#define d_mid 211
#define c_mid 237

#define timeDelay2 200
#define VOLUME 15

// Same notes different names
#define c4  238
#define c4s 224
#define d4  212
#define d4s 200
#define e4  189
#define f4  178
#define f4s 168
#define g4  158
#define g4s 149
#define a4  141
#define a4s 133
#define b4  126
#define c5 118
#define c5s  112
#define d5 105
#define d5s 99
#define e5  94
#define f5  88
#define f5s 83
#define g5  79
#define g5s 74
#define a5  70
#define a5s 66
#define b5  62
#define c6  59

/** Local Function Prototypes **************************************/
void beatDelay(char beats);
void tone(char freq, char beats);
void sleep(char beats);
void maryHadALittleLamb(void); 
void mexicanHatDance(void); 
void marioTheme(void);

// ============================================================
// Configuration Bits 
// For details on PIC18F configuration bit settings, see 
// PIC18 Configuration Settings in MPLAB-IDE Help
// ============================================================

#pragma config OSC = INTIO67 // Fosc = 1 MHz (the default internal oscillator)
#pragma config WDT = OFF
#pragma config LVP = OFF
#pragma config BOREN = OFF
#pragma config XINST = OFF


/** Declarations *************************************************/
char timeDelay = 35;
char i;

/*****************************************************************
* Function:        void main(void)
******************************************************************/
#pragma code

void main (void)
{
	OpenTimer2(TIMER_INT_OFF & T2_PS_1_4);
	//PWM period =[(period ) + 1] x 4 x TOSC x TMR2 prescaler
	// Fosc = 1 MHz (the default internal oscillator)
	// TMR2 prescaler = 4

	//OpenPWM1(note frequency using #defines);
	OpenPWM1(a_mid);
	SetDCPWM1(VOLUME);  // set the duty cycle (provides volume)

	timeDelay = 35;
	maryHadALittleLamb();
	mexicanHatDance();	
	
	timeDelay = 15;		// Mario needed to play faster
	marioTheme();




	// Play some random noise
  	for (i=0;i<6;i++){
		Delay100TCYx(timeDelay2);
		OpenPWM1(a_up1);
		SetDCPWM1(100);

		Delay100TCYx(timeDelay2);
		SetDCPWM1(200);
		OpenPWM1(d_up1);

		Delay100TCYx(timeDelay2);
		SetDCPWM1(400);
		OpenPWM1(a_mid);

		Delay100TCYx(timeDelay2);
		SetDCPWM1(800);
		OpenPWM1(c_mid);
	}

	SetDCPWM1(0);
	while (1)
		;

}

/*****************************************************************
* Function:			void beatDelay(char beats)
* Input Variables:	beats - determines the number of beats to delay
					timeDelay - determines the length of a beat
					  (Note: timeDelay is a Global variable so not passed)
* Output return:	none
* Overview:			This function delays for a number of beats to let things play
******************************************************************/
void beatDelay(char beats){
	Delay1KTCYx(beats*timeDelay);
}

/*****************************************************************
* Function:			void tone(char freq, char beats)
* Input Variables:	freq - The frequency to play
					beats - The number of beats to play it for
* Output return:	none
* Overview:			Creates a tone for a length of time
******************************************************************/
void tone(char freq, char beats){
		OpenPWM1(freq);
		beatDelay(beats);
}

/*****************************************************************
* Function:			void sleep(char beats)
* Input Variables:	beats - Determines the number of beats to mute the buzzer
* Output return:	none
* Overview:			Creates a period of no sound
******************************************************************/
void sleep(char beats){
	SetDCPWM1(0);
	beatDelay(beats);
	SetDCPWM1(VOLUME);
}

/*****************************************************************
* Function:			void maryHadALittleLamb()
* Input Variables:	none
* Output return:	none
* Overview:			Uses sheet music to play a short song - Mary Had a Little Lamb
******************************************************************/
void maryHadALittleLamb() 
{
    SetDCPWM1(VOLUME);
    tone(b_mid,2 );
    tone(a_mid,2 );
    tone(g_mid,2 );
    tone(a_mid,2 );

    tone(b_mid,2);
    tone(b_mid,2 );
    tone(b_mid,4 );

    tone(a_mid,2 );
    tone(a_mid,2 );
    tone(a_mid,4 );

	tone(b_mid,2);
	tone(d_up1,2);
	tone(d_up1,4);

	tone(b_mid,2);
	tone(a_mid,2);
	tone(g_mid,2);
	tone(a_mid,2);

	tone(b_mid,2);
	tone(b_mid,2);
	tone(b_mid,2);
	tone(b_mid,2);

	tone(a_mid,2);
	tone(a_mid,2);
	tone(b_mid,2);
	tone(a_mid,2);

	tone(g_mid,2);
	SetDCPWM1(0);
    sleep(6);
}


/*****************************************************************
* Function:			void mexicanHatDance() 
* Input Variables:	none
* Output return:	none
* Overview:			Uses sheet music to play a short song - Mexican Hat Dance
*						Coding done by Megan O'Brien
******************************************************************/
void mexicanHatDance() 
{
    SetDCPWM1(VOLUME);
	tone(c_mid,1 );
	tone(f_mid,1 );
	beatDelay(1);
	tone(c_mid,1 );
	tone(f_mid,1 );
	beatDelay(1);
	tone(c_mid,1 );
	tone(f_mid,2 );
	beatDelay(2);
	tone(c_mid,1 );
	tone(f_mid,1 );
	tone(g_mid,1 );
	tone(f_mid,1 );
	tone(e_mid,1 );
	beatDelay(1);
	tone(f_mid,1 );
	tone(g_mid,2 );
	beatDelay(2);

	tone(c_mid,1 );
	tone(e_mid,1 );
	beatDelay(1);
	tone(c_mid,1 );
	tone(e_mid,1 );
	beatDelay(1);
	tone(c_mid,1 );
	tone(e_mid,1 );
	beatDelay(2);
	tone(c_mid,1 );
	tone(e_mid,1 );
	tone(f_mid,1 );
	tone(e_mid,1 );
	tone(d_mid,1 );
	beatDelay(1);
	tone(e_mid,1 );
	tone(f_mid,2 );
	beatDelay(4);

	tone(c_up1,1 );
    tone(b_mid,1 );

    tone(c_up1,1 );
    tone(a_mid,1 );
    tone(g_sharp_mid,1 );
    tone(a_mid,1 );
    tone(f_mid,1 );
    tone(e_mid,1 );

	tone(f_mid,1 );
	tone(c_mid,1 );
	beatDelay(2 );
	tone(c_mid,1 ); //actually a_low but won't play
	tone(c_mid,1 ); //actually b_flat_low
	beatDelay(1);

	tone(c_mid,1 );
	tone(d_mid,1 );
	tone(e_mid,1 );
	tone(f_mid,1 );
	tone(g_mid,1 );
	tone(a_mid,1 );

	tone(b_flat_mid,1 ); 
	tone(g_mid,1 );
	beatDelay(1);
	tone(b_flat_mid,1 ); 
	tone(a_mid,1 );

	tone(b_flat_mid,1 );
	tone(g_mid,1 );
	tone(f_sharp_mid,1 );
	tone(g_mid,1 );
	tone(e_mid,1 );
	tone(d_sharp_mid,1 );
	
	tone(e_mid,1 );
	tone(c_mid,1 );
	beatDelay(2);
	
	tone(c_up1,1 );
	tone(b_mid,1 );
	
	tone(c_up1,1 );
	tone(d_up1,1 );
	tone(c_up1,1 );
	tone(b_flat_mid,1 );
	tone(a_mid,1 );
	tone(g_mid,1 );
	
	tone(c_up1,1 );
	tone(d_up1,1 );
	tone(c_up1,1 );
	tone(b_flat_mid,1 );
	tone(a_mid,1 );
	tone(g_mid,1 );
	
	tone(f_mid,2 );
	beatDelay(2);

	tone(c_mid,1 );
	tone(f_mid,1 );


	SetDCPWM1(0);
    sleep(6);
}


/*****************************************************************
* Function:			void marioTheme() 
* Input Variables:	none
* Output return:	none
* Overview:			Uses sheet music to play a short song - Mario Theme
*						Coding done by Dan Soledad
******************************************************************/
void marioTheme() 
{
    SetDCPWM1(VOLUME);
	tone(e5 ,3);
	tone(e5 ,6);
	tone(e5 ,3);
	sleep(3);
	tone(c5 ,3);
	tone(e5 ,6);
	tone(g5 ,12);
	tone(g4 ,12);
	
	tone(c5 ,6);
	sleep(3);
	tone(g4 ,3);
	sleep(6);
	tone(e4 ,6);
	sleep(3);
	tone(a4 ,3);
	sleep(3);
	tone(b4 ,3);
	sleep(3);
	tone(a4s,3);
	tone(a4 ,6);
	
	tone(g4 ,4);
	tone(e5 ,4);
	tone(g5 ,4);
	tone(a5 ,6);
	tone(f5 ,3);
	tone(g5 ,3);
	sleep(3);
	tone(e5 ,3);
	sleep(3);
	tone(c5 ,3);
	tone(d5 ,3);
	tone(b4 ,3);
	sleep(6);
	
	tone(c5 ,6);
	sleep(3);
	tone(g4 ,3);
	sleep(6);
	tone(e4 ,6);
	sleep(3);
	tone(a4 ,3);
	sleep(3);
	tone(b4 ,3);
	sleep(3);
	tone(a4s,3);
	tone(a4 ,6);
	
	tone(g4 ,4);
	tone(e5 ,4);
	tone(g5 ,4);
	tone(a5 ,6);
	tone(f5 ,3);
	tone(g5 ,3);
	sleep(3);
	tone(e5 ,3);
	sleep(3);
	tone(c5 ,3);
	tone(d5 ,3);
	tone(b4 ,3);
	sleep(6);

	sleep(6);
	tone(g5 ,3);
	tone(f5s,3);
	tone(f5 ,3);
	tone(d5s,6);
	tone(e5 ,3);
	sleep(3);
	tone(g4s,3);
	tone(a4 ,3);
	tone(c5 ,3);
	sleep(3);
	tone(a4 ,3);
	tone(c5 ,3);
	tone(d5 ,3);

	sleep(6);
	tone(g5 ,3);
	tone(f5s,3);
	tone(f5 ,3);
	tone(d5s,6);
	tone(e5 ,3);
	sleep(3);
	tone(c6 ,3);
	sleep(3);
	tone(c6 ,3);
	tone(c6 ,12);


	sleep(6);
	tone(g5 ,3);
	tone(f5s,3);
	tone(f5 ,3);
	tone(d5s,6);
	tone(e5 ,3);
	sleep(3);
	tone(g4s,3);
	tone(a4 ,3);
	tone(c5 ,3);
	sleep(3);
	tone(a4 ,3);
	tone(c5 ,3);
	tone(d5 ,3);

	sleep(6);
	tone(d5s,6);
	sleep(3);
	tone(d5 ,3);
	sleep(6);
	tone(c5 ,12);
	sleep(12);

	SetDCPWM1(0);
    sleep(6);
}