1 ; TODO: melody is still not 100% correct!
11 #define x r24 //==a1==Mh
16 #define v34 r29 //voice 3/4 selector
20 #define Ml t //mod3 vars
22 #define a1 x //mul_ vars
45 .org 0x0000 ; RESET interrupt
50 .org 0x0008 ; TIM0_OVF interrupt
54 .byte 0x84, 0x9d, 0xb0, 0x69, 0x9d, 0x84, 0x69, 0x58
55 .byte 0x75, 0x8c, 0xb0, 0x69, 0x8c, 0x75, 0x69, 0x58
57 voice34a: ; voice34a(v34, i3.i2.i1) -> t
58 ; first helper function for voice 3 and 4
90 voice34b: ; voice34b(v34, t, x) -> acc
91 ; second helper function for voice 3 and 4
104 LSR tmp ; only when /3
109 LSR tmp ; only when /5
113 LSR tmp ; only when /3
118 LSR tmp ; only when /5
124 mod3: ; mod3(Mh.Ml) -> t
128 ADC Mh, Mh ; store carry in Mh
167 ADD Xlo, t ; NOTE: can't overflow, since RAMEND == 0x5F
172 ; begin of mulitiplication:
181 ; BRCC skip2 -- this bit is always zero
209 BRCC skip6 ;sbrc t, NNN
225 MOV t, a1 ;;TODO: use a1 in loop: directly
228 main: ; setup routine
229 ; NOTE: clr i0..i2 moved to .ord 0x0
231 CLR acc ; we output a dummy sample before the actual first one
232 LDI Xhi, hi8(FLASHM + notes) ; never changes
233 LDI one, 1 ; mostly for clearing TIM0_OVF bit
237 OUT SPL, x ; init stack ptr
239 OUT PUEB, zero ; disable pullups
241 OUT DDRB, x ; PORTB0:pwm, PORTB2:debug
243 OUT CCP, x ; change protected ioregs
244 OUT CLKPSR, one ; clock prescaler 1/2 (4Mhz)
245 LDI x, 0xa7 ; determined by trial-and-error (->PORTB2)
246 OUT OSCCAL, x ; set oscillator calibration
247 OUT WDTCSR, zero; turn off watchdog ;;TODO: incomplete - see datasheet pg48
248 ; OUT SMCR, 2 ; sleep mode 'power down' ('idle' (default) has faster response time)
250 ;set timer/counter0 to 8bit fastpwm, non-inverting, no prescaler
255 OUT TIMSK0, one ; enable tim0_ovf
260 SLEEP ; wait for interrupt
264 OUT OCR0AL, acc ; start by outputting a sample, because routine has variable runtime
265 SBI PORTB, 2 ; to measure runtime
329 SWAP acc ; acc<<4, to be passed to OCR0AL
336 CBI PORTB, 2 ; end runtime measurement
337 OUT TIFR0, one ; clear pending interrupt (routine takes two intr.cycles)
338 RETI ; reenables interrupts