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.
Remove these ads by
Signing UpStep 1Source code, Sound generation
.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
| « Previous Step | Download PDFView All Steps | Next Step » |
4
comments
|
Add Comment
|
admin
says:
admin
says:
![]() |
Add Comment
|









































