diff options
| -rw-r--r-- | keyboard/atomic/keymaps/pvc/config.h | 5 | ||||
| -rw-r--r-- | keyboard/atomic/keymaps/pvc/keymap.c | 107 | ||||
| -rw-r--r-- | keyboard/ergodox_ez/keymaps/zweihander-osx/keymap.c | 3 | ||||
| -rw-r--r-- | keyboard/planck/keymaps/pvc/config.h | 2 | ||||
| -rw-r--r-- | keyboard/planck/keymaps/pvc/keymap.c | 4 | ||||
| -rw-r--r-- | keyboard/planck/keymaps/pvc/makefile.mk | 3 | ||||
| -rw-r--r-- | quantum/audio/audio.c | 766 | ||||
| -rw-r--r-- | quantum/audio/audio.h | 6 | ||||
| -rw-r--r-- | quantum/audio/audio_pwm.c | 643 | ||||
| -rw-r--r-- | quantum/audio/frequency_lut.h | 357 | ||||
| -rw-r--r-- | quantum/audio/luts.c | 382 | ||||
| -rw-r--r-- | quantum/audio/luts.h | 15 | ||||
| -rw-r--r-- | quantum/audio/vibrato_lut.h | 28 | ||||
| -rw-r--r-- | quantum/audio/voices.c | 8 | ||||
| -rw-r--r-- | quantum/audio/voices.h | 3 | ||||
| -rw-r--r-- | quantum/keymap_common.c | 6 | ||||
| -rw-r--r-- | quantum/quantum.mk | 1 | 
17 files changed, 1447 insertions, 892 deletions
| diff --git a/keyboard/atomic/keymaps/pvc/config.h b/keyboard/atomic/keymaps/pvc/config.h index cc9263464..034bc5dc5 100644 --- a/keyboard/atomic/keymaps/pvc/config.h +++ b/keyboard/atomic/keymaps/pvc/config.h @@ -158,4 +158,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  //#define NO_ACTION_MACRO  //#define NO_ACTION_FUNCTION + +//#define VIBRATO_ENABLE +//#define VIBRATO_STRENGTH_ENABLE + +  #endif diff --git a/keyboard/atomic/keymaps/pvc/keymap.c b/keyboard/atomic/keymaps/pvc/keymap.c index e17c41e23..3d604a868 100644 --- a/keyboard/atomic/keymaps/pvc/keymap.c +++ b/keyboard/atomic/keymaps/pvc/keymap.c @@ -11,8 +11,8 @@  #define LAYER_QWERTY         0  #define LAYER_COLEMAK        1  #define LAYER_DVORAK         2 -#define LAYER_LOWER          3 -#define LAYER_RAISE          4 +#define LAYER_RAISE          3 +#define LAYER_LOWER          4  #define LAYER_FUNCTION       5  #define LAYER_MOUSE          6  #define LAYER_MUSIC          7 @@ -21,8 +21,8 @@  #define MACRO_QWERTY         0  #define MACRO_COLEMAK        1  #define MACRO_DVORAK         2 -#define MACRO_LOWER          3 -#define MACRO_RAISE          4 +#define MACRO_RAISE          3 +#define MACRO_LOWER          4  #define MACRO_FUNCTION       5  #define MACRO_MOUSE          6  #define MACRO_TIMBRE_1       7 @@ -42,8 +42,8 @@  #define M_QWRTY             M(MACRO_QWERTY)  #define M_COLMK             M(MACRO_COLEMAK)  #define M_DVORK             M(MACRO_DVORAK) -#define M_LOWER             M(MACRO_LOWER)  #define M_RAISE             M(MACRO_RAISE) +#define M_LOWER             M(MACRO_LOWER)  #define M_FUNCT             M(MACRO_FUNCTION)  #define M_MOUSE             M(MACRO_MOUSE)  #define TIMBR_1             M(MACRO_TIMBRE_1) @@ -148,23 +148,22 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {    { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_RAISE, KC_SPC,  KC_SPC,  M_LOWER, KC_RALT, KC_RGUI, KC_MENU, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT  },   }, + [LAYER_RAISE]        = { /* RAISED */ +  { KC_TILD, KC_PSCR, KC_PAUS, KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  ________________  }, +  { _______, KC_F1,   KC_F2,   KC_F3,   KC_F4,   _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS   }, +  { _______, KC_F5,   KC_F6,   KC_F7,   KC_F8,   _______, _______, _______, _______, _______, _______, _______, ________________, KC_HOME  }, +  { _______, KC_F9,   KC_F10,  KC_F11,  KC_F12,  _______, _______, _______, _______, _______, _______, ________________, _______, KC_END   }, +  { _______, _______, _______, _______, _______, ________________, _______, _______, _______, _______, _______, _______, _______, _______  }, + },   [LAYER_LOWER]        = { /* LOWERED */    { KC_GRV,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  ________________  }, -  { _______, _______, _______, _______, SC_CCLS, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS   }, -  { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, KC_HOME  }, -  { _______, SC_REDO, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, _______, KC_END   }, +  { _______, KC_F13,  KC_F14,  KC_F15,  KC_F16,  _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS   }, +  { _______, KC_F17,  KC_F18,  KC_F19,  KC_F20,  _______, _______, _______, _______, _______, _______, _______, ________________, KC_HOME  }, +  { _______, KC_F21,  KC_F22,  KC_F23,  KC_F24,  _______, _______, _______, _______, _______, _______, ________________, _______, KC_END   },    { _______, _______, _______, _______, _______, KC_BSPC, KC_BSPC, _______, _______, _______, _______, _______, _______, _______, _______  },   }, - [LAYER_RAISE]        = { /* RAISED */ -  { KC_TILD, KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  ________________  }, -  { _______, _______, _______, _______, SC_ACLS, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_INS   }, -  { _______, SC_SELA, SC_SAVE, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, KC_HOME  }, -  { _______, SC_UNDO, SC_CUT,  SC_COPY, SC_PSTE, _______, _______, _______, _______, _______, _______, ________________, _______, KC_END   }, -  { _______, _______, _______, _______, _______, ________________, _______, _______, _______, _______, _______, _______, _______, _______  }, - }, -   [LAYER_FUNCTION]     = { /* FUNCTION */    { KC_NLCK, KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  ________________  },    { KC_SLCK, KC_F13,  KC_F14,  KC_F15,  KC_F16,  KC_F17,  KC_F18,  KC_F19,  KC_F20,  KC_F21,  KC_F22,  KC_F23,  KC_F24,  _______, KC_PAUS  }, @@ -281,28 +280,28 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)              }              break; -        case MACRO_LOWER: +        case MACRO_RAISE:              if (record->event.pressed)              { -                layer_on(LAYER_LOWER); +                layer_on(LAYER_RAISE);                  update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST);              }              else              { -                layer_off(LAYER_LOWER); +                layer_off(LAYER_RAISE);                  update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST);              }              break; -        case MACRO_RAISE: +        case MACRO_LOWER:              if (record->event.pressed)              { -                layer_on(LAYER_RAISE); +                layer_on(LAYER_LOWER);                  update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST);              }              else              { -                layer_off(LAYER_RAISE); +                layer_off(LAYER_LOWER);                  update_tri_layer(LAYER_LOWER, LAYER_RAISE, LAYER_ADJUST);              }              break; @@ -468,36 +467,40 @@ void led_set_user(uint8_t usb_led)      _delay_ms(10); // gets rid of tick -    if ((usb_led & (1<<USB_LED_CAPS_LOCK)) && !(old_usb_led & (1<<USB_LED_CAPS_LOCK))) -    { -            // If CAPS LK LED is turning on... -            PLAY_NOTE_ARRAY(tone_caps_on,  false, LEGATO); -    } -    else if (!(usb_led & (1<<USB_LED_CAPS_LOCK)) && (old_usb_led & (1<<USB_LED_CAPS_LOCK))) -    { -            // If CAPS LK LED is turning off... -            PLAY_NOTE_ARRAY(tone_caps_off, false, LEGATO); -    } -    else if ((usb_led & (1<<USB_LED_NUM_LOCK)) && !(old_usb_led & (1<<USB_LED_NUM_LOCK))) -    { -            // If NUM LK LED is turning on... -            PLAY_NOTE_ARRAY(tone_numlk_on,  false, LEGATO); -    } -    else if (!(usb_led & (1<<USB_LED_NUM_LOCK)) && (old_usb_led & (1<<USB_LED_NUM_LOCK))) -    { -            // If NUM LED is turning off... -            PLAY_NOTE_ARRAY(tone_numlk_off, false, LEGATO); -    } -    else if ((usb_led & (1<<USB_LED_SCROLL_LOCK)) && !(old_usb_led & (1<<USB_LED_SCROLL_LOCK))) -    { -            // If SCROLL LK LED is turning on... -            PLAY_NOTE_ARRAY(tone_scroll_on,  false, LEGATO); -    } -    else if (!(usb_led & (1<<USB_LED_SCROLL_LOCK)) && (old_usb_led & (1<<USB_LED_SCROLL_LOCK))) -    { -            // If SCROLL LED is turning off... -            PLAY_NOTE_ARRAY(tone_scroll_off, false, LEGATO); -    } +	if (!is_playing_notes()) +	{ +	    if ((usb_led & (1<<USB_LED_CAPS_LOCK)) && !(old_usb_led & (1<<USB_LED_CAPS_LOCK))) +	    { +	            // If CAPS LK LED is turning on... +	            PLAY_NOTE_ARRAY(tone_caps_on,  false, LEGATO); +	    } +	    else if (!(usb_led & (1<<USB_LED_CAPS_LOCK)) && (old_usb_led & (1<<USB_LED_CAPS_LOCK))) +	    { +	            // If CAPS LK LED is turning off... +	            PLAY_NOTE_ARRAY(tone_caps_off, false, LEGATO); +	    } +	    else if ((usb_led & (1<<USB_LED_NUM_LOCK)) && !(old_usb_led & (1<<USB_LED_NUM_LOCK))) +	    { +	            // If NUM LK LED is turning on... +	            PLAY_NOTE_ARRAY(tone_numlk_on,  false, LEGATO); +	    } +	    else if (!(usb_led & (1<<USB_LED_NUM_LOCK)) && (old_usb_led & (1<<USB_LED_NUM_LOCK))) +	    { +	            // If NUM LED is turning off... +	            PLAY_NOTE_ARRAY(tone_numlk_off, false, LEGATO); +	    } +	    else if ((usb_led & (1<<USB_LED_SCROLL_LOCK)) && !(old_usb_led & (1<<USB_LED_SCROLL_LOCK))) +	    { +	            // If SCROLL LK LED is turning on... +	            PLAY_NOTE_ARRAY(tone_scroll_on,  false, LEGATO); +	    } +	    else if (!(usb_led & (1<<USB_LED_SCROLL_LOCK)) && (old_usb_led & (1<<USB_LED_SCROLL_LOCK))) +	    { +	            // If SCROLL LED is turning off... +	            PLAY_NOTE_ARRAY(tone_scroll_off, false, LEGATO); +	    } +	} +      old_usb_led = usb_led;  } diff --git a/keyboard/ergodox_ez/keymaps/zweihander-osx/keymap.c b/keyboard/ergodox_ez/keymaps/zweihander-osx/keymap.c index d019b731f..a9980593f 100644 --- a/keyboard/ergodox_ez/keymaps/zweihander-osx/keymap.c +++ b/keyboard/ergodox_ez/keymaps/zweihander-osx/keymap.c @@ -139,6 +139,8 @@ const uint16_t PROGMEM fn_actions[] = {      [1] = ACTION_LAYER_TAP_TOGGLE(SYMB)                // FN1 - Momentary Layer 1 (Symbols)  }; +// action_get_macro() is unused — remove the “#if 0” and “#endif” lines to reenable +#if 0  const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)  {    // MACRODOWN only works in this function @@ -153,6 +155,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)        }      return MACRO_NONE;  }; +#endif  // Runs just one time when the keyboard initializes.  void matrix_init_user(void) { diff --git a/keyboard/planck/keymaps/pvc/config.h b/keyboard/planck/keymaps/pvc/config.h index 7d64f0977..d435cc795 100644 --- a/keyboard/planck/keymaps/pvc/config.h +++ b/keyboard/planck/keymaps/pvc/config.h @@ -73,7 +73,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.   */  /* disable debug print */ -//#define NO_DEBUG +#define NO_DEBUG  /* disable print */  //#define NO_PRINT diff --git a/keyboard/planck/keymaps/pvc/keymap.c b/keyboard/planck/keymaps/pvc/keymap.c index 27850b215..830b00a4c 100644 --- a/keyboard/planck/keymaps/pvc/keymap.c +++ b/keyboard/planck/keymaps/pvc/keymap.c @@ -96,7 +96,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {   [LAYER_QWERTY]       = { /* QWERTY */    { KC_TAB,  KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,    KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_BSPC   }, -  { KC_BSPC, KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT  }, +  { KC_ESC,  KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT  },    { KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_N,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_ENT   },    { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_RAISE, KC_SPC,  KC_SPC,  M_LOWER, KC_UP,   KC_DOWN, KC_LEFT, KC_RGHT  },   }, @@ -115,7 +115,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {   [LAYER_COLEMAK]      = { /* COLEMAK */    { KC_TAB,  KC_Q,    KC_W,    KC_F,    KC_P,    KC_G,    KC_J,    KC_L,    KC_U,    KC_Y,    KC_SCLN, KC_ESC   }, -  { KC_ESC,  KC_A,    KC_R,    KC_S,    KC_T,    KC_D,    KC_H,    KC_N,    KC_E,    KC_I,    KC_O,    KC_QUOT  }, +  { KC_BSPC, KC_A,    KC_R,    KC_S,    KC_T,    KC_D,    KC_H,    KC_N,    KC_E,    KC_I,    KC_O,    KC_QUOT  },    { KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_K,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_ENT   },    { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_RAISE, KC_SPC,  KC_SPC,  M_LOWER, KC_UP,   KC_DOWN, KC_LEFT, KC_RGHT  },   }, diff --git a/keyboard/planck/keymaps/pvc/makefile.mk b/keyboard/planck/keymaps/pvc/makefile.mk index 4b9e34c53..b3f1b9e51 100644 --- a/keyboard/planck/keymaps/pvc/makefile.mk +++ b/keyboard/planck/keymaps/pvc/makefile.mk @@ -4,6 +4,7 @@ EXTRAKEY_ENABLE  = yes # Audio control and System control(+450)  CONSOLE_ENABLE   = yes # Console for debug(+400)  COMMAND_ENABLE   = yes # Commands for debug and configuration  NKRO_ENABLE      = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work +BACKLIGHT_ENABLE = no  # Enable keyboard backlight functionality  MIDI_ENABLE      = no  # MIDI controls  AUDIO_ENABLE     = no  # Audio output on port C6  UNICODE_ENABLE   = no  # Unicode @@ -13,4 +14,4 @@ RGBLIGHT_ENABLE  = no  # Enable WS2812 RGB underlight.  Do not enable this with  # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE  SLEEP_LED_ENABLE = no  # Breathing sleep LED during USB suspend -CONFIG_H = keymaps/$(KEYMAP)/config.h +CONFIG_H = keymaps/$(KEYMAP)/config.h
\ No newline at end of file diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index e85370d95..3a7f0f556 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -1,6 +1,6 @@  #include <stdio.h>  #include <string.h> -#include <math.h> +//#include <math.h>  #include <avr/pgmspace.h>  #include <avr/interrupt.h>  #include <avr/io.h> @@ -10,30 +10,28 @@  #include "eeconfig.h" -#ifdef VIBRATO_ENABLE -    #include "vibrato_lut.h" -#endif +#define CPU_PRESCALER 8 -#define PI 3.14159265 +// ----------------------------------------------------------------------------- +// Timer Abstractions +// ----------------------------------------------------------------------------- -#define CPU_PRESCALER 8 +// 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 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 +// 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)); -    float places[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -    uint16_t place_int = 0; -    bool repeat = true; -#endif +// Fast PWM Mode Controls +#define TIMER_3_PERIOD     ICR3 +#define TIMER_3_DUTY_CYCLE OCR3A + +// ----------------------------------------------------------------------------- -void delay_us(int count) { -  while(count--) { -    _delay_us(1); -  } -}  int voices = 0;  int voice_place = 0; @@ -45,26 +43,23 @@ 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;  float place = 0;  uint8_t * sample;  uint16_t sample_length = 0; -// float freq = 0; - -bool notes = false; -bool note = false; -float note_frequency = 0; -float note_length = 0; -float note_tempo = TEMPO_DEFAULT; -float note_timbre = TIMBRE_DEFAULT; + +bool     playing_notes = false; +bool     playing_note = false; +float    note_frequency = 0; +float    note_length = 0; +uint8_t  note_tempo = TEMPO_DEFAULT; +float    note_timbre = TIMBRE_DEFAULT;  uint16_t note_position = 0;  float (* notes_pointer)[][2];  uint16_t notes_count; -bool notes_repeat; -float notes_rest; -bool note_resting = false; +bool     notes_repeat; +float    notes_rest; +bool     note_resting = false;  uint8_t current_note = 0;  uint8_t rest_counter = 0; @@ -77,175 +72,65 @@ float vibrato_rate = 0.125;  float polyphony_rate = 0; -bool inited = false; +static bool audio_initialized = false;  audio_config_t audio_config;  uint16_t envelope_index = 0; -void audio_toggle(void) { -    audio_config.enable ^= 1; -    eeconfig_update_audio(audio_config.raw); -} - -void audio_on(void) { -    audio_config.enable = 1; -    eeconfig_update_audio(audio_config.raw); -} - -void audio_off(void) { -    audio_config.enable = 0; -    eeconfig_update_audio(audio_config.raw); -} - -#ifdef VIBRATO_ENABLE -// Vibrato rate functions - -void set_vibrato_rate(float rate) { -    vibrato_rate = rate; -} - -void increase_vibrato_rate(float change) { -    vibrato_rate *= change; -} - -void decrease_vibrato_rate(float change) { -    vibrato_rate /= change; -} - -#ifdef VIBRATO_STRENGTH_ENABLE - -void set_vibrato_strength(float strength) { -    vibrato_strength = strength; -} - -void increase_vibrato_strength(float change) { -    vibrato_strength *= change; -} - -void decrease_vibrato_strength(float change) { -    vibrato_strength /= change; -} - -#endif - -#endif - -// Polyphony functions - -void set_polyphony_rate(float rate) { -    polyphony_rate = rate; -} - -void enable_polyphony() { -    polyphony_rate = 5; -} - -void disable_polyphony() { -    polyphony_rate = 0; -} - -void increase_polyphony_rate(float change) { -    polyphony_rate *= change; -} - -void decrease_polyphony_rate(float change) { -    polyphony_rate /= change; -} - -// Timbre function - -void set_timbre(float timbre) { -    note_timbre = timbre; -} - -// Tempo functions - -void set_tempo(float tempo) { -    note_tempo = tempo; -} - -void decrease_tempo(uint8_t tempo_change) { -    note_tempo += (float) tempo_change; -} - -void increase_tempo(uint8_t tempo_change) { -    if (note_tempo - (float) tempo_change < 10) { -        note_tempo = 10; -    } else { -        note_tempo -= (float) tempo_change; -    } -} - -void audio_init() { +void audio_init() +{ -    /* check signature */ -    if (!eeconfig_is_enabled()) { +    // Check EEPROM +    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 */ +	// Set port PC6 (OC3A and /OC4A) as output +    DDRC |= _BV(PORTC6); -        /* 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; +    DISABLE_AUDIO_COUNTER_3_ISR; -        /* Enable the OC4A output */ -        DDRC |= _BV(PORTC6); +	// 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); -        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; +    audio_initialized = true;  } -void stop_all_notes() { -    if (!inited) { +void stop_all_notes() +{ +    if (!audio_initialized) {          audio_init();      }      voices = 0; -    #ifdef PWM_AUDIO -        TIMSK3 &= ~_BV(OCIE3A); -    #else -        TIMSK3 &= ~_BV(OCIE3A); -        TCCR3A &= ~_BV(COM3A1); -    #endif -    notes = false; -    note = false; + +    DISABLE_AUDIO_COUNTER_3_ISR; +    DISABLE_AUDIO_COUNTER_3_OUTPUT; + +    playing_notes = false; +    playing_note = false;      frequency = 0;      volume = 0; -    for (int i = 0; i < 8; i++) { +    for (uint8_t i = 0; i < 8; i++) +    {          frequencies[i] = 0;          volumes[i] = 0;      }  } -void stop_note(float freq) { -    if (note) { -        if (!inited) { +void stop_note(float freq) +{ +    if (playing_note) { +        if (!audio_initialized) {              audio_init();          } -        #ifdef PWM_AUDIO -            freq = freq / SAMPLE_RATE; -        #endif          for (int i = 7; i >= 0; i--) {              if (frequencies[i] == freq) {                  frequencies[i] = 0; @@ -266,15 +151,11 @@ void stop_note(float freq) {              voice_place = 0;          }          if (voices == 0) { -            #ifdef PWM_AUDIO -                TIMSK3 &= ~_BV(OCIE3A); -            #else -                TIMSK3 &= ~_BV(OCIE3A); -                TCCR3A &= ~_BV(COM3A1); -            #endif +            DISABLE_AUDIO_COUNTER_3_ISR; +            DISABLE_AUDIO_COUNTER_3_OUTPUT;              frequency = 0;              volume = 0; -            note = false; +            playing_note = false;          }      }  } @@ -289,9 +170,9 @@ float mod(float a, int b)  float vibrato(float average_freq) {      #ifdef VIBRATO_STRENGTH_ENABLE -        float vibrated_freq = average_freq * pow(VIBRATO_LUT[(int)vibrato_counter], vibrato_strength); +        float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);      #else -        float vibrated_freq = average_freq * VIBRATO_LUT[(int)vibrato_counter]; +        float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];      #endif      vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);      return vibrated_freq; @@ -299,295 +180,295 @@ float vibrato(float average_freq) {  #endif -ISR(TIMER3_COMPA_vect) { -    if (note) { -        #ifdef PWM_AUDIO -            if (voices == 1) { -                // SINE -                OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 2; - -                // SQUARE -                // if (((int)place) >= 1024){ -                //     OCR4A = 0xFF >> 2; -                // } else { -                //     OCR4A = 0x00; -                // } - -                // SAWTOOTH -                // OCR4A = (int)place / 4; - -                // TRIANGLE -                // if (((int)place) >= 1024) { -                //     OCR4A = (int)place / 2; -                // } else { -                //     OCR4A = 2048 - (int)place / 2; -                // } - -                place += frequency; - -                if (place >= SINE_LENGTH) -                    place -= SINE_LENGTH; - -            } else { -                int sum = 0; -                for (int i = 0; i < voices; i++) { -                    // SINE -                    sum += pgm_read_byte(&sinewave[(uint16_t)places[i]]) >> 2; - -                    // SQUARE -                    // if (((int)places[i]) >= 1024){ -                    //     sum += 0xFF >> 2; -                    // } else { -                    //     sum += 0x00; -                    // } - -                    places[i] += frequencies[i]; - -                    if (places[i] >= SINE_LENGTH) -                        places[i] -= SINE_LENGTH; -                } -                OCR4A = sum; -            } -        #else -            if (voices > 0) { -                float freq; -                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 { -                    #else -                    { -                    #endif -                        freq = frequencies[voice_place]; -                    }  -                } 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 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]; -                    } - - -                    #ifdef VIBRATO_ENABLE -                    if (vibrato_strength > 0) { -                        freq = vibrato(frequency); -                    } else { -                    #else -                    { -                    #endif -                        freq = frequency; -                    }  -                } +ISR(TIMER3_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 (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]; +				} + +				#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_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); +			TIMER_3_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_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); +			TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); +		} else { +			TIMER_3_PERIOD = 0; +			TIMER_3_DUTY_CYCLE = 0; +		} + +		note_position++; +		bool end_of_note = false; +		if (TIMER_3_PERIOD > 0) { +			end_of_note = (note_position >= (note_length / TIMER_3_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_3_ISR; +					DISABLE_AUDIO_COUNTER_3_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; +	} +} -                if (envelope_index < 65535) { -                    envelope_index++; -                } -                freq = voice_envelope(freq); +void play_note(float freq, int vol) { -                if (freq < 30.517578125) -                    freq = 30.52; -                ICR3 = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period -                OCR3A = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period -            } -        #endif +    if (!audio_initialized) { +        audio_init();      } -    // SAMPLE -    // OCR4A = pgm_read_byte(&sample[(uint16_t)place_int]); - -    // place_int++; - -    // if (place_int >= sample_length) -    //     if (repeat) -    //         place_int -= sample_length; -    //     else -    //         TIMSK3 &= ~_BV(OCIE3A); - - -    if (notes) { -        #ifdef PWM_AUDIO -            OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 0; - -            place += note_frequency; -            if (place >= SINE_LENGTH) -                place -= SINE_LENGTH; -        #else -            if (note_frequency > 0) { -                float freq; - -                #ifdef VIBRATO_ENABLE -                if (vibrato_strength > 0) { -                    freq = vibrato(note_frequency); -                } else { -                #else -                { -                #endif -                    freq = note_frequency; -                } +	if (audio_config.enable && voices < 8) { +	    DISABLE_AUDIO_COUNTER_3_ISR; -                if (envelope_index < 65535) { -                    envelope_index++; -                } -                freq = voice_envelope(freq); +	    // Cancel notes if notes are playing +	    if (playing_notes) +	        stop_all_notes(); -                ICR3 = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period -                OCR3A = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period -            } else { -                ICR3 = 0; -                OCR3A = 0; -            } -        #endif - - -        note_position++; -        bool end_of_note = false; -        if (ICR3 > 0) -            end_of_note = (note_position >= (note_length / ICR3 * 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 { -                    #ifdef PWM_AUDIO -                        TIMSK3 &= ~_BV(OCIE3A); -                    #else -                        TIMSK3 &= ~_BV(OCIE3A); -                        TCCR3A &= ~_BV(COM3A1); -                    #endif -                    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; -                #ifdef PWM_AUDIO -                    note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE; -                    note_length = (*notes_pointer)[current_note][1] * (note_tempo / 100); -                #else -                    envelope_index = 0; -                    note_frequency = (*notes_pointer)[current_note][0]; -                    note_length = ((*notes_pointer)[current_note][1] / 4) * (note_tempo / 100); -                #endif -            } -            note_position = 0; -        } +	    playing_note = true; -    } +	    envelope_index = 0; + +	    if (freq > 0) { +	        frequencies[voices] = freq; +	        volumes[voices] = vol; +	        voices++; +	    } + +        ENABLE_AUDIO_COUNTER_3_ISR; +        ENABLE_AUDIO_COUNTER_3_OUTPUT; +	} -    if (!audio_config.enable) { -        notes = false; -        note = false; -    }  } -void play_note(float freq, int vol) { +void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) +{ -    if (!inited) { +    if (!audio_initialized) {          audio_init();      } -if (audio_config.enable && voices < 8) { -    TIMSK3 &= ~_BV(OCIE3A); -    // Cancel notes if notes are playing -    if (notes) -        stop_all_notes(); -    note = true; -    envelope_index = 0; -    #ifdef PWM_AUDIO -        freq = freq / SAMPLE_RATE; -    #endif -    if (freq > 0) { -        frequencies[voices] = freq; -        volumes[voices] = vol; -        voices++; -    } +	if (audio_config.enable) { + +	    DISABLE_AUDIO_COUNTER_3_ISR; + +		// Cancel note if a note is playing +	    if (playing_note) +	        stop_all_notes(); + +	    playing_notes = true; + +	    notes_pointer = np; +	    notes_count = n_count; +	    notes_repeat = n_repeat; +	    notes_rest = n_rest; + +	    place = 0; +	    current_note = 0; + +        note_frequency = (*notes_pointer)[current_note][0]; +        note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); +	    note_position = 0; + + +        ENABLE_AUDIO_COUNTER_3_ISR; +        ENABLE_AUDIO_COUNTER_3_OUTPUT; +	} -    #ifdef PWM_AUDIO -        TIMSK3 |= _BV(OCIE3A); -    #else -        TIMSK3 |= _BV(OCIE3A); -        TCCR3A |= _BV(COM3A1); -    #endif  } +bool is_playing_notes(void) { +	return playing_notes;  } -void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) { +void audio_toggle(void) { +    audio_config.enable ^= 1; +    eeconfig_update_audio(audio_config.raw); +} -    if (!inited) { -        audio_init(); -    } +void audio_on(void) { +    audio_config.enable = 1; +    eeconfig_update_audio(audio_config.raw); +} -if (audio_config.enable) { -    TIMSK3 &= ~_BV(OCIE3A); -	// Cancel note if a note is playing -    if (note) -        stop_all_notes(); -    notes = true; - -    notes_pointer = np; -    notes_count = n_count; -    notes_repeat = n_repeat; -    notes_rest = n_rest; - -    place = 0; -    current_note = 0; -    #ifdef PWM_AUDIO -        note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE; -        note_length = (*notes_pointer)[current_note][1] * (note_tempo / 100); -    #else -        note_frequency = (*notes_pointer)[current_note][0]; -        note_length = ((*notes_pointer)[current_note][1] / 4) * (note_tempo / 100); -    #endif -    note_position = 0; +void audio_off(void) { +    audio_config.enable = 0; +    eeconfig_update_audio(audio_config.raw); +} +#ifdef VIBRATO_ENABLE -    #ifdef PWM_AUDIO -        TIMSK3 |= _BV(OCIE3A); -    #else -        TIMSK3 |= _BV(OCIE3A); -        TCCR3A |= _BV(COM3A1); -    #endif +// Vibrato rate functions + +void set_vibrato_rate(float rate) { +    vibrato_rate = rate;  } +void increase_vibrato_rate(float change) { +    vibrato_rate *= change;  } -#ifdef PWM_AUDIO -void play_sample(uint8_t * s, uint16_t l, bool r) { -    if (!inited) { -        audio_init(); -    } +void decrease_vibrato_rate(float change) { +    vibrato_rate /= change; +} -    if (audio_config.enable) { -        TIMSK3 &= ~_BV(OCIE3A); -        stop_all_notes(); -        place_int = 0; -        sample = s; -        sample_length = l; -        repeat = r; +#ifdef VIBRATO_STRENGTH_ENABLE + +void set_vibrato_strength(float strength) { +    vibrato_strength = strength; +} + +void increase_vibrato_strength(float change) { +    vibrato_strength *= change; +} + +void decrease_vibrato_strength(float change) { +    vibrato_strength /= change; +} + +#endif  /* VIBRATO_STRENGTH_ENABLE */ + +#endif /* VIBRATO_ENABLE */ -        TIMSK3 |= _BV(OCIE3A); +// Polyphony functions + +void set_polyphony_rate(float rate) { +    polyphony_rate = rate; +} + +void enable_polyphony() { +    polyphony_rate = 5; +} + +void disable_polyphony() { +    polyphony_rate = 0; +} + +void increase_polyphony_rate(float change) { +    polyphony_rate *= change; +} + +void decrease_polyphony_rate(float change) { +    polyphony_rate /= change; +} + +// Timbre function + +void set_timbre(float timbre) { +    note_timbre = timbre; +} + +// Tempo functions + +void set_tempo(uint8_t tempo) { +    note_tempo = tempo; +} + +void decrease_tempo(uint8_t tempo_change) { +    note_tempo += tempo_change; +} + +void increase_tempo(uint8_t tempo_change) { +    if (note_tempo - tempo_change < 10) { +        note_tempo = 10; +    } else { +        note_tempo -= tempo_change;      }  } -#endif +  //------------------------------------------------------------------------------  // Override these functions in your keymap file to play different tunes on @@ -597,11 +478,8 @@ void play_startup_tone()  {  } - -  __attribute__ ((weak))  void play_goodbye_tone()  { -  }  //------------------------------------------------------------------------------ diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h index 89769507e..3d706587a 100644 --- a/quantum/audio/audio.h +++ b/quantum/audio/audio.h @@ -56,7 +56,7 @@ void increase_polyphony_rate(float change);  void decrease_polyphony_rate(float change);  void set_timbre(float timbre); -void set_tempo(float tempo); +void set_tempo(uint8_t tempo);  void increase_tempo(uint8_t tempo_change);  void decrease_tempo(uint8_t tempo_change); @@ -83,7 +83,11 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)  #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)); + +bool is_playing_notes(void);  void play_goodbye_tone(void);  void play_startup_tone(void); + +  #endif
\ No newline at end of file diff --git a/quantum/audio/audio_pwm.c b/quantum/audio/audio_pwm.c new file mode 100644 index 000000000..328a253a7 --- /dev/null +++ b/quantum/audio/audio_pwm.c @@ -0,0 +1,643 @@ +#include <stdio.h> +#include <string.h> +//#include <math.h> +#include <avr/pgmspace.h> +#include <avr/interrupt.h> +#include <avr/io.h> +#include "print.h" +#include "audio.h" +#include "keymap_common.h" + +#include "eeconfig.h" + +#define PI 3.14159265 + +#define CPU_PRESCALER 8 + + +// Timer Abstractions + +// 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) + + +// 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)); + + +#define NOTE_PERIOD ICR3 +#define NOTE_DUTY_CYCLE OCR3A + + +#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) { +  while(count--) { +    _delay_us(1); +  } +} + +int voices = 0; +int voice_place = 0; +float frequency = 0; +int volume = 0; +long position = 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; + +float place = 0; + +uint8_t * sample; +uint16_t sample_length = 0; +// float freq = 0; + +bool     playing_notes = false; +bool     playing_note = false; +float    note_frequency = 0; +float    note_length = 0; +uint8_t  note_tempo = TEMPO_DEFAULT; +float    note_timbre = TIMBRE_DEFAULT; +uint16_t note_position = 0; +float (* notes_pointer)[][2]; +uint16_t notes_count; +bool     notes_repeat; +float    notes_rest; +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; + +static bool audio_initialized = false; + +audio_config_t audio_config; + +uint16_t envelope_index = 0; + +void audio_init() { + +    // Check EEPROM +    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); + +        DISABLE_AUDIO_COUNTER_3_ISR; // 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 + +    	// Set port PC6 (OC3A and /OC4A) as output +        DDRC |= _BV(PORTC6); + +        DISABLE_AUDIO_COUNTER_3_ISR; + +		// 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); + +    #endif + +    audio_initialized = true; +} + +void stop_all_notes() { +    if (!audio_initialized) { +        audio_init(); +    } +    voices = 0; +    #ifdef PWM_AUDIO +	    DISABLE_AUDIO_COUNTER_3_ISR; +    #else +        DISABLE_AUDIO_COUNTER_3_ISR; +        DISABLE_AUDIO_COUNTER_3_OUTPUT; +    #endif + +    playing_notes = false; +    playing_note = false; +    frequency = 0; +    volume = 0; + +    for (uint8_t i = 0; i < 8; i++) +    { +        frequencies[i] = 0; +        volumes[i] = 0; +    } +} + +void stop_note(float freq) +{ +    if (playing_note) { +        if (!audio_initialized) { +            audio_init(); +        } +        #ifdef PWM_AUDIO +            freq = freq / SAMPLE_RATE; +        #endif +        for (int i = 7; i >= 0; i--) { +            if (frequencies[i] == freq) { +                frequencies[i] = 0; +                volumes[i] = 0; +                for (int j = i; (j < 7); j++) { +                    frequencies[j] = frequencies[j+1]; +                    frequencies[j+1] = 0; +                    volumes[j] = volumes[j+1]; +                    volumes[j+1] = 0; +                } +                break; +            } +        } +        voices--; +        if (voices < 0) +            voices = 0; +        if (voice_place >= voices) { +            voice_place = 0; +        } +        if (voices == 0) { +            #ifdef PWM_AUDIO +                DISABLE_AUDIO_COUNTER_3_ISR; +            #else +                DISABLE_AUDIO_COUNTER_3_ISR; +                DISABLE_AUDIO_COUNTER_3_OUTPUT; +            #endif +            frequency = 0; +            volume = 0; +            playing_note = false; +        } +    } +} + +#ifdef VIBRATO_ENABLE + +float mod(float a, int b) +{ +    float r = fmod(a, b); +    return r < 0 ? r + b : r; +} + +float vibrato(float average_freq) { +    #ifdef VIBRATO_STRENGTH_ENABLE +        float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength); +    #else +        float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter]; +    #endif +    vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH); +    return vibrated_freq; +} + +#endif + +ISR(TIMER3_COMPA_vect) +{ +    if (playing_note) { +        #ifdef PWM_AUDIO +            if (voices == 1) { +                // SINE +                OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 2; + +                // SQUARE +                // if (((int)place) >= 1024){ +                //     OCR4A = 0xFF >> 2; +                // } else { +                //     OCR4A = 0x00; +                // } + +                // SAWTOOTH +                // OCR4A = (int)place / 4; + +                // TRIANGLE +                // if (((int)place) >= 1024) { +                //     OCR4A = (int)place / 2; +                // } else { +                //     OCR4A = 2048 - (int)place / 2; +                // } + +                place += frequency; + +                if (place >= SINE_LENGTH) +                    place -= SINE_LENGTH; + +            } else { +                int sum = 0; +                for (int i = 0; i < voices; i++) { +                    // SINE +                    sum += pgm_read_byte(&sinewave[(uint16_t)places[i]]) >> 2; + +                    // SQUARE +                    // if (((int)places[i]) >= 1024){ +                    //     sum += 0xFF >> 2; +                    // } else { +                    //     sum += 0x00; +                    // } + +                    places[i] += frequencies[i]; + +                    if (places[i] >= SINE_LENGTH) +                        places[i] -= SINE_LENGTH; +                } +                OCR4A = sum; +            } +        #else +            if (voices > 0) { +                float freq; +                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 { +                    #else +                    { +                    #endif +                        freq = frequencies[voice_place]; +                    } +                } 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 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]; +                    } + + +                    #ifdef VIBRATO_ENABLE +                    if (vibrato_strength > 0) { +                        freq = vibrato(frequency); +                    } else { +                    #else +                    { +                    #endif +                        freq = frequency; +                    } +                } + +                if (envelope_index < 65535) { +                    envelope_index++; +                } +                freq = voice_envelope(freq); + +                if (freq < 30.517578125) +                    freq = 30.52; +                NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period +                NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period +            } +        #endif +    } + +    // SAMPLE +    // OCR4A = pgm_read_byte(&sample[(uint16_t)place_int]); + +    // place_int++; + +    // if (place_int >= sample_length) +    //     if (repeat) +    //         place_int -= sample_length; +    //     else +    //         DISABLE_AUDIO_COUNTER_3_ISR; + + +    if (playing_notes) { +        #ifdef PWM_AUDIO +            OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 0; + +            place += note_frequency; +            if (place >= SINE_LENGTH) +                place -= SINE_LENGTH; +        #else +            if (note_frequency > 0) { +                float freq; + +                #ifdef VIBRATO_ENABLE +                if (vibrato_strength > 0) { +                    freq = vibrato(note_frequency); +                } else { +                #else +                { +                #endif +                    freq = note_frequency; +                } + +                if (envelope_index < 65535) { +                    envelope_index++; +                } +                freq = voice_envelope(freq); + +                NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period +                NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period +            } else { +                NOTE_PERIOD = 0; +                NOTE_DUTY_CYCLE = 0; +            } +        #endif + + +        note_position++; +        bool end_of_note = false; +        if (NOTE_PERIOD > 0) +            end_of_note = (note_position >= (note_length / NOTE_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 { +                    #ifdef PWM_AUDIO +                        DISABLE_AUDIO_COUNTER_3_ISR; +                    #else +                        DISABLE_AUDIO_COUNTER_3_ISR; +                        DISABLE_AUDIO_COUNTER_3_OUTPUT; +                    #endif +                    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; +                #ifdef PWM_AUDIO +                    note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE; +                    note_length = (*notes_pointer)[current_note][1] * (((float)note_tempo) / 100); +                #else +                    envelope_index = 0; +                    note_frequency = (*notes_pointer)[current_note][0]; +                    note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); +                #endif +            } +            note_position = 0; +        } + +    } + +    if (!audio_config.enable) { +        playing_notes = false; +        playing_note = false; +    } +} + +void play_note(float freq, int vol) { + +    if (!audio_initialized) { +        audio_init(); +    } + +	if (audio_config.enable && voices < 8) { +	    DISABLE_AUDIO_COUNTER_3_ISR; + +	    // Cancel notes if notes are playing +	    if (playing_notes) +	        stop_all_notes(); + +	    playing_note = true; + +	    envelope_index = 0; + +	    #ifdef PWM_AUDIO +	        freq = freq / SAMPLE_RATE; +	    #endif +	    if (freq > 0) { +	        frequencies[voices] = freq; +	        volumes[voices] = vol; +	        voices++; +	    } + +	    #ifdef PWM_AUDIO +	        ENABLE_AUDIO_COUNTER_3_ISR; +	    #else +	        ENABLE_AUDIO_COUNTER_3_ISR; +	        ENABLE_AUDIO_COUNTER_3_OUTPUT; +	    #endif +	} + +} + +void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) +{ + +    if (!audio_initialized) { +        audio_init(); +    } + +	if (audio_config.enable) { + +	    DISABLE_AUDIO_COUNTER_3_ISR; + +		// Cancel note if a note is playing +	    if (playing_note) +	        stop_all_notes(); + +	    playing_notes = true; + +	    notes_pointer = np; +	    notes_count = n_count; +	    notes_repeat = n_repeat; +	    notes_rest = n_rest; + +	    place = 0; +	    current_note = 0; + +	    #ifdef PWM_AUDIO +	        note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE; +	        note_length = (*notes_pointer)[current_note][1] * (((float)note_tempo) / 100); +	    #else +	        note_frequency = (*notes_pointer)[current_note][0]; +	        note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); +	    #endif +	    note_position = 0; + + +	    #ifdef PWM_AUDIO +	        ENABLE_AUDIO_COUNTER_3_ISR; +	    #else +	        ENABLE_AUDIO_COUNTER_3_ISR; +	        ENABLE_AUDIO_COUNTER_3_OUTPUT; +	    #endif +	} + +} + +#ifdef PWM_AUDIO +void play_sample(uint8_t * s, uint16_t l, bool r) { +    if (!audio_initialized) { +        audio_init(); +    } + +    if (audio_config.enable) { +        DISABLE_AUDIO_COUNTER_3_ISR; +        stop_all_notes(); +        place_int = 0; +        sample = s; +        sample_length = l; +        repeat = r; + +        ENABLE_AUDIO_COUNTER_3_ISR; +    } +} +#endif + + +void audio_toggle(void) { +    audio_config.enable ^= 1; +    eeconfig_update_audio(audio_config.raw); +} + +void audio_on(void) { +    audio_config.enable = 1; +    eeconfig_update_audio(audio_config.raw); +} + +void audio_off(void) { +    audio_config.enable = 0; +    eeconfig_update_audio(audio_config.raw); +} + +#ifdef VIBRATO_ENABLE + +// Vibrato rate functions + +void set_vibrato_rate(float rate) { +    vibrato_rate = rate; +} + +void increase_vibrato_rate(float change) { +    vibrato_rate *= change; +} + +void decrease_vibrato_rate(float change) { +    vibrato_rate /= change; +} + +#ifdef VIBRATO_STRENGTH_ENABLE + +void set_vibrato_strength(float strength) { +    vibrato_strength = strength; +} + +void increase_vibrato_strength(float change) { +    vibrato_strength *= change; +} + +void decrease_vibrato_strength(float change) { +    vibrato_strength /= change; +} + +#endif  /* VIBRATO_STRENGTH_ENABLE */ + +#endif /* VIBRATO_ENABLE */ + +// Polyphony functions + +void set_polyphony_rate(float rate) { +    polyphony_rate = rate; +} + +void enable_polyphony() { +    polyphony_rate = 5; +} + +void disable_polyphony() { +    polyphony_rate = 0; +} + +void increase_polyphony_rate(float change) { +    polyphony_rate *= change; +} + +void decrease_polyphony_rate(float change) { +    polyphony_rate /= change; +} + +// Timbre function + +void set_timbre(float timbre) { +    note_timbre = timbre; +} + +// Tempo functions + +void set_tempo(uint8_t tempo) { +    note_tempo = tempo; +} + +void decrease_tempo(uint8_t tempo_change) { +    note_tempo += tempo_change; +} + +void increase_tempo(uint8_t tempo_change) { +    if (note_tempo - tempo_change < 10) { +        note_tempo = 10; +    } else { +        note_tempo -= tempo_change; +    } +} + + +//------------------------------------------------------------------------------ +// Override these functions in your keymap file to play different tunes on +// startup and bootloader jump +__attribute__ ((weak)) +void play_startup_tone() +{ +} + +__attribute__ ((weak)) +void play_goodbye_tone() +{ +} +//------------------------------------------------------------------------------ diff --git a/quantum/audio/frequency_lut.h b/quantum/audio/frequency_lut.h deleted file mode 100644 index e62da5be4..000000000 --- a/quantum/audio/frequency_lut.h +++ /dev/null @@ -1,357 +0,0 @@ -#include <avr/io.h> -#include <avr/interrupt.h> -#include <avr/pgmspace.h> - -#define FREQUENCY_LUT_LENGTH 349 - -const uint16_t FREQUENCY_LUT[FREQUENCY_LUT_LENGTH] = { -0x8E0B, -0x8C02, -0x8A00, -0x8805, -0x8612, -0x8426, -0x8241, -0x8063, -0x7E8C, -0x7CBB, -0x7AF2, -0x792E, -0x7772, -0x75BB, -0x740B, -0x7261, -0x70BD, -0x6F20, -0x6D88, -0x6BF6, -0x6A69, -0x68E3, -0x6762, -0x65E6, -0x6470, -0x6300, -0x6194, -0x602E, -0x5ECD, -0x5D71, -0x5C1A, -0x5AC8, -0x597B, -0x5833, -0x56EF, -0x55B0, -0x5475, -0x533F, -0x520E, -0x50E1, -0x4FB8, -0x4E93, -0x4D73, -0x4C57, -0x4B3E, -0x4A2A, -0x491A, -0x480E, -0x4705, -0x4601, -0x4500, -0x4402, -0x4309, -0x4213, -0x4120, -0x4031, -0x3F46, -0x3E5D, -0x3D79, -0x3C97, -0x3BB9, -0x3ADD, -0x3A05, -0x3930, -0x385E, -0x3790, -0x36C4, -0x35FB, -0x3534, -0x3471, -0x33B1, -0x32F3, -0x3238, -0x3180, -0x30CA, -0x3017, -0x2F66, -0x2EB8, -0x2E0D, -0x2D64, -0x2CBD, -0x2C19, -0x2B77, -0x2AD8, -0x2A3A, -0x299F, -0x2907, -0x2870, -0x27DC, -0x2749, -0x26B9, -0x262B, -0x259F, -0x2515, -0x248D, -0x2407, -0x2382, -0x2300, -0x2280, -0x2201, -0x2184, -0x2109, -0x2090, -0x2018, -0x1FA3, -0x1F2E, -0x1EBC, -0x1E4B, -0x1DDC, -0x1D6E, -0x1D02, -0x1C98, -0x1C2F, -0x1BC8, -0x1B62, -0x1AFD, -0x1A9A, -0x1A38, -0x19D8, -0x1979, -0x191C, -0x18C0, -0x1865, -0x180B, -0x17B3, -0x175C, -0x1706, -0x16B2, -0x165E, -0x160C, -0x15BB, -0x156C, -0x151D, -0x14CF, -0x1483, -0x1438, -0x13EE, -0x13A4, -0x135C, -0x1315, -0x12CF, -0x128A, -0x1246, -0x1203, -0x11C1, -0x1180, -0x1140, -0x1100, -0x10C2, -0x1084, -0x1048, -0x100C, -0xFD1, -0xF97, -0xF5E, -0xF25, -0xEEE, -0xEB7, -0xE81, -0xE4C, -0xE17, -0xDE4, -0xDB1, -0xD7E, -0xD4D, -0xD1C, -0xCEC, -0xCBC, -0xC8E, -0xC60, -0xC32, -0xC05, -0xBD9, -0xBAE, -0xB83, -0xB59, -0xB2F, -0xB06, -0xADD, -0xAB6, -0xA8E, -0xA67, -0xA41, -0xA1C, -0x9F7, -0x9D2, -0x9AE, -0x98A, -0x967, -0x945, -0x923, -0x901, -0x8E0, -0x8C0, -0x8A0, -0x880, -0x861, -0x842, -0x824, -0x806, -0x7E8, -0x7CB, -0x7AF, -0x792, -0x777, -0x75B, -0x740, -0x726, -0x70B, -0x6F2, -0x6D8, -0x6BF, -0x6A6, -0x68E, -0x676, -0x65E, -0x647, -0x630, -0x619, -0x602, -0x5EC, -0x5D7, -0x5C1, -0x5AC, -0x597, -0x583, -0x56E, -0x55B, -0x547, -0x533, -0x520, -0x50E, -0x4FB, -0x4E9, -0x4D7, -0x4C5, -0x4B3, -0x4A2, -0x491, -0x480, -0x470, -0x460, -0x450, -0x440, -0x430, -0x421, -0x412, -0x403, -0x3F4, -0x3E5, -0x3D7, -0x3C9, -0x3BB, -0x3AD, -0x3A0, -0x393, -0x385, -0x379, -0x36C, -0x35F, -0x353, -0x347, -0x33B, -0x32F, -0x323, -0x318, -0x30C, -0x301, -0x2F6, -0x2EB, -0x2E0, -0x2D6, -0x2CB, -0x2C1, -0x2B7, -0x2AD, -0x2A3, -0x299, -0x290, -0x287, -0x27D, -0x274, -0x26B, -0x262, -0x259, -0x251, -0x248, -0x240, -0x238, -0x230, -0x228, -0x220, -0x218, -0x210, -0x209, -0x201, -0x1FA, -0x1F2, -0x1EB, -0x1E4, -0x1DD, -0x1D6, -0x1D0, -0x1C9, -0x1C2, -0x1BC, -0x1B6, -0x1AF, -0x1A9, -0x1A3, -0x19D, -0x197, -0x191, -0x18C, -0x186, -0x180, -0x17B, -0x175, -0x170, -0x16B, -0x165, -0x160, -0x15B, -0x156, -0x151, -0x14C, -0x148, -0x143, -0x13E, -0x13A, -0x135, -0x131, -0x12C, -0x128, -0x124, -0x120, -0x11C, -0x118, -0x114, -0x110, -0x10C, -0x108, -0x104, -0x100, -0xFD, -0xF9, -0xF5, -0xF2, -0xEE -};
\ No newline at end of file diff --git a/quantum/audio/luts.c b/quantum/audio/luts.c new file mode 100644 index 000000000..9f3de9a05 --- /dev/null +++ b/quantum/audio/luts.c @@ -0,0 +1,382 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/pgmspace.h> +#include "luts.h" + +const float vibrato_lut[VIBRATO_LUT_LENGTH] = +{ +	1.0022336811487, +	1.0042529943610, +	1.0058584256028, +	1.0068905285205, +	1.0072464122237, +	1.0068905285205, +	1.0058584256028, +	1.0042529943610, +	1.0022336811487, +	1.0000000000000, +	0.9977712970630, +	0.9957650169978, +	0.9941756956510, +	0.9931566259436, +	0.9928057204913, +	0.9931566259436, +	0.9941756956510, +	0.9957650169978, +	0.9977712970630, +	1.0000000000000, +}; + +const uint16_t frequency_lut[FREQUENCY_LUT_LENGTH] = +{ +	0x8E0B, +	0x8C02, +	0x8A00, +	0x8805, +	0x8612, +	0x8426, +	0x8241, +	0x8063, +	0x7E8C, +	0x7CBB, +	0x7AF2, +	0x792E, +	0x7772, +	0x75BB, +	0x740B, +	0x7261, +	0x70BD, +	0x6F20, +	0x6D88, +	0x6BF6, +	0x6A69, +	0x68E3, +	0x6762, +	0x65E6, +	0x6470, +	0x6300, +	0x6194, +	0x602E, +	0x5ECD, +	0x5D71, +	0x5C1A, +	0x5AC8, +	0x597B, +	0x5833, +	0x56EF, +	0x55B0, +	0x5475, +	0x533F, +	0x520E, +	0x50E1, +	0x4FB8, +	0x4E93, +	0x4D73, +	0x4C57, +	0x4B3E, +	0x4A2A, +	0x491A, +	0x480E, +	0x4705, +	0x4601, +	0x4500, +	0x4402, +	0x4309, +	0x4213, +	0x4120, +	0x4031, +	0x3F46, +	0x3E5D, +	0x3D79, +	0x3C97, +	0x3BB9, +	0x3ADD, +	0x3A05, +	0x3930, +	0x385E, +	0x3790, +	0x36C4, +	0x35FB, +	0x3534, +	0x3471, +	0x33B1, +	0x32F3, +	0x3238, +	0x3180, +	0x30CA, +	0x3017, +	0x2F66, +	0x2EB8, +	0x2E0D, +	0x2D64, +	0x2CBD, +	0x2C19, +	0x2B77, +	0x2AD8, +	0x2A3A, +	0x299F, +	0x2907, +	0x2870, +	0x27DC, +	0x2749, +	0x26B9, +	0x262B, +	0x259F, +	0x2515, +	0x248D, +	0x2407, +	0x2382, +	0x2300, +	0x2280, +	0x2201, +	0x2184, +	0x2109, +	0x2090, +	0x2018, +	0x1FA3, +	0x1F2E, +	0x1EBC, +	0x1E4B, +	0x1DDC, +	0x1D6E, +	0x1D02, +	0x1C98, +	0x1C2F, +	0x1BC8, +	0x1B62, +	0x1AFD, +	0x1A9A, +	0x1A38, +	0x19D8, +	0x1979, +	0x191C, +	0x18C0, +	0x1865, +	0x180B, +	0x17B3, +	0x175C, +	0x1706, +	0x16B2, +	0x165E, +	0x160C, +	0x15BB, +	0x156C, +	0x151D, +	0x14CF, +	0x1483, +	0x1438, +	0x13EE, +	0x13A4, +	0x135C, +	0x1315, +	0x12CF, +	0x128A, +	0x1246, +	0x1203, +	0x11C1, +	0x1180, +	0x1140, +	0x1100, +	0x10C2, +	0x1084, +	0x1048, +	0x100C, +	0xFD1, +	0xF97, +	0xF5E, +	0xF25, +	0xEEE, +	0xEB7, +	0xE81, +	0xE4C, +	0xE17, +	0xDE4, +	0xDB1, +	0xD7E, +	0xD4D, +	0xD1C, +	0xCEC, +	0xCBC, +	0xC8E, +	0xC60, +	0xC32, +	0xC05, +	0xBD9, +	0xBAE, +	0xB83, +	0xB59, +	0xB2F, +	0xB06, +	0xADD, +	0xAB6, +	0xA8E, +	0xA67, +	0xA41, +	0xA1C, +	0x9F7, +	0x9D2, +	0x9AE, +	0x98A, +	0x967, +	0x945, +	0x923, +	0x901, +	0x8E0, +	0x8C0, +	0x8A0, +	0x880, +	0x861, +	0x842, +	0x824, +	0x806, +	0x7E8, +	0x7CB, +	0x7AF, +	0x792, +	0x777, +	0x75B, +	0x740, +	0x726, +	0x70B, +	0x6F2, +	0x6D8, +	0x6BF, +	0x6A6, +	0x68E, +	0x676, +	0x65E, +	0x647, +	0x630, +	0x619, +	0x602, +	0x5EC, +	0x5D7, +	0x5C1, +	0x5AC, +	0x597, +	0x583, +	0x56E, +	0x55B, +	0x547, +	0x533, +	0x520, +	0x50E, +	0x4FB, +	0x4E9, +	0x4D7, +	0x4C5, +	0x4B3, +	0x4A2, +	0x491, +	0x480, +	0x470, +	0x460, +	0x450, +	0x440, +	0x430, +	0x421, +	0x412, +	0x403, +	0x3F4, +	0x3E5, +	0x3D7, +	0x3C9, +	0x3BB, +	0x3AD, +	0x3A0, +	0x393, +	0x385, +	0x379, +	0x36C, +	0x35F, +	0x353, +	0x347, +	0x33B, +	0x32F, +	0x323, +	0x318, +	0x30C, +	0x301, +	0x2F6, +	0x2EB, +	0x2E0, +	0x2D6, +	0x2CB, +	0x2C1, +	0x2B7, +	0x2AD, +	0x2A3, +	0x299, +	0x290, +	0x287, +	0x27D, +	0x274, +	0x26B, +	0x262, +	0x259, +	0x251, +	0x248, +	0x240, +	0x238, +	0x230, +	0x228, +	0x220, +	0x218, +	0x210, +	0x209, +	0x201, +	0x1FA, +	0x1F2, +	0x1EB, +	0x1E4, +	0x1DD, +	0x1D6, +	0x1D0, +	0x1C9, +	0x1C2, +	0x1BC, +	0x1B6, +	0x1AF, +	0x1A9, +	0x1A3, +	0x19D, +	0x197, +	0x191, +	0x18C, +	0x186, +	0x180, +	0x17B, +	0x175, +	0x170, +	0x16B, +	0x165, +	0x160, +	0x15B, +	0x156, +	0x151, +	0x14C, +	0x148, +	0x143, +	0x13E, +	0x13A, +	0x135, +	0x131, +	0x12C, +	0x128, +	0x124, +	0x120, +	0x11C, +	0x118, +	0x114, +	0x110, +	0x10C, +	0x108, +	0x104, +	0x100, +	0xFD, +	0xF9, +	0xF5, +	0xF2, +	0xEE, +}; + diff --git a/quantum/audio/luts.h b/quantum/audio/luts.h new file mode 100644 index 000000000..7df3078a7 --- /dev/null +++ b/quantum/audio/luts.h @@ -0,0 +1,15 @@ +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/pgmspace.h> + +#ifndef LUTS_H +#define LUTS_H + +#define VIBRATO_LUT_LENGTH 20 + +#define FREQUENCY_LUT_LENGTH 349 + +extern const float vibrato_lut[VIBRATO_LUT_LENGTH]; +extern const uint16_t frequency_lut[FREQUENCY_LUT_LENGTH]; + +#endif /* LUTS_H */
\ No newline at end of file diff --git a/quantum/audio/vibrato_lut.h b/quantum/audio/vibrato_lut.h deleted file mode 100644 index a2b1f3e5c..000000000 --- a/quantum/audio/vibrato_lut.h +++ /dev/null @@ -1,28 +0,0 @@ -#include <avr/io.h> -#include <avr/interrupt.h> -#include <avr/pgmspace.h> - -#define VIBRATO_LUT_LENGTH 20 - -const float VIBRATO_LUT[VIBRATO_LUT_LENGTH] = { \ -1.00223368114872, -1.00425299436105, -1.00585842560279, -1.00689052852052, -1.0072464122237, -1.00689052852052, -1.00585842560279, -1.00425299436105, -1.00223368114872, -1, -0.99777129706302, -0.99576501699778, -0.994175695650927, -0.993156625943589, -0.992805720491269, -0.993156625943589, -0.994175695650927, -0.99576501699778, -0.99777129706302, -1 -};
\ No newline at end of file diff --git a/quantum/audio/voices.c b/quantum/audio/voices.c index d2316ba1b..6d4172a06 100644 --- a/quantum/audio/voices.c +++ b/quantum/audio/voices.c @@ -1,6 +1,6 @@  #include "voices.h" +#include "audio.h"  #include "stdlib.h" -#include "vibrato_lut.h"  // these are imported from audio.c  extern uint16_t envelope_index; @@ -109,7 +109,7 @@ float voice_envelope(float frequency) {                  case 0 ... VOICE_VIBRATO_DELAY:                      break;                  default: -                    frequency = frequency * VIBRATO_LUT[(int)fmod((((float)compensated_index - (VOICE_VIBRATO_DELAY + 1))/1000*VOICE_VIBRATO_SPEED), VIBRATO_LUT_LENGTH)]; +                    frequency = frequency * vibrato_lut[(int)fmod((((float)compensated_index - (VOICE_VIBRATO_DELAY + 1))/1000*VOICE_VIBRATO_SPEED), VIBRATO_LUT_LENGTH)];                      break;              }              break; @@ -160,4 +160,6 @@ float voice_envelope(float frequency) {      }      return frequency; -}
\ No newline at end of file +} + + diff --git a/quantum/audio/voices.h b/quantum/audio/voices.h index 74c873f42..b2495b23b 100644 --- a/quantum/audio/voices.h +++ b/quantum/audio/voices.h @@ -2,8 +2,7 @@  #include <stdbool.h>  #include <avr/io.h>  #include <util/delay.h> -#include "musical_notes.h" -#include "song_list.h" +#include "luts.h"  #ifndef VOICES_H  #define VOICES_H diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 4b4bd6210..5e78d1157 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -24,10 +24,14 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  #include "action_macro.h"  #include "debug.h"  #include "backlight.h" -#include "keymap_midi.h"  #include "bootloader.h"  #include "eeconfig.h" +#ifdef MIDI_ENABLE +	#include "keymap_midi.h" +#endif + +  extern keymap_config_t keymap_config;  #include <stdio.h> diff --git a/quantum/quantum.mk b/quantum/quantum.mk index 83c4f1d1d..4a076eca4 100644 --- a/quantum/quantum.mk +++ b/quantum/quantum.mk @@ -29,6 +29,7 @@ endif  ifeq ($(strip $(AUDIO_ENABLE)), yes)  	SRC += $(QUANTUM_DIR)/audio/audio.c $(QUANTUM_DIR)/audio/voices.c +	SRC += $(QUANTUM_DIR)/audio/audio.c $(QUANTUM_DIR)/audio/luts.c  endif  ifeq ($(strip $(UNICODE_ENABLE)), yes) | 
