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