#pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // GP3/MCLR pin function select (GP3/MCLR pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#define _XTAL_FREQ 4000000 // Indicamos a que frecuencia de reloj esta funcionando el micro
#include <xc.h>
// Formato de la estructura
struct Melody
{
const unsigned char * MelodyArray;
unsigned char beat_speed;
unsigned int defaultduration;
unsigned int defaultoctave;
}
// Valores de los tonos
const unsigned char Melody1[] = {"2c,2g4,2c,2e,2c,2e,2g,2c,2c6,2b,2a,2g,g,16p,2g,2f,2d,2b4,2g4,2b4,2d,2f,2e,2c,2a,2g,g,2c,2c,2c,2b4,2c,2e,2c,2e,2g,2c,2c6,2b,2a,2g,g,16p,2g,2f,2d,2b4,2g4,2b4,2d,2b4,2c,2g4,2e,c.,p,p"};
const unsigned char Melody2[] = {"2c,2d,e.,f,g.,e,g,f,2e,f,d,e.,2c,2d,e.,f,g.,e,g,f,2e,f,d,c.,g,c6,b,a,g,g.,e,g,f,e,f,d,e,g,c,b,a,g,g,e,g,f,e,f,d,e,g,c,b,a,g,g"};//
const unsigned char Melody3[] = {"16g,16g,f,g,d6,eb,8g.,16g,a,g,d6,2c6,8g.,16g,g6,e6,c6,b,a,8f6.,16f6,e6,c6,d6,2c6,8g.,16g,a,g,c6,2b,8g.,16g,a,g,d6,2c6,8g.,16g,g6,e6,c6,b,a,8f6.,16f6,e6,c6,d6,2c6"};
// Definicion de las estructuras, aca es donde estan los valores de beat,duration, y a que array apunta
struct Melody MelodyA = {Melody1,220,1,5};
struct Melody MelodyB = {Melody2,200,4,5};
struct Melody MelodyC = {Melody3,150,4,5};
struct Melody * Melody[3] = {MelodyA,MelodyB,MelodyC};
#define TONE GPIObits.GP2
void InitTimer(void);
//void delayms(unsigned char cnt);
void PlayNote(unsigned short note, unsigned char octave, unsigned int duration);
unsigned char beep;
unsigned char preloadTMR1L;
unsigned char preloadTMR1H;
unsigned short TMR0Count;
unsigned char beat_speed;
//#define MusicBoxDancer
//#define HomeSweetHome
//#define HappyBirthday
void main(void)
{
/* Loop */
while(1)
{
unsigned int pointer = 0;
unsigned int octave = 0;
unsigned int duration = 0;
unsigned short note = 0;
unsigned int defaultoctave = 0;
unsigned int defaultduration = 0;
TRISIO = 0;
GPIO = 0;
beep = 0;
InitTimer();
PEIE = 1;
GIE = 1; /* Enable General Purpose Interrupts */
do {
octave = defaultoctave; /* Set Default Octave */
if ((Melody[pointer] == '3') && (Melody[pointer+1] == '2')) {
duration = 32;
pointer += 2;
}
else if ((Melody[pointer] == '1') && (Melody[pointer+1] == '6')) {
duration = 16;
pointer += 2;
}
else if (Melody[pointer] == '8') {
duration = 8;
pointer++;
}
else if (Melody[pointer] == '4') {
duration = 4;
pointer++;
}
else if (Melody[pointer] == '2') {
duration = 2;
pointer++;
}
else if (Melody[pointer] == '1') {
duration = 1;
pointer++;
} else duration = defaultduration;
if (Melody[pointer + 1] == '#') {
/* Process Sharps */
switch (Melody[pointer]) {
case 'c' : note = 3608;//2146;
break;
case 'd' : note = 3214;//1805;
break;
case 'f' : note = 2725;//1608;
break;
case 'g' : note = 2408;//1351;
break;
case 'a' : note = 2145;//1205;
break;
}
pointer +=2;
} else {
switch (Melody[pointer]) {
case 'c' : note = 3822;//2273;
break;
case 'd' : note = 3405;//2024;
break;
case 'e' : note = 3034;//1912;
break;
case 'f' : note = 2863;//1704;
break;
case 'g' : note = 2551;//1517;
break;
case 'a' : note = 2273;//1433;
break;
case 'b' : note = 2025;//1275;
break;
case 'p' : note = 0;
break;
}
pointer++;
}
if (Melody[pointer] == '.') {
/* Duration 1.5x */
duration = duration + 128;
pointer++;
}
if (Melody[pointer] == '4') {
octave = 4;
pointer++;
} else if (Melody[pointer] == '5') {
octave = 5;
pointer++;
} else if (Melody[pointer] == '6') {
octave = 6;
pointer++;
} else if (Melody[pointer] == '7') {
octave = 7;
pointer++;
}
if (Melody[pointer] == '.') {
/* Duration 1.5x */
duration = duration + 128;
pointer++;
}
PlayNote(note, octave, duration);
} while (Melody[pointer++] == ',');
/* Wait until last note has played */
while(TMR0Count) { };
beep = 0;
}
}
void PlayNote(unsigned short note, unsigned char octave, unsigned int duration)
{
/* Process octave */
switch (octave) {
case 4 : /* Do noting */
break;
case 5 : /* %2 */
note = note >> 1;
break;
case 6 : /* %4 */
note = note >> 2;
break;
case 7 : /* %8 */
note = note >> 4;
break;
}
/* Wait until last note has played */
while(TMR0Count) { };
beep = 0;
/* Process New Note Frequency */
if (note) {
note = ~note;
preloadTMR1L = (note & 0xFF);
preloadTMR1H = ((note & 0xFF00) >> 8);
}
/* Process Note Duration */
TMR0Count = 255/(duration & 0x7F);
/* If duration is 1.5x add .5 to duration */
if (duration & 0x80) TMR0Count = (TMR0Count + (TMR0Count >> 1));
if (note) beep = 1;
}