second test pcint0 implementation
[Chiptunes.git] / foo.S
CommitLineData
f180febe 1/* REGISTER NAMES */
6d672b87
TG
2#define acc r16
3#define i0 r17
4#define i1 r18
5#define i2 r19
6#define i3 r20
7#define n r21
8#define s r22
9#define t r23 //==Ml
f99fd6f3
TG
10#define x r24 //==a1==Mh
11#define _ r25 //==a2
12#define Xlo r26
13#define Xhi r27
ce618731 14#define one r28
f180febe
TG
15; r29
16; r30 Zlo
17; r31 Zhi
18; aliases:
ce618731
TG
19#define Ml t //mod3 vars
20#define Mh x // -"-
21#define a1 x //mul_ vars
22#define a2 _ // -"-
da32ed67 23
f180febe
TG
24/* I/O REGISTERS */
25OCR0AL = 0x26
26DDRB = 0x01
34fa6d04 27PORTB = 0x02
f180febe
TG
28PUEB = 0x03
29SPL = 0x3D
30SPH = 0x3E
31CCP = 0x3C
32CLKPSR = 0x36
2af726bc 33OSCCAL = 0x39
19e320a6 34WDTCSR = 0x31
f180febe
TG
35SMCR = 0x3A
36TCCR0A = 0x2E
37TCCR0B = 0x2D
38TIMSK0 = 0x2B
39TIFR0 = 0x2A
95d26108
TG
40PCMSK = 0x10
41PCIFR = 0x11
42PCICR = 0x12
43PRR = 0x35
f99fd6f3
TG
44RAMEND = 0x5F
45FLASHM = 0x4000
4466dd8b 46
f180febe 47.section .text
19e320a6 48.org 0x0000 ; RESET interrupt
cf36b4c3 49 CLR i0
19e320a6 50 RJMP main
95d26108
TG
51.org 0x0004 ; PCINT0 interrupt
52 CBI PCICR, 0 ; disable interrupt
8d6ea016 53 RJMP wakeup
19e320a6
TG
54.org 0x0008 ; TIM0_OVF interrupt
55 RJMP sample
4466dd8b 56
f99fd6f3
TG
57notes:
58 .byte 0x84, 0x9d, 0xb0, 0x69, 0x9d, 0x84, 0x69, 0x58
59 .byte 0x75, 0x8c, 0xb0, 0x69, 0x8c, 0x75, 0x69, 0x58
60
f180febe 61mod3: ; mod3(Mh.Ml) -> t
8d8c00e4 62 #define tmp _
65aa7cd6
TG
63 ADD Ml, Mh
64 CLR Mh
6d672b87 65 ADC Mh, Mh ; store carry in Mh
65aa7cd6
TG
66 MOV tmp, Ml
67 SWAP tmp
68 ANDI tmp, 0x0f
69 SWAP Mh
70 OR tmp, Mh
71 ANDI Ml, 0x0f
72 ADD Ml, tmp
73 MOV tmp, Ml
74 LSR tmp
75 LSR tmp
76 ANDI Ml, 0x03
77 ADD Ml, tmp
78 MOV tmp, Ml
79 LSR tmp
80 LSR tmp
81 ANDI Ml, 0x03
82 ADD Ml, tmp
83 CPI Ml, 3
26799bab 84 BRCS skip
65aa7cd6
TG
85 SUBI Ml, 3
86 skip:
4283632d 87 RET
8d8c00e4 88 #undef tmp
f180febe 89
f180febe 90g: ; g(i, t) -> t
6d672b87
TG
91 CLR a1
92
d35c3d70 93 #define tmp _
6d672b87 94 #define zero a1
65aa7cd6
TG
95 ANDI t, 0x07
96 MOV tmp, i2
97 ANDI tmp, 3
65aa7cd6
TG
98 CPSE tmp, zero
99 SUBI t, -8
6d672b87 100 #undef zero
02f61e33 101 #undef tmp
4466dd8b 102
d44d4b47 103 LDI Xlo, lo8(notes)
95d26108 104 ADD Xlo, t ; NOTE: notes are positioned so that hi8(notes) never changes
d44d4b47 105 LD t, X
4466dd8b 106
986f12ae
TG
107 CLR a2
108
dd3193ab
TG
109 ; begin of mulitiplication:
110 LSR t
111 BRCC skip1
112 ADD a1, i0
113 ADC a2, i1
114 skip1:
115 LSR a2
116 ROR a1
117 LSR t
118 ; BRCC skip2 -- this bit is always zero
119 ; ADD a1, i0
120 ; ADC a2, i1
121 ;skip2:
122 LSR a2
123 ROR a1
124 LSR t
125 BRCC skip3
126 ADD a1, i0
127 ADC a2, i1
128 skip3:
129 LSR a2
130 ROR a1
131 LSR t
132 BRCC skip4
133 ADD a1, i0
134 ADC a2, i1
135 skip4:
136 LSR a2
137 ROR a1
138 LSR t
139 BRCC skip5
140 ADD a1, i0
141 ADC a2, i1
142 skip5:
143 LSR a2
144 ROR a1
145 LSR t
146 BRCC skip6 ;sbrc t, NNN
147 ADD a1, i0
148 skip6:
149 LSR a1
150 LSR t
151 BRCC skip7
152 ADD a1, i0
153 skip7:
154 LSR a1
155 LSR t
156 BRCC skip8
157 ADD a1, i0
158 skip8:
159 LSR a1
4466dd8b 160
2af726bc 161 MOV t, a1 ;;TODO: use a1 in loop: directly
ce618731 162 RET
61fab018 163
19e320a6 164main: ; setup routine
95d26108
TG
165 ; NOTE: clr i0 moved to .ord 0x0
166 CLR i1
167 CLR i2
65aa7cd6 168 CLR i3
19e320a6 169 CLR acc ; we output a dummy sample before the actual first one
f99fd6f3 170 LDI Xhi, hi8(FLASHM + notes) ; never changes
ce618731 171 LDI one, 1 ; mostly for clearing TIM0_OVF bit
19e320a6 172
6d672b87 173 #define zero i0
f99fd6f3 174 LDI x, RAMEND
19e320a6
TG
175 OUT SPL, x ; init stack ptr
176 OUT SPH, zero ; -"-
177 OUT PUEB, zero ; disable pullups
ea40b11f
TG
178 LDI x, 0x05
179 OUT DDRB, x ; PORTB0:pwm, PORTB2:debug
19e320a6
TG
180 LDI x, 0xd8
181 OUT CCP, x ; change protected ioregs
182 OUT CLKPSR, one ; clock prescaler 1/2 (4Mhz)
2af726bc
TG
183 LDI x, 0xa7 ; determined by trial-and-error (->PORTB2)
184 OUT OSCCAL, x ; set oscillator calibration
ce618731 185 OUT WDTCSR, zero; turn off watchdog
19e320a6
TG
186
187 ;set timer/counter0 to 8bit fastpwm, non-inverting, no prescaler
188 LDI x, 0x81
189 OUT TCCR0A, x
190 LDI x, 0x09
191 OUT TCCR0B, x
192 OUT TIMSK0, one ; enable tim0_ovf
19e320a6 193 SEI
6d672b87 194 #undef zero
19e320a6
TG
195
196loop:
8d6ea016
TG
197 CPI i2, 0x78>>5 ; 16m23 -- one loop
198;TODO^: s/>>5//
199 BREQ halt
200
201 SLEEP ; wait for interrupt -- XXX: does not work, since we forgot to set sleep_enable bit!
19e320a6
TG
202 RJMP loop
203
8d6ea016
TG
204halt:
205 CLR i2 ; clear halt condition
206
207 #define zero i2
208 ; disable periphials (timer0), then set all pins as input+pullup to conserve battery.
209 LDI x, 0x3 ; could use one-register to save on ROM (would keep adc enabled on attiny5/10)
210 OUT PRR, x
211 OUT DDRB, zero
212 LDI x, 0x0f
213 OUT PUEB, x
214
215 SBI PCMSK, 2 ; listen for pin change on the audio out pin (i.e. wake up when a audio sink is connected)
216;TODO^: s/2/0/
217 SBI PCICR, 0 ; enable PCINT0
218
219 ;enter power-down-mode
220 LDI x, 0x05 ; sleep mode: power-down, enabled
221 OUT SMCR, x
222 SLEEP
223 OUT SMCR, one ; sleep mode: idle, enabled
224
225 RJMP loop
226
227wakeup:
228 SBI PCIFR, 0 ; clear interrupt
229 LDI x, 0x05
230 OUT DDRB, x
231 OUT PUEB, zero
232 LDI x, 0x02
233 OUT PRR, x ; not using zero, so devices with adc keep it disabled
234 RETI
235 #undef zero
236
19e320a6 237sample:
19e320a6 238 OUT OCR0AL, acc ; start by outputting a sample, because routine has variable runtime
ce618731 239#ifdef DEBUG
34fa6d04 240 SBI PORTB, 2 ; to measure runtime
ce618731 241#endif // DEBUG
19e320a6 242
65aa7cd6
TG
243 MOV n, i2
244 LSL n
245 LSL n
f6ef1520 246 #define tmp _
65aa7cd6
TG
247 MOV tmp, i1
248 SWAP tmp
249 ANDI tmp, 0x0f
250 LSR tmp
251 LSR tmp
252 OR n, tmp
f6ef1520 253 #undef tmp
65aa7cd6
TG
254 MOV s, i3
255 LSR s
256 ROR s
257 ANDI s, 0x80
f6ef1520 258 #define tmp _
65aa7cd6
TG
259 MOV tmp, i2
260 LSR tmp
261 OR s, tmp
f6ef1520 262 #undef tmp
3b86ca43 263
65aa7cd6
TG
264 ; voice 1:
265 MOV t, n
266 RCALL g
267 SWAP t
268 ANDI t, 1
269 MOV acc, t
3b86ca43 270
65aa7cd6 271 ; voice 2:
f6ef1520 272 #define tmp _
65aa7cd6
TG
273 MOV tmp, i2
274 LSL tmp
275 LSL tmp
276 LSL tmp
277 MOV t, i1
278 SWAP t
279 ANDI t, 0xf
280 LSR t
281 OR t, tmp
f6ef1520 282 #undef tmp
65aa7cd6
TG
283 EOR t, n
284 RCALL g
285 LSR t
286 LSR t
287 ANDI t, 3
288 AND t, s
289 ADD acc, t
3b86ca43 290
65aa7cd6
TG
291 ; voice 3:
292 MOV Ml, i2
293 SWAP Ml
294 ANDI Ml, 0xf0
295 LSL Ml
f6ef1520 296 #define tmp _
65aa7cd6
TG
297 MOV tmp, i1
298 LSR tmp
299 LSR tmp
300 LSR tmp
301 OR Ml, tmp
f6ef1520 302 #undef tmp
65aa7cd6
TG
303 MOV Mh, i3
304 SWAP Mh
305 ANDI Mh, 0xf0
306 LSL Mh
f6ef1520 307 #define tmp _
65aa7cd6
TG
308 MOV tmp, i2
309 LSR tmp
310 LSR tmp
311 LSR tmp
312 OR Mh, tmp
f6ef1520 313 #undef tmp
65aa7cd6
TG
314 RCALL mod3
315 ADD t, n
316 RCALL g
317 LSR t
318 LSR t
319 ANDI t, 3
320 MOV x, s
321 INC x
f6ef1520 322 #define tmp _
65aa7cd6
TG
323 MOV tmp, x
324 LSR tmp
325 LSR tmp
326 ADD tmp, x
327 ROR tmp
328 LSR tmp
329 ADD tmp, x
330 ROR tmp
331 LSR tmp
332 ADD tmp, x
333 ROR tmp
334 LSR tmp
335 AND t, tmp
f6ef1520 336 #undef tmp
65aa7cd6 337 ADD acc, t
f6ef1520 338
65aa7cd6
TG
339 ; voice 4:
340 MOV Ml, i2
341 SWAP Ml
342 ANDI Ml, 0xf0
343 LSL Ml
344 LSL Ml
f6ef1520 345 #define tmp _
65aa7cd6
TG
346 MOV tmp, i1
347 LSR tmp
348 LSR tmp
349 OR Ml, tmp
f6ef1520 350 #undef tmp
65aa7cd6
TG
351 MOV Mh, i3
352 SWAP Mh
353 ANDI Mh, 0xf0
354 LSL Mh
355 LSL Mh
f6ef1520 356 #define tmp _
65aa7cd6
TG
357 MOV tmp, i2
358 LSR tmp
359 LSR tmp
360 OR Mh, tmp
f6ef1520 361 #undef tmp
65aa7cd6
TG
362 RCALL mod3
363 SUB t, n
364 NEG t
365 SUBI t, -8
366 RCALL g
367 LSR t
368 ANDI t, 3
369 INC s
f6ef1520 370 #define tmp _
65aa7cd6
TG
371 MOV tmp, s
372 LSR tmp
373 ADD tmp, s
374 ROR tmp
375 LSR tmp
376 LSR tmp
377 ADD tmp, s
378 ROR tmp
379 ADD tmp, s
380 ROR tmp
381 LSR tmp
382 LSR tmp
383 AND t, tmp
f6ef1520 384 #undef tmp
65aa7cd6 385 ADD acc, t
3b86ca43 386
19e320a6
TG
387 SWAP acc ; acc<<4, to be passed to OCR0AL
388
f6ef1520
TG
389 SUBI i0, -1
390 SBCI i1, -1
391 SBCI i2, -1
392 SBCI i3, -1
bfce2f8c 393
ce618731
TG
394#ifdef DEBUG
395 CBI PORTB, 2 ; end runtime measurement
396#endif // DEBUG
397 OUT TIFR0, one ; clear pending interrupt (routine takes two intr.cycles)
19e320a6 398 RETI ; reenables interrupts
Imprint / Impressum