source: avrstuff/Beep/main.c@ 26d7f34

main
Last change on this file since 26d7f34 was 26d7f34, checked in by Adrien Destugues <pulkomandy@…>, 14 years ago

Ajout de blinkdel (projet de test basique) et beep (synthèse musicale sur atmega8)

git-svn-id: svn://pulkomandy.tk/avrstuff@20 c6672c3c-f6b6-47f9-9001-1fd6b12fecbe

  • Property mode set to 100644
File size: 10.5 KB
Line 
1/**********************************************************************
2 * Music Player for the ATMega8
3 * Uses all 3 timers for generating a 2voices, 1bit sound.
4 * Copyright 2010, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
5 * Distributed under the terms of the MIT licence
6 **********************************************************************/
7
8#include <avr/io.h>
9#include <avr/interrupt.h>
10#include <avr/wdt.h>
11#include <avr/pgmspace.h>
12#include <util/delay.h>
13
14#include <string.h>
15#include <stdbool.h>
16
17#define C2_SoundOn() TCCR2 |= (1<<CS22)|(1<<CS20) /* enable timer */
18#define C2_SoundOff() TCCR2 &= ~((1<<CS22)|(1<<CS20)) /* disable timer */
19#define C2_SetFreq(f) OCR2 = (f)
20
21#define C1_SoundOn() TCCR1B |= (1<<CS12) /* enable timer */
22#define C1_SoundOff() TCCR1B &= ~(1<<CS12) /* disable timer */
23#define C1_SetFreq(f) OCR1A = (f)
24
25typedef enum {
26 S, // silence
27 N, // normal
28 A, // arpeggio
29 V, // vibrato
30 T, // tremolo
31} FX;
32
33// A note is made of frequency, duration, and a boolean indicating if it is
34// silence or a real note. Things that should be changed here :
35// * Have a note value instead of an hardcoded frequency,and have an octave
36// * Allow for effects (arpegio, vibrato for example)
37typedef struct {
38 unsigned char n; // note
39 unsigned char d; // length
40 FX f; // FX
41 unsigned char p; // params
42} C2_Note;
43
44// Mapping of notes to OCR2 values for timer 2.
45static const char Note2Reg[] = {
46 0xEC,
47 0xE0,
48 0xD1,
49 0xC4,
50 0xB8,
51 0xAF,
52 0xA6,
53 0x9F,
54 0x97,
55 0x8D,
56 0x84,
57 0x7E,
58
59 0x76,
60 0x6F,
61 0x6A,
62 0x64,
63 0x5E,
64 0x58,
65 0x53,
66 0x4F,
67 0x4A,
68 0x45,
69 0x42,
70 0x3F,
71
72 0x3B, // C
73 0x37, // C#
74 0x34, // D
75 0x32, // D#
76 0x2F, // E
77 0x2C, // F
78 0x29, // F#
79 0x27, // G
80 0x25, // G#
81 0x23, // A
82 0x21, // A#
83 0x1F, // B
84
85 0x1D, // C
86 0x1B, // C#
87 0x1A, // D
88 0x18, // D#
89 0x17, // E
90 0x16, // F
91 0x14, // F#
92 0x13, // G
93 0x12, // G#
94 0x11, // A
95 0x10, // A#
96 0xF // B
97 //0xE, // C
98 //0xD // C#
99};
100
101#define C(n) 12*n
102#define Cs(n) C(n)+1
103#define D(n) C(n)+2
104#define Ds(n) C(n)+3
105#define E(n) C(n)+4
106#define F(n) C(n)+5
107#define Fs(n) C(n)+6
108#define G(n) C(n)+7
109#define Gs(n) C(n)+8
110#define A(n) C(n)+9
111#define As(n) C(n)+10
112#define B(n) C(n)+11
113
114// Song data. A list of notes. Looped.
115/*
116static const C2_Note song[] = {
117 { G(2), 10, N, 0x00 },
118 { 0, 1, S, 0x00 },
119 { G(2), 10, N, 0x00 },
120 { 0, 1, S, 0x00 },
121 { G(2), 10, N, 0x00 },
122 { 0, 1, S, 0x00 },
123 { Ds(2), 7, N, 0x00 },
124 { As(2), 4, N, 0x00 },
125 { G(2), 10, N, 0x00 },
126 { 0, 1, S, 0x00 },
127 { Ds(2), 7, N, 0x00 },
128 { As(2), 4, N, 0x00 },
129 { G(2), 10, N, 0x00 },
130 { 0, 7, S, 0x00 },
131
132 { D(3), 10, N, 0x00 },
133 { 0, 1, S, 0x00 },
134 { D(3), 10, N, 0x00 },
135 { 0, 1, S, 0x00 },
136 { D(3), 10, N, 0x00 },
137 { 0, 1, S, 0x00 },
138 { Ds(3), 7, N, 0x00 },
139 { As(2), 4, N, 0x00 },
140 { Fs(2), 10, N, 0x00 },
141 { 0, 1, S, 0x00 },
142 { Ds(2), 7, N, 0x00 },
143 { As(2), 4, N, 0x00 },
144 { G(2), 10, N, 0x00 },
145 { 0, 7, S, 0x00 },
146
147 { G(3), 10, N, 0x00 },
148 { 0, 1, S, 0x00 },
149 { G(3), 10, N, 0x00 },
150 { 0, 1, S, 0x00 },
151 { G(3), 10, N, 0x00 },
152 { 0, 1, S, 0x00 },
153 { G(3), 6, N, 0x00 },
154 { 0, 1, S, 0x00 },
155 { Fs(3), 2, N, 0x00 },
156 { F(3), 2, N, 0x00 },
157 { E(3), 3, N, 0x00 },
158 { Ds(3), 7, N, 0x00 },
159 { 0, 1, S, 0x00 },
160 { E(2), 4, N, 0x00 },
161 { Gs(2), 10, N, 0x00 },
162 { 0, 4, S, 0x00 },
163
164 { Cs(3), 4, N, 0x00 },
165 { C(3), 4, N, 0x00 },
166 { B(2), 4, N, 0x00 },
167 { As(2), 4, N, 0x00 },
168 { A(2), 4, N, 0x00 },
169
170
171 { 0, 40, S, 0x00 },
172 {0,0,0} // Song end marker - zero-length note
173};
174*/
175
176static const C2_Note song[] PROGMEM = {
177 { E(3), 8, N, 0x00 },
178 { B(2), 4, N, 0x00 },
179 { C(3), 4, N, 0x00 },
180 { D(3), 4, N, 0x00 },
181 { 0 , 4, S, 0x00 },
182 { C(3), 4, N, 0x00 },
183 { B(2), 4, N, 0x00 },
184 { A(2), 4, N, 0x00 },
185 { 0 , 4, S, 0x00 },
186 { A(2), 4, N, 0x00 },
187 { C(3), 4, N, 0x00 },
188 { E(3), 4, N, 0x00 },
189 { 0 , 4, S, 0x00 },
190 { D(3), 4, N, 0x00 },
191 { C(3), 4, N, 0x00 },
192 { B(2), 4, N, 0x00 },
193 { 0 , 8, S, 0x00 },
194 { C(3), 4, N, 0x00 },
195 { D(3), 8, N, 0x00 },
196 { E(3), 8, N, 0x00 },
197 { C(3), 8, N, 0x00 },
198 { A(2), 7, N, 0x00 },
199 { 0 , 1, S, 0x00 },
200 { A(2), 8, N, 0x00 },
201 { 0 , 8, S, 0x00 },
202
203 { D(3), 12, N, 0x00 },
204 { F(3), 4, N, 0x00 },
205 { A(3), 8, N, 0x00 },
206 { G(3), 4, N, 0x00 },
207 { F(3), 4, N, 0x00 },
208 { E(3), 8, N, 0x00 },
209 { 0 , 4, S, 0x00 },
210 { C(3), 4, N, 0x00 },
211 { E(3), 8, N, 0x00 },
212 { D(3), 4, N, 0x00 },
213 { C(3), 4, N, 0x00 },
214 { B(2), 4, N, 0x00 },
215 { 0 , 8, S, 0x00 },
216 { C(3), 4, N, 0x00 },
217 { D(3), 8, N, 0x00 },
218 { E(3), 8, N, 0x00 },
219 { C(3), 8, N, 0x00 },
220 { A(2), 7, N, 0x00 },
221 { 0 , 1, S, 0x00 },
222 { A(2), 8, N, 0x00 },
223 { 0 , 8, S, 0x00 },
224
225/*
226 { E(3), 8, N, 0x00 },
227 { B(2), 4, N, 0x00 },
228 { C(3), 4, N, 0x00 },
229 { D(3), 4, N, 0x00 },
230 { 0 , 4, S, 0x00 },
231 { C(3), 4, N, 0x00 },
232 { B(2), 4, N, 0x00 },
233 { A(2), 4, N, 0x00 },
234 { 0 , 4, S, 0x00 },
235 { A(2), 4, N, 0x00 },
236 { C(3), 4, N, 0x00 },
237 { E(3), 4, N, 0x00 },
238 { 0 , 4, S, 0x00 },
239 { D(3), 4, N, 0x00 },
240 { C(3), 4, N, 0x00 },
241 { B(2), 4, N, 0x00 },
242 { 0 , 8, S, 0x00 },
243 { C(3), 4, N, 0x00 },
244 { D(3), 8, N, 0x00 },
245 { E(3), 8, N, 0x00 },
246 { C(3), 8, N, 0x00 },
247 { A(2), 7, N, 0x00 },
248 { 0 , 1, S, 0x00 },
249 { A(2), 8, N, 0x00 },
250 { 0 , 8, S, 0x00 },
251
252 { D(3), 12, N, 0x00 },
253 { F(3), 4, N, 0x00 },
254 { A(3), 8, N, 0x00 },
255 { G(3), 4, N, 0x00 },
256 { F(3), 4, N, 0x00 },
257 { E(3), 8, N, 0x00 },
258 { 0 , 4, S, 0x00 },
259 { C(3), 4, N, 0x00 },
260 { E(3), 8, N, 0x00 },
261 { D(3), 4, N, 0x00 },
262 { C(3), 4, N, 0x00 },
263 { B(2), 4, N, 0x00 },
264 { 0 , 8, S, 0x00 },
265 { C(3), 4, N, 0x00 },
266 { D(3), 8, N, 0x00 },
267 { E(3), 8, N, 0x00 },
268 { C(3), 8, N, 0x00 },
269 { A(2), 7, N, 0x00 },
270 { 0 , 1, S, 0x00 },
271 { A(2), 8, N, 0x00 },
272 { 0 , 8, S, 0x00 },
273*/
274 { E(3), 16, N, 0x00 },
275 { C(3), 16, N, 0x00 },
276 { D(3), 16, N, 0x00 },
277 { B(2), 16, N, 0x00 },
278 { C(3), 16, N, 0x00 },
279 { A(2), 16, N, 0x00 },
280 { G(2), 16, N, 0x00 },
281 { Gs(2), 16, N, 0x00 },
282
283 { 0 , 8, S, 0x00 },
284
285 { E(3), 16, N, 0x00 },
286 { C(3), 16, N, 0x00 },
287 { D(3), 16, N, 0x00 },
288 { B(2), 16, N, 0x00 },
289
290 { C(3), 8, N, 0x00 },
291 { D(3), 8, N, 0x00 },
292
293 {0,0,S,0} // Song end marker - zero-length note
294};
295
296static const C2_Note song2[] PROGMEM = {
297 { C(2), 4, N, 0x00 },
298 { C(3), 4, N, 0x00 },
299 { C(2), 4, N, 0x00 },
300 { C(3), 4, N, 0x00 },
301 { C(2), 4, N, 0x00 },
302 { C(3), 4, N, 0x00 },
303 { C(2), 4, N, 0x00 },
304 { C(3), 4, N, 0x00 },
305
306 { G(2), 4, N, 0x00 },
307 { G(3), 4, N, 0x00 },
308 { G(2), 4, N, 0x00 },
309 { G(3), 4, N, 0x00 },
310 { G(2), 4, N, 0x00 },
311 { G(3), 4, N, 0x00 },
312 { G(2), 4, N, 0x00 },
313 { G(3), 4, N, 0x00 },
314
315 { E(2), 4, N, 0x00 },
316 { E(3), 4, N, 0x00 },
317 { E(2), 4, N, 0x00 },
318 { E(3), 4, N, 0x00 },
319 { B(1), 4, N, 0x00 },
320 { B(2), 4, N, 0x00 },
321 { B(1), 4, N, 0x00 },
322 { B(2), 4, N, 0x00 },
323
324 { C(2), 4, N, 0x00 },
325 { C(3), 4, N, 0x00 },
326 { C(2), 4, N, 0x00 },
327 { C(3), 4, N, 0x00 },
328 { C(2), 16, N, 0x00 },
329
330 {0,0,S,0} // Song end marker - zero-length note
331};
332
333// This allows us to know where we are in the song.
334volatile int tick;
335
336// Timer 0 interrupt handler
337ISR(TIMER0_OVF_vect)
338{
339 tick++;
340}
341
342void main() {
343 // WATCHDOG
344 wdt_enable(WDTO_2S);
345
346 // TIMER 0 : timebase, 1 tick every 1ms
347 TCCR0 =(1<<CS02) | (1<<CS00); // prescaler /1024
348 TIMSK = 1 << TOIE0; // enable timer interrupt
349 tick = 0;
350
351 // TIMER 1 : Freq generator
352 TCCR1A = (1<<COM1A0);
353 TCCR1B = (1<<WGM12);
354
355 OCR1A = 0x5E;
356
357 // TIMER 2 : Frequency generator (on OC2)
358 // CTC mode allows us to set the frequency through OCR2 register
359 // Prescaler is set to 1024 in C2_SoundOn.
360 TCCR2 = (1<<WGM21) // CTC
361 |(1<<COM20); // toggle output on match
362 ASSR = 0; // Disable async mode
363
364 // Port B as output so we can use the timers
365 DDRB = 255;
366
367 // Enable interrupts
368 sei();
369
370
371 // TEST
372 //OCR2 = 0xFF;
373 //C2_SoundOn();
374
375 int step = 0;
376 int step2 = 0;
377 long nexttime = 0;
378 long nexttime2 = 0;
379 long time = 0;
380 char subtick = 0;
381 char subtick2 = 0;
382 C2_Note current = song[0];
383 C2_Note current2 = song2[0];
384
385 PORTB = 0xFF;
386
387 // Main loop
388 while(1) {
389 wdt_reset();
390
391 // PLAYER CODE
392 if (tick) {
393 tick--;
394
395
396 // CHANNEL 1 ---------------------------------
397 if (nexttime <= time) {
398 current = song2[step];
399 step++;
400 subtick = 0;
401 // Go to next step
402 nexttime = time + current.d;
403 if(current.f != 0) C1_SoundOn();
404 else C1_SoundOff();
405
406 // Test if song is finished, if so loop over
407 if (current.p == S && current.d == 0) {
408 step = 0;
409 time = 0;
410 nexttime = 1;
411 }
412 }
413
414 subtick++;
415 switch (current.f) {
416 default: case N: C1_SetFreq(Note2Reg[current.n]); break;
417 case A:
418 switch(subtick) {
419 case 0: C1_SetFreq(Note2Reg[current.n + ((current.p&0xF0)>>8)]); break;
420 case 1: C1_SetFreq(Note2Reg[current.n]); break;
421 case 2: C1_SetFreq(Note2Reg[current.n + (current.p&0xF)]); subtick = 0; break;
422 }
423 break;
424 case V: C1_SetFreq(Note2Reg[current.n]-current.p/2+subtick%current.p); break;
425 case T: if(subtick%current.p == 0) { C1_SoundOn(); C1_SetFreq(Note2Reg[current.n]); } else C1_SoundOff(); break;
426 }
427
428
429 // CHANNEL 2 -------------------------------
430 if (nexttime2 <= time) {
431 current2 = song[step2];
432 step2++;
433 subtick2 = 0;
434 // Go to next step
435 nexttime2 = time + current2.d;
436 if(current2.f != 0) C2_SoundOn();
437 else C2_SoundOff();
438
439 // Test if song is finished, if so loop over
440 if (current2.p == S && current2.d == 0) {
441 step2 = 0;
442 time = 0;
443 nexttime2 = 1;
444 }
445 }
446
447 subtick2++;
448 switch (current2.f) {
449 default: case N: C2_SetFreq(Note2Reg[current2.n]); break;
450 case A:
451 switch(subtick2) {
452 case 0: C2_SetFreq(Note2Reg[current2.n + ((current2.p&0xF0)>>8)]); break;
453 case 1: C2_SetFreq(Note2Reg[current2.n]); break;
454 case 2: C2_SetFreq(Note2Reg[current2.n + (current2.p&0xF)]); subtick2 = 0; break;
455 }
456 break;
457 case V: C2_SetFreq(Note2Reg[current2.n]-current2.p/2+subtick2%current2.p); break;
458 case T: if(subtick2%current2.p == 0) { C2_SoundOn(); C2_SetFreq(Note2Reg[current2.n]); } else C2_SoundOff(); break;
459 }
460
461
462 time++;
463 }
464 }
465}
466
Note: See TracBrowser for help on using the repository browser.