play songs

Dependencies:   mbed

main.cpp

Committer:
maclobdell
Date:
2016-05-12
Revision:
2:610196c7b41c
Parent:
1:8922cc02aec7
Child:
3:c04186a77ede

File content as of revision 2:610196c7b41c:

#include "mbed.h"       // this tells us to load mbed  related functions
#include "tones.h"      // list of all the tones and their frequencies
#include "rtos.h"       // using the rtos for timing features.  Just want to block the play_song function until it is time to play the next note.

PwmOut buzzer(D3);                   // our buzzer is a PWM output (pulse-width modulation)

static int BPM = 120;

static void silence() {
    buzzer.write(0.0f); // silence!
}

// this is our function that plays a tone. 
// Takes in a tone frequency, and after duration (in ms.) we stop playing again
static void play_tone(int tone) {
    buzzer.period_us(1000000/(tone));
    buzzer.write(0.10f); // 10% duty cycle, otherwise it's too loud
}

static void play_song(int notes_left, int* melody, int* duration) {
    
    // YOUR CODE HERE
    //REMOVE
    // melody and duration are pointers, they point to the array of tones and durations we declared earlier
// every time we play a note we up these pointers (move one element forward)
// so the current tone is always the first element of melody (same for duration)

int length;

while(notes_left > 0)
{

    int tone = melody[0];
    // BPM is quarter notes per minute, so length in milliseconds is:
    length = static_cast<int>(static_cast<float>(1000 / duration[0]) * (60000.0f / static_cast<float>(BPM * 1000)));

    play_tone(tone);
    
    // after half the length of this tone, we silence
    Thread::wait(length / 2);  //block this main thread until it is time to silence.  This lets other threads run.
    silence();

    //after the full length of this tone, call next note 
    Thread::wait(length); //block this main thread until it is time to play the next note.  This lets other threads run.
               
    // after the full length of this tone, we up the melody, and down the notes_left
    
    notes_left--;
    melody++;
    duration++;
        
}  

// we're done! just finish this note and silence
Thread::wait(length / 2);  //block this main thread until it is time to silence.  This lets other threads run.
silence();
    
    //END REMOVE    
}

// this code runs when the microcontroller starts up
int main() {

    // declare a melody
    int melody[] = {
        NOTE_G4, NOTE_G4, NOTE_G4, NOTE_DS3, NOTE_AS4, 
        NOTE_G4, NOTE_DS3, NOTE_AS4, NOTE_G4, 
        NOTE_D4, NOTE_D4, NOTE_D4, NOTE_DS4, NOTE_AS4, 
        NOTE_FS4, NOTE_DS4, NOTE_AS4, NOTE_G4 
    };
 
    // note durations: 4 = quarter note, 8 = eighth note, etc.:
    int duration[] = {
        2, 2, 2, 4, 4, 
        2, 4, 4, 1, 
        2, 2, 2, 4, 4, 
        2, 4, 4, 1 
    };    
    
    // melody & duration are on the heap, need to get them on the stack
    int *m = new int[sizeof(melody) / sizeof(int)];
    memcpy(m, melody, sizeof(melody));
    int *d = new int[sizeof(duration) / sizeof(int)];
    memcpy(d, duration, sizeof(duration));
    
    if (sizeof(melody) != sizeof(duration)) {
        printf("Melody and duration do not have same number of elements! Aborting!\r\n");
        return 1;
    }
    
    play_song(sizeof(melody) / sizeof(int), m, d);
    
    return 0;
}