2 #define CAL_MAGIC 0x9e // attiny4 handwired
3 //#define CAL_MAGIC 0x8d // attiny4 devboard
4 //#define CAL_MAGIC 0xa7 // attiny9 devboard
12 ; XXX: move registers down!
16 #define x r24 //==a1==Mh
25 #define Ml t //mod3 vars
27 #define a1 x //mul_ vars
52 .org 0x0000 ; RESET interrupt
54 .org 0x0002 ; INT0 interrupt
55 CBI EIMSK, 0 ; disable interrupt
56 ;TODO: can move 1 instruction here
58 .org 0x0008 ; TIM0_OVF interrupt
62 .byte 0x84, 0x9d, 0xb0, 0x69, 0x9d, 0x84, 0x69, 0x58
63 .byte 0x75, 0x8c, 0xb0, 0x69, 0x8c, 0x75, 0x69, 0x58
65 mod3: ; mod3(Mh.Ml) -> t
69 ADC Mh, Mh ; store carry in Mh
113 ; begin of mulitiplication:
122 ; BRCC skip2 -- this bit is always zero
165 MOV t, a1 ;;TODO: use a1 in loop: directly
168 main: ; setup routine
172 CLR acc ; we output a dummy sample before the actual first one
173 LDI Xhi, hi8(FLASHM + notes) ; never changes
174 LDI one, 1 ; mostly for clearing TIM0_OVF bit
178 OUT SPL, x ; init stack ptr
180 OUT PUEB, zero ; disable pullups
182 OUT DDRB, x ; PORTB0:pwm, PORTB1:debug (PORTB2:wakeup-input)
184 OUT CCP, x ; change protected ioregs
185 OUT CLKPSR, one ; clock prescaler 1/2 (4Mhz)
186 LDI x, CAL_MAGIC ; determined by trial-and-error (->PORTB1)
187 OUT OSCCAL, x ; set oscillator calibration
188 OUT WDTCSR, zero; turn off watchdog
190 ;set timer/counter0 to 8bit fastpwm, non-inverting, no prescaler
195 OUT TIMSK0, one ; enable tim0_ovf
200 CPI i2, 0x78 ; 16m23 -- one loop
201 ;cpi i2, 1 ;TODO:removeme
207 //we use an external pullup(>= 1kohm), as line-input usually has an impedance
208 //between 20-100kohm, while the attiny's internal pullups are "only" 20-50kohm
209 //(which is too strong)
211 ;stop the music, and check whether PINB0 is plugged into an audio
212 ;sink. Until then, conserve as much battery as possible.
213 CLR i2 ; clear halt condition
216 OUT TCCR0A, zero ; https://www.avrfreaks.net/forum/oc1a-state-during-pwm-disable
217 OUT TCCR0B, zero ; disable timer to free audio pin for wakeup function
219 ;TODO: both of these necessary?
220 SBI PORTB, 0 ; assert high level on pin2, so we can detect a plugged-in state as a low level.
221 SBI PORTB, 2 ; assert high level on pin2, so we can detect a plugged-in state as a low level.
223 OUT DDRB, zero ; set all pins as input
224 ;;;OUT PUEB, zero ; disable pullups on all pins (already done @ init/main)
226 ;set up INT0 to wake up when a audio sink is connected
227 SBI EIMSK, 0 ; set-bit-0 high => enable interrupt
228 OUT EICRA, zero ; logical low generates INT0
230 ;enter power-down-mode
231 LDI x, 0x05 ; sleep mode: power-down, enabled
234 ;OUT SMCR, one ; sleep mode: idle, enabled
235 OUT SMCR, zero ; sleep mode: disabled
240 ;;;SBI PCIFR, 1 ; clear interrupt (handled by reti)
241 ;;;OUT PUEB, zero ; remove pullups (already in main)
242 LDI x, 0x03 ; restore output pins
245 OUT TCCR0A, x ; reenable COMA bits
247 OUT TCCR0B, x ; reenable timer0
252 OUT OCR0AL, acc ; start by outputting a sample, because routine has variable runtime
254 SBI PORTB, 1 ; to measure runtime
379 SWAP acc ; acc<<4, to be passed to OCR0AL
386 CBI PORTB, 1 ; end runtime measurement
388 OUT TIFR0, one ; clear pending interrupt (routine takes two intr.cycles)
389 RETI ; reenables interrupts