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
;