]> git.gir.st - Chiptunes.git/blob - foo.S
s/BRPL/BRCS/
[Chiptunes.git] / foo.S
1 ; TODO: melody is still not 100% correct!
2 /* REGISTER NAMES */
3 #define acc r16
4 #define i0 r17
5 #define i1 r18
6 #define i2 r19
7 #define i3 r20
8 #define n r21
9 #define s r22
10 #define t r23 //==Ml
11 #define x r24 //==a1==Mh
12 #define _ r25 //==a2
13 #define Xlo r26
14 #define Xhi r27
15 #define one r28
16 #define v34 r29 //voice 3/4 selector
17 ; r30 Zlo
18 ; r31 Zhi
19 ; aliases:
20 #define Ml t //mod3 vars
21 #define Mh x // -"-
22 #define a1 x //mul_ vars
23 #define a2 _ // -"-
24
25 /* I/O REGISTERS */
26 OCR0AL = 0x26
27 DDRB = 0x01
28 PORTB = 0x02
29 PUEB = 0x03
30 SPL = 0x3D
31 SPH = 0x3E
32 CCP = 0x3C
33 CLKPSR = 0x36
34 OSCCAL = 0x39
35 WDTCSR = 0x31
36 SMCR = 0x3A
37 TCCR0A = 0x2E
38 TCCR0B = 0x2D
39 TIMSK0 = 0x2B
40 TIFR0 = 0x2A
41 RAMEND = 0x5F
42 FLASHM = 0x4000
43
44 .section .text
45 .org 0x0000 ; RESET interrupt
46 CLR i0
47 CLR i1
48 CLR i2
49 RJMP main
50 .org 0x0008 ; TIM0_OVF interrupt
51 RJMP sample
52
53 notes:
54 .byte 0x84, 0x9d, 0xb0, 0x69, 0x9d, 0x84, 0x69, 0x58
55 .byte 0x75, 0x8c, 0xb0, 0x69, 0x8c, 0x75, 0x69, 0x58
56
57 voice34a: ; voice34a(v34, i3.i2.i1) -> t
58 ; first helper function for voice 3 and 4
59 MOV Ml, i2
60 SWAP Ml
61 ANDI Ml, 0xf0
62 LSL Ml
63 SBRS v34, 1
64 LSL Ml
65 #define tmp _
66 MOV tmp, i1
67 LSR tmp
68 LSR tmp
69 SBRC v34, 1
70 LSR tmp
71 OR Ml, tmp
72 #undef tmp
73 MOV Mh, i3
74 SWAP Mh
75 ANDI Mh, 0xf0
76 LSL Mh
77 SBRS v34, 1
78 LSL Mh
79 #define tmp _
80 MOV tmp, i2
81 LSR tmp
82 LSR tmp
83 SBRC v34, 1
84 LSR tmp
85 OR Mh, tmp
86 #undef tmp
87 RCALL mod3
88 RET
89
90 voice34b: ; voice34b(v34, t, x) -> acc
91 ; second helper function for voice 3 and 4
92 ; modifies _
93 RCALL g
94 LSR t
95 SBRC v34, 1
96 LSR t ; only when /3
97 ANDI t, 3
98 MOV x, s
99 INC x
100 #define tmp _
101 MOV tmp, x
102 LSR tmp
103 SBRC v34, 1
104 LSR tmp ; only when /3
105 ADD tmp, x
106 ROR tmp
107 LSR tmp
108 SBRS v34, 1
109 LSR tmp ; only when /5
110 ADD tmp, x
111 ROR tmp
112 SBRC v34, 1
113 LSR tmp ; only when /3
114 ADD tmp, x
115 ROR tmp
116 LSR tmp
117 SBRS v34, 1
118 LSR tmp ; only when /5
119 AND t, tmp
120 #undef tmp
121 ADD acc, t
122 RET
123
124 mod3: ; mod3(Mh.Ml) -> t
125 #define tmp _
126 ADD Ml, Mh
127 CLR Mh
128 ADC Mh, Mh ; store carry in Mh
129 MOV tmp, Ml
130 SWAP tmp
131 ANDI tmp, 0x0f
132 SWAP Mh
133 OR tmp, Mh
134 ANDI Ml, 0x0f
135 ADD Ml, tmp
136 MOV tmp, Ml
137 LSR tmp
138 LSR tmp
139 ANDI Ml, 0x03
140 ADD Ml, tmp
141 MOV tmp, Ml
142 LSR tmp
143 LSR tmp
144 ANDI Ml, 0x03
145 ADD Ml, tmp
146 CPI Ml, 3
147 BRCS skip
148 SUBI Ml, 3
149 skip:
150 RET
151 #undef tmp
152
153 g: ; g(i, t) -> t
154 CLR a1
155
156 #define tmp _
157 #define zero a1
158 ANDI t, 0x07
159 MOV tmp, i2
160 ANDI tmp, 3
161 CPSE tmp, zero
162 SUBI t, -8
163 #undef zero
164 #undef tmp
165
166 LDI Xlo, lo8(notes)
167 ADD Xlo, t ; NOTE: can't overflow, since RAMEND == 0x5F
168 LD t, X
169
170 CLR a2
171
172 ; begin of mulitiplication:
173 LSR t
174 BRCC skip1
175 ADD a1, i0
176 ADC a2, i1
177 skip1:
178 LSR a2
179 ROR a1
180 LSR t
181 ; BRCC skip2 -- this bit is always zero
182 ; ADD a1, i0
183 ; ADC a2, i1
184 ;skip2:
185 LSR a2
186 ROR a1
187 LSR t
188 BRCC skip3
189 ADD a1, i0
190 ADC a2, i1
191 skip3:
192 LSR a2
193 ROR a1
194 LSR t
195 BRCC skip4
196 ADD a1, i0
197 ADC a2, i1
198 skip4:
199 LSR a2
200 ROR a1
201 LSR t
202 BRCC skip5
203 ADD a1, i0
204 ADC a2, i1
205 skip5:
206 LSR a2
207 ROR a1
208 LSR t
209 BRCC skip6 ;sbrc t, NNN
210 ADD a1, i0
211 skip6:
212 LSR a1
213 LSR t
214 BRCC skip7
215 ADD a1, i0
216 skip7:
217 LSR a1
218 LSR t
219 BRCC skip8
220 ADD a1, i0
221 skip8:
222 LSR a1
223
224
225 MOV t, a1 ;;TODO: use a1 in loop: directly
226 RET
227
228 main: ; setup routine
229 ; NOTE: clr i0..i2 moved to .ord 0x0
230 CLR i3
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
234
235 #define zero i0
236 LDI x, RAMEND
237 OUT SPL, x ; init stack ptr
238 OUT SPH, zero ; -"-
239 OUT PUEB, zero ; disable pullups
240 LDI x, 0x05
241 OUT DDRB, x ; PORTB0:pwm, PORTB2:debug
242 LDI x, 0xd8
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)
249
250 ;set timer/counter0 to 8bit fastpwm, non-inverting, no prescaler
251 LDI x, 0x81
252 OUT TCCR0A, x
253 LDI x, 0x09
254 OUT TCCR0B, x
255 OUT TIMSK0, one ; enable tim0_ovf
256 SEI
257 #undef zero
258
259 loop:
260 SLEEP ; wait for interrupt
261 RJMP loop
262
263 sample:
264 OUT OCR0AL, acc ; start by outputting a sample, because routine has variable runtime
265 SBI PORTB, 2 ; to measure runtime
266
267 MOV n, i2
268 LSL n
269 LSL n
270 #define tmp _
271 MOV tmp, i1
272 SWAP tmp
273 ANDI tmp, 0x0f
274 LSR tmp
275 LSR tmp
276 OR n, tmp
277 #undef tmp
278 MOV s, i3
279 LSR s
280 ROR s
281 ANDI s, 0x80
282 #define tmp _
283 MOV tmp, i2
284 LSR tmp
285 OR s, tmp
286 #undef tmp
287
288 ; voice 1:
289 MOV t, n
290 RCALL g
291 SWAP t
292 ANDI t, 1
293 MOV acc, t
294
295 ; voice 2:
296 #define tmp _
297 MOV tmp, i2
298 LSL tmp
299 LSL tmp
300 LSL tmp
301 MOV t, i1
302 SWAP t
303 ANDI t, 0xf
304 LSR t
305 OR t, tmp
306 #undef tmp
307 EOR t, n
308 RCALL g
309 LSR t
310 LSR t
311 ANDI t, 3
312 AND t, s
313 ADD acc, t
314
315 ; voice 3:
316 LDI v34, 3
317 RCALL voice34a
318 ADD t, n
319 RCALL voice34b
320
321 ; voice 4:
322 LDI v34, 4
323 RCALL voice34a
324 SUB t, n
325 NEG t
326 SUBI t, -8
327 RCALL voice34b
328
329 SWAP acc ; acc<<4, to be passed to OCR0AL
330
331 SUBI i0, -1
332 SBCI i1, -1
333 SBCI i2, -1
334 SBCI i3, -1
335
336 CBI PORTB, 2 ; end runtime measurement
337 OUT TIFR0, one ; clear pending interrupt (routine takes two intr.cycles)
338 RETI ; reenables interrupts
Imprint / Impressum