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/>.
21 #include <avr/pgmspace.h>
22 #include <avr/interrupt.h>
32 #define CPU_PRESCALER 8
34 // -----------------------------------------------------------------------------
36 // -----------------------------------------------------------------------------
38 // TIMSK3 - Timer/Counter #3 Interrupt Mask Register
39 // Turn on/off 3A interputs, stopping/enabling the ISR calls
41 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
42 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
46 #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
47 #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
50 // TCCR3A: Timer/Counter #3 Control Register
51 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
54 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
55 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
59 #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1);
60 #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0));
63 // Fast PWM Mode Controls
66 #define TIMER_3_PERIOD ICR3
67 #define TIMER_3_DUTY_CYCLE OCR3A
71 #define TIMER_1_PERIOD ICR1
72 #define TIMER_1_DUTY_CYCLE OCR1A
76 // -----------------------------------------------------------------------------
82 float frequency_alt = 0;
86 float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
87 int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
93 uint16_t sample_length = 0;
95 bool playing_notes = false;
96 bool playing_note = false;
97 float note_frequency = 0;
98 float note_length = 0;
99 uint8_t note_tempo = TEMPO_DEFAULT;
100 float note_timbre = TIMBRE_DEFAULT;
101 uint16_t note_position = 0;
102 float (* notes_pointer)[][2];
103 uint16_t notes_count;
105 bool note_resting = false;
107 uint8_t current_note = 0;
108 uint8_t rest_counter = 0;
110 #ifdef VIBRATO_ENABLE
111 float vibrato_counter = 0;
112 float vibrato_strength = .5;
113 float vibrato_rate = 0.125;
116 float polyphony_rate = 0;
118 static bool audio_initialized = false;
120 audio_config_t audio_config;
122 uint16_t envelope_index = 0;
123 bool glissando = true;
126 #define STARTUP_SONG SONG(STARTUP_SOUND)
128 #ifndef AUDIO_ON_SONG
129 #define AUDIO_ON_SONG SONG(AUDIO_ON_SOUND)
131 #ifndef AUDIO_OFF_SONG
132 #define AUDIO_OFF_SONG SONG(AUDIO_OFF_SOUND)
134 float startup_song[][2] = STARTUP_SONG;
135 float audio_on_song[][2] = AUDIO_ON_SONG;
136 float audio_off_song[][2] = AUDIO_OFF_SONG;
142 if (!eeconfig_is_enabled())
146 audio_config.raw = eeconfig_read_audio();
148 if (!audio_initialized) {
150 // Set port PC6 (OC3A and /OC4A) as output
155 // DDRC |= _BV(PORTC6); // Why is PC6 being set as output low, if C6_audio isn't defined?
156 // PORTC &= ~_BV(PORTC6);
162 // DDRB |= _BV(PORTB5); // Same as with PC6
163 // PORTB &= ~_BV(PORTB5);
167 DISABLE_AUDIO_COUNTER_3_ISR;
171 DISABLE_AUDIO_COUNTER_1_ISR;
174 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
175 // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
176 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
177 // Clock Select (CS3n) = 0b010 = Clock / 8
180 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
181 TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
185 TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
186 TCCR1B = (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
188 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (440 * CPU_PRESCALER));
189 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre);
192 audio_initialized = true;
195 if (audio_config.enable) {
196 PLAY_SONG(startup_song);
201 void stop_all_notes()
203 dprintf("audio stop all notes");
205 if (!audio_initialized) {
212 DISABLE_AUDIO_COUNTER_3_ISR;
213 DISABLE_AUDIO_COUNTER_3_OUTPUT;
217 DISABLE_AUDIO_COUNTER_1_ISR;
218 DISABLE_AUDIO_COUNTER_1_OUTPUT;
221 playing_notes = false;
222 playing_note = false;
227 for (uint8_t i = 0; i < 8; i++)
234 void stop_note(float freq)
236 dprintf("audio stop note freq=%d", (int)freq);
239 if (!audio_initialized) {
242 for (int i = 7; i >= 0; i--) {
243 if (frequencies[i] == freq) {
246 for (int j = i; (j < 7); j++) {
247 frequencies[j] = frequencies[j+1];
248 frequencies[j+1] = 0;
249 volumes[j] = volumes[j+1];
258 if (voice_place >= voices) {
263 DISABLE_AUDIO_COUNTER_3_ISR;
264 DISABLE_AUDIO_COUNTER_3_OUTPUT;
267 DISABLE_AUDIO_COUNTER_1_ISR;
268 DISABLE_AUDIO_COUNTER_1_OUTPUT;
273 playing_note = false;
278 #ifdef VIBRATO_ENABLE
280 float mod(float a, int b)
282 float r = fmod(a, b);
283 return r < 0 ? r + b : r;
286 float vibrato(float average_freq) {
287 #ifdef VIBRATO_STRENGTH_ENABLE
288 float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
290 float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
292 vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
293 return vibrated_freq;
299 ISR(TIMER3_COMPA_vect)
309 if (polyphony_rate == 0) {
311 if (frequency_alt != 0 && frequency_alt < frequencies[voices - 2] && frequency_alt < frequencies[voices - 2] * pow(2, -440/frequencies[voices - 2]/12/2)) {
312 frequency_alt = frequency_alt * pow(2, 440/frequency_alt/12/2);
313 } else if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440/frequencies[voices - 2]/12/2)) {
314 frequency_alt = frequency_alt * pow(2, -440/frequency_alt/12/2);
316 frequency_alt = frequencies[voices - 2];
319 frequency_alt = frequencies[voices - 2];
322 #ifdef VIBRATO_ENABLE
323 if (vibrato_strength > 0) {
324 freq_alt = vibrato(frequency_alt);
326 freq_alt = frequency_alt;
329 freq_alt = frequency_alt;
333 if (envelope_index < 65535) {
337 freq_alt = voice_envelope(freq_alt);
339 if (freq_alt < 30.517578125) {
343 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq_alt * CPU_PRESCALER));
344 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq_alt * CPU_PRESCALER)) * note_timbre);
348 if (polyphony_rate > 0) {
350 voice_place %= voices;
351 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
352 voice_place = (voice_place + 1) % voices;
357 #ifdef VIBRATO_ENABLE
358 if (vibrato_strength > 0) {
359 freq = vibrato(frequencies[voice_place]);
361 freq = frequencies[voice_place];
364 freq = frequencies[voice_place];
368 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
369 frequency = frequency * pow(2, 440/frequency/12/2);
370 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
371 frequency = frequency * pow(2, -440/frequency/12/2);
373 frequency = frequencies[voices - 1];
376 frequency = frequencies[voices - 1];
379 #ifdef VIBRATO_ENABLE
380 if (vibrato_strength > 0) {
381 freq = vibrato(frequency);
390 if (envelope_index < 65535) {
394 freq = voice_envelope(freq);
396 if (freq < 30.517578125) {
400 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
401 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
406 if (note_frequency > 0) {
407 #ifdef VIBRATO_ENABLE
408 if (vibrato_strength > 0) {
409 freq = vibrato(note_frequency);
411 freq = note_frequency;
414 freq = note_frequency;
417 if (envelope_index < 65535) {
420 freq = voice_envelope(freq);
422 TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
423 TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
426 TIMER_3_DUTY_CYCLE = 0;
430 bool end_of_note = false;
431 if (TIMER_3_PERIOD > 0) {
433 end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF - 1));
435 end_of_note = (note_position >= (note_length));
437 end_of_note = (note_position >= (note_length));
442 if (current_note >= notes_count) {
446 DISABLE_AUDIO_COUNTER_3_ISR;
447 DISABLE_AUDIO_COUNTER_3_OUTPUT;
448 playing_notes = false;
455 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
459 note_frequency = (*notes_pointer)[current_note][0];
463 note_resting = false;
465 note_frequency = (*notes_pointer)[current_note][0];
466 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
473 if (!audio_config.enable) {
474 playing_notes = false;
475 playing_note = false;
481 ISR(TIMER1_COMPA_vect)
483 #if defined(B5_AUDIO) && !defined(C6_AUDIO)
488 if (polyphony_rate > 0) {
490 voice_place %= voices;
491 if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
492 voice_place = (voice_place + 1) % voices;
497 #ifdef VIBRATO_ENABLE
498 if (vibrato_strength > 0) {
499 freq = vibrato(frequencies[voice_place]);
501 freq = frequencies[voice_place];
504 freq = frequencies[voice_place];
508 if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
509 frequency = frequency * pow(2, 440/frequency/12/2);
510 } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
511 frequency = frequency * pow(2, -440/frequency/12/2);
513 frequency = frequencies[voices - 1];
516 frequency = frequencies[voices - 1];
519 #ifdef VIBRATO_ENABLE
520 if (vibrato_strength > 0) {
521 freq = vibrato(frequency);
530 if (envelope_index < 65535) {
534 freq = voice_envelope(freq);
536 if (freq < 30.517578125) {
540 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
541 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
546 if (note_frequency > 0) {
547 #ifdef VIBRATO_ENABLE
548 if (vibrato_strength > 0) {
549 freq = vibrato(note_frequency);
551 freq = note_frequency;
554 freq = note_frequency;
557 if (envelope_index < 65535) {
560 freq = voice_envelope(freq);
562 TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
563 TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
566 TIMER_1_DUTY_CYCLE = 0;
570 bool end_of_note = false;
571 if (TIMER_1_PERIOD > 0) {
573 end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF - 1));
575 end_of_note = (note_position >= (note_length));
577 end_of_note = (note_position >= (note_length));
582 if (current_note >= notes_count) {
586 DISABLE_AUDIO_COUNTER_1_ISR;
587 DISABLE_AUDIO_COUNTER_1_OUTPUT;
588 playing_notes = false;
595 if ((*notes_pointer)[current_note][0] == (*notes_pointer)[current_note + 1][0]) {
599 note_frequency = (*notes_pointer)[current_note][0];
603 note_resting = false;
605 note_frequency = (*notes_pointer)[current_note][0];
606 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
613 if (!audio_config.enable) {
614 playing_notes = false;
615 playing_note = false;
621 void play_note(float freq, int vol) {
623 dprintf("audio play note freq=%d vol=%d", (int)freq, vol);
625 if (!audio_initialized) {
629 if (audio_config.enable && voices < 8) {
631 DISABLE_AUDIO_COUNTER_3_ISR;
634 DISABLE_AUDIO_COUNTER_1_ISR;
637 // Cancel notes if notes are playing
646 frequencies[voices] = freq;
647 volumes[voices] = vol;
652 ENABLE_AUDIO_COUNTER_3_ISR;
653 ENABLE_AUDIO_COUNTER_3_OUTPUT;
658 ENABLE_AUDIO_COUNTER_1_ISR;
659 ENABLE_AUDIO_COUNTER_1_OUTPUT;
662 ENABLE_AUDIO_COUNTER_1_ISR;
663 ENABLE_AUDIO_COUNTER_1_OUTPUT;
670 void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat)
673 if (!audio_initialized) {
677 if (audio_config.enable) {
680 DISABLE_AUDIO_COUNTER_3_ISR;
683 DISABLE_AUDIO_COUNTER_1_ISR;
686 // Cancel note if a note is playing
690 playing_notes = true;
693 notes_count = n_count;
694 notes_repeat = n_repeat;
699 note_frequency = (*notes_pointer)[current_note][0];
700 note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
705 ENABLE_AUDIO_COUNTER_3_ISR;
706 ENABLE_AUDIO_COUNTER_3_OUTPUT;
710 ENABLE_AUDIO_COUNTER_1_ISR;
711 ENABLE_AUDIO_COUNTER_1_OUTPUT;
718 bool is_playing_notes(void) {
719 return playing_notes;
722 bool is_audio_on(void) {
723 return (audio_config.enable != 0);
726 void audio_toggle(void) {
727 audio_config.enable ^= 1;
728 eeconfig_update_audio(audio_config.raw);
729 if (audio_config.enable)
733 void audio_on(void) {
734 audio_config.enable = 1;
735 eeconfig_update_audio(audio_config.raw);
737 PLAY_SONG(audio_on_song);
740 void audio_off(void) {
741 PLAY_SONG(audio_off_song);
744 audio_config.enable = 0;
745 eeconfig_update_audio(audio_config.raw);
748 #ifdef VIBRATO_ENABLE
750 // Vibrato rate functions
752 void set_vibrato_rate(float rate) {
756 void increase_vibrato_rate(float change) {
757 vibrato_rate *= change;
760 void decrease_vibrato_rate(float change) {
761 vibrato_rate /= change;
764 #ifdef VIBRATO_STRENGTH_ENABLE
766 void set_vibrato_strength(float strength) {
767 vibrato_strength = strength;
770 void increase_vibrato_strength(float change) {
771 vibrato_strength *= change;
774 void decrease_vibrato_strength(float change) {
775 vibrato_strength /= change;
778 #endif /* VIBRATO_STRENGTH_ENABLE */
780 #endif /* VIBRATO_ENABLE */
782 // Polyphony functions
784 void set_polyphony_rate(float rate) {
785 polyphony_rate = rate;
788 void enable_polyphony() {
792 void disable_polyphony() {
796 void increase_polyphony_rate(float change) {
797 polyphony_rate *= change;
800 void decrease_polyphony_rate(float change) {
801 polyphony_rate /= change;
806 void set_timbre(float timbre) {
807 note_timbre = timbre;
812 void set_tempo(uint8_t tempo) {
816 void decrease_tempo(uint8_t tempo_change) {
817 note_tempo += tempo_change;
820 void increase_tempo(uint8_t tempo_change) {
821 if (note_tempo - tempo_change < 10) {
824 note_tempo -= tempo_change;