void buzzer_play(note *notes) { /* Allow buzzer PWM output on P2.7 */ P2SEL |= BIT7; /* 0x000F is the "stop bit" */ while (PITCH(*notes) != 0x000F) { if (PITCH(*notes) == 0) { /* Stop the timer! We are playing a rest */ TA1CTL &= ~MC_3; } else { /* Set PWM frequency */ TA1CCR0 = base_notes[PITCH(*notes)] >> OCTAVE(*notes); /* Start the timer */ TA1CTL |= MC__UP; } /* Delay for DURATION(*notes) milliseconds, use LPM1 because we need SMCLK for tone generation */ timer0_delay(DURATION(*notes), LPM1_bits); /* Advance to the next note */ notes++; } /* Stop buzzer */ buzzer_stop(); }
void buzzer_callback() { /* Start by incrementing the counter; we are playing the next note * This is here because the index must atually point to the note * currently playing, so main knows if we can go to LPM3 */ buzzer_counter++; /* Here the -1 is needed for the offset of buzzer_counter due to the * increment above. */ note n = *(buzzer_buffer + buzzer_counter - 1); /* 0x000F is the "stop bit" */ if(PITCH(n) == 0) { /* Stop buzzer */ buzzer_stop(); return; } if (PITCH(n) == 0x000F) { /* Stop the timer! We are playing a rest */ TA1CTL &= ~MC_3; } else { /* Set PWM frequency */ TA1CCR0 = base_notes[PITCH(n)] >> OCTAVE(n); /* Start the timer */ TA1CTL |= MC__UP; } /* Delay for DURATION(*n) milliseconds, */ timer0_delay_callback(DURATION(n), &buzzer_callback); }
// Play a sequence of MelodyNotes // Sequence must terminate with octave == -1 void playMelody(prog_uint16_t* notes) { int i=0; while (true) { uint16_t melody_note = pgm_read_word_near(notes + i); i++; uint8_t duration = DURATION(melody_note); if (duration == 0) { // Silence the buzzer at the end, in case the sequence did not do so. playMidiNote(0, NOTE_SILENCE); return; } uint8_t octave = OCTAVE(melody_note); uint8_t note = NOTE(melody_note); playMidiNote(octave, note); // NOTE(mikey): Originally, we used the busy-loop _delay_ms method to avoid // tmr0. This was blowing up the program size as well. delay(duration); } }