aboutsummaryrefslogtreecommitdiff
path: root/quantum/audio
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2017-06-26 22:24:30 -0400
committerJack Humbert <jack.humb@gmail.com>2017-06-27 14:20:14 -0400
commiteabf530a0eaffb5fb7d6ebe375225e2d8b0b559a (patch)
tree8fef79b792e02c41beeacf141b444e3bdcf791ce /quantum/audio
parent1a4a66fd015990942a7248160aa63eb2fa6e59af (diff)
downloadqmk_firmware-eabf530a0eaffb5fb7d6ebe375225e2d8b0b559a.tar.gz
qmk_firmware-eabf530a0eaffb5fb7d6ebe375225e2d8b0b559a.zip
b5 audio
Diffstat (limited to 'quantum/audio')
-rw-r--r--quantum/audio/audio.c260
1 files changed, 240 insertions, 20 deletions
diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c
index 597073611..f2948f18a 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
@@ -105,16 +129,43 @@ void audio_init()
105 audio_config.raw = eeconfig_read_audio(); 129 audio_config.raw = eeconfig_read_audio();
106 130
107 // Set port PC6 (OC3A and /OC4A) as output 131 // Set port PC6 (OC3A and /OC4A) as output
108 DDRC |= _BV(PORTC6);
109 132
110 DISABLE_AUDIO_COUNTER_3_ISR; 133 #ifdef C6_AUDIO
134 DDRC |= _BV(PORTC6);
135 #else
136 DDRC |= _BV(PORTC6);
137 PORTC &= ~_BV(PORTC6);
138 #endif
139
140 #ifdef B5_AUDIO
141 DDRB |= _BV(PORTB5);
142 #else
143 DDRB |= _BV(PORTB5);
144 PORTB &= ~_BV(PORTB5);
145 #endif
146
147 #ifdef C6_AUDIO
148 DISABLE_AUDIO_COUNTER_3_ISR;
149 #endif
150
151 #ifdef B5_AUDIO
152 DISABLE_AUDIO_COUNTER_1_ISR;
153 #endif
111 154
112 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers 155 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
113 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 156 // 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) 157 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
115 // Clock Select (CS3n) = 0b010 = Clock / 8 158 // Clock Select (CS3n) = 0b010 = Clock / 8
116 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); 159
117 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); 160 #ifdef C6_AUDIO
161 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
162 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
163 #endif
164
165 #ifdef B5_AUDIO
166 TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
167 TCCR1B = (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
168 #endif
118 169
119 audio_initialized = true; 170 audio_initialized = true;
120} 171}
@@ -128,8 +179,16 @@ void stop_all_notes()
128 } 179 }
129 voices = 0; 180 voices = 0;
130 181
131 DISABLE_AUDIO_COUNTER_3_ISR; 182
132 DISABLE_AUDIO_COUNTER_3_OUTPUT; 183 #ifdef C6_AUDIO
184 DISABLE_AUDIO_COUNTER_3_ISR;
185 DISABLE_AUDIO_COUNTER_3_OUTPUT;
186 #endif
187
188 #ifdef B5_AUDIO
189 DISABLE_AUDIO_COUNTER_1_ISR;
190 DISABLE_AUDIO_COUNTER_1_OUTPUT;
191 #endif
133 192
134 playing_notes = false; 193 playing_notes = false;
135 playing_note = false; 194 playing_note = false;
@@ -171,8 +230,14 @@ void stop_note(float freq)
171 voice_place = 0; 230 voice_place = 0;
172 } 231 }
173 if (voices == 0) { 232 if (voices == 0) {
174 DISABLE_AUDIO_COUNTER_3_ISR; 233 #ifdef C6_AUDIO
175 DISABLE_AUDIO_COUNTER_3_OUTPUT; 234 DISABLE_AUDIO_COUNTER_3_ISR;
235 DISABLE_AUDIO_COUNTER_3_OUTPUT;
236 #endif
237 #ifdef B5_AUDIO
238 DISABLE_AUDIO_COUNTER_1_ISR;
239 DISABLE_AUDIO_COUNTER_1_OUTPUT;
240 #endif
176 frequency = 0; 241 frequency = 0;
177 volume = 0; 242 volume = 0;
178 playing_note = false; 243 playing_note = false;
@@ -200,6 +265,7 @@ float vibrato(float average_freq) {
200 265
201#endif 266#endif
202 267
268#ifdef C6_AUDIO
203ISR(TIMER3_COMPA_vect) 269ISR(TIMER3_COMPA_vect)
204{ 270{
205 float freq; 271 float freq;
@@ -328,6 +394,138 @@ ISR(TIMER3_COMPA_vect)
328 playing_note = false; 394 playing_note = false;
329 } 395 }
330} 396}
397#endif
398
399#ifdef B5_AUDIO
400ISR(TIMER1_COMPA_vect)
401{
402 float freq;
403
404 if (playing_note) {
405 if (voices > 0) {
406 if (polyphony_rate > 0) {
407 if (voices > 1) {
408 voice_place %= voices;
409 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
410 voice_place = (voice_place + 1) % voices;
411 place = 0.0;
412 }
413 }
414
415 #ifdef VIBRATO_ENABLE
416 if (vibrato_strength > 0) {
417 freq = vibrato(frequencies[voice_place]);
418 } else {
419 freq = frequencies[voice_place];
420 }
421 #else
422 freq = frequencies[voice_place];
423 #endif
424 } else {
425 if (glissando) {
426 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
427 frequency = frequency * pow(2, 440/frequency/12/2);
428 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
429 frequency = frequency * pow(2, -440/frequency/12/2);
430 } else {
431 frequency = frequencies[voices - 1];
432 }
433 } else {
434 frequency = frequencies[voices - 1];
435 }
436
437 #ifdef VIBRATO_ENABLE
438 if (vibrato_strength > 0) {
439 freq = vibrato(frequency);
440 } else {
441 freq = frequency;
442 }
443 #else
444 freq = frequency;
445 #endif
446 }
447
448 if (envelope_index < 65535) {
449 envelope_index++;
450 }
451
452 freq = voice_envelope(freq);
453
454 if (freq < 30.517578125) {
455 freq = 30.52;
456 }
457
458 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
459 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
460 }
461 }
462
463 if (playing_notes) {
464 if (note_frequency > 0) {
465 #ifdef VIBRATO_ENABLE
466 if (vibrato_strength > 0) {
467 freq = vibrato(note_frequency);
468 } else {
469 freq = note_frequency;
470 }
471 #else
472 freq = note_frequency;
473 #endif
474
475 if (envelope_index < 65535) {
476 envelope_index++;
477 }
478 freq = voice_envelope(freq);
479
480 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
481 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
482 } else {
483 TIMER_1_PERIOD = 0;
484 TIMER_1_DUTY_CYCLE = 0;
485 }
486
487 note_position++;
488 bool end_of_note = false;
489 if (TIMER_1_PERIOD > 0) {
490 end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF));
491 } else {
492 end_of_note = (note_position >= (note_length * 0x7FF));
493 }
494
495 if (end_of_note) {
496 current_note++;
497 if (current_note >= notes_count) {
498 if (notes_repeat) {
499 current_note = 0;
500 } else {
501 DISABLE_AUDIO_COUNTER_1_ISR;
502 DISABLE_AUDIO_COUNTER_1_OUTPUT;
503 playing_notes = false;
504 return;
505 }
506 }
507 if (!note_resting && (notes_rest > 0)) {
508 note_resting = true;
509 note_frequency = 0;
510 note_length = notes_rest;
511 current_note--;
512 } else {
513 note_resting = false;
514 envelope_index = 0;
515 note_frequency = (*notes_pointer)[current_note][0];
516 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
517 }
518
519 note_position = 0;
520 }
521 }
522
523 if (!audio_config.enable) {
524 playing_notes = false;
525 playing_note = false;
526 }
527}
528#endif
331 529
332void play_note(float freq, int vol) { 530void play_note(float freq, int vol) {
333 531
@@ -338,7 +536,12 @@ void play_note(float freq, int vol) {
338 } 536 }
339 537
340 if (audio_config.enable && voices < 8) { 538 if (audio_config.enable && voices < 8) {
341 DISABLE_AUDIO_COUNTER_3_ISR; 539 #ifdef C6_AUDIO
540 DISABLE_AUDIO_COUNTER_3_ISR;
541 #endif
542 #ifdef B5_AUDIO
543 DISABLE_AUDIO_COUNTER_1_ISR;
544 #endif
342 545
343 // Cancel notes if notes are playing 546 // Cancel notes if notes are playing
344 if (playing_notes) 547 if (playing_notes)
@@ -354,8 +557,14 @@ void play_note(float freq, int vol) {
354 voices++; 557 voices++;
355 } 558 }
356 559
357 ENABLE_AUDIO_COUNTER_3_ISR; 560 #ifdef C6_AUDIO
358 ENABLE_AUDIO_COUNTER_3_OUTPUT; 561 ENABLE_AUDIO_COUNTER_3_ISR;
562 ENABLE_AUDIO_COUNTER_3_OUTPUT;
563 #endif
564 #ifdef B5_AUDIO
565 ENABLE_AUDIO_COUNTER_1_ISR;
566 ENABLE_AUDIO_COUNTER_1_OUTPUT;
567 #endif
359 } 568 }
360 569
361} 570}
@@ -369,7 +578,12 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
369 578
370 if (audio_config.enable) { 579 if (audio_config.enable) {
371 580
372 DISABLE_AUDIO_COUNTER_3_ISR; 581 #ifdef C6_AUDIO
582 DISABLE_AUDIO_COUNTER_3_ISR;
583 #endif
584 #ifdef B5_AUDIO
585 DISABLE_AUDIO_COUNTER_1_ISR;
586 #endif
373 587
374 // Cancel note if a note is playing 588 // Cancel note if a note is playing
375 if (playing_note) 589 if (playing_note)
@@ -390,8 +604,14 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
390 note_position = 0; 604 note_position = 0;
391 605
392 606
393 ENABLE_AUDIO_COUNTER_3_ISR; 607 #ifdef C6_AUDIO
394 ENABLE_AUDIO_COUNTER_3_OUTPUT; 608 ENABLE_AUDIO_COUNTER_3_ISR;
609 ENABLE_AUDIO_COUNTER_3_OUTPUT;
610 #endif
611 #ifdef B5_AUDIO
612 ENABLE_AUDIO_COUNTER_1_ISR;
613 ENABLE_AUDIO_COUNTER_1_OUTPUT;
614 #endif
395 } 615 }
396 616
397} 617}