10 #define x r24 //==a1==Mh
19 #define Ml t //mod3 vars
21 #define a1 x //mul_ vars
48 .org 0x0000 ; RESET interrupt
51 .org 0x0004 ; PCINT0 interrupt
52 CBI PCICR, 0 ; disable interrupt
54 .org 0x0008 ; TIM0_OVF interrupt
58 .byte 0x84, 0x9d, 0xb0, 0x69, 0x9d, 0x84, 0x69, 0x58
59 .byte 0x75, 0x8c, 0xb0, 0x69, 0x8c, 0x75, 0x69, 0x58
61 mod3: ; mod3(Mh.Ml) -> t
65 ADC Mh, Mh ; store carry in Mh
104 ADD Xlo, t ; NOTE: notes are positioned so that hi8(notes) never changes
109 ; begin of mulitiplication:
118 ; BRCC skip2 -- this bit is always zero
146 BRCC skip6 ;sbrc t, NNN
161 MOV t, a1 ;;TODO: use a1 in loop: directly
164 main: ; setup routine
165 ; NOTE: clr i0 moved to .ord 0x0
169 CLR acc ; we output a dummy sample before the actual first one
170 LDI Xhi, hi8(FLASHM + notes) ; never changes
171 LDI one, 1 ; mostly for clearing TIM0_OVF bit
175 OUT SPL, x ; init stack ptr
177 OUT PUEB, zero ; disable pullups
179 OUT DDRB, x ; PORTB0:pwm, PORTB2:debug
181 OUT CCP, x ; change protected ioregs
182 OUT CLKPSR, one ; clock prescaler 1/2 (4Mhz)
183 LDI x, 0xa7 ; determined by trial-and-error (->PORTB2)
184 OUT OSCCAL, x ; set oscillator calibration
185 OUT WDTCSR, zero; turn off watchdog
187 ;set timer/counter0 to 8bit fastpwm, non-inverting, no prescaler
192 OUT TIMSK0, one ; enable tim0_ovf
197 SLEEP ; wait for interrupt
201 OUT OCR0AL, acc ; start by outputting a sample, because routine has variable runtime
203 SBI PORTB, 2 ; to measure runtime
350 SWAP acc ; acc<<4, to be passed to OCR0AL
357 CPI i2, 0x78 ; 16m23 -- one loop
362 CBI PORTB, 2 ; end runtime measurement
364 OUT TIFR0, one ; clear pending interrupt (routine takes two intr.cycles)
365 RETI ; reenables interrupts
369 ; To reduce physical size, we won't use a latching power switch. Instead,
370 ; playback will stop after a full iteration (16m23s). Then, a momentary
371 ; button will trigger a RESET, INT0 or PCINT0 interrupt to resume
372 ; playback. Meanwhile, all periphials will be shut down and the clock
373 ; turned off. The watchdog is permanently off to reduce power consumption.
374 ; Note: it is not necessary to switch the clock source from the 8MHz
375 ; oscillator to the 128kHz one, since power-down mode disables the clock
378 ; TODO: if we are using pcint on the audio-out pin, we could instruct the user to short the audio plug to ground to start playback (which should be triggered by a connected audio source). this would eliminate the button (and associated wiring) completely.
381 ;set all pins as input & enable pullups and disable periphials to conserve energy
386 LDI x, 0x3 ; bit0: disable Timer0, bit1: disable attiny5/10's ADC
389 SBI PCMSK, 0 ; enable PCINT0 on PB0 (pin1; also audio out)
390 SBI PCICR, 0 ; enable PCINT0
392 ;enter power-down-mode
393 LDI x, 0x05 ; power-down mode:____010_ ; enable:_______1
403 SBI PCIFR, 0 ; clear interrupt
409 OUT PRR, x ; reset prr (not using zero, so devices with adc keep it disabled)
410 ; TODO: should probably reset i0/i1/i2
413 ; XXX: 14 byte too large; should probably purge i3, rerun fakeasm-tests with length reduced to 7864320. a dedicated five-register will save 2 instructions, too.