DISCLAIMER: This project is what you would call a SMOP, a "simple matter of programming". That means it is of trivial complexity but lengthy... so unless you can tolerate boredom to the extent where it borders self-annihilation, you will find this painful to work on.
Knowledge of assembly language, basic electronics, and microcontrollers is assumed. This isn't simple, but it's not rocket surgery either.
The music box has 4 stages: Song storage, Sound generation, Amplification and Power.
It can produce a full 8 octaves of square wave music, that's just under 100 notes on a logarithmic scale from 5 kilohertz to just under 20 hertz. The quality is approximately that of old game consoles or the very first midi sound cards.
There isn't that much to describe. It accepts parallel port input through PORTB, and outputs a variable frequency square wave on PORTA, PIN1. Runs on a attiny26l-8pu, at 1Mhz. Doubling clock speed raises notes an octave higher, useful if you've made a miscalculation, like I did (I doubled it to 2Mhz, the final song sounded much better).
Low power consumption and simplicity were paramount in this project, that is why I didn't design some sort of serial/parallel DAC to give me proper sine wave output. I also wasn't willing to trash an mp3 player (the other design option for this project) for something I could do adequately with 10$ worth of parts.
It is designed such that a second AVR sits right next to it, and contains the song information.
An atmega16 @4Mhz sends 8-bit numbers out it's PORTA for set durations, each number corresponding to a note on the other AVR... basically the simplest possible sound format, there's not even volume control right now, but if I did add it I would use PORTB on the "song info" chip to give me 8 levels of volume, each pin raised high would cause the "song interpreter" chip to use an additional pin as output. They'd all connect to an opamp through a resistor network, such that more pins--> more voltage on the amp input.
I originally used another attiny26l-8pu for song storage, but the memory (2k) was not sufficient for the song of 313 notes (~2800 lines of code). The only working chip I had lying about unused was an atmega16.
A two stage amplifier was constructed using 2x N2222 NPN transistors (darlington pair). It sends output to a piezo buzzer. I noticed some buzzers worked, others did not... headphones/speakers always worked.
Deep magic: if you connect pin0, port A to the base of the first transistor in the darlington pair, you get audio output. If you ALSO connect pin7 to the first stage of the darlington pair, the ouput becomes VERY LOUD. I suspect I accidentally defined pin 7 as the output in the source... but the darlington pair is sensitive enough to pick up some leakage somewhere and it still works fine but a little quietly. I ended up connecting the first stage of the darlington pair to pin0, and the second stage to both the output of the first stage and PIN7. This produced the optimal volume for my purposes. See edit in the first source code file, near the start.
Nothing fancy here. A 9v battery and a TL780 voltage regulator.