aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--quantum/audio/audio.c316
-rw-r--r--quantum/audio/voices.c2
2 files changed, 296 insertions, 22 deletions
diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c
index 597073611..04f346003 100644
--- a/quantum/audio/audio.c
+++ b/quantum/audio/audio.c
@@ -33,17 +33,41 @@
33 33
34// TIMSK3 - Timer/Counter #3 Interrupt Mask Register 34// TIMSK3 - Timer/Counter #3 Interrupt Mask Register
35// Turn on/off 3A interputs, stopping/enabling the ISR calls 35// Turn on/off 3A interputs, stopping/enabling the ISR calls
36#define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A) 36#ifdef C6_AUDIO
37#define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A) 37 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
38 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
39#endif
40
41#ifdef B5_AUDIO
42 #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
43 #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
44#endif
38 45
39// TCCR3A: Timer/Counter #3 Control Register 46// TCCR3A: Timer/Counter #3 Control Register
40// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 47// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
41#define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1); 48
42#define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0)); 49#ifdef C6_AUDIO
50 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
51 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
52#endif
53
54#ifdef B5_AUDIO
55 #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1);
56 #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0));
57#endif
43 58
44// Fast PWM Mode Controls 59// Fast PWM Mode Controls
45#define TIMER_3_PERIOD ICR3 60
46#define TIMER_3_DUTY_CYCLE OCR3A 61#ifdef C6_AUDIO
62 #define TIMER_3_PERIOD ICR3
63 #define TIMER_3_DUTY_CYCLE OCR3A
64#endif
65
66#ifdef B5_AUDIO
67 #define TIMER_1_PERIOD ICR1
68 #define TIMER_1_DUTY_CYCLE OCR1A
69#endif
70
47 71
48// ----------------------------------------------------------------------------- 72// -----------------------------------------------------------------------------
49 73
@@ -51,6 +75,7 @@
51int voices = 0; 75int voices = 0;
52int voice_place = 0; 76int voice_place = 0;
53float frequency = 0; 77float frequency = 0;
78float frequency_alt = 0;
54int volume = 0; 79int volume = 0;
55long position = 0; 80long position = 0;
56 81
@@ -105,16 +130,43 @@ void audio_init()
105 audio_config.raw = eeconfig_read_audio(); 130 audio_config.raw = eeconfig_read_audio();
106 131
107 // Set port PC6 (OC3A and /OC4A) as output 132 // Set port PC6 (OC3A and /OC4A) as output
108 DDRC |= _BV(PORTC6);
109 133
110 DISABLE_AUDIO_COUNTER_3_ISR; 134 #ifdef C6_AUDIO
135 DDRC |= _BV(PORTC6);
136 #else
137 DDRC |= _BV(PORTC6);
138 PORTC &= ~_BV(PORTC6);
139 #endif
140
141 #ifdef B5_AUDIO
142 DDRB |= _BV(PORTB5);
143 #else
144 DDRB |= _BV(PORTB5);
145 PORTB &= ~_BV(PORTB5);
146 #endif
147
148 #ifdef C6_AUDIO
149 DISABLE_AUDIO_COUNTER_3_ISR;
150 #endif
151
152 #ifdef B5_AUDIO
153 DISABLE_AUDIO_COUNTER_1_ISR;
154 #endif
111 155
112 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers 156 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
113 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 157 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
114 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A) 158 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
115 // Clock Select (CS3n) = 0b010 = Clock / 8 159 // Clock Select (CS3n) = 0b010 = Clock / 8
116 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); 160
117 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); 161 #ifdef C6_AUDIO
162 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
163 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
164 #endif
165
166 #ifdef B5_AUDIO
167 TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
168 TCCR1B = (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
169 #endif
118 170
119 audio_initialized = true; 171 audio_initialized = true;
120} 172}
@@ -128,12 +180,21 @@ void stop_all_notes()
128 } 180 }
129 voices = 0; 181 voices = 0;
130 182
131 DISABLE_AUDIO_COUNTER_3_ISR; 183
132 DISABLE_AUDIO_COUNTER_3_OUTPUT; 184 #ifdef C6_AUDIO
185 DISABLE_AUDIO_COUNTER_3_ISR;
186 DISABLE_AUDIO_COUNTER_3_OUTPUT;
187 #endif
188
189 #ifdef B5_AUDIO
190 DISABLE_AUDIO_COUNTER_1_ISR;
191 DISABLE_AUDIO_COUNTER_1_OUTPUT;
192 #endif
133 193
134 playing_notes = false; 194 playing_notes = false;
135 playing_note = false; 195 playing_note = false;
136 frequency = 0; 196 frequency = 0;
197 frequency_alt = 0;
137 volume = 0; 198 volume = 0;
138 199
139 for (uint8_t i = 0; i < 8; i++) 200 for (uint8_t i = 0; i < 8; i++)
@@ -171,9 +232,16 @@ void stop_note(float freq)
171 voice_place = 0; 232 voice_place = 0;
172 } 233 }
173 if (voices == 0) { 234 if (voices == 0) {
174 DISABLE_AUDIO_COUNTER_3_ISR; 235 #ifdef C6_AUDIO
175 DISABLE_AUDIO_COUNTER_3_OUTPUT; 236 DISABLE_AUDIO_COUNTER_3_ISR;
237 DISABLE_AUDIO_COUNTER_3_OUTPUT;
238 #endif
239 #ifdef B5_AUDIO
240 DISABLE_AUDIO_COUNTER_1_ISR;
241 DISABLE_AUDIO_COUNTER_1_OUTPUT;
242 #endif
176 frequency = 0; 243 frequency = 0;
244 frequency_alt = 0;
177 volume = 0; 245 volume = 0;
178 playing_note = false; 246 playing_note = false;
179 } 247 }
@@ -200,12 +268,55 @@ float vibrato(float average_freq) {
200 268
201#endif 269#endif
202 270
271#ifdef C6_AUDIO
203ISR(TIMER3_COMPA_vect) 272ISR(TIMER3_COMPA_vect)
204{ 273{
205 float freq; 274 float freq, freq_alt = 0;
206 275
207 if (playing_note) { 276 if (playing_note) {
208 if (voices > 0) { 277 if (voices > 0) {
278
279 #ifdef B5_AUDIO
280 if (voices > 1) {
281 if (polyphony_rate == 0) {
282 if (glissando) {
283 if (frequency_alt != 0 && frequency_alt < frequencies[voices - 2] && frequency_alt < frequencies[voices - 2] * pow(2, -440/frequencies[voices - 2]/12/2)) {
284 frequency_alt = frequency_alt * pow(2, 440/frequency_alt/12/2);
285 } else if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440/frequencies[voices - 2]/12/2)) {
286 frequency_alt = frequency_alt * pow(2, -440/frequency_alt/12/2);
287 } else {
288 frequency_alt = frequencies[voices - 2];
289 }
290 } else {
291 frequency_alt = frequencies[voices - 2];
292 }
293
294 #ifdef VIBRATO_ENABLE
295 if (vibrato_strength > 0) {
296 freq_alt = vibrato(frequency_alt);
297 } else {
298 freq_alt = frequency_alt;
299 }
300 #else
301 freq_alt = frequency_alt;
302 #endif
303 }
304
305 if (envelope_index < 65535) {
306 envelope_index++;
307 }
308
309 freq_alt = voice_envelope(freq_alt);
310
311 if (freq_alt < 30.517578125) {
312 freq_alt = 30.52;
313 }
314
315 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq_alt * CPU_PRESCALER));
316 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq_alt * CPU_PRESCALER)) * note_timbre);
317 }
318 #endif
319
209 if (polyphony_rate > 0) { 320 if (polyphony_rate > 0) {
210 if (voices > 1) { 321 if (voices > 1) {
211 voice_place %= voices; 322 voice_place %= voices;
@@ -328,6 +439,138 @@ ISR(TIMER3_COMPA_vect)
328 playing_note = false; 439 playing_note = false;
329 } 440 }
330} 441}
442#endif
443
444ISR(TIMER1_COMPA_vect)
445{
446 #if defined(B5_AUDIO) && !defined(C6_AUDIO)
447 float freq = 0;
448
449 if (playing_note) {
450 if (voices > 0) {
451 if (polyphony_rate > 0) {
452 if (voices > 1) {
453 voice_place %= voices;
454 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
455 voice_place = (voice_place + 1) % voices;
456 place = 0.0;
457 }
458 }
459
460 #ifdef VIBRATO_ENABLE
461 if (vibrato_strength > 0) {
462 freq = vibrato(frequencies[voice_place]);
463 } else {
464 freq = frequencies[voice_place];
465 }
466 #else
467 freq = frequencies[voice_place];
468 #endif
469 } else {
470 if (glissando) {
471 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
472 frequency = frequency * pow(2, 440/frequency/12/2);
473 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
474 frequency = frequency * pow(2, -440/frequency/12/2);
475 } else {
476 frequency = frequencies[voices - 1];
477 }
478 } else {
479 frequency = frequencies[voices - 1];
480 }
481
482 #ifdef VIBRATO_ENABLE
483 if (vibrato_strength > 0) {
484 freq = vibrato(frequency);
485 } else {
486 freq = frequency;
487 }
488 #else
489 freq = frequency;
490 #endif
491 }
492
493 if (envelope_index < 65535) {
494 envelope_index++;
495 }
496
497 freq = voice_envelope(freq);
498
499 if (freq < 30.517578125) {
500 freq = 30.52;
501 }
502
503 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
504 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
505 }
506 }
507
508 if (playing_notes) {
509 if (note_frequency > 0) {
510 #ifdef VIBRATO_ENABLE
511 if (vibrato_strength > 0) {
512 freq = vibrato(note_frequency);
513 } else {
514 freq = note_frequency;
515 }
516 #else
517 freq = note_frequency;
518 #endif
519
520 if (envelope_index < 65535) {
521 envelope_index++;
522 }
523 freq = voice_envelope(freq);
524
525 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
526 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
527 } else {
528 TIMER_1_PERIOD = 0;
529 TIMER_1_DUTY_CYCLE = 0;
530 }
531
532 note_position++;
533 bool end_of_note = false;
534 if (TIMER_1_PERIOD > 0) {
535 end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF));
536 } else {
537 end_of_note = (note_position >= (note_length * 0x7FF));
538 }
539
540 if (end_of_note) {
541 current_note++;
542 if (current_note >= notes_count) {
543 if (notes_repeat) {
544 current_note = 0;
545 } else {
546 DISABLE_AUDIO_COUNTER_1_ISR;
547 DISABLE_AUDIO_COUNTER_1_OUTPUT;
548 playing_notes = false;
549 return;
550 }
551 }
552 if (!note_resting && (notes_rest > 0)) {
553 note_resting = true;
554 note_frequency = 0;
555 note_length = notes_rest;
556 current_note--;
557 } else {
558 note_resting = false;
559 envelope_index = 0;
560 note_frequency = (*notes_pointer)[current_note][0];
561 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
562 }
563
564 note_position = 0;
565 }
566 }
567
568 if (!audio_config.enable) {
569 playing_notes = false;
570 playing_note = false;
571 }
572#endif
573}
331 574
332void play_note(float freq, int vol) { 575void play_note(float freq, int vol) {
333 576
@@ -338,7 +581,12 @@ void play_note(float freq, int vol) {
338 } 581 }
339 582
340 if (audio_config.enable && voices < 8) { 583 if (audio_config.enable && voices < 8) {
341 DISABLE_AUDIO_COUNTER_3_ISR; 584 #ifdef C6_AUDIO
585 DISABLE_AUDIO_COUNTER_3_ISR;
586 #endif
587 #ifdef B5_AUDIO
588 DISABLE_AUDIO_COUNTER_1_ISR;
589 #endif
342 590
343 // Cancel notes if notes are playing 591 // Cancel notes if notes are playing
344 if (playing_notes) 592 if (playing_notes)
@@ -354,8 +602,21 @@ void play_note(float freq, int vol) {
354 voices++; 602 voices++;
355 } 603 }
356 604
357 ENABLE_AUDIO_COUNTER_3_ISR; 605 #ifdef C6_AUDIO
358 ENABLE_AUDIO_COUNTER_3_OUTPUT; 606 ENABLE_AUDIO_COUNTER_3_ISR;
607 ENABLE_AUDIO_COUNTER_3_OUTPUT;
608 #endif
609 #ifdef B5_AUDIO
610 #ifdef C6_AUDIO
611 if (voices > 1) {
612 ENABLE_AUDIO_COUNTER_1_ISR;
613 ENABLE_AUDIO_COUNTER_1_OUTPUT;
614 }
615 #else
616 ENABLE_AUDIO_COUNTER_1_ISR;
617 ENABLE_AUDIO_COUNTER_1_OUTPUT;
618 #endif
619 #endif
359 } 620 }
360 621
361} 622}
@@ -369,7 +630,12 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
369 630
370 if (audio_config.enable) { 631 if (audio_config.enable) {
371 632
372 DISABLE_AUDIO_COUNTER_3_ISR; 633 #ifdef C6_AUDIO
634 DISABLE_AUDIO_COUNTER_3_ISR;
635 #endif
636 #ifdef B5_AUDIO
637 DISABLE_AUDIO_COUNTER_1_ISR;
638 #endif
373 639
374 // Cancel note if a note is playing 640 // Cancel note if a note is playing
375 if (playing_note) 641 if (playing_note)
@@ -390,8 +656,16 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
390 note_position = 0; 656 note_position = 0;
391 657
392 658
393 ENABLE_AUDIO_COUNTER_3_ISR; 659 #ifdef C6_AUDIO
394 ENABLE_AUDIO_COUNTER_3_OUTPUT; 660 ENABLE_AUDIO_COUNTER_3_ISR;
661 ENABLE_AUDIO_COUNTER_3_OUTPUT;
662 #endif
663 #ifdef B5_AUDIO
664 #ifndef C6_AUDIO
665 ENABLE_AUDIO_COUNTER_1_ISR;
666 ENABLE_AUDIO_COUNTER_1_OUTPUT;
667 #endif
668 #endif
395 } 669 }
396 670
397} 671}
diff --git a/quantum/audio/voices.c b/quantum/audio/voices.c
index 54ebd423b..94147ccb6 100644
--- a/quantum/audio/voices.c
+++ b/quantum/audio/voices.c
@@ -44,7 +44,7 @@ float voice_envelope(float frequency) {
44 44
45 switch (voice) { 45 switch (voice) {
46 case default_voice: 46 case default_voice:
47 glissando = true; 47 glissando = false;
48 note_timbre = TIMBRE_50; 48 note_timbre = TIMBRE_50;
49 polyphony_rate = 0; 49 polyphony_rate = 0;
50 break; 50 break;