]> git.gir.st - Chiptunes.git/blob - foo.S
3rd iteration (still not working)
[Chiptunes.git] / foo.S
1 /* REGISTER NAMES */
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
10 #define x r24 //==a1==Mh
11 #define _ r25 //==a2
12 #define Xlo r26
13 #define Xhi r27
14 #define one r28
15 ; r29
16 ; r30 Zlo
17 ; r31 Zhi
18 ; aliases:
19 #define Ml t //mod3 vars
20 #define Mh x // -"-
21 #define a1 x //mul_ vars
22 #define a2 _ // -"-
23
24 /* I/O REGISTERS */
25 OCR0AL = 0x26
26 DDRB = 0x01
27 PORTB = 0x02
28 PUEB = 0x03
29 SPL = 0x3D
30 SPH = 0x3E
31 CCP = 0x3C
32 CLKPSR = 0x36
33 OSCCAL = 0x39
34 WDTCSR = 0x31
35 SMCR = 0x3A
36 TCCR0A = 0x2E
37 TCCR0B = 0x2D
38 TIMSK0 = 0x2B
39 TIFR0 = 0x2A
40 PCMSK = 0x10
41 PCIFR = 0x11
42 PCICR = 0x12
43 PRR = 0x35
44 RAMEND = 0x5F
45 FLASHM = 0x4000
46
47 .section .text
48 .org 0x0000 ; RESET interrupt
49 CLR i0
50 RJMP main
51 .org 0x0004 ; PCINT0 interrupt
52 CBI PCICR, 0 ; disable interrupt
53 RJMP wakeup
54 .org 0x0008 ; TIM0_OVF interrupt
55 RJMP sample
56
57 notes:
58 .byte 0x84, 0x9d, 0xb0, 0x69, 0x9d, 0x84, 0x69, 0x58
59 .byte 0x75, 0x8c, 0xb0, 0x69, 0x8c, 0x75, 0x69, 0x58
60
61 mod3: ; mod3(Mh.Ml) -> t
62 #define tmp _
63 ADD Ml, Mh
64 CLR Mh
65 ADC Mh, Mh ; store carry in Mh
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
84 BRCS skip
85 SUBI Ml, 3
86 skip:
87 RET
88 #undef tmp
89
90 g: ; g(i, t) -> t
91 CLR a1
92
93 #define tmp _
94 #define zero a1
95 ANDI t, 0x07
96 MOV tmp, i2
97 ANDI tmp, 3
98 CPSE tmp, zero
99 SUBI t, -8
100 #undef zero
101 #undef tmp
102
103 LDI Xlo, lo8(notes)
104 ADD Xlo, t ; NOTE: notes are positioned so that hi8(notes) never changes
105 LD t, X
106
107 CLR a2
108
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
160
161 MOV t, a1 ;;TODO: use a1 in loop: directly
162 RET
163
164 main: ; setup routine
165 ; NOTE: clr i0 moved to .ord 0x0
166 CLR i1
167 CLR i2
168 CLR i3
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
172
173 #define zero i0
174 LDI x, RAMEND
175 OUT SPL, x ; init stack ptr
176 OUT SPH, zero ; -"-
177 OUT PUEB, zero ; disable pullups
178 LDI x, 0x05
179 OUT DDRB, x ; PORTB0:pwm, PORTB2:debug
180 LDI x, 0xd8
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
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
193 SEI
194 #undef zero
195
196 loop:
197 CPI i2, 0x78>>5 ; 16m23 -- one loop
198 ;TODO^: s/>>5//
199 BREQ halt
200
201 SLEEP
202 RJMP loop
203
204 halt:
205 CLR i2 ; clear halt condition
206
207 #define zero i2
208 ; disable timer0, set all pins as input+pullup to conserve battery.
209 LDI x, 0x08 ; disable timer clock
210 OUT TCCR0B, x
211 ;OUT PRR, one ; ยง8.3: only helps in idle and active modes
212
213
214 sbi PORTB, 0 ; force pin high, so pcint triggers on connect to ground --- XXX TODO: this does not work reliably for PORTB0
215 sbi PORTB, 2 ; force pin high, so pcint triggers on connect to ground (works reliably for portb2)
216
217
218 OUT DDRB, zero
219 LDI x, 0x0f
220 OUT PUEB, x
221
222
223
224 SBI PCMSK, 2 ; listen for pin change on the audio out pin (i.e. wake up when a audio sink is connected)
225 ;TODO^: s/2/0/
226 OUT PCICR, one ; enable PCINT0
227
228 ;enter power-down-mode
229 LDI x, 0x05 ; sleep mode: power-down, enabled
230 OUT SMCR, x
231 SLEEP
232 OUT SMCR, one ; sleep mode: idle, enabled
233
234 RJMP loop
235
236 wakeup:
237 SBI PCIFR, 0 ; clear interrupt
238 OUT PUEB, zero ; remove pullups
239 LDI x, 0x05 ; restore output pins
240 OUT DDRB, x
241 ;OUT PRR, zero ; reenable periphials
242 LDI x, 0x09
243 OUT TCCR0B, x ; reenable timer0
244 RETI
245 #undef zero
246
247 sample:
248 OUT OCR0AL, acc ; start by outputting a sample, because routine has variable runtime
249 #ifdef DEBUG
250 SBI PORTB, 2 ; to measure runtime
251 #endif // DEBUG
252
253 MOV n, i2
254 LSL n
255 LSL n
256 #define tmp _
257 MOV tmp, i1
258 SWAP tmp
259 ANDI tmp, 0x0f
260 LSR tmp
261 LSR tmp
262 OR n, tmp
263 #undef tmp
264 MOV s, i3
265 LSR s
266 ROR s
267 ANDI s, 0x80
268 #define tmp _
269 MOV tmp, i2
270 LSR tmp
271 OR s, tmp
272 #undef tmp
273
274 ; voice 1:
275 MOV t, n
276 RCALL g
277 SWAP t
278 ANDI t, 1
279 MOV acc, t
280
281 ; voice 2:
282 #define tmp _
283 MOV tmp, i2
284 LSL tmp
285 LSL tmp
286 LSL tmp
287 MOV t, i1
288 SWAP t
289 ANDI t, 0xf
290 LSR t
291 OR t, tmp
292 #undef tmp
293 EOR t, n
294 RCALL g
295 LSR t
296 LSR t
297 ANDI t, 3
298 AND t, s
299 ADD acc, t
300
301 ; voice 3:
302 MOV Ml, i2
303 SWAP Ml
304 ANDI Ml, 0xf0
305 LSL Ml
306 #define tmp _
307 MOV tmp, i1
308 LSR tmp
309 LSR tmp
310 LSR tmp
311 OR Ml, tmp
312 #undef tmp
313 MOV Mh, i3
314 SWAP Mh
315 ANDI Mh, 0xf0
316 LSL Mh
317 #define tmp _
318 MOV tmp, i2
319 LSR tmp
320 LSR tmp
321 LSR tmp
322 OR Mh, tmp
323 #undef tmp
324 RCALL mod3
325 ADD t, n
326 RCALL g
327 LSR t
328 LSR t
329 ANDI t, 3
330 MOV x, s
331 INC x
332 #define tmp _
333 MOV tmp, x
334 LSR tmp
335 LSR tmp
336 ADD tmp, x
337 ROR tmp
338 LSR tmp
339 ADD tmp, x
340 ROR tmp
341 LSR tmp
342 ADD tmp, x
343 ROR tmp
344 LSR tmp
345 AND t, tmp
346 #undef tmp
347 ADD acc, t
348
349 ; voice 4:
350 MOV Ml, i2
351 SWAP Ml
352 ANDI Ml, 0xf0
353 LSL Ml
354 LSL Ml
355 #define tmp _
356 MOV tmp, i1
357 LSR tmp
358 LSR tmp
359 OR Ml, tmp
360 #undef tmp
361 MOV Mh, i3
362 SWAP Mh
363 ANDI Mh, 0xf0
364 LSL Mh
365 LSL Mh
366 #define tmp _
367 MOV tmp, i2
368 LSR tmp
369 LSR tmp
370 OR Mh, tmp
371 #undef tmp
372 RCALL mod3
373 SUB t, n
374 NEG t
375 SUBI t, -8
376 RCALL g
377 LSR t
378 ANDI t, 3
379 INC s
380 #define tmp _
381 MOV tmp, s
382 LSR tmp
383 ADD tmp, s
384 ROR tmp
385 LSR tmp
386 LSR tmp
387 ADD tmp, s
388 ROR tmp
389 ADD tmp, s
390 ROR tmp
391 LSR tmp
392 LSR tmp
393 AND t, tmp
394 #undef tmp
395 ADD acc, t
396
397 SWAP acc ; acc<<4, to be passed to OCR0AL
398
399 SUBI i0, -1
400 SBCI i1, -1
401 SBCI i2, -1
402 SBCI i3, -1
403
404 #ifdef DEBUG
405 CBI PORTB, 2 ; end runtime measurement
406 #endif // DEBUG
407 OUT TIFR0, one ; clear pending interrupt (routine takes two intr.cycles)
408 RETI ; reenables interrupts
Imprint / Impressum