;############################################################################### ; # ; 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! # ; # ;############################################################################### ;############################################################################### ; the isr from timer 1 overflow is then central part for sound output ;############################################################################### timerint: push ZH ;save Z-register on stack push ZL in sreg,SREG ;save status .if ctype == 88 sts OCR1AH,byte0 sts OCR1AL,sigh ;PWM-value MSB sts OCR1BH,byte0 sts OCR1BL,temp1 ;PWM-value MSB (inverted output) out OCR0B,sigl ;PWM-value LSB .endif .if ctype == 08 out OCR1AH,byte0 out OCR1AL,sigh ;PWM-value MSB out OCR1BH,byte0 out OCR1BL,temp1 ;PWM-value MSB (inverted output) out OCR2,sigl ;PWM-value LSB .endif mov sigh,byte127 ;preset signal to 50% mov sigl,byte0 lds temp1,sysram+34 ;speed value inc speed1 ;speed-counter +1 cp temp1,speed1 ;is max-value reached? brne channel1 ;no clr speed1 ;set speed-counter to zero inc XL ;prescaler for click-generation mov anfev,byte127 ;set envelope count request cpi XL,64 ;is max-value of prescaler reached? brne channel1 ;no ori status,0x80 ;request new data from main program clr XL ;set prescaler to zero ;------------------------------------------------------------------------------- ; generate signal for channel 1 ;------------------------------------------------------------------------------- channel1: sbrs status,0 ;channel enabled? rjmp channel2 ;if not, skip channel lds wpl,sysram+0 ;read wave pointer lds wph,sysram+1 lds wal,sysram+2 ;read wave increment lds wah,sysram+3 lds ZL,sysram+4 ;wavetable LSB lds ZH,sysram+5 ;wavetable MSB lds epl,sysram+6 ;envelope pointer LSB lds eph,sysram+7 ;envelope pointer MSB lds eal,sysram+8 ;increment envelope LSB lds eah,sysram+9 ;increment envelope MSB add wpl,wal ;calculate new wave position adc wph,wah ;calculate new wave position sts sysram+0,wpl ;write back wave pointer LSB sts sysram+1,wph ;write back wave pointer LSB ldi temp1,0x08 ;factor for downscale wavepointer mul wpl,temp1 ;we multiply with 8 to divide by 32 mov wpl,r1 mul wph,temp1 mov wph,r1 add wpl,r0 andi wpl,0xfe add ZL,wpl ;calculate absolute adr of actual value adc ZH,wph lpm wpl,Z+ ;get actual wave value lpm wph,Z bst wph,7 ;store sign andi wph,0x7f ;clear sign sbrs anfev,0 ;request for envelope? rjmp channel1_01 ;no and anfev,byte254 ;clear request add epl,eal ;calculate new envelope pointer adc eph,eah brcc channel1_01 ;are we beyond the end? mov epl,byte0 ;set value to zero mov eph,byte0 cbr status,0x01 ;disable channel rjmp channel1_02 ;dont calculate a new value channel1_01: sts sysram+6,epl ;write back envelope pointer sts sysram+7,eph lds ZL,sysram+10 ;start address envelope table lds ZH,sysram+11 add ZL,eph ;calculate absolute adr of actual value adc ZH,byte0 add ZL,eph adc ZH,byte0 lpm epl,Z+ ;read actual envelope value lpm eph,Z channel1_02: mul eph,wph ;multiply envelope value with wave value mov temp1,r1 mov temp2,r0 mul eph,wpl add temp2,r1 adc temp1,byte0 mul epl,wph add temp2,r1 adc temp1,byte0 lds epl,sysram+12 ;channel volume mul epl,temp1 ;multiply with result of last operation mov wph,r1 mov wpl,r0 mul epl,temp2 add wpl,r1 adc wph,byte0 brts channel1_03 ;jump, if negative add sigl,wpl ;add LSB to signal adc sigh,wph ;add MSB to signal rjmp channel2 channel1_03: sub sigl,wpl ;sub LSB from signal sbc sigh,wph ;sub MSB from signal ;------------------------------------------------------------------------------- ; generate signal for channel 2 ;------------------------------------------------------------------------------- channel2: sbrs status,1 ;channel enabled? rjmp channel_out ;if not, skip channel lds wpl,sysram+16 ;wave pointer LSB lds wph,sysram+17 ;wave pointer MSB lds wal,sysram+18 ;increment wave LSB lds wah,sysram+19 ;increment wave MSB lds ZL,sysram+20 ;wavetable LSB lds ZH,sysram+21 ;wavetable MSB lds epl,sysram+22 ;envelope pointer LSB lds eph,sysram+23 ;envelope pointer MSB lds eal,sysram+24 ;increment envelope LSB lds eah,sysram+25 ;imcrement envelope MSB add wpl,wal ;calculate new wave position adc wph,wah ;calculate new wave position sts sysram+16,wpl ;writeback wave pointer LSB sts sysram+17,wph ;writeback wave pointer MSB ldi temp1,0x08 ;factor for downscale wavepointer mul wpl,temp1 ;we multiply with 8 to divide by 32 mov wpl,r1 mul wph,temp1 mov wph,r1 add wpl,r0 andi wpl,0xfe add ZL,wpl ;calculate absolute adr of actual value adc ZH,wph lpm wpl,Z+ ;get actual wave value lpm wph,Z bst wph,7 ;store sign andi wph,0x7f ;clear sign sbrs anfev,1 ;request for envelope? rjmp channel2_01 ;no ldi temp2,0xfd and anfev,temp2 ;clear request add epl,eal ;calculate new envelope pointer adc eph,eah brcc channel2_01 ;are we beyond the end? mov epl,byte0 ;set value to zero mov eph,byte0 cbr status,0x02 ;disable channel rjmp channel2_02 ;dont calculate a new value channel2_01: sts sysram+22,epl ;write back envelope pointer sts sysram+23,eph lds ZL,sysram+26 ;start address envelope table lds ZH,sysram+27 add ZL,eph ;calculate absolute adr of actual value adc ZH,byte0 add ZL,eph adc ZH,byte0 lpm epl,Z+ ;read actual envelope value lpm eph,Z channel2_02: mul eph,wph ;multiply envelope value with wave value mov temp1,r1 mov temp2,r0 mul eph,wpl add temp2,r1 adc temp1,byte0 mul epl,wph add temp2,r1 adc temp1,byte0 lds epl,sysram+28 ;channel volume mul epl,temp1 ;multiply with result of last operation mov wph,r1 mov wpl,r0 mul epl,temp2 add wpl,r1 adc wph,byte0 brts channel2_03 ;jump, if negative add sigl,wpl ;add LSB to signal adc sigh,wph ;add MSB to signal rjmp channel_out channel2_03: sub sigl,wpl ;sub LSB from signal sbc sigh,wph ;sub MSB from signal ;------------------------------------------------------------------------------- ;calculate PWM-signals, restore registers and leave isr ;------------------------------------------------------------------------------- channel_out: sub sigl,byte128 ;shift for LSB-PWM sbc sigh,byte0 ;correct MSB in case of overflow ldi temp1,0xfe ;maximal value sub temp1,sigh ;calculate inverted value out SREG,sreg ;restore status pop ZL ;restore Z-register pop ZH ;restore Z-register reti ;leave isr