Back 5 years ago it was great project but it had a few drawbacks. First it used a PIC12C508 OTP. Yep One Time Programmable, what a pain in the a$$ if you need to change code. Burn change, burn change and rinse and repeat till you get it right, meanwhile at $0.50 a chip development of anything got expensive. Second I only had a couple of songs, I'm not musically inclined so figuring out songs to assembly language (ASM) was a real pain.
Well here is the original article with the 12C508.
A very simple PIC project to try. With the basic program available to download below you can insert any tune you like. My three year old son likes this Teletubbies tune. With a little more circuitry I wired it to the door of the car. Everytime he closed the door the car plays the Teletubbies tune. It was wired from the 0V of the car body to the wire that connects to the door switch. When the door is opened the supply to the PIC is shorted. When the door is closed the supply is reinstated and the PIC restarts its program again. Alternately it could be powered off batteries and hidden inside a childs toy.
Hex code
:020000040000FA
:100000002500490A540855084E0845082008560896
:1000100031082E0830080B02E2016808C208010806
:100020006808960800087F08F60800086808DE08D7
:1000300005085E0898080208770827080608680877
:10004000580802087F08C40805088D08ED0806084E
:100050006808C20801086808960800087F08F608C2
:1000600000086808DE0805085E08F20801085E0856
:10007000A60800087708060801085E087E0806083A
:100080006808B10804085408D00805085008350865
:100090000C082A0C2600400006006B005809620973
:1000A0003C0C8B0043074E0AFF0C06000300490A74
:1000B0000B092700AB020B092800AB020B09290032
:1000C000AB020008A90207026B096602E802630A94
:1000D000E902630A00082A00000000000000000096
:0800E0000000EA026C0A0008AE
:021FFE00EA0FE8
:00000001FF
ASM File
; FILE TUNE.ASM
; FOR 12C508A
; CLOCK Internal
TITLE "TUNE Program"
LIST P=12c508a
include p12c508a.inc
;config settings for PICSTART Programmer
__CONFIG _IntRC_OSC & _CP_OFF & _WDT_OFF & _MCLRE_OFF
constant noteLG =.159 ;G note constants
constant noteA =.141 ;A
constant noteB =.127 ;B
constant noteC =.119 ;C
constant noteD =.104 ;D
constant noteE =.94 ;E
constant noteFS =.84 ;F#
constant noteG =.80 ;G
constant MINIM =.250000 ;note length constants
constant SEMIN =MINIM/2
constant CROTCH =SEMIN/2
constant QUAVER =CROTCH/2
constant SEMIQV =QUAVER/2
NOTE macro freq,length
retlw freq
retlw low ((length) / freq)
retlw high ((length) / freq)
endm
;File registers
org 7
freq res 1
len res 1
lenh res 1
frq res 1
tabpos res 1
org 0
movwf OSCCAL
goto start
retlw 'T' ;chip identification
retlw 'U'
retlw 'N'
retlw 'E'
retlw ' '
retlw 'V'
retlw '1'
retlw '.'
retlw '0'
tune movf tabpos,w
addwf PCL,f
;example tune
tunest
NOTE noteC,CROTCH ;1
NOTE noteD,CROTCH ;2
NOTE noteF,QUAVER ;3
NOTE noteE,QUAVER ;4
NOTE noteD,QUAVER ;5
NOTE noteC,CROTCH ;6
NOTE noteG,CROTCH ;7
NOTE noteF,QUAVER ;8
NOTE noteE,QUAVER ;9
NOTE noteD,QUAVER ;10
NOTE noteC,CROTCH ;11
NOTE noteG,CROTCH ;12
NOTE noteF,QUAVER ;13
NOTE noteE,QUAVER ;14
NOTE noteF,QUAVER ;15
NOTE noteD,QUAVER ;16
endtab ;end of tune
start movlw b'00101010' ;set outputs
movwf GPIO
clrw
tris GPIO ;GPIO all outputs
clrf tabpos ;reset table position
nxtnote call getnote ;get note from table
call play ;play note
movlw endtab - tunest ;check if at end
subwf tabpos,w ;of table
btfss STATUS,Z
goto nxtnote ;no then get next note
movlw b'11111111' ;set outputs to high
tris GPIO ;impedence input mode
sleep ;put PIC in low power mode
goto start ;re-start if woken up
getnote call tune ;get note from table
movwf freq
incf tabpos,f
call tune ;get length lower byte
movwf len
incf tabpos,f
call tune ;get length high byte
movwf lenh
incf tabpos,f
return
play incf lenh,f
play2 movf freq,w
call note ;wait 1/2 frequency
comf GPIO,f ;toggle sounder
decfsz len,f
goto play2 ;keep looping until
decfsz lenh,f ;note finished
goto play2
return
note movwf frq ;wait 1/2 of frequency
wait nop
nop
nop
nop
nop
decfsz frq,f
goto wait
return
end
