Here is another weekend hack that plays around with my midi to AVR conversion script and library. With xmas fast approaching I thought it would be fun to convert a pacman candy tin to an xmas ornament and have it play music. Below is the result, pressing a button on the tin will cycle through three Ms. Pacman songs converted from midi files found online.

Construction

Once I had the circuit working on a breadboard it was just a matter of finding a prototype board that fit and some ugly soldering to glue it all together. In my case I had these parts lying around (including the tin) but if you wanted to buy everything it would cost between $5-$10.

Other materials..

The circuit is only slightly more complicated than the musical greeting card. Two 1K potentiometers are used to mix the two square waves into one speaker. The push switch is connected to the external interrupt pin which is set low when pressed. On the prototype board the switch is wired on the opposite side of the circuit so that the speaker faces down when placed in the candy tin. This makes it louder by drilling holes in the back piece (see below). Standoffs are used to prop up the non-speaker side of the circuit.

Nothing is needed to hold the the circuit board in the tin since the button keeps it in place and there isn’t a lot of extra room when it is put together.

Software

(for more on the PlayTune library see my earlier post on using the PlayTune library with an Arduino)

Like the musical greeting card we will use the PlayTune library to play the melody and the xml2h.py to handle the musical conversion. The conversion takes a single track and converts it into two byte arrays of pitches and delays. The pitch values are a function of clock frequency and the prescaler.

The total size of the program ends up being around 2k so there is plenty of room to add more songs if you are inclined.

I used three midi files for the songs and loaded them into musescore. In the application it was necessary to transpose it an octave, other than that there wasn’t much else to do since these songs are already two-tracks which is exactly what we want for the attiny.

After saving the midi file as a MusicXML file a header file is created for each song. These header files are what the PlayTune library uses for tone and delay values.

The prescale values scale the frequency of the clock by a power of 2. Ideally you want the lowest value given in the list though TIMER0 only supports values of 1024, 256, 64 and 8 so for the first part “64″ is chosen.
For TIMER1 (part2) the lowest number can be selected to give the highest timer resolution. The reason this is important is because the frequency of the square waves generated on the two microcontroller pins are only an approximation of the note frequency. Higher frequency == greater timer resolution == better pitch accuracy.

The AVR is immediatly put into power-down sleep mode. When an external level change on the INT0 pin is detected (button press) the ISR routine will run which will play one of the three tunes.


#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "playtune.h"
#include "songs/mspacman-acti-they-meet-attiny.h"
#include "songs/mspacman-game-start-attiny.h"
#include "songs/mspacman-actii-the-chase-attiny.h"

int main(void)
{
    // setup interrupt
    GIMSK |= (1<<INT0); // INT0 enabled for interrupts
    while(1) {
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        sleep_mode();
    }
    return(0);
}

volatile uint8_t tune = 0;
ISR (INT0_vect)
{
    PlayTune theymeet0(0,MSPACMAN_ACTI_THEY_MEET0);
    PlayTune theymeet1(1,MSPACMAN_ACTI_THEY_MEET1);
    PlayTune gamestart0(0,MSPACMAN_GAME_START0);
    PlayTune gamestart1(1,MSPACMAN_GAME_START1);
    PlayTune thechase0(0,MSPACMAN_ACTII_THE_CHASE0);
    PlayTune thechase1(1,MSPACMAN_ACTII_THE_CHASE1);

    switch(tune) {

        case 1:
            while ( theymeet0.isPlaying() || theymeet1.isPlaying() ) {

                theymeet0.playNote();
                theymeet1.playNote();
                _delay_ms(65);
            }
            break;
        case 2:
            while ( gamestart0.isPlaying() || gamestart1.isPlaying() ) {
                gamestart0.playNote();
                gamestart1.playNote();
                _delay_ms(15);
            }
            break;

        case 3:
            while ( thechase0.isPlaying() || thechase1.isPlaying() ) {

                thechase0.playNote();
                thechase1.playNote();
                _delay_ms(65);
            }
            break;
    }

    if (tune == 3) {
        tune = 1;
    } else {
        tune++;
    }
}



3 Responses to “Musical Ms. Pacman Candy Tin Hack”

  1. You are just tooooo clever…I really appreciate your expertise. I could never follow the instructions…I would love to make music tins using other music…I have an old Elvis tin …got any Ideas for an already assembled music gadget?…If it’s together I can install it….
    Blessins,
    Madonna B.

  2. 2 Chris N.

    This is a really neat project that I’ve tried to replicate myself, but I’m running into an issue with the songs. They play very low pitched and slow. I’m using the same chip that you listed above, but i can’t seem to get it to play at normal speed. Any idea what’s wrong?

    • 3 jarv

      That usually means the internal oscillator is not set to 8MHz, did you check the fuse bits?