flex PCB, version 1
[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
a19907b3
TG
12#define n r20
13#define s r21
14#define t r22 //==Ml
15#define x r23 //==a1==Mh
16#define _ r24 //==a2
17#define one r25
f99fd6f3
TG
18#define Xlo r26
19#define Xhi r27
a19907b3 20; 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 // -"-
da32ed67 27
f180febe
TG
28/* I/O REGISTERS */
29OCR0AL = 0x26
30DDRB = 0x01
34fa6d04 31PORTB = 0x02
f180febe
TG
32PUEB = 0x03
33SPL = 0x3D
34SPH = 0x3E
35CCP = 0x3C
36CLKPSR = 0x36
2af726bc 37OSCCAL = 0x39
19e320a6 38WDTCSR = 0x31
f180febe
TG
39SMCR = 0x3A
40TCCR0A = 0x2E
41TCCR0B = 0x2D
42TIMSK0 = 0x2B
43TIFR0 = 0x2A
cfca61bf
TG
44EIMSK = 0x13
45EICRA = 0x15
f99fd6f3
TG
46RAMEND = 0x5F
47FLASHM = 0x4000
4466dd8b 48
f180febe 49.section .text
19e320a6
TG
50.org 0x0000 ; RESET interrupt
51 RJMP main
cfca61bf
TG
52.org 0x0002 ; INT0 interrupt
53 CBI EIMSK, 0 ; disable interrupt
8d6ea016 54 RJMP wakeup
19e320a6
TG
55.org 0x0008 ; TIM0_OVF interrupt
56 RJMP sample
4466dd8b 57
f99fd6f3
TG
58notes:
59 .byte 0x84, 0x9d, 0xb0, 0x69, 0x9d, 0x84, 0x69, 0x58
60 .byte 0x75, 0x8c, 0xb0, 0x69, 0x8c, 0x75, 0x69, 0x58
61
f180febe 62mod3: ; mod3(Mh.Ml) -> t
8d8c00e4 63 #define tmp _
65aa7cd6
TG
64 ADD Ml, Mh
65 CLR Mh
6d672b87 66 ADC Mh, Mh ; store carry in Mh
65aa7cd6
TG
67 MOV tmp, Ml
68 SWAP tmp
69 ANDI tmp, 0x0f
70 SWAP Mh
71 OR tmp, Mh
72 ANDI Ml, 0x0f
73 ADD Ml, tmp
74 MOV tmp, Ml
75 LSR tmp
76 LSR tmp
77 ANDI Ml, 0x03
78 ADD Ml, tmp
79 MOV tmp, Ml
80 LSR tmp
81 LSR tmp
82 ANDI Ml, 0x03
83 ADD Ml, tmp
84 CPI Ml, 3
26799bab 85 BRCS skip
65aa7cd6
TG
86 SUBI Ml, 3
87 skip:
4283632d 88 RET
8d8c00e4 89 #undef tmp
f180febe 90
f180febe 91g: ; g(i, t) -> t
a19907b3
TG
92 #define a1 x
93 #define a2 _
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
a19907b3
TG
165 #undef a1
166 #undef a2
ce618731 167 RET
61fab018 168
19e320a6 169main: ; setup routine
cfca61bf 170 CLR i0
95d26108
TG
171 CLR i1
172 CLR i2
19e320a6 173 CLR acc ; we output a dummy sample before the actual first one
f99fd6f3 174 LDI Xhi, hi8(FLASHM + notes) ; never changes
ce618731 175 LDI one, 1 ; mostly for clearing TIM0_OVF bit
19e320a6 176
6d672b87 177 #define zero i0
f99fd6f3 178 LDI x, RAMEND
19e320a6
TG
179 OUT SPL, x ; init stack ptr
180 OUT SPH, zero ; -"-
181 OUT PUEB, zero ; disable pullups
cfca61bf
TG
182 LDI x, 0x03
183 OUT DDRB, x ; PORTB0:pwm, PORTB1:debug (PORTB2:wakeup-input)
19e320a6
TG
184 LDI x, 0xd8
185 OUT CCP, x ; change protected ioregs
186 OUT CLKPSR, one ; clock prescaler 1/2 (4Mhz)
cfca61bf 187 LDI x, CAL_MAGIC ; determined by trial-and-error (->PORTB1)
2af726bc 188 OUT OSCCAL, x ; set oscillator calibration
ce618731 189 OUT WDTCSR, zero; turn off watchdog
19e320a6
TG
190
191 ;set timer/counter0 to 8bit fastpwm, non-inverting, no prescaler
192 LDI x, 0x81
193 OUT TCCR0A, x
194 LDI x, 0x09
195 OUT TCCR0B, x
196 OUT TIMSK0, one ; enable tim0_ovf
19e320a6 197 SEI
6d672b87 198 #undef zero
19e320a6
TG
199
200loop:
cfca61bf 201 CPI i2, 0x78 ; 16m23 -- one loop
8d6ea016
TG
202 BREQ halt
203
899e1656 204 SLEEP
19e320a6
TG
205 RJMP loop
206
cfca61bf
TG
207//we use an external pullup(>= 1kohm), as line-input usually has an impedance
208//between 20-100kohm, while the attiny's internal pullups are "only" 20-50kohm
209//(which is too strong)
8d6ea016 210halt:
cfca61bf
TG
211 ;stop the music, and check whether PINB0 is plugged into an audio
212 ;sink. Until then, conserve as much battery as possible.
8d6ea016
TG
213 CLR i2 ; clear halt condition
214
215 #define zero i2
780cda35
TG
216 ; disable timer to free audio pin for wakeup function:
217 OUT TCCR0A, zero
218 OUT TCCR0B, zero
899e1656 219
780cda35
TG
220 #define five x
221 LDI x, 0x05
222
223 ;assert high level on pullup pins to avoid accidentally triggering INT0:
224 OUT PORTB, five
899e1656 225
cfca61bf 226 OUT DDRB, zero ; set all pins as input
899e1656 227
cfca61bf 228 ;set up INT0 to wake up when a audio sink is connected
780cda35
TG
229 SBI EIMSK, 0 ; set-bit-0 high => enable interrupt
230 OUT EICRA, zero ; logical low generates INT0
8d6ea016
TG
231
232 ;enter power-down-mode
780cda35 233 OUT SMCR, five ; sleep mode: power-down, enabled
8d6ea016 234 SLEEP
cfca61bf
TG
235 ;OUT SMCR, one ; sleep mode: idle, enabled
236 OUT SMCR, zero ; sleep mode: disabled
780cda35 237 #undef five
8d6ea016
TG
238
239 RJMP loop
240
241wakeup:
cfca61bf 242 LDI x, 0x03 ; restore output pins
8d6ea016 243 OUT DDRB, x
cfca61bf
TG
244 LDI x, 0x81
245 OUT TCCR0A, x ; reenable COMA bits
899e1656 246 LDI x, 0x09
cfca61bf 247 OUT TCCR0B, x ; reenable timer0
8d6ea016
TG
248 RETI
249 #undef zero
250
19e320a6 251sample:
19e320a6 252 OUT OCR0AL, acc ; start by outputting a sample, because routine has variable runtime
ce618731 253#ifdef DEBUG
cfca61bf 254 SBI PORTB, 1 ; to measure runtime
ce618731 255#endif // DEBUG
19e320a6 256
65aa7cd6
TG
257 MOV n, i2
258 LSL n
259 LSL n
f6ef1520 260 #define tmp _
65aa7cd6
TG
261 MOV tmp, i1
262 SWAP tmp
263 ANDI tmp, 0x0f
264 LSR tmp
265 LSR tmp
266 OR n, tmp
f6ef1520 267 #undef tmp
5e5a35c0 268 MOV s, i2
65aa7cd6 269 LSR s
3b86ca43 270
65aa7cd6
TG
271 ; voice 1:
272 MOV t, n
273 RCALL g
274 SWAP t
275 ANDI t, 1
276 MOV acc, t
3b86ca43 277
65aa7cd6 278 ; voice 2:
f6ef1520 279 #define tmp _
65aa7cd6
TG
280 MOV tmp, i2
281 LSL tmp
282 LSL tmp
283 LSL tmp
284 MOV t, i1
285 SWAP t
286 ANDI t, 0xf
287 LSR t
288 OR t, tmp
f6ef1520 289 #undef tmp
65aa7cd6
TG
290 EOR t, n
291 RCALL g
292 LSR t
293 LSR t
294 ANDI t, 3
295 AND t, s
296 ADD acc, t
3b86ca43 297
65aa7cd6
TG
298 ; voice 3:
299 MOV Ml, i2
300 SWAP Ml
301 ANDI Ml, 0xf0
302 LSL Ml
f6ef1520 303 #define tmp _
65aa7cd6
TG
304 MOV tmp, i1
305 LSR tmp
306 LSR tmp
307 LSR tmp
308 OR Ml, tmp
f6ef1520 309 #undef tmp
5e5a35c0
TG
310 MOV Mh, i2
311 LSR Mh
312 LSR Mh
313 LSR Mh
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
5e5a35c0
TG
351 MOV Mh, i2
352 LSR Mh
353 LSR Mh
65aa7cd6
TG
354 RCALL mod3
355 SUB t, n
356 NEG t
357 SUBI t, -8
358 RCALL g
359 LSR t
360 ANDI t, 3
361 INC s
f6ef1520 362 #define tmp _
65aa7cd6
TG
363 MOV tmp, s
364 LSR tmp
365 ADD tmp, s
366 ROR tmp
367 LSR tmp
368 LSR tmp
369 ADD tmp, s
370 ROR tmp
371 ADD tmp, s
372 ROR tmp
373 LSR tmp
374 LSR tmp
375 AND t, tmp
f6ef1520 376 #undef tmp
65aa7cd6 377 ADD acc, t
3b86ca43 378
19e320a6
TG
379 SWAP acc ; acc<<4, to be passed to OCR0AL
380
f6ef1520
TG
381 SUBI i0, -1
382 SBCI i1, -1
383 SBCI i2, -1
bfce2f8c 384
ce618731 385#ifdef DEBUG
cfca61bf 386 CBI PORTB, 1 ; end runtime measurement
ce618731
TG
387#endif // DEBUG
388 OUT TIFR0, one ; clear pending interrupt (routine takes two intr.cycles)
19e320a6 389 RETI ; reenables interrupts
Imprint / Impressum