;############################################################################### ; # ; avrmusicbox V0.38 zweistimmige Klangerzeugung (Spieluhr) mit ATMEGA8/88 # ; (c)2006 Jörg Wolfram joerg@jcwolfram.de # ; # ; Dieses Programm ist freie Software. Sie können es unter den Bedingungen # ; der GNU General Public License, wie von der Free Software Foundation # ; veröffentlicht, weitergeben und/oder modifizieren, entweder gemäss # ; Version 2 der Lizenz oder (nach Ihrer Option) jeder späteren Version. # ; # ; Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es # ; Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, auch ohne die # ; implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN # ; BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License. # ; # ; Sie sollten ein Exemplar der GNU General Public License zusammen mit # ; diesem Programm erhalten haben. Falls nicht, schreiben Sie an die Free # ; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, # ; USA. # ; # ; Jede Nutzung der Software/Informationen nonkonform zur GPL oder ausserhalb # ; des Geltungsbereiches der GPL ist untersagt! # ; # ;############################################################################### ;############################################################################### ; data interpreter ;############################################################################### ;------------------------------------------------------------------------------- ;here we start playing ;------------------------------------------------------------------------------- play: ldi deltac,16 play_01: lpm temp,Z+ nop ;optional title output dec deltac brne play_01 sts sysram+13,byte0 ;offset channel 1 sts sysram+29,byte0 ;offset channel 2 lpm verse,Z+ ;get number of verses lpm deltac,Z+ ;get speed sts sysram+37,verse ;store number of verses lds temp,sysram+36 ;play or preview? sbrc temp,0 ;preview has double speed lsr deltac ;speed *2 sts sysram+34,deltac ;store speed lpm temp,Z+ ;volume channel 1 sts sysram+12,temp sts sysram+38,temp lpm temp,Z+ ;volume channel 2 sts sysram+28,temp sts sysram+39,temp sts sysram+32,ZL ;store pointer to music data sts sysram+33,ZH clr XL clr speed1 sei ;enable interrupts play_02: lds ZL,sysram+32 ;reload pointer lds ZH,sysram+33 ;------------------------------------------------------------------------------- ;intloop interprets the music data ;------------------------------------------------------------------------------- intloop: mov deltac,byte0 ;set delta-time to zero inc deltac ;+1 clr YH ; intloop_01: sbrc status,7 ;wait for click rjmp intloop_03 ;yes, there is a click lds temp,sysram+36 ;mode sbrc temp,0 ;skip, if we are in play mode rjmp intloop_01 ;preview mode sbic PIND,3 ;key pressed? rjmp intloop_01 ;no intloop_02: sts sysram+40,byte127 ;set stopp flag intloop_03: cbr status,0x80 ;clear click bit dec deltac ;deltacounter -1 brne intloop_01 ;deltacounter is not 0 intloop_04: lpm temp,Z+ ;get next databyte lds YL,sysram+40 ;stopp-flag cpi YL,127 brne intloop_04a sts sysram+40,byte0 sts sysram+12,byte0 ;mute channel 1 sts sysram+28,byte0 ;mute channel 2 ret intloop_04a: mov YL,temp ;store for calculating value mov XH,temp ;datatype andi XH,0xf0 ;mask bits cpi temp,0xf0 ;are we at the end? brne intloop_07 ;no dec verse ;verse counter mov temp,verse sbrc temp,6 ;check bit 6 rjmp intloop_05 brne play_02 ;next verse ret ;thats all intloop_05: andi temp,0x3f ;set bit 6 and 7 to zero brne intloop_06 ;have we played all? ret ;yes intloop_06: cpi temp,0x03 ;is this verse one of the both last? brcc play_02 ;no lds temp,sysram+12 ;get volume of channel 1 lsr temp ;/2 sts sysram+12,temp ;write back olume of channel 1 lds temp,sysram+28 ;get volume of channel 2 lsr temp ;/2 sts sysram+28,temp ;write back volume of channel 2 rjmp play_02 ;play next verse intloop_07: brcs intloop_08 ; andi temp,0x0f ;calc delta-counter mov deltac,temp or status,anfno ;set collected note requests mov anfno,byte0 ;clear temporary note requests rjmp intloop_01 ;wait for next click intloop_08: sbrc temp,7 ;note? rjmp intloop_09 ;no ldi YH,HIGH(ddstab) ;MSB Table andi YL,0x3f ;set offset notechannel_1: sbrc temp,6 ;channel 1? rjmp notechannel_2 ;no, next lds temp,sysram+13 ;halftone shift add YL,temp ;add to note value lsl YL ;*2 andi YL,0x7f ;there are 64 2-byte-values in table ldi YH,HIGH(ddstab) ;start of table ld temp,Y+ ;get LSB sts sysram+2,temp ;write ld temp,Y ;get MSB sts sysram+3,temp ;write sbr anfno,0x01 ;set note request sts sysram+0,byte0 ;set all Pointers to initial value sts sysram+1,byte0 sts sysram+6,byte0 sts sysram+7,byte0 rjmp intloop_04 ;2 next databyte notechannel_2: lds temp,sysram+29 ;halftone shift add YL,temp ;add to note value lsl YL ;*2 andi YL,0x7f ;there are 64 2-byte-values in table ldi YH,HIGH(ddstab) ;start of table ld temp,Y+ ;get LSB sts sysram+18,temp ;write ld temp,Y ;get MSB sts sysram+19,temp ;write sbr anfno,0x02 ;set note request sts sysram+16,byte0 ;set all Pointer to initial value sts sysram+17,byte0 sts sysram+22,byte0 sts sysram+23,byte0 rjmp intloop_04 ;next databyte intloop_09: cpi XH,0x80 ;set envelope? brne intloop_10 ;no andi YL,0x07 ;bit 0-3 are the new value lsl YL ;*2 ldi YH,HIGH(eofftab) ;start of envelope-increment table MSB andi temp,0x08 ;only channel address envchannel_1: cpi temp,0x00 ;channel 1? brne envchannel_2 ;no, next ld temp,Y+ ;get value sts sysram+8,temp ;LSB ld temp,Y ;get value sts sysram+9,temp ;MSB rjmp intloop_04 ;next databyte envchannel_2: ld temp,Y+ ;get value sts sysram+24,temp ;LSB ld temp,Y ;get value sts sysram+25,temp ;MSB rjmp intloop_04 ;next databyte intloop_10: cpi XH,0x90 ;volume? brne intloop_11 ;no andi temp,0x08 ;only channel address volchannel_1: cpi temp,0x00 ;channel 1? brne envchannel_2 ;no, next lpm YL,Z+ ;get value sts sysram+12,YL ;write rjmp intloop_04 ;next databyte volchannel_2: lpm YL,Z+ ;get value sts sysram+28,YL ;write rjmp intloop_04 ;next databyte intloop_11: cpi XH,0xa0 ;halftone offset? brne intloop_12 ;no andi temp,0x08 ;only channel address verchannel_1: cpi temp,0x00 ;channel 1? brne verchannel_2 ;no, next lpm YL,Z+ ;get value sts sysram+13,YL ;write rjmp intloop_04 ;next databyte verchannel_2: lpm YL,Z+ ;get value sts sysram+29,YL ;write rjmp intloop_04 ;next databyte intloop_12: cpi XH,0xb0 ;set wavetable? brne intloop_13 ;no andi temp,0x08 ;only channel address wadchannel_1: cpi temp,0x00 ;channel 1? brne wadchannel_2 ;no, next lpm YL,Z+ ;get LSB of address sts sysram+4,YL ;write lpm YL,Z+ ;get MSB of address sts sysram+5,YL ;write rjmp intloop_04 ;next databyte wadchannel_2: lpm YL,Z+ ;get value sts sysram+20,YL ;write lpm YL,Z+ ;get MSB of address sts sysram+21,YL ;write rjmp intloop_04 ;next databyte intloop_13: cpi XH,0xc0 ;set envelopetable? brne intloop_14 ;no andi temp,0x08 ;only channel address eadchannel_1: cpi temp,0x00 ;channel 1? brne eadchannel_2 ;no, next lpm YL,Z+ ;get LSB of address sts sysram+10,YL ;write lpm YL,Z+ ;get MSB of address sts sysram+11,YL ;write rjmp intloop_04 ;next databyte eadchannel_2: lpm YL,Z+ ;get value sts sysram+26,YL ;write lpm YL,Z+ ;get MSB of address sts sysram+27,YL ;write rjmp intloop_04 ;next databyte intloop_14: cpi temp,0xe0 ;end of preview? brne intloop_15 ;no lds temp,sysram+36 ;mode sbrc temp,0 ;ignore, if we are in play mode ret ;end, if we are in preview-mode intloop_15: rjmp intloop_04