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