diff options
Diffstat (limited to 'quantum')
| -rw-r--r-- | quantum/audio.c | 230 | ||||
| -rw-r--r-- | quantum/audio.h | 22 | ||||
| -rw-r--r-- | quantum/vibrato_lut.h | 82 | 
3 files changed, 153 insertions, 181 deletions
diff --git a/quantum/audio.c b/quantum/audio.c index 8ea1bf6ff..ab3444bc9 100644 --- a/quantum/audio.c +++ b/quantum/audio.c @@ -10,20 +10,23 @@  #include "eeconfig.h" -#include "vibrato_lut.h" +#ifdef VIBRATO_ENABLE +    #include "vibrato_lut.h" +#endif  #define PI 3.14159265  #define CPU_PRESCALER 8 -// Largely untested PWM audio mode (doesn't sound as good) -// #define PWM_AUDIO -  #ifdef PWM_AUDIO      #include "wave.h"      #define SAMPLE_DIVIDER 39      #define SAMPLE_RATE (2000000.0/SAMPLE_DIVIDER/2048)      // Resistor value of 1/ (2 * PI * 10nF * (2000000 hertz / SAMPLE_DIVIDER / 10)) for 10nF cap + +    float places[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +    uint16_t place_int = 0; +    bool repeat = true;  #endif  void delay_us(int count) { @@ -34,25 +37,21 @@ void delay_us(int count) {  int voices = 0;  int voice_place = 0; -double frequency = 0; +float frequency = 0;  int volume = 0;  long position = 0; -double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0}; +float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};  int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};  bool sliding = false;  int max = 0xFF;  float sum = 0; -int value = 128;  float place = 0; -float places[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint16_t place_int = 0; -bool repeat = true;  uint8_t * sample;  uint16_t sample_length = 0; -double freq = 0; +// float freq = 0;  bool notes = false;  bool note = false; @@ -62,7 +61,7 @@ float note_tempo = TEMPO_DEFAULT;  float note_timbre = TIMBRE_DEFAULT;  uint16_t note_position = 0;  float (* notes_pointer)[][2]; -uint8_t notes_count; +uint16_t notes_count;  bool notes_repeat;  float notes_rest;  bool note_resting = false; @@ -70,11 +69,15 @@ bool note_resting = false;  uint8_t current_note = 0;  uint8_t rest_counter = 0; +#ifdef VIBRATO_ENABLE  float vibrato_counter = 0;  float vibrato_strength = .5;  float vibrato_rate = 0.125; +#endif + +float polyphony_rate = 0; -float polyphony_rate = .5; +bool inited = false;  audio_config_t audio_config; @@ -94,6 +97,7 @@ void audio_off(void) {      eeconfig_write_audio(audio_config.raw);  } +#ifdef VIBRATO_ENABLE  // Vibrato rate functions  void set_vibrato_rate(float rate) { @@ -124,6 +128,8 @@ void decrease_vibrato_strength(float change) {  #endif +#endif +  // Polyphony functions  void set_polyphony_rate(float rate) { @@ -170,7 +176,50 @@ void increase_tempo(uint8_t tempo_change) {      }  } +void audio_init() { + +    /* check signature */ +    if (!eeconfig_is_enabled()) { +        eeconfig_init(); +    } +    audio_config.raw = eeconfig_read_audio(); + +    #ifdef PWM_AUDIO +        PLLFRQ = _BV(PDIV2); +        PLLCSR = _BV(PLLE); +        while(!(PLLCSR & _BV(PLOCK))); +        PLLFRQ |= _BV(PLLTM0); /* PCK 48MHz */ + +        /* Init a fast PWM on Timer4 */ +        TCCR4A = _BV(COM4A0) | _BV(PWM4A); /* Clear OC4A on Compare Match */ +        TCCR4B = _BV(CS40); /* No prescaling => f = PCK/256 = 187500Hz */ +        OCR4A = 0; + +        /* Enable the OC4A output */ +        DDRC |= _BV(PORTC6); + +        TIMSK3 &= ~_BV(OCIE3A); // Turn off 3A interputs + +        TCCR3A = 0x0; // Options not needed +        TCCR3B = _BV(CS31) | _BV(CS30) | _BV(WGM32); // 64th prescaling and CTC +        OCR3A = SAMPLE_DIVIDER - 1; // Correct count/compare, related to sample playback +    #else +        DDRC |= _BV(PORTC6); + +        TIMSK3 &= ~_BV(OCIE3A); // Turn off 3A interputs + +        TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); +        TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); +    #endif + +    inited = true; +    _delay_ms(500); +} +  void stop_all_notes() { +    if (!inited) { +        audio_init(); +    }      voices = 0;      #ifdef PWM_AUDIO          TIMSK3 &= ~_BV(OCIE3A); @@ -189,9 +238,11 @@ void stop_all_notes() {      }  } -void stop_note(double freq) { +void stop_note(float freq) {      if (note) { -        cli(); +        if (!inited) { +            audio_init(); +        }          #ifdef PWM_AUDIO              freq = freq / SAMPLE_RATE;          #endif @@ -225,46 +276,10 @@ void stop_note(double freq) {              volume = 0;              note = false;          } -        sei();      }  } -void init_notes() { - -    /* check signature */ -    if (!eeconfig_is_enabled()) { -        eeconfig_init(); -    } -    audio_config.raw = eeconfig_read_audio(); - -    #ifdef PWM_AUDIO -        PLLFRQ = _BV(PDIV2); -        PLLCSR = _BV(PLLE); -        while(!(PLLCSR & _BV(PLOCK))); -        PLLFRQ |= _BV(PLLTM0); /* PCK 48MHz */ - -        /* Init a fast PWM on Timer4 */ -        TCCR4A = _BV(COM4A0) | _BV(PWM4A); /* Clear OC4A on Compare Match */ -        TCCR4B = _BV(CS40); /* No prescaling => f = PCK/256 = 187500Hz */ -        OCR4A = 0; - -        /* Enable the OC4A output */ -        DDRC |= _BV(PORTC6); - -        TIMSK3 &= ~_BV(OCIE3A); // Turn off 3A interputs - -        TCCR3A = 0x0; // Options not needed -        TCCR3B = _BV(CS31) | _BV(CS30) | _BV(WGM32); // 64th prescaling and CTC -        OCR3A = SAMPLE_DIVIDER - 1; // Correct count/compare, related to sample playback -    #else -        DDRC |= _BV(PORTC6); - -        TIMSK3 &= ~_BV(OCIE3A); // Turn off 3A interputs - -        TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); -        TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); -    #endif -} +#ifdef VIBRATO_ENABLE  float mod(float a, int b)  { @@ -282,6 +297,8 @@ float vibrato(float average_freq) {      return vibrated_freq;  } +#endif +  ISR(TIMER3_COMPA_vect) {      if (note) {          #ifdef PWM_AUDIO @@ -333,6 +350,7 @@ ISR(TIMER3_COMPA_vect) {              }          #else              if (voices > 0) { +                float freq;                  if (polyphony_rate > 0) {                                      if (voices > 1) {                          voice_place %= voices; @@ -341,9 +359,13 @@ ISR(TIMER3_COMPA_vect) {                              place = 0.0;                          }                      } +                    #ifdef VIBRATO_ENABLE                      if (vibrato_strength > 0) {                          freq = vibrato(frequencies[voice_place]);                      } else { +                    #else +                    { +                    #endif                          freq = frequencies[voice_place];                      }                   } else { @@ -355,9 +377,14 @@ ISR(TIMER3_COMPA_vect) {                          frequency = frequencies[voices - 1];                      } + +                    #ifdef VIBRATO_ENABLE                      if (vibrato_strength > 0) {                          freq = vibrato(frequency);                      } else { +                    #else +                    { +                    #endif                          freq = frequency;                      }                   } @@ -390,9 +417,13 @@ ISR(TIMER3_COMPA_vect) {              if (note_frequency > 0) {                  float freq; +                #ifdef VIBRATO_ENABLE                  if (vibrato_strength > 0) {                      freq = vibrato(note_frequency);                  } else { +                #else +                { +                #endif                      freq = note_frequency;                  } @@ -453,10 +484,45 @@ ISR(TIMER3_COMPA_vect) {      }  } -void play_notes(float (*np)[][2], uint8_t n_count, bool n_repeat, float n_rest) { +void play_note(float freq, int vol) { + +    if (!inited) { +        audio_init(); +    } + +if (audio_config.enable && voices < 8) { +    TIMSK3 &= ~_BV(OCIE3A); +    // Cancel notes if notes are playing +    if (notes) +        stop_all_notes(); +    note = true; +    #ifdef PWM_AUDIO +        freq = freq / SAMPLE_RATE; +    #endif +    if (freq > 0) { +        frequencies[voices] = freq; +        volumes[voices] = vol; +        voices++; +    } + +    #ifdef PWM_AUDIO +        TIMSK3 |= _BV(OCIE3A); +    #else +        TIMSK3 |= _BV(OCIE3A); +        TCCR3A |= _BV(COM3A1); +    #endif +} + +} + +void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) { + +    if (!inited) { +        audio_init(); +    }  if (audio_config.enable) { -    cli(); +    TIMSK3 &= ~_BV(OCIE3A);  	// Cancel note if a note is playing      if (note)          stop_all_notes(); @@ -485,57 +551,28 @@ if (audio_config.enable) {          TIMSK3 |= _BV(OCIE3A);          TCCR3A |= _BV(COM3A1);      #endif -    sei();  }  } +#ifdef PWM_AUDIO  void play_sample(uint8_t * s, uint16_t l, bool r) { +    if (!inited) { +        audio_init(); +    } -if (audio_config.enable) { - -    stop_all_notes(); -    place_int = 0; -    sample = s; -    sample_length = l; -    repeat = r; - -    #ifdef PWM_AUDIO -        TIMSK3 |= _BV(OCIE3A); -    #else -    #endif - -} - -} - -void play_note(double freq, int vol) { - -if (audio_config.enable && voices < 8) { -    cli(); -    // Cancel notes if notes are playing -    if (notes) +    if (audio_config.enable) { +        TIMSK3 &= ~_BV(OCIE3A);          stop_all_notes(); -    note = true; -    #ifdef PWM_AUDIO -        freq = freq / SAMPLE_RATE; -    #endif -    if (freq > 0) { -        frequencies[voices] = freq; -        volumes[voices] = vol; -        voices++; -    } +        place_int = 0; +        sample = s; +        sample_length = l; +        repeat = r; -    #ifdef PWM_AUDIO -        TIMSK3 |= _BV(OCIE3A); -    #else          TIMSK3 |= _BV(OCIE3A); -        TCCR3A |= _BV(COM3A1); -    #endif -    sei(); -} - +    }  } +#endif  //------------------------------------------------------------------------------  // Override these functions in your keymap file to play different tunes on @@ -545,8 +582,11 @@ void play_startup_tone()  {  } + +  __attribute__ ((weak))  void play_goodbye_tone()  { +  }  //------------------------------------------------------------------------------ diff --git a/quantum/audio.h b/quantum/audio.h index 85756af9d..2d4d303ce 100644 --- a/quantum/audio.h +++ b/quantum/audio.h @@ -8,6 +8,11 @@  #ifndef AUDIO_H  #define AUDIO_H +// Largely untested PWM audio mode (doesn't sound as good) +// #define PWM_AUDIO + +// #define VIBRATO_ENABLE +  // Enable vibrato strength/amplitude - slows down ISR too much  // #define VIBRATO_STRENGTH_ENABLE @@ -25,6 +30,8 @@ void audio_off(void);  // Vibrato rate functions +#ifdef VIBRATO_ENABLE +  void set_vibrato_rate(float rate);  void increase_vibrato_rate(float change);  void decrease_vibrato_rate(float change); @@ -37,6 +44,8 @@ void decrease_vibrato_strength(float change);  #endif +#endif +  // Polyphony functions  void set_polyphony_rate(float rate); @@ -51,12 +60,15 @@ void set_tempo(float tempo);  void increase_tempo(uint8_t tempo_change);  void decrease_tempo(uint8_t tempo_change); +void audio_init(); + +#ifdef PWM_AUDIO  void play_sample(uint8_t * s, uint16_t l, bool r); -void play_note(double freq, int vol); -void stop_note(double freq); +#endif +void play_note(float freq, int vol); +void stop_note(float freq);  void stop_all_notes(void); -void init_notes(void); -void play_notes(float (*np)[][2], uint8_t n_count, bool n_repeat, float n_rest); +void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest);  #define SCALE (int []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \  						0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \ @@ -67,7 +79,7 @@ void play_notes(float (*np)[][2], uint8_t n_count, bool n_repeat, float n_rest);  // These macros are used to allow play_notes to play an array of indeterminate  // length. This works around the limitation of C's sizeof operation on pointers.  // The global float array for the song must be used here. -#define NOTE_ARRAY_SIZE(x) ((int)(sizeof(x) / (sizeof(x[0])))) +#define NOTE_ARRAY_SIZE(x) ((int16_t)(sizeof(x) / (sizeof(x[0]))))  #define PLAY_NOTE_ARRAY(note_array, note_repeat, note_rest_style) play_notes(¬e_array, NOTE_ARRAY_SIZE((note_array)), (note_repeat), (note_rest_style));  void play_goodbye_tone(void); diff --git a/quantum/vibrato_lut.h b/quantum/vibrato_lut.h index 4c267a626..a2b1f3e5c 100644 --- a/quantum/vibrato_lut.h +++ b/quantum/vibrato_lut.h @@ -2,107 +2,27 @@  #include <avr/interrupt.h>  #include <avr/pgmspace.h> -#define VIBRATO_LUT_LENGTH 100 +#define VIBRATO_LUT_LENGTH 20  const float VIBRATO_LUT[VIBRATO_LUT_LENGTH] = { \ -1.00045346811453, -1.00090535101508, -1.00135386178926, -1.00179722447259,  1.00223368114872, -1.0026614990145, -1.00307897737994, -1.00348445457284, -1.00387631471807,  1.00425299436105, -1.00461298890553, -1.00495485883603, -1.00527723569589, -1.00557882779254,  1.00585842560279, -1.00611490685176, -1.00634724124066, -1.00655449479987, -1.00673583384565,  1.00689052852052, -1.00701795589922, -1.00711760264454, -1.0071890671992, -1.00723206150266,  1.0072464122237, -1.00723206150266, -1.0071890671992, -1.00711760264454, -1.00701795589922,  1.00689052852052, -1.00673583384565, -1.00655449479987, -1.00634724124066, -1.00611490685176,  1.00585842560279, -1.00557882779254, -1.00527723569589, -1.00495485883603, -1.00461298890553,  1.00425299436105, -1.00387631471807, -1.00348445457284, -1.00307897737994, -1.0026614990145,  1.00223368114872, -1.00179722447259, -1.00135386178926, -1.00090535101508, -1.00045346811453,  1, -0.999546737425598, -0.999095467903976, -0.998647968674285, -0.998205999748565,  0.99777129706302, -0.997345565759612, -0.996930473622346, -0.996527644691494, -0.996138653077835,  0.99576501699778, -0.995408193048995, -0.995069570744927, -0.994750467325326, -0.994452122858643,  0.994175695650927, -0.993922257974591, -0.99369279212925, -0.993488186845591, -0.993309234042139,  0.993156625943589, -0.993030952568311, -0.99293269959154, -0.992862246589715, -0.992819865670409,  0.992805720491269, -0.992819865670409, -0.992862246589715, -0.99293269959154, -0.993030952568311,  0.993156625943589, -0.993309234042139, -0.993488186845591, -0.99369279212925, -0.993922257974591,  0.994175695650927, -0.994452122858643, -0.994750467325326, -0.995069570744927, -0.995408193048995,  0.99576501699778, -0.996138653077835, -0.996527644691494, -0.996930473622346, -0.997345565759612,  0.99777129706302, -0.998205999748565, -0.998647968674285, -0.999095467903976, -0.999546737425598,  1  };
\ No newline at end of file  | 
