Introduction: Poor Man's AVR Music Box

About: I publish my failures and my successes, as my teachers have done before me. I am a member of Foulab, an independent, nonprofit research and engineering group in Montreal. Check out our webpage at www.foul…

This is a simple AVR music box, costing about 10$ to build.

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.

Sound generation:

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.

Song Storage:

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.

Amplification:

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.

Power:

Nothing fancy here. A 9v battery and a TL780 voltage regulator.

Step 1: Source Code, Sound Generation

START:
.INCLUDE "tn26def.inc"
clr r23
clr r24
clr r25
clr r26
clr r27
clr r28
clr r29
clr r30
clr r31
ldi r25, 0b10000000 ;here is where I defined the wrong output pin... It shoud be
ldi r26, 0b00000000 ; 0b00000001 I think. Just use 0b11111111 for testing if unsure.
out DDRA, r25
nop
out PORTA, r26
nop
out DDRB, r26
nop
INPUT:
;96 notes possible, plus silence (zero)
out PORTA, r26 ;Silence if no input
nop
in r28, PINB
mov r31, r28
cpi r28, 0b00000000
breq INPUT

D8S:
;5.1khz
cpi r28, 0b00000001
brne D8
ldi r29, 0b00010000
ldi r30, 0b00000001

D8:
;4.63khz
cpi r28, 0b00000010
brne C8S
ldi r29, 0b00010010
ldi r30, 0b00000001

C8S:
;4.42khz
cpi r28, 0b00000011
brne C8
ldi r29, 0b00010011
ldi r30, 0b00000001

C8:
;4.24khz
cpi r28, 0b00000100
brne B7
ldi r29, 0b00010100
ldi r30, 0b00000001
rjmp B7

INPUT91:
rjmp INPUT

B7:
;3.91khz
cpi r28, 0b00000101
brne A7S
ldi r29, 0b00010110
ldi r30, 0b00000001

A7S:
;3.70khz
cpi r28, 0b00000110
brne A7
ldi r29, 0b00010111
ldi r30, 0b00000001

A7:
;3.57khz
cpi r28, 0b00000111
brne G7
ldi r29, 0b00011001
ldi r30, 0b00000001

G7:
;3.13khz
cpi r28, 0b00001000
brne F7S
ldi r29, 0b00011010
ldi r30, 0b00000001

F7S:
;2.94khz
cpi r28, 0b00001001
brne F7
ldi r29, 0b00011110
ldi r30, 0b00000001

F7:
;2.78khz
cpi r28, 0b00001010
brne E7
ldi r29, 0b00100000
ldi r30, 0b00000001

E7:
;2.63khz
cpi r28, 0b00001011
brne D7S
ldi r29, 0b00100010
ldi r30, 0b00000001

D7S:
;2.50khz
cpi r28, 0b00001100
brne D7
ldi r29, 0b00100101
ldi r30, 0b00000001

D7:
;2.33khz
cpi r28, 0b00001101
brne C7S
ldi r29, 0b00100111
ldi r30, 0b00000001

C7S:
;2.22khz
cpi r28, 0b00001110
brne C7
ldi r29, 0b00101010
ldi r30, 0b00000001

C7:
;2.08khz
cpi r28, 0b00001111
brne B6
ldi r29, 0b00101100
ldi r30, 0b00000001
rjmp B6

INPUT92:
rjmp INPUT91

B6:
;1.96khz
cpi r28, 0b00010000
brne A6S
ldi r29, 0b00101111
ldi r30, 0b00000001

A6S:
;1.85khz
cpi r28, 0b00010001
brne A6
ldi r29, 0b00110010
ldi r30, 0b00000001

A6:
;1.75khz
cpi r28, 0b00010010
brne G6S
ldi r29, 0b00110101
ldi r30, 0b00000001

G6S:
;1.67khz
cpi r28, 0b00010011
brne G6
ldi r29, 0b00111001
ldi r30, 0b00000001

G6:
;1.56khz
cpi r28, 0b00010100
brne F6S
ldi r29, 0b00111100
ldi r30, 0b00000001

F6S:
;1.47khz
cpi r28, 0b00010101
brne F6
ldi r29, 0b01000000
ldi r30, 0b00000001

F6:
;1.39khz
cpi r28, 0b00010110
brne E6
ldi r29, 0b01000100
ldi r30, 0b00000001

E6:
;1.32khz
cpi r28, 0b00010111
brne D6S
ldi r29, 0b01001000
ldi r30, 0b00000001

D6S:
;1.25khz
cpi r28, 0b00011000
brne D6
ldi r29, 0b01001101
ldi r30, 0b00000001

D6:
;1.18khz
cpi r28, 0b00011001
brne C6S
ldi r29, 0b01010010
ldi r30, 0b00000001

C6S:
;1.11khz
cpi r28, 0b00011010
brne C6
ldi r29, 0b01010111
ldi r30, 0b00000001

C6:
;1.04khz
cpi r28, 0b00011011
brne B5
ldi r29, 0b01011100
ldi r30, 0b00000001
rjmp B5

INPUT93:
rjmp INPUT92

B5:
;990Hz
cpi r28, 0b00011100
brne A5S
ldi r29, 0b01100010
ldi r30, 0b00000001

A5S:
;935Hz
cpi r28, 0b00011101
brne A5
ldi r29, 0b01101000
ldi r30, 0b00000001

A5:
;877Hz
cpi r28, 0b00011110
brne G5S
ldi r29, 0b01101110
ldi r30, 0b00000001

G5S:
;833Hz
cpi r28, 0b00011111
brne G5
ldi r29, 0b01110101
ldi r30, 0b00000001

G5:
;781Hz
cpi r28, 0b00100000
brne F5S
ldi r29, 0b01111100
ldi r30, 0b00000001

F5S:
;741Hz
cpi r28, 0b00100001
brne F5
ldi r29, 0b10000100
ldi r30, 0b00000001

F5:
;699Hz
cpi r28, 0b00100010
brne E5
ldi r29, 0b10001100
ldi r30, 0b00000001

E5:
;658Hz
cpi r28, 0b00100011
brne D5S
ldi r29, 0b10010100
ldi r30, 0b00000001

D5S:
;621Hz
cpi r28, 0b00100100
brne D5
ldi r29, 0b10011101
ldi r30, 0b00000001

D5:
;588Hz
cpi r28, 0b00100101
brne C5S
ldi r29, 0b10100111
ldi r30, 0b00000001

C5S:
;555Hz
cpi r28, 0b00100110
brne C5
ldi r29, 0b10110001
ldi r30, 0b00000001

C5:
;524Hz
cpi r28, 0b00100111
brne B4
ldi r29, 0b10111100
ldi r30, 0b00000001
rjmp B4

INPUT94:
rjmp INPUT93

B4:
;
cpi r28, 0b00101000
brne A4S
ldi r29, 0b11000111
ldi r30, 0b00000001

A4S:
;
cpi r28, 0b00101001
brne A4
ldi r29, 0b11010011
ldi r30, 0b00000001

A4:
;
cpi r28, 0b00101010
brne G4S
ldi r29, 0b11100000
ldi r30, 0b00000001

G4S:
;
cpi r28, 0b00101011
brne G4
ldi r29, 0b11101101
ldi r30, 0b00000001

G4:
;
cpi r28, 0b00101100
brne F4S
ldi r29, 0b11111100
ldi r30, 0b00000001

F4S:
;
cpi r28, 0b00101101
brne F4
ldi r29, 0b00101011
ldi r30, 0b00000101

F4:
;
cpi r28, 0b00101110
brne E4
ldi r29, 0b00101101
ldi r30, 0b00000101

E4:
;
cpi r28, 0b00101111
brne D4S
ldi r29, 0b00110000
ldi r30, 0b00000101

D4S:
;
cpi r28, 0b00110000
brne D4
ldi r29, 0b00110011
ldi r30, 0b00000101

D4:
;
cpi r28, 0b00110001
brne C4S
ldi r29, 0b00110110
ldi r30, 0b00000101

C4S:
;
cpi r28, 0b00110010
brne C4
ldi r29, 0b00111010
ldi r30, 0b00000101

C4:
;
cpi r28, 0b00110011
brne B3
ldi r29, 0b00111101
ldi r30, 0b00000101
rjmp B3

INPUT95:
rjmp INPUT94

B3:
;
cpi r28, 0b00110100
brne A3S
ldi r29, 0b01000001
ldi r30, 0b00000101

A3S:
;
cpi r28, 0b00110101
brne A3
ldi r29, 0b01000101
ldi r30, 0b00000101

A3:
;
cpi r28, 0b00110110
brne G3S
ldi r29, 0b01001001
ldi r30, 0b00000101

G3S:
;
cpi r28, 0b00110111
brne G3
ldi r29, 0b01001110
ldi r30, 0b00000101

G3:
;
cpi r28, 0b00111000
brne F3S
ldi r29, 0b01010011
ldi r30, 0b00000101

F3S:
;
cpi r28, 0b00111001
brne F3
ldi r29, 0b01011000
ldi r30, 0b00000101

F3:
;
cpi r28, 0b00111010
brne E3
ldi r29, 0b01011101
ldi r30, 0b00000101

E3:
;
cpi r28, 0b00111011
brne D3S
ldi r29, 0b01100011
ldi r30, 0b00000101

D3S:
;
cpi r28, 0b00111100
brne D3
ldi r29, 0b01101000
ldi r30, 0b00000101

D3:
;
cpi r28, 0b00111101
brne C3S
ldi r29, 0b01101111
ldi r30, 0b00000101

C3S:
;
cpi r28, 0b00111110
brne C3
ldi r29, 0b01110101
ldi r30, 0b00000101

C3:
;
cpi r28, 0b01111111
brne B2
ldi r29, 0b01111101
ldi r30, 0b00000101
rjmp B2

INPUT96:
rjmp INPUT95

B2:
;
cpi r28, 0b01000000
brne A2S
ldi r29, 0b10000101
ldi r30, 0b00000101

A2S:
;
cpi r28, 0b01000001
brne A2
ldi r29, 0b10001101
ldi r30, 0b00000101

A2:
;
cpi r28, 0b01000010
brne G2S
ldi r29, 0b10010101
ldi r30, 0b00000101

G2S:
;
cpi r28, 0b01000011
brne G2
ldi r29, 0b10011110
ldi r30, 0b00000101

G2:
;
cpi r28, 0b01000100
brne F2S
ldi r29, 0b10101000
ldi r30, 0b00000101

F2S:
;
cpi r28, 0b01000101
brne F2
ldi r29, 0b10110010
ldi r30, 0b00000101

F2:
;
cpi r28, 0b01000110
brne E2
ldi r29, 0b10111100
ldi r30, 0b00000101

E2:
;
cpi r28, 0b01000111
brne D2S
ldi r29, 0b11001000
ldi r30, 0b00000101

D2S:
;
cpi r28, 0b01001000
brne D2
ldi r29, 0b11010100
ldi r30, 0b00000101

D2:
;
cpi r28, 0b01001001
brne C2S
ldi r29, 0b11100001
ldi r30, 0b00000101

C2S:
;
cpi r28, 0b01001010
brne C2
ldi r29, 0b11101110
ldi r30, 0b00000101

C2:
;
cpi r28, 0b01001011
brne B1
ldi r29, 0b11111100
ldi r30, 0b00000101
rjmp B1

INPUT97:
rjmp INPUT96

B1:
;
cpi r28, 0b01001011
brne A1S
ldi r29, 0b00111111
ldi r30, 0b00011001

A1S:
;
cpi r28, 0b01001100
brne A1
ldi r29, 0b01000010
ldi r30, 0b00011001

A1:
;
cpi r28, 0b01001101
brne G1S
ldi r29, 0b01000110
ldi r30, 0b00011001

G1S:
;
cpi r28, 0b01001110
brne G1
ldi r29, 0b01001011
ldi r30, 0b00011001

G1:
;
cpi r28, 0b01001111
brne F1S
ldi r29, 0b01001111
ldi r30, 0b00011001

F1S:
;
cpi r28, 0b01010000
brne F1
ldi r29, 0b01010100
ldi r30, 0b00011001

F1:
;
cpi r28, 0b01010001
brne E1
ldi r29, 0b01011001
ldi r30, 0b00011001

E1:
;
cpi r28, 0b01010010
brne D1S
ldi r29, 0b01011111
ldi r30, 0b00011001

D1S:
;
cpi r28, 0b01010011
brne D1
ldi r29, 0b01100101
ldi r30, 0b00011001

D1:
;
cpi r28, 0b01010100
brne C1S
ldi r29, 0b01101011
ldi r30, 0b00011001

C1S:
;
cpi r28, 0b01010101
brne C1
ldi r29, 0b01110001
ldi r30, 0b00011001

C1:
;
cpi r28, 0b01010110
brne B0
ldi r29, 0b01111000
ldi r30, 0b00011001
rjmp B0

INPUT98:
rjmp INPUT97

B0:
;
cpi r28, 0b01010111
brne A0S
ldi r29, 0b01111111
ldi r30, 0b00011001

A0S:
;
cpi r28, 0b01011000
brne A0
ldi r29, 0b10000111
ldi r30, 0b00011001

A0:
;
cpi r28, 0b01011001
brne G0S
ldi r29, 0b10001111
ldi r30, 0b00011001

G0S:
;
cpi r28, 0b01011010
brne G0
ldi r29, 0b10011000
ldi r30, 0b00011001

G0:
;
cpi r28, 0b01011011
brne F0S
ldi r29, 0b10100001
ldi r30, 0b00011001

F0S:
;
cpi r28, 0b01011100
brne F0
ldi r29, 0b10101011
ldi r30, 0b00011001

F0:
;
cpi r28, 0b01011101
brne E0
ldi r29, 0b10110101
ldi r30, 0b00011001

E0:
;
cpi r28, 0b01011110
brne D0S
ldi r29, 0b11000000
ldi r30, 0b00011001

D0S:
;
cpi r28, 0b01011111
brne D0
ldi r29, 0b11001011
ldi r30, 0b00011001

D0:
;
cpi r28, 0b01100000
brne C0S
ldi r29, 0b11011000
ldi r30, 0b00011001

C0S:
;
cpi r28, 0b01100001
brne C0
ldi r29, 0b11100101
ldi r30, 0b00011001

C0:
;
cpi r28, 0b01100010
brne hi
ldi r29, 0b11110010
ldi r30, 0b00011001
rjmp hi

INPUT99:
rjmp INPUT98

hi:
out PORTA, r25
clr r27
nop ;To compensate for INPUT1 function, making hi/lo equal lengths
nop
nop
nop
nop

TIMER0h: ;5 cpu cycles per count
inc r24
nop
cp r24,r29
brne TIMER0h
rjmp TIMER1h

TIMER1h: ;6 cpu cycles per count
clr r24
inc r27
cp r27, r30
nop
brne TIMER0h
rjmp lo

lo:
out PORTA, r26
clr r27

TIMER0l: ;5 cpu cycles per count
inc r24
nop
cp r24,r29
brne TIMER0l
rjmp TIMER1l

TIMER1l: ;6 cpu cycles per count
inc r27
nop
clr r24
cp r27,r30
brne TIMER0l
rjmp INPUT1

INPUT1: ;Check to see if input has changed, if not, continue output
in r28,PINB ;5 cycles in this function
cp r28, r31
brne INPUT99
rjmp hi

Step 2: Source Code Explained

The program flows as follows:

Start:
Clear registers
Set data direction on ports of interest

Loop0:
if no input, produce no output
if input, continue

Note0:
is input=note0?
if so, load values into timer registers that let the output functions produce the correct square wave frequency
if not, continue

(Produce a NoteX loop for every possible note over 8 octaves)

Hi:
raise output high (1)

timerhi:
defines how long the output stays high

lo:
Render output to low (0)

timerlo:
defines how long the output stays low (0)

input:
check to see if the input has changed
if so, use dirty tricks to get back to loop0
if not, go to hi

There are many "rjmp islands" that let the program return to the start... this microcontroller does not support the jmp opcode, and rjmp can only bring you to a function within a distance of a certain number of instructions. We solve this by "seeding" the program with rjmp statements that are skipped on the way "down" to program, but can be used to climb back up to the program start.

BUG WARNING: Somewhere 3/4 the way down the scale, there is a cluster of a few (3-4) notes that aren't quite right. Out of the 3 values used for r30, I suspect the highest one used is incorrect (too low), I probably miscalculated the number of clock cycles somewhere, or perhaps put a wrong value for r29 somewhere... I'm just going to work around it, fix it if you like (and tell me where the mistake was!)

INEFFICIENCY WARNING: I know, I could have just used PWM and some EEPROM table, but by the time I thought of it, it was already working this way.

Step 3: Song Storage Source Code

START:
.INCLUDE "m16def.inc"
ldi r16, (1<out TCCR0, r16
ldi r21, 0xFF
out DDRA, r21
ldi r19, 0b00000001
clr r20
clr r23

timer1:
in r17, TIFR
cpi r17, 0b00000001
breq clr0
cpi r17, 0b00000011
breq clr0
rjmp timer1

clr0:
ldi r16, (1<
out TIFR, r16


loop1:
inc r18
cp r18,r19
breq incnote
rjmp timer1


incnote: ;note# stored in r20,and r23. Note length in r19, note pitch in r22
cpi r20, 0xFF
breq incnote2
inc r20
rjmp song

incnote2: ;This allows the song to be up to 512 notes long
inc r23 ;If I used both registers in the other way, it would allow for 65k notes,
; but would increase program complexity a bit, and more importantly, execution time.
song:

clr r18

n1:
cpi r20,0x01 ;Start with some silence silence between song loops
brne n2
ldi r19, 0x40
ldi r22, 0x00
out PORTA, r22
rjmp n2

bogo2:
rjmp timer1

n2:
cpi r20,0x02 ;Start with some silence silence between song loops
brne n3
ldi r19, 0x20
ldi r22, 0x00
out PORTA, r22
rjmp n3

n3:
cpi r20,0x03 ;a3, 250msec
brne n4
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n4:
cpi r20,0x04 ;b3, 250msec
brne n5
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n5:
cpi r20,0x05 ;c4, 250msec
brne n6
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n6:
cpi r20,0x06 ;e3, 250msec
brne n7
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n7:
cpi r20,0x07 ;c4, 250msec
brne n8
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n8:
cpi r20,0x08 ;e3, 250msec
brne n9
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n9:
cpi r20,0x09 ;c4, 250msec
brne n10
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22
rjmp n10

bogo3:
rjmp bogo2

n10:
cpi r20,0x0A ;e3, 250msec
brne n11
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n11:
cpi r20,0x0B ;c4, 250msec
brne n12
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n12:
cpi r20,0x0C ;e3, 250msec
brne n13
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n13:
cpi r20,0x0D ;d4, 250msec
brne n14
ldi r19, 0x19
ldi r22, 0b00110001
out PORTA, r22

n14:
cpi r20,0x0D ;e3, 250msec
brne n15
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n15:
cpi r20,0x0E ;c4, 250msec
brne n16
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n16:
cpi r20,0x0F ;e3, 250msec
brne n17
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n17:
cpi r20,0x19 ;b3, 250msec
brne n18
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n18:
cpi r20,0x11 ;e3, 250msec
brne n19
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22
rjmp n19

bogo4:
rjmp bogo3

n19:
cpi r20,0x12 ;b3, 250msec
brne n20
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n20:
cpi r20,0x13 ;e3, 250msec
brne n21
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n21:
cpi r20,0x14 ;b3, 130msec
brne n22
ldi r19, 0x0D
ldi r22, 0b00110100
out PORTA, r22

n22:
cpi r20,0x15 ;e3, 130msec
brne n23
ldi r19, 0x0C
ldi r22, 0b00111011
out PORTA, r22

n23:
cpi r20,0x16 ;b3, 250msec
brne n24
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n24:
cpi r20,0x17 ;e3, 250msec
brne n25
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n25:
cpi r20,0x18 ;c4, 250msec
brne n26
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n26:
cpi r20,0x19 ;e3, 250msec
brne n27
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n27:
cpi r20,0x1A ;b3, 250msec
brne n28
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n28:
cpi r20,0x1B ;e3, 380msec
brne n29
ldi r19, 0x26
ldi r22, 0b00111011
out PORTA, r22

n29:
cpi r20,0x1C ;a3, 260msec
brne n30
ldi r19, 0x1A
ldi r22, 0b00110110
out PORTA, r22
rjmp n30

bogo5:
rjmp bogo4

n30:
cpi r20,0x1D ;rest, 30msec
brne n31
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n31:
cpi r20,0x1E ;a3, 20msec
brne n32
ldi r19, 0x04
ldi r22, 0b00110110
out PORTA, r22

n32:
cpi r20,0x1F ;rest, 20msec
brne n33
ldi r19, 0x04
ldi r22, 0b00000000
out PORTA, r22

n33:
cpi r20,0x20 ;b3, 30msec
brne n34
ldi r19, 0x05
ldi r22, 0b00110100
out PORTA, r22

n34:
cpi r20,0x21 ;rest, 30msec
brne n35
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n35:
cpi r20,0x22 ;a3, 280msec, two notes on decompiled midi...
brne n36
ldi r19, 0x1C
ldi r22, 0b00110110
out PORTA, r22

n36:
cpi r20,0x23 ;b3, 40msec
brne n37
ldi r19, 0x04
ldi r22, 0b00110100
out PORTA, r22

n37:
cpi r20,0x24 ;a3, 320msec, two notes on decompiled midi... now note# and row number are aligned
brne n38 ; on my spreadsheet. Before they weren't because of the two initial pauses.
ldi r19, 0x20 ; Convenient for me!
ldi r22, 0b00110110
out PORTA, r22

n38:
cpi r20,0x25 ;b3
brne n39
ldi r19, 0x07
ldi r22, 0b00110100
out PORTA, r22

n39:
cpi r20,0x26 ;a3
brne n40
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22
rjmp n40

bogo6:
rjmp bogo5

n40:
cpi r20,0x27 ;g3
brne n41
ldi r19, 0x19
ldi r22, 0b00111000
out PORTA, r22

n41:
cpi r20,0x28 ;e3
brne n42
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n42:
cpi r20,0x29 ;d3
brne n43
ldi r19, 0x19
ldi r22, 0b00111101
out PORTA, r22

n43:
cpi r20,0x2A ;e3
brne n44
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n44:
cpi r20,0x2B ;a3
brne n45
ldi r19, 0x36
ldi r22, 0b00110110
out PORTA, r22

n45:
cpi r20,0x2C ;b3
brne n46
ldi r19, 0x36
ldi r22, 0b00110100
out PORTA, r22

n46:
cpi r20,0x2D ;c4
brne n47
ldi r19, 0x26
ldi r22, 0b00110011
out PORTA, r22

n47:
cpi r20,0x2F ;e3
brne n48
ldi r19, 0x26
ldi r22, 0b00111011
out PORTA, r22

n48:
cpi r20,0x30 ;c4
brne n49
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n49:
cpi r20,0x31 ;e3
brne n50
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22
rjmp n50

bogo7:
rjmp bogo6

n50:
cpi r20,0x32 ;c4
brne n51
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n51:
cpi r20,0x33 ;e3
brne n52
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n52:
cpi r20,0x34 ;c4
brne n53
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n53:
cpi r20,0x35 ;e3
brne n54
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n54:
cpi r20,0x36 ;d4
brne n55
ldi r19, 0x19
ldi r22, 0b00110001
out PORTA, r22

n55:
cpi r20,0x37 ;e3
brne n56
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n56:
cpi r20,0x38 ;c4
brne n57
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n57:
cpi r20,0x39 ;e3
brne n58
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n58:
cpi r20,0x3A ;b3
brne n59
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n59:
cpi r20,0x3B ;e3
brne n60
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22
rjmp n60

bogo8:
rjmp bogo7

n60:
cpi r20,0x3C ;b3
brne n61
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n61:
cpi r20,0x3D ;e3
brne n62
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n62:
cpi r20,0x3E ;b3
brne n63
ldi r19, 0x0D
ldi r22, 0b00110100
out PORTA, r22

n63:
cpi r20,0x3F ;e3
brne n64
ldi r19, 0x0C
ldi r22, 0b00111011
out PORTA, r22

n64:
cpi r20,0x40 ;b3
brne n65
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n65:
cpi r20,0x41 ;null
brne n66
ldi r19, 0x06
ldi r22, 0b00000000
out PORTA, r22

n66:
cpi r20,0x42 ;e3
brne n67
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n67:
cpi r20,0x43 ;c4
brne n68
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n68:
cpi r20,0x44 ;e3
brne n69
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n69:
cpi r20,0x45 ;b3
brne n70
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22
rjmp n70

bogo9:
rjmp bogo8

n70:
cpi r20,0x46 ;e3
brne n71
ldi r19, 0x26
ldi r22, 0b00111011
out PORTA, r22

n71:
cpi r20,0x47 ;a3
brne n72
ldi r19, 0x1A
ldi r22, 0b00110110
out PORTA, r22

n72:
cpi r20,0x48 ;a3
brne n73
ldi r19, 0x04
ldi r22, 0b00110110
out PORTA, r22

n73:
cpi r20,0x49 ;b3
brne n74
ldi r19, 0x05
ldi r22, 0b00110100
out PORTA, r22

n74:
cpi r20,0x4A ;null
brne n75
ldi r19, 0x04
ldi r22, 0b00000000
out PORTA, r22

n75:
cpi r20,0x4B ;a3
brne n76
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n76:
cpi r20,0x4C ;a3
brne n77
ldi r19, 0x06
ldi r22, 0b00110110
out PORTA, r22

n77:
cpi r20,0x4D ;b3
brne n78
ldi r19, 0x06
ldi r22, 0b00110100
out PORTA, r22

n78:
cpi r20,0x4E ;a3
brne n79
ldi r19, 0x1A
ldi r22, 0b00110110
out PORTA, r22

n79:
cpi r20,0x4F ;null
brne n80
ldi r19, 0x0A
ldi r22, 0b00000000
out PORTA, r22
rjmp n80

bogo10:
rjmp bogo9

n80:
cpi r20,0x50 ;a3
brne n81
ldi r19, 0x08
ldi r22, 0b00110110
out PORTA, r22

n81:
cpi r20,0x51 ;b3
brne n82
ldi r19, 0x09
ldi r22, 0b00110100
out PORTA, r22

n82:
cpi r20,0x52 ;a3
brne n83
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22

n83:
cpi r20,0x53 ;g3
brne n84
ldi r19, 0x19
ldi r22, 0b00111000
out PORTA, r22

n84:
cpi r20,0x54 ;e3
brne n85
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n85:
cpi r20,0x55 ;d3
brne n86
ldi r19, 0x40
ldi r22, 0b00111101
out PORTA, r22

n86:
cpi r20,0x56 ;e3
brne n87
ldi r19, 0x40
ldi r22, 0b00111011
out PORTA, r22

n87:
cpi r20,0x57 ;a3
brne n88
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n88:
cpi r20,0x58 ;b3
brne n89
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n89:
cpi r20,0x59 ;c4
brne n90
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22
rjmp n90

bogo11:
rjmp bogo10

n90:
cpi r20,0x5A ;e3
brne n91
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n91:
cpi r20,0x5B ;c4
brne n92
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n92:
cpi r20,0x5C ;e3
brne n93
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n93:
cpi r20,0x5D ;c4
brne n93b
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n93b:
cpi r20,0x5E ;e3
brne n94
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n94:
cpi r20,0x5F ;e3
brne n95
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n95:
cpi r20,0x60 ;c4
brne n96
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n96:
cpi r20,0x61 ;e3
brne n97
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n97:
cpi r20,0x62 ;d4
brne n98
ldi r19, 0x19
ldi r22, 0b00110001
out PORTA, r22

n98:
cpi r20,0x63 ;e3
brne n99
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n99:
cpi r20,0x64 ;c4
brne n100
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22
rjmp n100

bogo12:
rjmp bogo11

n100:
cpi r20,0x65 ;e3
brne n101
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n101:
cpi r20,0x66 ;b3
brne n102
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n102:
cpi r20,0x67 ;e3
brne n103
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n103:
cpi r20,0x68 ;b3
brne n104
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n104:
cpi r20,0x69 ;e3
brne n105
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n105:
cpi r20,0x6A ;b3
brne n106
ldi r19, 0x0D
ldi r22, 0b00110100
out PORTA, r22

n106:
cpi r20,0x6B ;e3
brne n107
ldi r19, 0x0C
ldi r22, 0b00111011
out PORTA, r22

n107:
cpi r20,0x6C ;b3
brne n108
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n108:
cpi r20,0x6D ;e3
brne n109
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n109:
cpi r20,0x6E ;c4
brne n110
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22
rjmp n110

bogo13:
rjmp bogo12

n110:
cpi r20,0x6F ;e3
brne n111
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n111:
cpi r20,0x70 ;b3
brne n112
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n112:
cpi r20,0x71 ;e3
brne n113
ldi r19, 0x26
ldi r22, 0b00111011
out PORTA, r22

n113:
cpi r20,0x72 ;a3
brne n114
ldi r19, 0x1A
ldi r22, 0b00110110
out PORTA, r22

n114:
cpi r20,0x73 ;a3
brne n115
ldi r19, 0x05
ldi r22, 0b00110110
out PORTA, r22

n115:
cpi r20,0x74 ;null
brne n116
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n116:
cpi r20,0x75 ;b3
brne n117
ldi r19, 0x06
ldi r22, 0b00110100
out PORTA, r22

n117:
cpi r20,0x76 ;a3
brne n118
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n118:
cpi r20,0x77 ;a3
brne n119
ldi r19, 0x07
ldi r22, 0b00110110
out PORTA, r22

n119:
cpi r20,0x78 ;b3
brne n120
ldi r19, 0x07
ldi r22, 0b00110100
out PORTA, r22
rjmp n120

bogo14:
rjmp bogo13

n120:
cpi r20,0x79 ;a3
brne n121
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n121:
cpi r20,0x7A ;a3
brne n122
ldi r19, 0x08
ldi r22, 0b00110110
out PORTA, r22

n122:
cpi r20,0x7B ;null
brne n123
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n123:
cpi r20,0x7C ;b3
brne n124
ldi r19, 0x08
ldi r22, 0b00110100
out PORTA, r22

n124:
cpi r20,0x7D ;a3
brne n125
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22

n125:
cpi r20,0x7E ;g3
brne n126
ldi r19, 0x05
ldi r22, 0b00111000
out PORTA, r22

n126:
cpi r20,0x7F ;e3
brne n127
ldi r19, 0x19
ldi r22, 0b00111011
out PORTA, r22

n127:
cpi r20,0x80 ;g3
brne n128
ldi r19, 0x19
ldi r22, 0b00111000
out PORTA, r22

n128:
cpi r20,0x81 ;a3
brne n129
ldi r19, 0x4A
ldi r22, 0b00110110
out PORTA, r22

n129:
cpi r20,0x82 ;a3
brne n130
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22
rjmp n130

bogo15:
rjmp bogo14

n130:
cpi r20,0x83 ;null
brne n131
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n131:
cpi r20,0x84 ;b3
brne n132
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n132:
cpi r20,0x85 ;null
brne n133
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n133:
cpi r20,0x86 ;c4
brne n134
ldi r19, 0x4D
ldi r22, 0b00110011
out PORTA, r22

n134:
cpi r20,0x87 ;d4
brne n135
ldi r19, 0x0C
ldi r22, 0b00110001
out PORTA, r22

n135:
cpi r20,0x88 ;c4
brne n136
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22

n136:
cpi r20,0x89 ;b3
brne n137
ldi r19, 0x4D
ldi r22, 0b00110100
out PORTA, r22

n137:
cpi r20,0x8A ;c4
brne n138
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22

n138:
cpi r20,0x8B ;b3
brne n139
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n139:
cpi r20,0x8C ;a3
brne n140
ldi r19, 0x40
ldi r22, 0b00110110
out PORTA, r22
rjmp n140

bogo16:
rjmp bogo15

n140:
cpi r20,0x8D ;null
brne n141
ldi r19, 0x08
ldi r22, 0b00000000
out PORTA, r22

n141:
cpi r20,0x8E ;null
brne n142
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n142:
cpi r20,0x8F ;b3
brne n143
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n143:
cpi r20,0x90 ;a3
brne n144
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22

n144:
cpi r20,0x91 ;g3
brne n145
ldi r19, 0x0C
ldi r22, 0b00111000
out PORTA, r22

n145:
cpi r20,0x92 ;null
brne n146
ldi r19, 0x03
ldi r22, 0b00000000
out PORTA, r22

n146:
cpi r20,0x93 ;e3
brne n147
ldi r19, 0x4D
ldi r22, 0b00111011
out PORTA, r22

n147:
cpi r20,0x94 ;a3
brne n148
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22

n148:
cpi r20,0x95 ;b3
brne n149
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n149:
cpi r20,0x96 ;c4
brne n150
ldi r19, 0x33
ldi r22, 0b00110011
out PORTA, r22
rjmp n150

bogo17:
rjmp bogo16

n150:
cpi r20,0x97 ;b3
brne n151
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n151:
cpi r20,0x98 ;c4
brne n152
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n152:
cpi r20,0x99 ;d4
brne n153
ldi r19, 0x26
ldi r22, 0b00110001
out PORTA, r22

n153:
cpi r20,0x9A ;c4
brne n154
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n154:
cpi r20,0x9B ;d4
brne n155
ldi r19, 0x19
ldi r22, 0b00110001
out PORTA, r22

n155:
cpi r20,0x9C ;e4
brne n156
ldi r19, 0x26
ldi r22, 0b00101111
out PORTA, r22

n156:
cpi r20,0x9D ;a3
brne n157
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n157:
cpi r20,0x9E ;b3
brne n158
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n158:
cpi r20,0x9F ;c4
brne n159
ldi r19, 0x26
ldi r22, 0b00110011
out PORTA, r22

n159:
cpi r20,0xA0 ;d4
brne n160
ldi r19, 0x19
ldi r22, 0b00110001
out PORTA, r22
rjmp n160

bogo18:
rjmp bogo17

n160:
cpi r20,0xA1 ;c4
brne n161
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n161:
cpi r20,0xA2 ;b3
brne n162
ldi r19, 0x22
ldi r22, 0b00110100
out PORTA, r22

n162:
cpi r20,0xA3 ;c4
brne n163
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n163:
cpi r20,0xA4 ;b3
brne n164
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n164:
cpi r20,0xA5 ;a3
brne n165
ldi r19, 0x26
ldi r22, 0b00110110
out PORTA, r22

n165:
cpi r20,0xA6 ;null
brne n166
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n166:
cpi r20,0xA7 ;b3
brne n167
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n167:
cpi r20,0xA8 ;null
brne n168
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n168:
cpi r20,0xA9 ;a3
brne n169
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n169:
cpi r20,0xAA ;g3
brne n170
ldi r19, 0x19
ldi r22, 0b00111000
out PORTA, r22
rjmp n170

bogo19:
rjmp bogo18

n170:
cpi r20,0xAB ;e3
brne n171
ldi r19, 0x33
ldi r22, 0b00111011
out PORTA, r22

n171:
cpi r20,0xAC ;a3
brne n172
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n172:
cpi r20,0xAD ;b3
brne n173
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n173:
cpi r20,0xAE ;c4
brne n174
ldi r19, 0x26
ldi r22, 0b00110011
out PORTA, r22

n174:
cpi r20,0xAF ;d4
brne n175
ldi r19, 0x19
ldi r22, 0b00110001
out PORTA, r22

n175:
cpi r20,0xB0 ;c4
brne n176
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n176:
cpi r20,0xB1 ;b3
brne n177
ldi r19, 0x26
ldi r22, 0b00110100
out PORTA, r22

n177:
cpi r20,0xB2 ;a3
brne n178
ldi r19, 0x22
ldi r22, 0b00110110
out PORTA, r22

n178:
cpi r20,0xB3 ;null
brne n179
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n179:
cpi r20,0xB4 ;g3
brne n180
ldi r19, 0x0C
ldi r22, 0b00111000
out PORTA, r22
rjmp n180

bogo20:
rjmp bogo19

n180:
cpi r20,0xB5 ;null
brne n181
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n181:
cpi r20,0xB6 ;b3
brne n182
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n182:
cpi r20,0xB7 ;a3
brne n183
ldi r19, 0x65
ldi r22, 0b00110110
out PORTA, r22

n183:
cpi r20,0xB8 ;a3
brne n184
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22

n184:
cpi r20,0xB9 ;null
brne n185
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n185:
cpi r20,0xBA ;b3
brne n186
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n186:
cpi r20,0xBB ;null
brne n187
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n187:
cpi r20,0xBC ;c4
brne n188
ldi r19, 0x3E
ldi r22, 0b00110011
out PORTA, r22

n188:
cpi r20,0xBD ;null
brne n189
ldi r19, 0x14
ldi r22, 0b00000000
out PORTA, r22

n189:
cpi r20,0xBE ;d4
brne n190
ldi r19, 0x0C
ldi r22, 0b00110001
out PORTA, r22
rjmp n190

bogo21:
rjmp bogo20

n190:
cpi r20,0xBF ;null
brne n191
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n191:
cpi r20,0xC0 ;c4
brne n192
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22

n192:
cpi r20,0xC1 ;null
brne n193
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n193:
cpi r20,0xC2 ;b3
brne n194
ldi r19, 0x3E
ldi r22, 0b00110100
out PORTA, r22

n194:
cpi r20,0xC3 ;null
brne n195
ldi r19, 0x14
ldi r22, 0b00000000
out PORTA, r22

n195:
cpi r20,0xC4 ;c4
brne n196
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22

n196:
cpi r20,0xC5 ;null
brne n197
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n197:
cpi r20,0xC6 ;b3
brne n198
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n198:
cpi r20,0xC7 ;null
brne n199
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n199:
cpi r20,0xC8 ;a3
brne n200
ldi r19, 0x34
ldi r22, 0b00110110
out PORTA, r22
rjmp n200

bogo22:
rjmp bogo21

n200:
cpi r20,0xC9 ;null
brne n201
ldi r19, 0x0A
ldi r22, 0b00000000
out PORTA, r22

n201:
cpi r20,0xCA ;b3
brne n202
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n202:
cpi r20,0xCB ;a3
brne n203
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22

n203:
cpi r20,0xCC ;g3
brne n204
ldi r19, 0x0C
ldi r22, 0b00111000
out PORTA, r22

n204:
cpi r20,0xCD ;null
brne n205
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n205:
cpi r20,0xCE ;e3
brne n206
ldi r19, 0x3E
ldi r22, 0b00111011
out PORTA, r22

n206:
cpi r20,0xCF ;null
brne n207
ldi r19, 0x14
ldi r22, 0b00000000
out PORTA, r22

n207:
cpi r20,0xD0 ;a3
brne n208
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22

n208:
cpi r20,0xD1 ;null
brne n209
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n209:
cpi r20,0xD2 ;b3
brne n210
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22
rjmp n210

bogo23:
rjmp bogo22

n210:
cpi r20,0xD3 ;null
brne n211
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n211:
cpi r20,0xD4 ;c4
brne n212
ldi r19, 0x30
ldi r22, 0b00110011
out PORTA, r22

n212:
cpi r20,0xD5 ;b3
brne n213
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n213:
cpi r20,0xD6 ;c4
brne n214
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n214:
cpi r20,0xD7 ;d4
brne n215
ldi r19, 0x30
ldi r22, 0b00110001
out PORTA, r22


n215:
cpi r20,0xD8 ;c4
brne n216
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n216:
cpi r20,0xD9 ;d4
brne n217
ldi r19, 0x19
ldi r22, 0b00110001
out PORTA, r22

n217:
cpi r20,0xDA ;e4
brne n218
ldi r19, 0x65
ldi r22, 0b00101111
out PORTA, r22

n218:
cpi r20,0xDB ;a3
brne n219
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n219:
cpi r20,0xDC ;b3
brne n220
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22
rjmp n220

bogo24:
rjmp bogo23

n220:
cpi r20,0xDD ;c4
brne n221
ldi r19, 0x30
ldi r22, 0b00110011
out PORTA, r22

n221:
cpi r20,0xDE ;d4
brne n222
ldi r19, 0x19
ldi r22, 0b00110001
out PORTA, r22

n222:
cpi r20,0xDF ;c4
brne n223
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n223:
cpi r20,0xE0 ;b3
brne n224
ldi r19, 0x30
ldi r22, 0b00110100
out PORTA, r22

n224:
cpi r20,0xE1 ;c4
brne n225
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n225:
cpi r20,0xE2 ;b3
brne n226
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n226:
cpi r20,0xE3 ;a3
brne n227
ldi r19, 0x25
ldi r22, 0b00110110
out PORTA, r22

n227:
cpi r20,0xE4 ;null
brne n228
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n228:
cpi r20,0xE5 ;b3
brne n229
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n229:
cpi r20,0xE6 ;null
brne n230
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22
rjmp n230

bogo25:
rjmp bogo24

n230:
cpi r20,0xE7 ;a3
brne n231
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n231:
cpi r20,0xE8 ;g3
brne n232
ldi r19, 0x19
ldi r22, 0b00111000
out PORTA, r22

n232:
cpi r20,0xE9 ;e3
brne n233
ldi r19, 0x30
ldi r22, 0b00111011
out PORTA, r22

n233:
cpi r20,0xEA ;a3
brne n234
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n234:
cpi r20,0xEB ;b3
brne n235
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n235:
cpi r20,0xEC ;c4
brne n236
ldi r19, 0x30
ldi r22, 0b00110011
out PORTA, r22

n236:
cpi r20,0xED ;d4
brne n237
ldi r19, 0x19
ldi r22, 0b00110001
out PORTA, r22

n237:
cpi r20,0xEE ;c4
brne n238
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n238:
cpi r20,0xEF ;b3
brne n239
ldi r19, 0x30
ldi r22, 0b00110100
out PORTA, r22

n239:
cpi r20,0xF0 ;a3
brne n240
ldi r19, 0x25
ldi r22, 0b00110110
out PORTA, r22
rjmp n240

bogo26:
rjmp bogo25

n240:
cpi r20,0xF1 ;null
brne n241
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n241:
cpi r20,0xF2 ;g3
brne n242
ldi r19, 0x0C
ldi r22, 0b00111000
out PORTA, r22

n242:
cpi r20,0xF3 ;null
brne n243
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n243:
cpi r20,0xF4 ;b3
brne n244
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n244:
cpi r20,0xF5 ;a3
brne n245
ldi r19, 0x65
ldi r22, 0b00110110
out PORTA, r22

n245:
cpi r20,0xF6 ;c4
brne n246
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22

n246:
cpi r20,0xF7 ;null
brne n247
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n247:
cpi r20,0xF8 ;d4
brne n248
ldi r19, 0x0C
ldi r22, 0b00110001
out PORTA, r22

n248:
cpi r20,0xF9 ;e4
brne n249
ldi r19, 0x0C
ldi r22, 0b00101111
out PORTA, r22

n249:
cpi r20,0xFA ;null
brne n250
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22
rjmp n250

bogo27:
rjmp bogo26

n250:
cpi r20,0xFB ;d4
brne n251
ldi r19, 0x30
ldi r22, 0b00110001
out PORTA, r22

n251:
cpi r20,0xFC ;null
brne n252
ldi r19, 0x08
ldi r22, 0b00000000
out PORTA, r22

n252:
cpi r20,0xFD ;c4
brne n253
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22

n253:
cpi r20,0xFE ;d4
brne n254
ldi r19, 0x0C
ldi r22, 0b00110001
out PORTA, r22

n254:
cpi r20,0xFF ;e4
brne n255
ldi r19, 0x34
ldi r22, 0b00101111
out PORTA, r22

n255:
cpi r23,0x01 ;null, also register switch from r20 to r23 here
brne n256
ldi r19, 0x08
ldi r22, 0b00000000
out PORTA, r22

n256:
cpi r23,0x02 ;d4
brne n257
ldi r19, 0x19
ldi r22, 0b00110001
out PORTA, r22

n257:
cpi r23,0x03 ;c4
brne n258
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n258:
cpi r23,0x04 ;d4
brne n259
ldi r19, 0x0C
ldi r22, 0b00110001
out PORTA, r22

n259:
cpi r23,0x05 ;c4
brne n260
ldi r19, 0x25
ldi r22, 0b00110011
out PORTA, r22
rjmp n260

bogo28:
rjmp bogo27

n260:
cpi r23,0x06 ;b3
brne n261
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n261:
cpi r23,0x07 ;c4
brne n262
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22

n262:
cpi r23,0x08 ;d4
brne n263
ldi r19, 0x34
ldi r22, 0b00110001
out PORTA, r22

n263:
cpi r23,0x09 ;null
brne n264
ldi r19, 0x0D
ldi r22, 0b00000000
out PORTA, r22

n264:
cpi r23,0x0A ;c4
brne n265
ldi r19, 0x19
ldi r22, 0b00110011
out PORTA, r22

n265:
cpi r23,0x0B ;b3
brne n266
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n266:
cpi r23,0x0C ;c4
brne n267
ldi r19, 0x30
ldi r22, 0b00110011
out PORTA, r22

n267:
cpi r23,0x0D ;a3
brne n268
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n268:
cpi r23,0x0E ;b3
brne n269
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n269:
cpi r23,0x0F ;c4
brne n270
ldi r19, 0x3E
ldi r22, 0b00110011
out PORTA, r22
rjmp n270

bogo29:
rjmp bogo28

n270:
cpi r23,0x10 ;b3
brne n271
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n271:
cpi r23,0x11 ;null
brne n272
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n272:
cpi r23,0x12 ;a3
brne n273
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22

n273:
cpi r23,0x13 ;null
brne n274
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n274:
cpi r23,0x14 ;g3
brne n275
ldi r19, 0x50
ldi r22, 0b00111000
out PORTA, r22

n275:
cpi r23,0x15 ;null
brne n276
ldi r19, 0x18
ldi r22, 0b00000000
out PORTA, r22

n276:
cpi r23,0x16 ;a3
brne n277
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22

n277:
cpi r23,0x17 ;null
brne n278
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n278:
cpi r23,0x18 ;b3
brne n279
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n279:
cpi r23,0x19 ;c4
brne n280
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22
rjmp n280

bogo30:
rjmp bogo29

n280:
cpi r23,0x1A ;null
brne n281
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n281:
cpi r23,0x1B ;b3
brne n282
ldi r19, 0x25
ldi r22, 0b00110100
out PORTA, r22

n282:
cpi r23,0x1C ;null
brne n283
ldi r19, 0x0D
ldi r22, 0b00000000
out PORTA, r22

n283:
cpi r23,0x1D ;a3
brne n284
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22

n284:
cpi r23,0x1E ;c4
brne n285
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22

n285:
cpi r23,0x1F ;b3
brne n286
ldi r19, 0x4B
ldi r22, 0b00110100
out PORTA, r22

n286:
cpi r23,0x20 ;c4
brne n287
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22

n287:
cpi r23,0x21 ;null
brne n288
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n288:
cpi r23,0x22 ;b3
brne n289
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n289:
cpi r23,0x23 ;null
brne n290
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22
rjmp n290

bogo31:
rjmp bogo30

n290:
cpi r23,0x24 ;c4
brne n291
ldi r19, 0x25
ldi r22, 0b00110011
out PORTA, r22

n291:
cpi r23,0x25 ;null
brne n292
ldi r19, 0x0A
ldi r22, 0b00000000
out PORTA, r22

n292:
cpi r23,0x26 ;b3
brne n293
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

n293:
cpi r23,0x27 ;a3
brne n294
ldi r19, 0x0C
ldi r22, 0b00110110
out PORTA, r22

n294:
cpi r23,0x28 ;null
brne n295
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n295:
cpi r23,0x29 ;g3
brne n296
ldi r19, 0x19
ldi r22, 0b00111000
out PORTA, r22

n296:
cpi r23,0x2A ;null
brne n297
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n297:
cpi r23,0x2B ;e3
brne n298
ldi r19, 0x34
ldi r22, 0b00111011
out PORTA, r22

n298:
cpi r23,0x2C ;null
brne n299
ldi r19, 0x08
ldi r22, 0b00000000
out PORTA, r22

n299:
cpi r23,0x2D ;a3
brne n300
ldi r19, 0x19
ldi r22, 0b00110110
out PORTA, r22
rjmp n300

bogo32:
rjmp bogo31

n300:
cpi r23,0x2E ;b3
brne n301
ldi r19, 0x19
ldi r22, 0b00110100
out PORTA, r22

n301:
cpi r23,0x2F ;c4
brne n302
ldi r19, 0x30
ldi r22, 0b00110011
out PORTA, r22

n302:
cpi r23,0x30 ;d4
brne n303
ldi r19, 0x25
ldi r22, 0b00110001
out PORTA, r22

n303:
cpi r23,0x31 ;null
brne n304
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n304:
cpi r23,0x32 ;c4
brne n305
ldi r19, 0x0C
ldi r22, 0b00110011
out PORTA, r22

n305:
cpi r23,0x33 ;null
brne n306
ldi r19, 0x05
ldi r22, 0b00000000
out PORTA, r22

n306:
cpi r23,0x34 ;b3
brne n307
ldi r19, 0x30
ldi r22, 0b00110100
out PORTA, r22

n307:
cpi r23,0x35 ;a3
brne n308
ldi r19, 0x25
ldi r22, 0b00110110
out PORTA, r22

n308:
cpi r23,0x36 ;null
brne n309
ldi r19, 0x0A
ldi r22, 0b00000000
out PORTA, r22

n309:
cpi r23,0x37 ;g3
brne n310
ldi r19, 0x0C
ldi r22, 0b00111000
out PORTA, r22
rjmp n310

bogo33:
inc r24
cpi r24, 0b11111111 ;Timing tweak
breq bogo32
rjmp bogo33

n310:
cpi r23,0x38 ;b3
brne n312
ldi r19, 0x0C
ldi r22, 0b00110100
out PORTA, r22

;n311:
;cpi r23,0x39 ;null
;brne n312
;ldi r19, 0x05
;ldi r22, 0b00000000
;out PORTA, r22

;n312:
;cpi r23,0x3A ;a3, not necessary
;brne n313
;ldi r19, 0x4B
;ldi r22, 0b00110110
;out PORTA, r22

n312:
cpi r23, 0x3B
ldi r24, 0b00000000
brne bogo33
clr r23
clr r20
clr r17
ldi r22, 0b00000000
out PORTA, r22
rjmp bogo33

Step 4: Song Storage Code Explained

It works like this:

control:
Start timer
Wait for timer overflow
Loop a certain number of times (this is the note length)
increment note number

Song data:
is the note number =1?
if so, output the correct number out port A, PIN0, and load the note length into a register
if not, continue

is the note number=2?
...
...
ad nauseum, over 300 notes
...
...
is the song finished?
if yes, clear all registers
if not, return to the "wait for timer overflow" step, with the correct note length value in the appropriate register. It will then increment note number and return to the "song data" function.

Step 5: About the Song

I did not write the song... it is from an old computer game (Ultima) , and is called "Stones".

Over the years (it is an old game), people have done many different versions on many instruments. I would go so far as to say it is one of the best MIDI songs from that era of computer gaming. I've sort of always wanted to build a music box, and this was the obvious choice... cutting open one of those annoying "happy birthday" musical cards for the sound thing was simply not adequate this time :D

More photos will come later, as I build the electronics into the false bottom of a wooden box.

This first photo is of the soldered and fully functional circuit. There is one glitch: If you poke the darlington pair, the music can freeze on the current note (not sure precisely why yet)! I plan to fix this by simply securing the circuit properly so those parts don't contact anything less resistant than air... should work just fine.

Now that it is in the black plastic box, it works great. I have varnished a wooden box to hold all this, soon I will have photos of the finished product. I think this will make a great birthday gift!

Step 6: The Box Proper

To fit it into a false section of an actual box was a bit of a challenge. The box I had... which I had built 10 years ago because my high school thought it was a great idea to teach us to make boxes... had an indentation in the lid that looked promising. This gave me 2 centimeters of depth to play with, which was not much, but I did manage to cram everything in there.

I had varnished the box with satin finish black polyurethane varnish I had lying about. The varnish job turned out well enough, but there are a few places I made mistakes in. Notably, the colour I had added in to the varnish increased it's drying time to the point where it was hard to work with. Next time, I'll use wood stain and spray-on satin varnish.

Since I had decided to line the box with velvet, I decided to wrap the plastic box holding the electronics in velvet so that it would just barely fit in, and friction would hold it in place. That was surprisingly easy once I discovered that using a foam spacer to keep the speaker in place was very effective. All fabric was attached using double-sided tape, the memory of which now causes me to twitch (tip: do not use dollar-store double sided tape or you will likely go mad as a hatter).

Lining the rest of the box with velvet was troublesome, and I have to say I'm not entirely satisfied with the results. I tried to calculate the correct amount of cloth to use to create seamless lining for the inside of the box, and somehow failed miserably. Clearly, unlike my ancestors, I am not destined for the upholstery business.

In any case it's done, and overall I'm satisfied with the way it turned out. I may tweak a few bits to fix the fabric, and/or integrate a photo into the box to cleverly cover up one of the suboptimal spots.