1 /* Copyright 2016 Jack Humbert
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <avr/pgmspace.h>
20 #include <avr/interrupt.h>
28 #define CPU_PRESCALER 8
30 // -----------------------------------------------------------------------------
32 // -----------------------------------------------------------------------------
34 // TIMSK3 - Timer/Counter #3 Interrupt Mask Register
35 // Turn on/off 3A interputs, stopping/enabling the ISR calls
37 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
38 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
42 #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
43 #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
46 // TCCR3A: Timer/Counter #3 Control Register
47 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
50 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
51 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
55 #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1);
56 #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0));
59 // Fast PWM Mode Controls
62 #define TIMER_3_PERIOD ICR3
63 #define TIMER_3_DUTY_CYCLE OCR3A
67 #define TIMER_1_PERIOD ICR1
68 #define TIMER_1_DUTY_CYCLE OCR1A
72 // -----------------------------------------------------------------------------
78 float frequency_alt = 0;
82 float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
83 int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
89 uint16_t sample_length = 0;
91 bool playing_notes = false;
92 bool playing_note = false;
93 float note_frequency = 0;
94 float note_length = 0;
95 uint8_t note_tempo = TEMPO_DEFAULT;
96 float note_timbre = TIMBRE_DEFAULT;
97 uint16_t note_position = 0;
98 float (* notes_pointer)[][2];
102 bool note_resting = false;
104 uint8_t current_note = 0;
105 uint8_t rest_counter = 0;
107 #ifdef VIBRATO_ENABLE
108 float vibrato_counter = 0;
109 float vibrato_strength = .5;
110 float vibrato_rate = 0.125;
113 float polyphony_rate = 0;
115 static bool audio_initialized = false;
117 audio_config_t audio_config;
119 uint16_t envelope_index = 0;
120 bool glissando = true;
126 if (!eeconfig_is_enabled())
130 audio_config.raw = eeconfig_read_audio();
132 // Set port PC6 (OC3A and /OC4A) as output
138 PORTC &= ~_BV(PORTC6);
145 PORTB &= ~_BV(PORTB5);
149 DISABLE_AUDIO_COUNTER_3_ISR;
153 DISABLE_AUDIO_COUNTER_1_ISR;
156 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
157 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
158 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
159 // Clock Select (CS3n) = 0b010 = Clock / 8
162 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
163 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
167 TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
168 TCCR1B = (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
171 audio_initialized = true;
174 void stop_all_notes()
176 dprintf("audio stop all notes");
178 if (!audio_initialized) {
185 DISABLE_AUDIO_COUNTER_3_ISR;
186 DISABLE_AUDIO_COUNTER_3_OUTPUT;
190 DISABLE_AUDIO_COUNTER_1_ISR;
191 DISABLE_AUDIO_COUNTER_1_OUTPUT;
194 playing_notes = false;
195 playing_note = false;
200 for (uint8_t i = 0; i < 8; i++)
207 void stop_note(float freq)
209 dprintf("audio stop note freq=%d", (int)freq);
212 if (!audio_initialized) {
215 for (int i = 7; i >= 0; i--) {
216 if (frequencies[i] == freq) {
219 for (int j = i; (j < 7); j++) {
220 frequencies[j] = frequencies[j+1];
221 frequencies[j+1] = 0;
222 volumes[j] = volumes[j+1];
231 if (voice_place >= voices) {
236 DISABLE_AUDIO_COUNTER_3_ISR;
237 DISABLE_AUDIO_COUNTER_3_OUTPUT;
240 DISABLE_AUDIO_COUNTER_1_ISR;
241 DISABLE_AUDIO_COUNTER_1_OUTPUT;
246 playing_note = false;
251 #ifdef VIBRATO_ENABLE
253 float mod(float a, int b)
255 float r = fmod(a, b);
256 return r < 0 ? r + b : r;
259 float vibrato(float average_freq) {
260 #ifdef VIBRATO_STRENGTH_ENABLE
261 float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
263 float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
265 vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
266 return vibrated_freq;
272 ISR(TIMER3_COMPA_vect)
274 float freq, freq_alt = 0;
281 if (polyphony_rate == 0) {
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);
288 frequency_alt = frequencies[voices - 2];
291 frequency_alt = frequencies[voices - 2];
294 #ifdef VIBRATO_ENABLE
295 if (vibrato_strength > 0) {
296 freq_alt = vibrato(frequency_alt);
298 freq_alt = frequency_alt;
301 freq_alt = frequency_alt;
305 if (envelope_index < 65535) {
309 freq_alt = voice_envelope(freq_alt);
311 if (freq_alt < 30.517578125) {
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);
320 if (polyphony_rate > 0) {
322 voice_place %= voices;
323 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
324 voice_place = (voice_place + 1) % voices;
329 #ifdef VIBRATO_ENABLE
330 if (vibrato_strength > 0) {
331 freq = vibrato(frequencies[voice_place]);
333 freq = frequencies[voice_place];
336 freq = frequencies[voice_place];
340 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
341 frequency = frequency * pow(2, 440/frequency/12/2);
342 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
343 frequency = frequency * pow(2, -440/frequency/12/2);
345 frequency = frequencies[voices - 1];
348 frequency = frequencies[voices - 1];
351 #ifdef VIBRATO_ENABLE
352 if (vibrato_strength > 0) {
353 freq = vibrato(frequency);
362 if (envelope_index < 65535) {
366 freq = voice_envelope(freq);
368 if (freq < 30.517578125) {
372 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
373 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
378 if (note_frequency > 0) {
379 #ifdef VIBRATO_ENABLE
380 if (vibrato_strength > 0) {
381 freq = vibrato(note_frequency);
383 freq = note_frequency;
386 freq = note_frequency;
389 if (envelope_index < 65535) {
392 freq = voice_envelope(freq);
394 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
395 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
398 TIMER_3_DUTY_CYCLE = 0;
402 bool end_of_note = false;
403 if (TIMER_3_PERIOD > 0) {
404 end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF));
406 end_of_note = (note_position >= (note_length * 0x7FF));
411 if (current_note >= notes_count) {
415 DISABLE_AUDIO_COUNTER_3_ISR;
416 DISABLE_AUDIO_COUNTER_3_OUTPUT;
417 playing_notes = false;
421 if (!note_resting && (notes_rest > 0)) {
424 note_length = notes_rest;
427 note_resting = false;
429 note_frequency = (*notes_pointer)[current_note][0];
430 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
437 if (!audio_config.enable) {
438 playing_notes = false;
439 playing_note = false;
444 ISR(TIMER1_COMPA_vect)
446 #if defined(B5_AUDIO) && !defined(C6_AUDIO)
451 if (polyphony_rate > 0) {
453 voice_place %= voices;
454 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
455 voice_place = (voice_place + 1) % voices;
460 #ifdef VIBRATO_ENABLE
461 if (vibrato_strength > 0) {
462 freq = vibrato(frequencies[voice_place]);
464 freq = frequencies[voice_place];
467 freq = frequencies[voice_place];
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);
476 frequency = frequencies[voices - 1];
479 frequency = frequencies[voices - 1];
482 #ifdef VIBRATO_ENABLE
483 if (vibrato_strength > 0) {
484 freq = vibrato(frequency);
493 if (envelope_index < 65535) {
497 freq = voice_envelope(freq);
499 if (freq < 30.517578125) {
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);
509 if (note_frequency > 0) {
510 #ifdef VIBRATO_ENABLE
511 if (vibrato_strength > 0) {
512 freq = vibrato(note_frequency);
514 freq = note_frequency;
517 freq = note_frequency;
520 if (envelope_index < 65535) {
523 freq = voice_envelope(freq);
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);
529 TIMER_1_DUTY_CYCLE = 0;
533 bool end_of_note = false;
534 if (TIMER_1_PERIOD > 0) {
535 end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF));
537 end_of_note = (note_position >= (note_length * 0x7FF));
542 if (current_note >= notes_count) {
546 DISABLE_AUDIO_COUNTER_1_ISR;
547 DISABLE_AUDIO_COUNTER_1_OUTPUT;
548 playing_notes = false;
552 if (!note_resting && (notes_rest > 0)) {
555 note_length = notes_rest;
558 note_resting = false;
560 note_frequency = (*notes_pointer)[current_note][0];
561 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
568 if (!audio_config.enable) {
569 playing_notes = false;
570 playing_note = false;
575 void play_note(float freq, int vol) {
577 dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
579 if (!audio_initialized) {
583 if (audio_config.enable && voices < 8) {
585 DISABLE_AUDIO_COUNTER_3_ISR;
588 DISABLE_AUDIO_COUNTER_1_ISR;
591 // Cancel notes if notes are playing
600 frequencies[voices] = freq;
601 volumes[voices] = vol;
606 ENABLE_AUDIO_COUNTER_3_ISR;
607 ENABLE_AUDIO_COUNTER_3_OUTPUT;
612 ENABLE_AUDIO_COUNTER_1_ISR;
613 ENABLE_AUDIO_COUNTER_1_OUTPUT;
616 ENABLE_AUDIO_COUNTER_1_ISR;
617 ENABLE_AUDIO_COUNTER_1_OUTPUT;
624 void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
627 if (!audio_initialized) {
631 if (audio_config.enable) {
634 DISABLE_AUDIO_COUNTER_3_ISR;
637 DISABLE_AUDIO_COUNTER_1_ISR;
640 // Cancel note if a note is playing
644 playing_notes = true;
647 notes_count = n_count;
648 notes_repeat = n_repeat;
654 note_frequency = (*notes_pointer)[current_note][0];
655 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
660 ENABLE_AUDIO_COUNTER_3_ISR;
661 ENABLE_AUDIO_COUNTER_3_OUTPUT;
665 ENABLE_AUDIO_COUNTER_1_ISR;
666 ENABLE_AUDIO_COUNTER_1_OUTPUT;
673 bool is_playing_notes(void) {
674 return playing_notes;
677 bool is_audio_on(void) {
678 return (audio_config.enable != 0);
681 void audio_toggle(void) {
682 audio_config.enable ^= 1;
683 eeconfig_update_audio(audio_config.raw);
684 if (audio_config.enable)
688 void audio_on(void) {
689 audio_config.enable = 1;
690 eeconfig_update_audio(audio_config.raw);
694 void audio_off(void) {
695 audio_config.enable = 0;
696 eeconfig_update_audio(audio_config.raw);
699 #ifdef VIBRATO_ENABLE
701 // Vibrato rate functions
703 void set_vibrato_rate(float rate) {
707 void increase_vibrato_rate(float change) {
708 vibrato_rate *= change;
711 void decrease_vibrato_rate(float change) {
712 vibrato_rate /= change;
715 #ifdef VIBRATO_STRENGTH_ENABLE
717 void set_vibrato_strength(float strength) {
718 vibrato_strength = strength;
721 void increase_vibrato_strength(float change) {
722 vibrato_strength *= change;
725 void decrease_vibrato_strength(float change) {
726 vibrato_strength /= change;
729 #endif /* VIBRATO_STRENGTH_ENABLE */
731 #endif /* VIBRATO_ENABLE */
733 // Polyphony functions
735 void set_polyphony_rate(float rate) {
736 polyphony_rate = rate;
739 void enable_polyphony() {
743 void disable_polyphony() {
747 void increase_polyphony_rate(float change) {
748 polyphony_rate *= change;
751 void decrease_polyphony_rate(float change) {
752 polyphony_rate /= change;
757 void set_timbre(float timbre) {
758 note_timbre = timbre;
763 void set_tempo(uint8_t tempo) {
767 void decrease_tempo(uint8_t tempo_change) {
768 note_tempo += tempo_change;
771 void increase_tempo(uint8_t tempo_change) {
772 if (note_tempo - tempo_change < 10) {
775 note_tempo -= tempo_change;