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 //Currently we support timers 1 and 3 used at the sime time, channels A-C,
39 //pins PB5, PB6, PB7, PC4, PC5, and PC6
42 #define CPIN_SET_DIRECTION DDRC |= _BV(PORTC6);
43 #define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
44 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
45 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
46 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
47 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
48 #define TIMER_3_PERIOD ICR3
49 #define TIMER_3_DUTY_CYCLE OCR3A
50 #define TIMER3_AUDIO_vect TIMER3_COMPA_vect
54 #define CPIN_SET_DIRECTION DDRC |= _BV(PORTC5);
55 #define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3B1) | (0 << COM3B0) | (1 << WGM31) | (0 << WGM30);
56 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3B)
57 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3B)
58 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3B1);
59 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3B1) | _BV(COM3B0));
60 #define TIMER_3_PERIOD ICR3
61 #define TIMER_3_DUTY_CYCLE OCR3B
62 #define TIMER3_AUDIO_vect TIMER3_COMPB_vect
66 #define CPIN_SET_DIRECTION DDRC |= _BV(PORTC4);
67 #define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3C1) | (0 << COM3C0) | (1 << WGM31) | (0 << WGM30);
68 #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3C)
69 #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3C)
70 #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3C1);
71 #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3C1) | _BV(COM3C0));
72 #define TIMER_3_PERIOD ICR3
73 #define TIMER_3_DUTY_CYCLE OCR3C
74 #define TIMER3_AUDIO_vect TIMER3_COMPC_vect
79 #define BPIN_SET_DIRECTION DDRC |= _BV(PORTB5);
80 #define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
81 #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
82 #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
83 #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1);
84 #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0));
85 #define TIMER_1_PERIOD ICR1
86 #define TIMER_1_DUTY_CYCLE OCR1A
87 #define TIMER1_AUDIO_vect TIMER1_COMPA_vect
91 #define BPIN_SET_DIRECTION DDRC |= _BV(PORTB6);
92 #define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1B1) | (0 << COM1B0) | (1 << WGM11) | (0 << WGM10);
93 #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1B)
94 #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1B)
95 #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1B1);
96 #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1B1) | _BV(COM1B0));
97 #define TIMER_1_PERIOD ICR1
98 #define TIMER_1_DUTY_CYCLE OCR1B
99 #define TIMER1_AUDIO_vect TIMER1_COMPB_vect
101 #if defined(B7_AUDIO)
103 #define BPIN_SET_DIRECTION DDRC |= _BV(PORTB7);
104 #define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1C1) | (0 << COM1C0) | (1 << WGM11) | (0 << WGM10);
105 #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1C)
106 #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1C)
107 #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1C1);
108 #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1C1) | _BV(COM1C0));
109 #define TIMER_1_PERIOD ICR1
110 #define TIMER_1_DUTY_CYCLE OCR1C
111 #define TIMER1_AUDIO_vect TIMER1_COMPC_vect
113 // -----------------------------------------------------------------------------
119 float frequency_alt
= 0;
123 float frequencies
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
124 int volumes
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
125 bool sliding
= false;
130 uint16_t sample_length
= 0;
132 bool playing_notes
= false;
133 bool playing_note
= false;
134 float note_frequency
= 0;
135 float note_length
= 0;
136 uint8_t note_tempo
= TEMPO_DEFAULT
;
137 float note_timbre
= TIMBRE_DEFAULT
;
138 uint16_t note_position
= 0;
139 float (* notes_pointer
)[][2];
140 uint16_t notes_count
;
142 bool note_resting
= false;
144 uint8_t current_note
= 0;
145 uint8_t rest_counter
= 0;
147 #ifdef VIBRATO_ENABLE
148 float vibrato_counter
= 0;
149 float vibrato_strength
= .5;
150 float vibrato_rate
= 0.125;
153 float polyphony_rate
= 0;
155 static bool audio_initialized
= false;
157 audio_config_t audio_config
;
159 uint16_t envelope_index
= 0;
160 bool glissando
= true;
163 #define STARTUP_SONG SONG(STARTUP_SOUND)
165 #ifndef AUDIO_ON_SONG
166 #define AUDIO_ON_SONG SONG(AUDIO_ON_SOUND)
168 #ifndef AUDIO_OFF_SONG
169 #define AUDIO_OFF_SONG SONG(AUDIO_OFF_SOUND)
171 float startup_song
[][2] = STARTUP_SONG
;
172 float audio_on_song
[][2] = AUDIO_ON_SONG
;
173 float audio_off_song
[][2] = AUDIO_OFF_SONG
;
179 if (!eeconfig_is_enabled())
183 audio_config
.raw
= eeconfig_read_audio();
185 if (!audio_initialized
) {
187 // Set audio ports as output
196 DISABLE_AUDIO_COUNTER_3_ISR
;
199 DISABLE_AUDIO_COUNTER_1_ISR
;
202 // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers TCCR3A/TCCR3B, TCCR1A/TCCR1B
203 // Compare Output Mode (COM3An and COM1An) = 0b00 = Normal port operation
211 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14. Period = ICR3, Duty Cycle OCR3A)
219 // Clock Select (CS3n) = 0b010 = Clock / 8
222 TCCR3B
= (1 << WGM33
) | (1 << WGM32
) | (0 << CS32
) | (1 << CS31
) | (0 << CS30
);
223 TIMER_3_PERIOD
= (uint16_t)(((float)F_CPU
) / (440 * CPU_PRESCALER
));
224 TIMER_3_DUTY_CYCLE
= (uint16_t)((((float)F_CPU
) / (440 * CPU_PRESCALER
)) * note_timbre
);
228 TCCR1B
= (1 << WGM13
) | (1 << WGM12
) | (0 << CS12
) | (1 << CS11
) | (0 << CS10
);
229 TIMER_1_PERIOD
= (uint16_t)(((float)F_CPU
) / (440 * CPU_PRESCALER
));
230 TIMER_1_DUTY_CYCLE
= (uint16_t)((((float)F_CPU
) / (440 * CPU_PRESCALER
)) * note_timbre
);
233 audio_initialized
= true;
236 if (audio_config
.enable
) {
237 PLAY_SONG(startup_song
);
242 void stop_all_notes()
244 dprintf("audio stop all notes");
246 if (!audio_initialized
) {
252 DISABLE_AUDIO_COUNTER_3_ISR
;
253 DISABLE_AUDIO_COUNTER_3_OUTPUT
;
257 DISABLE_AUDIO_COUNTER_1_ISR
;
258 DISABLE_AUDIO_COUNTER_1_OUTPUT
;
261 playing_notes
= false;
262 playing_note
= false;
267 for (uint8_t i
= 0; i
< 8; i
++)
274 void stop_note(float freq
)
276 dprintf("audio stop note freq=%d", (int)freq
);
279 if (!audio_initialized
) {
282 for (int i
= 7; i
>= 0; i
--) {
283 if (frequencies
[i
] == freq
) {
286 for (int j
= i
; (j
< 7); j
++) {
287 frequencies
[j
] = frequencies
[j
+1];
288 frequencies
[j
+1] = 0;
289 volumes
[j
] = volumes
[j
+1];
298 if (voice_place
>= voices
) {
303 DISABLE_AUDIO_COUNTER_3_ISR
;
304 DISABLE_AUDIO_COUNTER_3_OUTPUT
;
307 DISABLE_AUDIO_COUNTER_1_ISR
;
308 DISABLE_AUDIO_COUNTER_1_OUTPUT
;
313 playing_note
= false;
318 #ifdef VIBRATO_ENABLE
320 float mod(float a
, int b
)
322 float r
= fmod(a
, b
);
323 return r
< 0 ? r
+ b
: r
;
326 float vibrato(float average_freq
) {
327 #ifdef VIBRATO_STRENGTH_ENABLE
328 float vibrated_freq
= average_freq
* pow(vibrato_lut
[(int)vibrato_counter
], vibrato_strength
);
330 float vibrated_freq
= average_freq
* vibrato_lut
[(int)vibrato_counter
];
332 vibrato_counter
= mod((vibrato_counter
+ vibrato_rate
* (1.0 + 440.0/average_freq
)), VIBRATO_LUT_LENGTH
);
333 return vibrated_freq
;
339 ISR(TIMER3_AUDIO_vect
)
349 if (polyphony_rate
== 0) {
351 if (frequency_alt
!= 0 && frequency_alt
< frequencies
[voices
- 2] && frequency_alt
< frequencies
[voices
- 2] * pow(2, -440/frequencies
[voices
- 2]/12/2)) {
352 frequency_alt
= frequency_alt
* pow(2, 440/frequency_alt
/12/2);
353 } else if (frequency_alt
!= 0 && frequency_alt
> frequencies
[voices
- 2] && frequency_alt
> frequencies
[voices
- 2] * pow(2, 440/frequencies
[voices
- 2]/12/2)) {
354 frequency_alt
= frequency_alt
* pow(2, -440/frequency_alt
/12/2);
356 frequency_alt
= frequencies
[voices
- 2];
359 frequency_alt
= frequencies
[voices
- 2];
362 #ifdef VIBRATO_ENABLE
363 if (vibrato_strength
> 0) {
364 freq_alt
= vibrato(frequency_alt
);
366 freq_alt
= frequency_alt
;
369 freq_alt
= frequency_alt
;
373 if (envelope_index
< 65535) {
377 freq_alt
= voice_envelope(freq_alt
);
379 if (freq_alt
< 30.517578125) {
383 TIMER_1_PERIOD
= (uint16_t)(((float)F_CPU
) / (freq_alt
* CPU_PRESCALER
));
384 TIMER_1_DUTY_CYCLE
= (uint16_t)((((float)F_CPU
) / (freq_alt
* CPU_PRESCALER
)) * note_timbre
);
388 if (polyphony_rate
> 0) {
390 voice_place
%= voices
;
391 if (place
++ > (frequencies
[voice_place
] / polyphony_rate
/ CPU_PRESCALER
)) {
392 voice_place
= (voice_place
+ 1) % voices
;
397 #ifdef VIBRATO_ENABLE
398 if (vibrato_strength
> 0) {
399 freq
= vibrato(frequencies
[voice_place
]);
401 freq
= frequencies
[voice_place
];
404 freq
= frequencies
[voice_place
];
408 if (frequency
!= 0 && frequency
< frequencies
[voices
- 1] && frequency
< frequencies
[voices
- 1] * pow(2, -440/frequencies
[voices
- 1]/12/2)) {
409 frequency
= frequency
* pow(2, 440/frequency
/12/2);
410 } else if (frequency
!= 0 && frequency
> frequencies
[voices
- 1] && frequency
> frequencies
[voices
- 1] * pow(2, 440/frequencies
[voices
- 1]/12/2)) {
411 frequency
= frequency
* pow(2, -440/frequency
/12/2);
413 frequency
= frequencies
[voices
- 1];
416 frequency
= frequencies
[voices
- 1];
419 #ifdef VIBRATO_ENABLE
420 if (vibrato_strength
> 0) {
421 freq
= vibrato(frequency
);
430 if (envelope_index
< 65535) {
434 freq
= voice_envelope(freq
);
436 if (freq
< 30.517578125) {
440 TIMER_3_PERIOD
= (uint16_t)(((float)F_CPU
) / (freq
* CPU_PRESCALER
));
441 TIMER_3_DUTY_CYCLE
= (uint16_t)((((float)F_CPU
) / (freq
* CPU_PRESCALER
)) * note_timbre
);
446 if (note_frequency
> 0) {
447 #ifdef VIBRATO_ENABLE
448 if (vibrato_strength
> 0) {
449 freq
= vibrato(note_frequency
);
451 freq
= note_frequency
;
454 freq
= note_frequency
;
457 if (envelope_index
< 65535) {
460 freq
= voice_envelope(freq
);
462 TIMER_3_PERIOD
= (uint16_t)(((float)F_CPU
) / (freq
* CPU_PRESCALER
));
463 TIMER_3_DUTY_CYCLE
= (uint16_t)((((float)F_CPU
) / (freq
* CPU_PRESCALER
)) * note_timbre
);
466 TIMER_3_DUTY_CYCLE
= 0;
470 bool end_of_note
= false;
471 if (TIMER_3_PERIOD
> 0) {
473 end_of_note
= (note_position
>= (note_length
/ TIMER_3_PERIOD
* 0xFFFF - 1));
475 end_of_note
= (note_position
>= (note_length
));
477 end_of_note
= (note_position
>= (note_length
));
482 if (current_note
>= notes_count
) {
486 DISABLE_AUDIO_COUNTER_3_ISR
;
487 DISABLE_AUDIO_COUNTER_3_OUTPUT
;
488 playing_notes
= false;
495 if ((*notes_pointer
)[current_note
][0] == (*notes_pointer
)[current_note
+ 1][0]) {
499 note_frequency
= (*notes_pointer
)[current_note
][0];
503 note_resting
= false;
505 note_frequency
= (*notes_pointer
)[current_note
][0];
506 note_length
= ((*notes_pointer
)[current_note
][1] / 4) * (((float)note_tempo
) / 100);
513 if (!audio_config
.enable
) {
514 playing_notes
= false;
515 playing_note
= false;
521 ISR(TIMER1_AUDIO_vect
)
523 #if defined(BPIN_AUDIO) && !defined(CPIN_AUDIO)
528 if (polyphony_rate
> 0) {
530 voice_place
%= voices
;
531 if (place
++ > (frequencies
[voice_place
] / polyphony_rate
/ CPU_PRESCALER
)) {
532 voice_place
= (voice_place
+ 1) % voices
;
537 #ifdef VIBRATO_ENABLE
538 if (vibrato_strength
> 0) {
539 freq
= vibrato(frequencies
[voice_place
]);
541 freq
= frequencies
[voice_place
];
544 freq
= frequencies
[voice_place
];
548 if (frequency
!= 0 && frequency
< frequencies
[voices
- 1] && frequency
< frequencies
[voices
- 1] * pow(2, -440/frequencies
[voices
- 1]/12/2)) {
549 frequency
= frequency
* pow(2, 440/frequency
/12/2);
550 } else if (frequency
!= 0 && frequency
> frequencies
[voices
- 1] && frequency
> frequencies
[voices
- 1] * pow(2, 440/frequencies
[voices
- 1]/12/2)) {
551 frequency
= frequency
* pow(2, -440/frequency
/12/2);
553 frequency
= frequencies
[voices
- 1];
556 frequency
= frequencies
[voices
- 1];
559 #ifdef VIBRATO_ENABLE
560 if (vibrato_strength
> 0) {
561 freq
= vibrato(frequency
);
570 if (envelope_index
< 65535) {
574 freq
= voice_envelope(freq
);
576 if (freq
< 30.517578125) {
580 TIMER_1_PERIOD
= (uint16_t)(((float)F_CPU
) / (freq
* CPU_PRESCALER
));
581 TIMER_1_DUTY_CYCLE
= (uint16_t)((((float)F_CPU
) / (freq
* CPU_PRESCALER
)) * note_timbre
);
586 if (note_frequency
> 0) {
587 #ifdef VIBRATO_ENABLE
588 if (vibrato_strength
> 0) {
589 freq
= vibrato(note_frequency
);
591 freq
= note_frequency
;
594 freq
= note_frequency
;
597 if (envelope_index
< 65535) {
600 freq
= voice_envelope(freq
);
602 TIMER_1_PERIOD
= (uint16_t)(((float)F_CPU
) / (freq
* CPU_PRESCALER
));
603 TIMER_1_DUTY_CYCLE
= (uint16_t)((((float)F_CPU
) / (freq
* CPU_PRESCALER
)) * note_timbre
);
606 TIMER_1_DUTY_CYCLE
= 0;
610 bool end_of_note
= false;
611 if (TIMER_1_PERIOD
> 0) {
613 end_of_note
= (note_position
>= (note_length
/ TIMER_1_PERIOD
* 0xFFFF - 1));
615 end_of_note
= (note_position
>= (note_length
));
617 end_of_note
= (note_position
>= (note_length
));
622 if (current_note
>= notes_count
) {
626 DISABLE_AUDIO_COUNTER_1_ISR
;
627 DISABLE_AUDIO_COUNTER_1_OUTPUT
;
628 playing_notes
= false;
635 if ((*notes_pointer
)[current_note
][0] == (*notes_pointer
)[current_note
+ 1][0]) {
639 note_frequency
= (*notes_pointer
)[current_note
][0];
643 note_resting
= false;
645 note_frequency
= (*notes_pointer
)[current_note
][0];
646 note_length
= ((*notes_pointer
)[current_note
][1] / 4) * (((float)note_tempo
) / 100);
653 if (!audio_config
.enable
) {
654 playing_notes
= false;
655 playing_note
= false;
661 void play_note(float freq
, int vol
) {
663 dprintf("audio play note freq=%d vol=%d", (int)freq
, vol
);
665 if (!audio_initialized
) {
669 if (audio_config
.enable
&& voices
< 8) {
671 DISABLE_AUDIO_COUNTER_3_ISR
;
674 DISABLE_AUDIO_COUNTER_1_ISR
;
677 // Cancel notes if notes are playing
686 frequencies
[voices
] = freq
;
687 volumes
[voices
] = vol
;
692 ENABLE_AUDIO_COUNTER_3_ISR
;
693 ENABLE_AUDIO_COUNTER_3_OUTPUT
;
698 ENABLE_AUDIO_COUNTER_1_ISR
;
699 ENABLE_AUDIO_COUNTER_1_OUTPUT
;
702 ENABLE_AUDIO_COUNTER_1_ISR
;
703 ENABLE_AUDIO_COUNTER_1_OUTPUT
;
710 void play_notes(float (*np
)[][2], uint16_t n_count
, bool n_repeat
)
713 if (!audio_initialized
) {
717 if (audio_config
.enable
) {
720 DISABLE_AUDIO_COUNTER_3_ISR
;
723 DISABLE_AUDIO_COUNTER_1_ISR
;
726 // Cancel note if a note is playing
730 playing_notes
= true;
733 notes_count
= n_count
;
734 notes_repeat
= n_repeat
;
739 note_frequency
= (*notes_pointer
)[current_note
][0];
740 note_length
= ((*notes_pointer
)[current_note
][1] / 4) * (((float)note_tempo
) / 100);
745 ENABLE_AUDIO_COUNTER_3_ISR
;
746 ENABLE_AUDIO_COUNTER_3_OUTPUT
;
750 ENABLE_AUDIO_COUNTER_1_ISR
;
751 ENABLE_AUDIO_COUNTER_1_OUTPUT
;
758 bool is_playing_notes(void) {
759 return playing_notes
;
762 bool is_audio_on(void) {
763 return (audio_config
.enable
!= 0);
766 void audio_toggle(void) {
767 audio_config
.enable
^= 1;
768 eeconfig_update_audio(audio_config
.raw
);
769 if (audio_config
.enable
)
773 void audio_on(void) {
774 audio_config
.enable
= 1;
775 eeconfig_update_audio(audio_config
.raw
);
777 PLAY_SONG(audio_on_song
);
780 void audio_off(void) {
781 PLAY_SONG(audio_off_song
);
784 audio_config
.enable
= 0;
785 eeconfig_update_audio(audio_config
.raw
);
788 #ifdef VIBRATO_ENABLE
790 // Vibrato rate functions
792 void set_vibrato_rate(float rate
) {
796 void increase_vibrato_rate(float change
) {
797 vibrato_rate
*= change
;
800 void decrease_vibrato_rate(float change
) {
801 vibrato_rate
/= change
;
804 #ifdef VIBRATO_STRENGTH_ENABLE
806 void set_vibrato_strength(float strength
) {
807 vibrato_strength
= strength
;
810 void increase_vibrato_strength(float change
) {
811 vibrato_strength
*= change
;
814 void decrease_vibrato_strength(float change
) {
815 vibrato_strength
/= change
;
818 #endif /* VIBRATO_STRENGTH_ENABLE */
820 #endif /* VIBRATO_ENABLE */
822 // Polyphony functions
824 void set_polyphony_rate(float rate
) {
825 polyphony_rate
= rate
;
828 void enable_polyphony() {
832 void disable_polyphony() {
836 void increase_polyphony_rate(float change
) {
837 polyphony_rate
*= change
;
840 void decrease_polyphony_rate(float change
) {
841 polyphony_rate
/= change
;
846 void set_timbre(float timbre
) {
847 note_timbre
= timbre
;
852 void set_tempo(uint8_t tempo
) {
856 void decrease_tempo(uint8_t tempo_change
) {
857 note_tempo
+= tempo_change
;
860 void increase_tempo(uint8_t tempo_change
) {
861 if (note_tempo
- tempo_change
< 10) {
864 note_tempo
-= tempo_change
;