From eabf530a0eaffb5fb7d6ebe375225e2d8b0b559a Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Mon, 26 Jun 2017 22:24:30 -0400 Subject: b5 audio --- quantum/audio/audio.c | 260 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 240 insertions(+), 20 deletions(-) (limited to 'quantum') diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index 597073611a..f2948f18aa 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -33,17 +33,41 @@ // TIMSK3 - Timer/Counter #3 Interrupt Mask Register // Turn on/off 3A interputs, stopping/enabling the ISR calls -#define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A) -#define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A) +#ifdef C6_AUDIO + #define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A) + #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A) +#endif + +#ifdef B5_AUDIO + #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A) + #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A) +#endif // TCCR3A: Timer/Counter #3 Control Register // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 -#define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1); -#define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0)); + +#ifdef C6_AUDIO + #define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1); + #define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0)); +#endif + +#ifdef B5_AUDIO + #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1); + #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0)); +#endif // Fast PWM Mode Controls -#define TIMER_3_PERIOD ICR3 -#define TIMER_3_DUTY_CYCLE OCR3A + +#ifdef C6_AUDIO + #define TIMER_3_PERIOD ICR3 + #define TIMER_3_DUTY_CYCLE OCR3A +#endif + +#ifdef B5_AUDIO + #define TIMER_1_PERIOD ICR1 + #define TIMER_1_DUTY_CYCLE OCR1A +#endif + // ----------------------------------------------------------------------------- @@ -105,16 +129,43 @@ void audio_init() audio_config.raw = eeconfig_read_audio(); // Set port PC6 (OC3A and /OC4A) as output - DDRC |= _BV(PORTC6); - DISABLE_AUDIO_COUNTER_3_ISR; + #ifdef C6_AUDIO + DDRC |= _BV(PORTC6); + #else + DDRC |= _BV(PORTC6); + PORTC &= ~_BV(PORTC6); + #endif + + #ifdef B5_AUDIO + DDRB |= _BV(PORTB5); + #else + DDRB |= _BV(PORTB5); + PORTB &= ~_BV(PORTB5); + #endif + + #ifdef C6_AUDIO + DISABLE_AUDIO_COUNTER_3_ISR; + #endif + + #ifdef B5_AUDIO + DISABLE_AUDIO_COUNTER_1_ISR; + #endif // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A) // Clock Select (CS3n) = 0b010 = Clock / 8 - TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); - TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); + + #ifdef C6_AUDIO + TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); + TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); + #endif + + #ifdef B5_AUDIO + TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10); + TCCR1B = (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10); + #endif audio_initialized = true; } @@ -128,8 +179,16 @@ void stop_all_notes() } voices = 0; - DISABLE_AUDIO_COUNTER_3_ISR; - DISABLE_AUDIO_COUNTER_3_OUTPUT; + + #ifdef C6_AUDIO + DISABLE_AUDIO_COUNTER_3_ISR; + DISABLE_AUDIO_COUNTER_3_OUTPUT; + #endif + + #ifdef B5_AUDIO + DISABLE_AUDIO_COUNTER_1_ISR; + DISABLE_AUDIO_COUNTER_1_OUTPUT; + #endif playing_notes = false; playing_note = false; @@ -171,8 +230,14 @@ void stop_note(float freq) voice_place = 0; } if (voices == 0) { - DISABLE_AUDIO_COUNTER_3_ISR; - DISABLE_AUDIO_COUNTER_3_OUTPUT; + #ifdef C6_AUDIO + DISABLE_AUDIO_COUNTER_3_ISR; + DISABLE_AUDIO_COUNTER_3_OUTPUT; + #endif + #ifdef B5_AUDIO + DISABLE_AUDIO_COUNTER_1_ISR; + DISABLE_AUDIO_COUNTER_1_OUTPUT; + #endif frequency = 0; volume = 0; playing_note = false; @@ -200,6 +265,7 @@ float vibrato(float average_freq) { #endif +#ifdef C6_AUDIO ISR(TIMER3_COMPA_vect) { float freq; @@ -328,6 +394,138 @@ ISR(TIMER3_COMPA_vect) playing_note = false; } } +#endif + +#ifdef B5_AUDIO +ISR(TIMER1_COMPA_vect) +{ + float freq; + + if (playing_note) { + if (voices > 0) { + if (polyphony_rate > 0) { + if (voices > 1) { + voice_place %= voices; + if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) { + voice_place = (voice_place + 1) % voices; + place = 0.0; + } + } + + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(frequencies[voice_place]); + } else { + freq = frequencies[voice_place]; + } + #else + freq = frequencies[voice_place]; + #endif + } else { + if (glissando) { + 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)) { + frequency = frequency * pow(2, -440/frequency/12/2); + } else { + frequency = frequencies[voices - 1]; + } + } else { + frequency = frequencies[voices - 1]; + } + + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(frequency); + } else { + freq = frequency; + } + #else + freq = frequency; + #endif + } + + if (envelope_index < 65535) { + envelope_index++; + } + + freq = voice_envelope(freq); + + 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); + } + } + + if (playing_notes) { + if (note_frequency > 0) { + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(note_frequency); + } else { + freq = note_frequency; + } + #else + freq = note_frequency; + #endif + + if (envelope_index < 65535) { + envelope_index++; + } + freq = voice_envelope(freq); + + 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); + } else { + TIMER_1_PERIOD = 0; + TIMER_1_DUTY_CYCLE = 0; + } + + note_position++; + bool end_of_note = false; + if (TIMER_1_PERIOD > 0) { + end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF)); + } else { + end_of_note = (note_position >= (note_length * 0x7FF)); + } + + if (end_of_note) { + current_note++; + if (current_note >= notes_count) { + if (notes_repeat) { + current_note = 0; + } else { + DISABLE_AUDIO_COUNTER_1_ISR; + DISABLE_AUDIO_COUNTER_1_OUTPUT; + playing_notes = false; + return; + } + } + if (!note_resting && (notes_rest > 0)) { + note_resting = true; + note_frequency = 0; + note_length = notes_rest; + current_note--; + } else { + note_resting = false; + envelope_index = 0; + note_frequency = (*notes_pointer)[current_note][0]; + note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); + } + + note_position = 0; + } + } + + if (!audio_config.enable) { + playing_notes = false; + playing_note = false; + } +} +#endif void play_note(float freq, int vol) { @@ -338,7 +536,12 @@ void play_note(float freq, int vol) { } if (audio_config.enable && voices < 8) { - DISABLE_AUDIO_COUNTER_3_ISR; + #ifdef C6_AUDIO + DISABLE_AUDIO_COUNTER_3_ISR; + #endif + #ifdef B5_AUDIO + DISABLE_AUDIO_COUNTER_1_ISR; + #endif // Cancel notes if notes are playing if (playing_notes) @@ -354,8 +557,14 @@ void play_note(float freq, int vol) { voices++; } - ENABLE_AUDIO_COUNTER_3_ISR; - ENABLE_AUDIO_COUNTER_3_OUTPUT; + #ifdef C6_AUDIO + ENABLE_AUDIO_COUNTER_3_ISR; + ENABLE_AUDIO_COUNTER_3_OUTPUT; + #endif + #ifdef B5_AUDIO + ENABLE_AUDIO_COUNTER_1_ISR; + ENABLE_AUDIO_COUNTER_1_OUTPUT; + #endif } } @@ -369,7 +578,12 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) if (audio_config.enable) { - DISABLE_AUDIO_COUNTER_3_ISR; + #ifdef C6_AUDIO + DISABLE_AUDIO_COUNTER_3_ISR; + #endif + #ifdef B5_AUDIO + DISABLE_AUDIO_COUNTER_1_ISR; + #endif // Cancel note if a note is playing if (playing_note) @@ -390,8 +604,14 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) note_position = 0; - ENABLE_AUDIO_COUNTER_3_ISR; - ENABLE_AUDIO_COUNTER_3_OUTPUT; + #ifdef C6_AUDIO + ENABLE_AUDIO_COUNTER_3_ISR; + ENABLE_AUDIO_COUNTER_3_OUTPUT; + #endif + #ifdef B5_AUDIO + ENABLE_AUDIO_COUNTER_1_ISR; + ENABLE_AUDIO_COUNTER_1_OUTPUT; + #endif } } -- cgit v1.2.1 From bfc73e90cfc6532331d1532e2ff9020d25c96a69 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Mon, 26 Jun 2017 23:13:27 -0400 Subject: working duopholy --- quantum/audio/audio.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'quantum') diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index f2948f18aa..04f3460033 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -75,6 +75,7 @@ int voices = 0; int voice_place = 0; float frequency = 0; +float frequency_alt = 0; int volume = 0; long position = 0; @@ -193,6 +194,7 @@ void stop_all_notes() playing_notes = false; playing_note = false; frequency = 0; + frequency_alt = 0; volume = 0; for (uint8_t i = 0; i < 8; i++) @@ -239,6 +241,7 @@ void stop_note(float freq) DISABLE_AUDIO_COUNTER_1_OUTPUT; #endif frequency = 0; + frequency_alt = 0; volume = 0; playing_note = false; } @@ -268,10 +271,52 @@ float vibrato(float average_freq) { #ifdef C6_AUDIO ISR(TIMER3_COMPA_vect) { - float freq; + float freq, freq_alt = 0; if (playing_note) { if (voices > 0) { + + #ifdef B5_AUDIO + if (voices > 1) { + if (polyphony_rate == 0) { + if (glissando) { + 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)) { + frequency_alt = frequency_alt * pow(2, -440/frequency_alt/12/2); + } else { + frequency_alt = frequencies[voices - 2]; + } + } else { + frequency_alt = frequencies[voices - 2]; + } + + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq_alt = vibrato(frequency_alt); + } else { + freq_alt = frequency_alt; + } + #else + freq_alt = frequency_alt; + #endif + } + + if (envelope_index < 65535) { + envelope_index++; + } + + freq_alt = voice_envelope(freq_alt); + + 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); + } + #endif + if (polyphony_rate > 0) { if (voices > 1) { voice_place %= voices; @@ -396,10 +441,10 @@ ISR(TIMER3_COMPA_vect) } #endif -#ifdef B5_AUDIO ISR(TIMER1_COMPA_vect) { - float freq; + #if defined(B5_AUDIO) && !defined(C6_AUDIO) + float freq = 0; if (playing_note) { if (voices > 0) { @@ -524,8 +569,8 @@ ISR(TIMER1_COMPA_vect) playing_notes = false; playing_note = false; } -} #endif +} void play_note(float freq, int vol) { @@ -562,8 +607,15 @@ void play_note(float freq, int vol) { ENABLE_AUDIO_COUNTER_3_OUTPUT; #endif #ifdef B5_AUDIO + #ifdef C6_AUDIO + if (voices > 1) { + ENABLE_AUDIO_COUNTER_1_ISR; + ENABLE_AUDIO_COUNTER_1_OUTPUT; + } + #else ENABLE_AUDIO_COUNTER_1_ISR; ENABLE_AUDIO_COUNTER_1_OUTPUT; + #endif #endif } @@ -609,8 +661,10 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) ENABLE_AUDIO_COUNTER_3_OUTPUT; #endif #ifdef B5_AUDIO + #ifndef C6_AUDIO ENABLE_AUDIO_COUNTER_1_ISR; ENABLE_AUDIO_COUNTER_1_OUTPUT; + #endif #endif } -- cgit v1.2.1 From b82604dadad81872abdb9fdde18086ee69e66671 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Tue, 27 Jun 2017 14:12:25 -0400 Subject: no glide --- quantum/audio/voices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'quantum') diff --git a/quantum/audio/voices.c b/quantum/audio/voices.c index 54ebd423b1..94147ccb66 100644 --- a/quantum/audio/voices.c +++ b/quantum/audio/voices.c @@ -44,7 +44,7 @@ float voice_envelope(float frequency) { switch (voice) { case default_voice: - glissando = true; + glissando = false; note_timbre = TIMBRE_50; polyphony_rate = 0; break; -- cgit v1.2.1 From ea7590c8940bc85f8a83bd42b1e01bc1431c104b Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Tue, 27 Jun 2017 14:35:08 -0400 Subject: add new arguements, docs --- quantum/audio/audio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'quantum') diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index 04f3460033..3192d500f5 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -271,12 +271,13 @@ float vibrato(float average_freq) { #ifdef C6_AUDIO ISR(TIMER3_COMPA_vect) { - float freq, freq_alt = 0; + float freq; if (playing_note) { if (voices > 0) { #ifdef B5_AUDIO + float freq_alt = 0; if (voices > 1) { if (polyphony_rate == 0) { if (glissando) { -- cgit v1.2.1 From 7d28a417c035b66529d7f6d49479fe4c22737134 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Tue, 27 Jun 2017 15:28:13 -0400 Subject: don't let timer1 exist without b5 being enabled --- quantum/audio/audio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'quantum') diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index 3192d500f5..c924f2bd58 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -442,6 +442,7 @@ ISR(TIMER3_COMPA_vect) } #endif +#ifdef B5_AUDIO ISR(TIMER1_COMPA_vect) { #if defined(B5_AUDIO) && !defined(C6_AUDIO) @@ -572,6 +573,7 @@ ISR(TIMER1_COMPA_vect) } #endif } +#endif void play_note(float freq, int vol) { -- cgit v1.2.1