|
|
|
@ -127,7 +127,7 @@ bool playing_note = false;
|
|
|
|
|
float note_frequency = 0;
|
|
|
|
|
float note_length = 0;
|
|
|
|
|
uint8_t note_tempo = TEMPO_DEFAULT;
|
|
|
|
|
float note_timbre = TIMBRE_DEFAULT;
|
|
|
|
|
float note_timbre[NUMBER_OF_TIMERS] = {TIMBRE_DEFAULT};
|
|
|
|
|
uint16_t note_position = 0;
|
|
|
|
|
float (* notes_pointer)[][2];
|
|
|
|
|
uint16_t notes_count;
|
|
|
|
@ -149,8 +149,8 @@ static bool audio_initialized = false;
|
|
|
|
|
|
|
|
|
|
audio_config_t audio_config;
|
|
|
|
|
|
|
|
|
|
uint16_t envelope_index = 0;
|
|
|
|
|
bool glissando = true;
|
|
|
|
|
uint16_t envelope_index[NUMBER_OF_TIMERS] = {0};
|
|
|
|
|
bool glissando[NUMBER_OF_TIMERS] = {true};
|
|
|
|
|
|
|
|
|
|
#ifndef STARTUP_SONG
|
|
|
|
|
#define STARTUP_SONG SONG(STARTUP_SOUND)
|
|
|
|
@ -211,7 +211,7 @@ void audio_init()
|
|
|
|
|
DISABLE_AUDIO_COUNTER_3_ISR;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)
|
|
|
|
|
#ifdef B_AUDIO
|
|
|
|
|
DISABLE_AUDIO_COUNTER_1_ISR;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
@ -223,14 +223,17 @@ void audio_init()
|
|
|
|
|
#ifdef C6_AUDIO
|
|
|
|
|
TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
|
|
|
|
|
TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
|
|
|
|
|
|
|
|
|
|
TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (440 * CPU_PRESCALER));
|
|
|
|
|
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre[TIMER_3_INDEX]);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)
|
|
|
|
|
#ifdef B_AUDIO
|
|
|
|
|
TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
|
|
|
|
|
TCCR1B = (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
|
|
|
|
|
|
|
|
|
|
TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (440 * CPU_PRESCALER));
|
|
|
|
|
TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre);
|
|
|
|
|
TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre[TIMER_1_INDEX]);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
audio_initialized = true;
|
|
|
|
@ -257,7 +260,7 @@ void stop_all_notes()
|
|
|
|
|
DISABLE_AUDIO_COUNTER_3_OUTPUT;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)
|
|
|
|
|
#ifdef B_AUDIO
|
|
|
|
|
DISABLE_AUDIO_COUNTER_1_ISR;
|
|
|
|
|
DISABLE_AUDIO_COUNTER_1_OUTPUT;
|
|
|
|
|
#endif
|
|
|
|
@ -302,12 +305,18 @@ void stop_note(float freq)
|
|
|
|
|
if (voice_place >= voices) {
|
|
|
|
|
voice_place = 0;
|
|
|
|
|
}
|
|
|
|
|
if (voices == 1) {
|
|
|
|
|
#if defined(C6_AUDIO) && defined(B_AUDIO)
|
|
|
|
|
DISABLE_AUDIO_COUNTER_1_ISR;
|
|
|
|
|
DISABLE_AUDIO_COUNTER_1_OUTPUT;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
if (voices == 0) {
|
|
|
|
|
#ifdef C6_AUDIO
|
|
|
|
|
DISABLE_AUDIO_COUNTER_3_ISR;
|
|
|
|
|
DISABLE_AUDIO_COUNTER_3_OUTPUT;
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)
|
|
|
|
|
#ifdef B_AUDIO
|
|
|
|
|
DISABLE_AUDIO_COUNTER_1_ISR;
|
|
|
|
|
DISABLE_AUDIO_COUNTER_1_OUTPUT;
|
|
|
|
|
#endif
|
|
|
|
@ -347,11 +356,11 @@ ISR(TIMER3_COMPA_vect)
|
|
|
|
|
if (playing_note) {
|
|
|
|
|
if (voices > 0) {
|
|
|
|
|
|
|
|
|
|
#if defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)
|
|
|
|
|
#ifdef B_AUDIO
|
|
|
|
|
float freq_alt = 0;
|
|
|
|
|
if (voices > 1) {
|
|
|
|
|
if (polyphony_rate == 0) {
|
|
|
|
|
if (glissando) {
|
|
|
|
|
if (glissando[TIMER_1_INDEX] && NUMBER_OF_TIMERS == 1) {
|
|
|
|
|
if (frequency_alt != 0 && frequency_alt < frequencies[voices - 2] && frequency_alt < frequencies[voices - 2] * pow(2, -440/frequencies[voices - 2]/12/2)) {
|
|
|
|
|
frequency_alt = frequency_alt * pow(2, 440/frequency_alt/12/2);
|
|
|
|
|
} else if (frequency_alt != 0 && frequency_alt > frequencies[voices - 2] && frequency_alt > frequencies[voices - 2] * pow(2, 440/frequencies[voices - 2]/12/2)) {
|
|
|
|
@ -374,18 +383,18 @@ ISR(TIMER3_COMPA_vect)
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (envelope_index < 65535) {
|
|
|
|
|
envelope_index++;
|
|
|
|
|
if (envelope_index[TIMER_1_INDEX] < 65535) {
|
|
|
|
|
envelope_index[TIMER_1_INDEX]++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
freq_alt = voice_envelope(freq_alt);
|
|
|
|
|
freq_alt = voice_envelope(freq_alt,TIMER_1_INDEX);
|
|
|
|
|
|
|
|
|
|
if (freq_alt < 30.517578125) {
|
|
|
|
|
freq_alt = 30.52;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq_alt * CPU_PRESCALER));
|
|
|
|
|
TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq_alt * CPU_PRESCALER)) * note_timbre);
|
|
|
|
|
TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq_alt * CPU_PRESCALER)) * note_timbre[TIMER_1_INDEX]);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
@ -408,7 +417,7 @@ ISR(TIMER3_COMPA_vect)
|
|
|
|
|
freq = frequencies[voice_place];
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
if (glissando) {
|
|
|
|
|
if (glissando[TIMER_3_INDEX] && NUMBER_OF_TIMERS == 1) {
|
|
|
|
|
if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
|
|
|
|
|
frequency = frequency * pow(2, 440/frequency/12/2);
|
|
|
|
|
} else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
|
|
|
|
@ -431,18 +440,18 @@ ISR(TIMER3_COMPA_vect)
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (envelope_index < 65535) {
|
|
|
|
|
envelope_index++;
|
|
|
|
|
if (envelope_index[TIMER_3_INDEX] < 65535) {
|
|
|
|
|
envelope_index[TIMER_3_INDEX]++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
freq = voice_envelope(freq);
|
|
|
|
|
freq = voice_envelope(freq, TIMER_3_INDEX);
|
|
|
|
|
|
|
|
|
|
if (freq < 30.517578125) {
|
|
|
|
|
freq = 30.52;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
|
|
|
|
|
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
|
|
|
|
|
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre[TIMER_3_INDEX]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -458,13 +467,13 @@ ISR(TIMER3_COMPA_vect)
|
|
|
|
|
freq = note_frequency;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (envelope_index < 65535) {
|
|
|
|
|
envelope_index++;
|
|
|
|
|
if (envelope_index[TIMER_3_INDEX] < 65535) {
|
|
|
|
|
envelope_index[TIMER_3_INDEX]++;
|
|
|
|
|
}
|
|
|
|
|
freq = voice_envelope(freq);
|
|
|
|
|
freq = voice_envelope(freq, TIMER_3_INDEX);
|
|
|
|
|
|
|
|
|
|
TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
|
|
|
|
|
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
|
|
|
|
|
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre[TIMER_3_INDEX]);
|
|
|
|
|
} else {
|
|
|
|
|
TIMER_3_PERIOD = 0;
|
|
|
|
|
TIMER_3_DUTY_CYCLE = 0;
|
|
|
|
@ -505,7 +514,7 @@ ISR(TIMER3_COMPA_vect)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
note_resting = false;
|
|
|
|
|
envelope_index = 0;
|
|
|
|
|
envelope_index[TIMER_3_INDEX] = 0;
|
|
|
|
|
note_frequency = (*notes_pointer)[current_note][0];
|
|
|
|
|
note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
|
|
|
|
|
}
|
|
|
|
@ -521,10 +530,16 @@ ISR(TIMER3_COMPA_vect)
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)
|
|
|
|
|
#ifdef B_AUDIO
|
|
|
|
|
#ifdef B5_AUDIO
|
|
|
|
|
ISR(TIMER1_COMPA_vect)
|
|
|
|
|
#elif defined(B6_AUDIO)
|
|
|
|
|
ISR(TIMER1_COMPB_vect)
|
|
|
|
|
#elif defined(B7_AUDIO)
|
|
|
|
|
ISR(TIMER1_COMPC_vect)
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
#if (defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)) && !defined(C6_AUDIO)
|
|
|
|
|
#if defined(B_AUDIO) && !defined(C6_AUDIO)
|
|
|
|
|
float freq = 0;
|
|
|
|
|
|
|
|
|
|
if (playing_note) {
|
|
|
|
@ -548,7 +563,7 @@ ISR(TIMER1_COMPA_vect)
|
|
|
|
|
freq = frequencies[voice_place];
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
if (glissando) {
|
|
|
|
|
if (glissando[TIMER_1_INDEX] && NUMBER_OF_TIMERS == 1) {
|
|
|
|
|
if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
|
|
|
|
|
frequency = frequency * pow(2, 440/frequency/12/2);
|
|
|
|
|
} else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
|
|
|
|
@ -571,18 +586,18 @@ ISR(TIMER1_COMPA_vect)
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (envelope_index < 65535) {
|
|
|
|
|
envelope_index++;
|
|
|
|
|
if (envelope_index[TIMER_1_INDEX] < 65535) {
|
|
|
|
|
envelope_index[TIMER_1_INDEX]++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
freq = voice_envelope(freq);
|
|
|
|
|
freq = voice_envelope(freq, TIMER_1_INDEX);
|
|
|
|
|
|
|
|
|
|
if (freq < 30.517578125) {
|
|
|
|
|
freq = 30.52;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
|
|
|
|
|
TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
|
|
|
|
|
TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre[TIMER_1_INDEX]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -598,13 +613,13 @@ ISR(TIMER1_COMPA_vect)
|
|
|
|
|
freq = note_frequency;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (envelope_index < 65535) {
|
|
|
|
|
envelope_index++;
|
|
|
|
|
if (envelope_index[TIMER_1_INDEX] < 65535) {
|
|
|
|
|
envelope_index[TIMER_1_INDEX]++;
|
|
|
|
|
}
|
|
|
|
|
freq = voice_envelope(freq);
|
|
|
|
|
freq = voice_envelope(freq, TIMER_1_INDEX);
|
|
|
|
|
|
|
|
|
|
TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
|
|
|
|
|
TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
|
|
|
|
|
TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre[TIMER_1_INDEX]);
|
|
|
|
|
} else {
|
|
|
|
|
TIMER_1_PERIOD = 0;
|
|
|
|
|
TIMER_1_DUTY_CYCLE = 0;
|
|
|
|
@ -645,7 +660,7 @@ ISR(TIMER1_COMPA_vect)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
note_resting = false;
|
|
|
|
|
envelope_index = 0;
|
|
|
|
|
envelope_index[TIMER_1_INDEX] = 0;
|
|
|
|
|
note_frequency = (*notes_pointer)[current_note][0];
|
|
|
|
|
note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
|
|
|
|
|
}
|
|
|
|
@ -674,7 +689,7 @@ void play_note(float freq, int vol) {
|
|
|
|
|
#ifdef C6_AUDIO
|
|
|
|
|
DISABLE_AUDIO_COUNTER_3_ISR;
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)
|
|
|
|
|
#ifdef B_AUDIO
|
|
|
|
|
DISABLE_AUDIO_COUNTER_1_ISR;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
@ -684,7 +699,6 @@ void play_note(float freq, int vol) {
|
|
|
|
|
|
|
|
|
|
playing_note = true;
|
|
|
|
|
|
|
|
|
|
envelope_index = 0;
|
|
|
|
|
|
|
|
|
|
if (freq > 0) {
|
|
|
|
|
frequencies[voices] = freq;
|
|
|
|
@ -696,16 +710,23 @@ void play_note(float freq, int vol) {
|
|
|
|
|
ENABLE_AUDIO_COUNTER_3_ISR;
|
|
|
|
|
ENABLE_AUDIO_COUNTER_3_OUTPUT;
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)
|
|
|
|
|
|
|
|
|
|
#ifdef B_AUDIO
|
|
|
|
|
#ifdef C6_AUDIO
|
|
|
|
|
if (voices > 1) {
|
|
|
|
|
envelope_index[TIMER_3_INDEX] = 0;
|
|
|
|
|
ENABLE_AUDIO_COUNTER_1_ISR;
|
|
|
|
|
ENABLE_AUDIO_COUNTER_1_OUTPUT;
|
|
|
|
|
} else {
|
|
|
|
|
envelope_index[TIMER_3_INDEX] = 0;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
envelope_index[TIMER_1_INDEX] = 0;
|
|
|
|
|
ENABLE_AUDIO_COUNTER_1_ISR;
|
|
|
|
|
ENABLE_AUDIO_COUNTER_1_OUTPUT;
|
|
|
|
|
#endif
|
|
|
|
|
#else
|
|
|
|
|
envelope_index[TIMER_3_INDEX] = 0;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -723,7 +744,7 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat)
|
|
|
|
|
#ifdef C6_AUDIO
|
|
|
|
|
DISABLE_AUDIO_COUNTER_3_ISR;
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)
|
|
|
|
|
#ifdef B_AUDIO
|
|
|
|
|
DISABLE_AUDIO_COUNTER_1_ISR;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
@ -749,7 +770,7 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat)
|
|
|
|
|
ENABLE_AUDIO_COUNTER_3_ISR;
|
|
|
|
|
ENABLE_AUDIO_COUNTER_3_OUTPUT;
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(B5_AUDIO) || defined(B6_AUDIO) || defined(B7_AUDIO)
|
|
|
|
|
#ifdef B_AUDIO
|
|
|
|
|
#ifndef C6_AUDIO
|
|
|
|
|
ENABLE_AUDIO_COUNTER_1_ISR;
|
|
|
|
|
ENABLE_AUDIO_COUNTER_1_OUTPUT;
|
|
|
|
@ -847,8 +868,8 @@ void decrease_polyphony_rate(float change) {
|
|
|
|
|
|
|
|
|
|
// Timbre function
|
|
|
|
|
|
|
|
|
|
void set_timbre(float timbre) {
|
|
|
|
|
note_timbre = timbre;
|
|
|
|
|
void set_timbre(float timbre, uint8_t timer_index) {
|
|
|
|
|
note_timbre[timer_index] = timbre;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Tempo functions
|
|
|
|
|