summary refs log tree commit diff
path: root/quantum
diff options
context:
space:
mode:
authorIBNobody <protospherex@gmail.com>2016-04-18 15:47:10 -0500
committerIBNobody <protospherex@gmail.com>2016-04-18 15:47:10 -0500
commitcbcf0abe62b764a9f3d80848611dca8291d93eb8 (patch)
tree2014b1d839bfaa29acdbf432265d908562304834 /quantum
parentd5cc31d7d4fc1a36fc3e3e0018369cb52553f50f (diff)
parent4f4b5b8c18d4f1bf4fd4c51ad6f316501dfbd6cc (diff)
Merge remote-tracking branch 'refs/remotes/origin/personal_atomic_planck'
Diffstat (limited to 'quantum')
-rw-r--r--quantum/audio.c259
-rw-r--r--quantum/audio.h45
-rw-r--r--quantum/keymap_common.c275
-rw-r--r--quantum/keymap_common.h32
-rw-r--r--quantum/led.c1
-rw-r--r--quantum/musical_notes.h217
-rw-r--r--quantum/quantum.mk9
-rw-r--r--quantum/song_list.h101
-rw-r--r--quantum/tools/README.md6
-rw-r--r--quantum/tools/eeprom_reset.hex9
10 files changed, 752 insertions, 202 deletions
diff --git a/quantum/audio.c b/quantum/audio.c
index f29d941d7c..627e3d80a1 100644
--- a/quantum/audio.c
+++ b/quantum/audio.c
@@ -4,12 +4,16 @@
 #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
+
 // #define PWM_AUDIO
 
 #ifdef PWM_AUDIO
@@ -30,6 +34,8 @@ int voice_place = 0;
 double frequency = 0;
 int volume = 0;
 long position = 0;
+int duty_place = 1;
+int duty_counter = 0;
 
 double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
 int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
@@ -51,11 +57,36 @@ bool notes = false;
 bool note = false;
 float note_frequency = 0;
 float note_length = 0;
+float note_tempo = TEMPO_DEFAULT;
+float note_timbre = TIMBRE_DEFAULT;
 uint16_t note_position = 0;
 float (* notes_pointer)[][2];
-uint8_t notes_length;
+uint8_t notes_count;
 bool notes_repeat;
+float notes_rest;
+bool note_resting = false;
+
 uint8_t current_note = 0;
+uint8_t rest_counter = 0;
+
+audio_config_t audio_config;
+
+
+void audio_toggle(void) {
+    audio_config.enable ^= 1;
+    eeconfig_write_audio(audio_config.raw);
+}
+
+void audio_on(void) {
+    audio_config.enable = 1;
+    eeconfig_write_audio(audio_config.raw);
+}
+
+void audio_off(void) {
+    audio_config.enable = 0;
+    eeconfig_write_audio(audio_config.raw);
+}
+
 
 void stop_all_notes() {
     voices = 0;
@@ -77,58 +108,66 @@ void stop_all_notes() {
 }
 
 void stop_note(double freq) {
-    #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;
-            }
-        }
-    }
-    voices--;
-    if (voices < 0)
-        voices = 0;
-    if (voices == 0) {
+    if (note) {
         #ifdef PWM_AUDIO
-            TIMSK3 &= ~_BV(OCIE3A);
-        #else
-            TIMSK3 &= ~_BV(OCIE3A);
-            TCCR3A &= ~_BV(COM3A1);
+            freq = freq / SAMPLE_RATE;
         #endif
-        frequency = 0;
-        volume = 0;
-        note = false;
-    } else {
-        double freq = frequencies[voices - 1];
-        int vol = volumes[voices - 1];
-        double starting_f = frequency;
-        if (frequency < freq) {
-            sliding = true;
-            for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) {
-                frequency = f;
+        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;
+                }
             }
-            sliding = false;
-        } else if (frequency > freq) {
-            sliding = true;
-            for (double f = starting_f; f >= freq; f -= ((starting_f - freq) / 2000.0)) {
-                frequency = f;
+        }
+        voices--;
+        if (voices < 0)
+            voices = 0;
+        if (voices == 0) {
+            #ifdef PWM_AUDIO
+                TIMSK3 &= ~_BV(OCIE3A);
+            #else
+                TIMSK3 &= ~_BV(OCIE3A);
+                TCCR3A &= ~_BV(COM3A1);
+            #endif
+            frequency = 0;
+            volume = 0;
+            note = false;
+        } else {
+            double freq = frequencies[voices - 1];
+            int vol = volumes[voices - 1];
+            double starting_f = frequency;
+            if (frequency < freq) {
+                sliding = true;
+                for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) {
+                    frequency = f;
+                }
+                sliding = false;
+            } else if (frequency > freq) {
+                sliding = true;
+                for (double f = starting_f; f >= freq; f -= ((starting_f - freq) / 2000.0)) {
+                    frequency = f;
+                }
+                sliding = false;
             }
-            sliding = false;
+            frequency = freq;
+            volume = vol;
         }
-        frequency = freq;
-        volume = vol;
     }
 }
 
 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);
@@ -144,7 +183,7 @@ void init_notes() {
         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
@@ -160,20 +199,19 @@ void init_notes() {
 
 
 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;
 
@@ -213,13 +251,20 @@ ISR(TIMER3_COMPA_vect) {
             if (frequency > 0) {
                 // ICR3 = (int)(((double)F_CPU) / frequency); // Set max to the period
                 // OCR3A = (int)(((double)F_CPU) / frequency) >> 1; // Set compare to half the period
-                if (place > 10) {
+                voice_place %= voices;
+                if (place > (frequencies[voice_place] / 50)) {
                     voice_place = (voice_place + 1) % voices;
                     place = 0.0;
                 }
-                ICR3 = (int)(((double)F_CPU) / frequencies[voice_place]); // Set max to the period
-                OCR3A = (int)(((double)F_CPU) / frequencies[voice_place]) >> 1; // Set compare to half the period
+                ICR3 = (int)(((double)F_CPU) / (frequencies[voice_place] * CPU_PRESCALER)); // Set max to the period
+                OCR3A = (int)((((double)F_CPU) / (frequencies[voice_place] * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
+                //OCR3A = (int)(((double)F_CPU) / (frequencies[voice_place] * CPU_PRESCALER)) >> 1 * duty_place; // Set compare to half the period
                 place++;
+                // if (duty_counter > (frequencies[voice_place] / 500)) {
+                //     duty_place = (duty_place % 3) + 1;
+                //     duty_counter = 0;
+                // }
+                // duty_counter++;
             }
         #endif
     }
@@ -245,8 +290,8 @@ ISR(TIMER3_COMPA_vect) {
                 place -= SINE_LENGTH;
         #else
             if (note_frequency > 0) {
-                ICR3 = (int)(((double)F_CPU) / note_frequency); // Set max to the period
-                OCR3A = (int)(((double)F_CPU) / note_frequency) >> 1; // Set compare to half the period
+                ICR3 = (int)(((double)F_CPU) / (note_frequency * CPU_PRESCALER)); // Set max to the period
+                OCR3A = (int)((((double)F_CPU) / (note_frequency * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
             } else {
                 ICR3 = 0;
                 OCR3A = 0;
@@ -255,9 +300,14 @@ ISR(TIMER3_COMPA_vect) {
 
 
         note_position++;
-        if (note_position >= note_length) {
+        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_length) {
+            if (current_note >= notes_count) {
                 if (notes_repeat) {
                     current_note = 0;
                 } else {
@@ -271,37 +321,54 @@ ISR(TIMER3_COMPA_vect) {
                     return;
                 }
             }
-            #ifdef PWM_AUDIO
-                note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
-                note_length = (*notes_pointer)[current_note][1];
-            #else
-                note_frequency = (*notes_pointer)[current_note][0];
-                note_length = (*notes_pointer)[current_note][1] / 4;
-            #endif
+            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
+                    note_frequency = (*notes_pointer)[current_note][0];
+                    note_length = ((*notes_pointer)[current_note][1] / 4) * (note_tempo / 100);
+                #endif
+            }
             note_position = 0;
         }
 
     }
 
+    if (!audio_config.enable) {
+        notes = false;
+        note = false;
+    }
 }
 
-void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat) {
+void play_notes(float (*np)[][2], uint8_t n_count, bool n_repeat, float n_rest) {
+
+if (audio_config.enable) {
+
+	// Cancel note if a note is playing
     if (note)
         stop_all_notes();
     notes = true;
 
     notes_pointer = np;
-    notes_length = n_length;
+    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_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_length = ((*notes_pointer)[current_note][1] / 4) * (note_tempo / 100);
     #endif
     note_position = 0;
 
@@ -312,9 +379,15 @@ void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat) {
         TIMSK3 |= _BV(OCIE3A);
         TCCR3A |= _BV(COM3A1);
     #endif
+
+}
+
 }
 
 void play_sample(uint8_t * s, uint16_t l, bool r) {
+
+if (audio_config.enable) {
+
     stop_all_notes();
     place_int = 0;
     sample = s;
@@ -325,9 +398,16 @@ void play_sample(uint8_t * s, uint16_t l, bool r) {
         TIMSK3 |= _BV(OCIE3A);
     #else
     #endif
+
+}
+
 }
 
 void play_note(double freq, int vol) {
+
+if (audio_config.enable && voices < 8) {
+
+    // Cancel notes if notes are playing
     if (notes)
         stop_all_notes();
     note = true;
@@ -338,7 +418,7 @@ void play_note(double freq, int vol) {
         if (frequency != 0) {
             double starting_f = frequency;
             if (frequency < freq) {
-                for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) {   
+                for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) {
                     frequency = f;
                 }
             } else if (frequency > freq) {
@@ -362,4 +442,47 @@ void play_note(double freq, int vol) {
         TCCR3A |= _BV(COM3A1);
     #endif
 
-}
\ No newline at end of file
+}
+
+}
+
+void set_timbre(float timbre)
+{
+	note_timbre = timbre;
+}
+
+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;
+		}
+}
+
+//------------------------------------------------------------------------------
+// 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.h b/quantum/audio.h
index 99203cea7a..44cafccd68 100644
--- a/quantum/audio.h
+++ b/quantum/audio.h
@@ -2,10 +2,49 @@
 #include <stdbool.h>
 #include <avr/io.h>
 #include <util/delay.h>
+#include "musical_notes.h"
+#include "song_list.h"
+
+#ifndef AUDIO_H
+#define AUDIO_H
+
+typedef union {
+    uint8_t raw;
+    struct {
+        bool    enable :1;
+        uint8_t level  :7;
+    };
+} audio_config_t;
+
+void audio_toggle(void);
+void audio_on(void);
+void audio_off(void);
 
 void play_sample(uint8_t * s, uint16_t l, bool r);
 void play_note(double freq, int vol);
 void stop_note(double freq);
-void stop_all_notes();
-void init_notes();
-void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat);
\ No newline at end of file
+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 set_timbre(float timbre);
+void set_tempo(float tempo);
+void increase_tempo(uint8_t tempo_change);
+void decrease_tempo(uint8_t tempo_change);
+
+#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), \
+						0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
+						0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
+						0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
+
+// 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 PLAY_NOTE_ARRAY(note_array, note_repeat, note_rest_style) play_notes(&note_array, NOTE_ARRAY_SIZE((note_array)), (note_repeat), (note_rest_style));
+
+void play_goodbye_tone(void);
+void play_startup_tone(void);
+
+#endif
\ No newline at end of file
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index ae6cddb343..4ee290ad03 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -26,143 +26,27 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "backlight.h"
 #include "keymap_midi.h"
 #include "bootloader.h"
+#include "eeconfig.h"
+
+extern keymap_config_t keymap_config;
 
 #include <stdio.h>
 #include <inttypes.h>
 #ifdef AUDIO_ENABLE
     #include "audio.h"
-
-    float goodbye[][2] = {
-        {440.0*pow(2.0,(67)/12.0), 400},
-        {0, 50},
-        {440.0*pow(2.0,(60)/12.0), 400},
-        {0, 50},
-        {440.0*pow(2.0,(55)/12.0), 600},
-    };
-#endif
+#endif /* AUDIO_ENABLE */
 
 static action_t keycode_to_action(uint16_t keycode);
 
 /* converts key to action */
 action_t action_for_key(uint8_t layer, keypos_t key)
 {
-	// 16bit keycodes - important
+    // 16bit keycodes - important
     uint16_t keycode = keymap_key_to_keycode(layer, key);
 
-    if (keycode >= 0x0100 && keycode < 0x2000) {
-    	// Has a modifier
-    	action_t action;
-    	// Split it up
-    	action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key
-    	return action;
-	} else if (keycode >= 0x2000 && keycode < 0x3000) {
-        // Is a shortcut for function layer, pull last 12bits
-        // This means we have 4,096 FN macros at our disposal
-        return keymap_func_to_action(keycode & 0xFFF);
-	} else if (keycode >= 0x3000 && keycode < 0x4000) {
-      // When the code starts with 3, it's an action macro.
-    	action_t action;
-    	action.code = ACTION_MACRO(keycode & 0xFF);
-    	return action;
-#ifdef BACKLIGHT_ENABLE
-	} else if (keycode >= BL_0 && keycode <= BL_15) {
-        action_t action;
-        action.code = ACTION_BACKLIGHT_LEVEL(keycode & 0x000F);
-        return action;
-    } else if (keycode == BL_DEC) {
-        action_t action;
-        action.code = ACTION_BACKLIGHT_DECREASE();
-        return action;
-    } else if (keycode == BL_INC) {
-        action_t action;
-        action.code = ACTION_BACKLIGHT_INCREASE();
-        return action;
-    } else if (keycode == BL_TOGG) {
-        action_t action;
-        action.code = ACTION_BACKLIGHT_TOGGLE();
-        return action;
-    } else if (keycode == BL_STEP) {
-        action_t action;
-        action.code = ACTION_BACKLIGHT_STEP();
-        return action;
-#endif
-    } else if (keycode == RESET) { // RESET is 0x5000, which is why this is here
-    	action_t action;
-        clear_keyboard();
-        #ifdef AUDIO_ENABLE
-            play_notes(&goodbye, 5, false);
-        #endif
-        _delay_ms(250);
-        #ifdef ATREUS_ASTAR
-            *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
-        #endif
-        bootloader_jump();
-        return action;
-    } else if (keycode == DEBUG) { // DEBUG is 0x5001
-      // TODO: Does this actually work?
-        action_t action;
-        print("\nDEBUG: enabled.\n");
-        debug_enable = true;
-        return action;
-    } else if (keycode >= 0x5000 && keycode < 0x6000) {
-        // Layer movement shortcuts
-        // See .h to see constraints/usage
-        int type = (keycode >> 0x8) & 0xF;
-        if (type == 0x1) {
-            // Layer set "GOTO"
-            int when = (keycode >> 0x4) & 0x3;
-            int layer = keycode & 0xF;
-            action_t action;
-            action.code = ACTION_LAYER_SET(layer, when);
-            return action;
-        } else if (type == 0x2) {
-            // Momentary layer
-            int layer = keycode & 0xFF;
-            action_t action;
-            action.code = ACTION_LAYER_MOMENTARY(layer);
-            return action;
-        } else if (type == 0x3) {
-            // Set default layer
-            int layer = keycode & 0xFF;
-            action_t action;
-            action.code = ACTION_DEFAULT_LAYER_SET(layer);
-            return action;
-        } else if (type == 0x4) {
-            // Set default layer
-            int layer = keycode & 0xFF;
-            action_t action;
-            action.code = ACTION_LAYER_TOGGLE(layer);
-            return action;
-        }
-#ifdef MIDI_ENABLE
-    } else if (keycode >= 0x6000 && keycode < 0x7000) {
-        action_t action;
-        action.code =  ACTION_FUNCTION_OPT(keycode & 0xFF, (keycode & 0x0F00) >> 8);
-        return action;
-#endif
-    } else if (keycode >= 0x7000 && keycode < 0x8000) {
-        action_t action;
-        action.code = ACTION_MODS_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
-        return action;
-    } else if (keycode >= 0x8000 && keycode < 0x9000) {
-        action_t action;
-        action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
-        return action;
-#ifdef UNICODE_ENABLE
-    } else if (keycode >= 0x8000000) {
-        action_t action;
-        uint16_t unicode = keycode & ~(0x8000);
-        action.code =  ACTION_FUNCTION_OPT(unicode & 0xFF, (unicode & 0xFF00) >> 8);
-        return action;
-#endif
-    } else {
-
-    }
-
     switch (keycode) {
         case KC_FN0 ... KC_FN31:
             return keymap_fn_to_action(keycode);
-#ifdef BOOTMAGIC_ENABLE
         case KC_CAPSLOCK:
         case KC_LOCKING_CAPS:
             if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
@@ -226,7 +110,6 @@ action_t action_for_key(uint8_t layer, keypos_t key)
                 return keycode_to_action(KC_BSLASH);
             }
             return keycode_to_action(KC_BSPACE);
-#endif
         default:
             return keycode_to_action(keycode);
     }
@@ -267,6 +150,142 @@ static action_t keycode_to_action(uint16_t keycode)
         case KC_TRNS:
             action.code = ACTION_TRANSPARENT;
             break;
+        case 0x0100 ... 0x1FFF: ;
+            // Has a modifier
+            // Split it up
+            action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key
+            break;
+        case 0x2000 ... 0x2FFF:
+            // Is a shortcut for function layer, pull last 12bits
+            // This means we have 4,096 FN macros at our disposal
+            return keymap_func_to_action(keycode & 0xFFF);
+            break;
+        case 0x3000 ... 0x3FFF: ;
+            // When the code starts with 3, it's an action macro.
+            action.code = ACTION_MACRO(keycode & 0xFF);
+            break;
+    #ifdef BACKLIGHT_ENABLE
+        case BL_0 ... BL_15:
+            action.code = ACTION_BACKLIGHT_LEVEL(keycode & 0x000F);
+            break;
+        case BL_DEC:
+            action.code = ACTION_BACKLIGHT_DECREASE();
+            break;
+        case BL_INC:
+            action.code = ACTION_BACKLIGHT_INCREASE();
+            break;
+        case BL_TOGG:
+            action.code = ACTION_BACKLIGHT_TOGGLE();
+            break;
+        case BL_STEP:
+            action.code = ACTION_BACKLIGHT_STEP();
+            break;
+    #endif
+        case RESET: ; // RESET is 0x5000, which is why this is here
+            clear_keyboard();
+            #ifdef AUDIO_ENABLE
+                play_goodbye_tone();
+            #endif
+            _delay_ms(250);
+            #ifdef ATREUS_ASTAR
+                *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
+            #endif
+            bootloader_jump();
+            break;
+        case DEBUG: ; // DEBUG is 0x5001
+            print("\nDEBUG: enabled.\n");
+            debug_enable = true;
+            break;
+        case 0x5002 ... 0x50FF:
+            // MAGIC actions (BOOTMAGIC without the boot)
+            if (!eeconfig_is_enabled()) {
+                eeconfig_init();
+            }
+            /* keymap config */
+            keymap_config.raw = eeconfig_read_keymap();
+            if (keycode == MAGIC_SWAP_CONTROL_CAPSLOCK) {
+                keymap_config.swap_control_capslock = 1;
+            } else if (keycode == MAGIC_CAPSLOCK_TO_CONTROL) {
+                keymap_config.capslock_to_control = 1;
+            } else if (keycode == MAGIC_SWAP_LALT_LGUI) {
+                keymap_config.swap_lalt_lgui = 1;
+            } else if (keycode == MAGIC_SWAP_RALT_RGUI) {
+                keymap_config.swap_ralt_rgui = 1;
+            } else if (keycode == MAGIC_NO_GUI) {
+                keymap_config.no_gui = 1;
+            } else if (keycode == MAGIC_SWAP_GRAVE_ESC) {
+                keymap_config.swap_grave_esc = 1;
+            } else if (keycode == MAGIC_SWAP_BACKSLASH_BACKSPACE) {
+                keymap_config.swap_backslash_backspace = 1;
+            } else if (keycode == MAGIC_HOST_NKRO) {
+                keymap_config.nkro = 1;
+            } else if (keycode == MAGIC_SWAP_ALT_GUI) {
+                keymap_config.swap_lalt_lgui = 1;
+                keymap_config.swap_ralt_rgui = 1;
+            }
+            /* UNs */
+            else if (keycode == MAGIC_UNSWAP_CONTROL_CAPSLOCK) {
+                keymap_config.swap_control_capslock = 0;
+            } else if (keycode == MAGIC_UNCAPSLOCK_TO_CONTROL) {
+                keymap_config.capslock_to_control = 0;
+            } else if (keycode == MAGIC_UNSWAP_LALT_LGUI) {
+                keymap_config.swap_lalt_lgui = 0;
+            } else if (keycode == MAGIC_UNSWAP_RALT_RGUI) {
+                keymap_config.swap_ralt_rgui = 0;
+            } else if (keycode == MAGIC_UNNO_GUI) {
+                keymap_config.no_gui = 0;
+            } else if (keycode == MAGIC_UNSWAP_GRAVE_ESC) {
+                keymap_config.swap_grave_esc = 0;
+            } else if (keycode == MAGIC_UNSWAP_BACKSLASH_BACKSPACE) {
+                keymap_config.swap_backslash_backspace = 0;
+            } else if (keycode == MAGIC_UNHOST_NKRO) {
+                keymap_config.nkro = 0;
+            } else if (keycode == MAGIC_UNSWAP_ALT_GUI) {
+                keymap_config.swap_lalt_lgui = 0;
+                keymap_config.swap_ralt_rgui = 0;
+            }
+            eeconfig_write_keymap(keymap_config.raw);
+            break;
+        case 0x5100 ... 0x5FFF: ;
+            // Layer movement shortcuts
+            // See .h to see constraints/usage
+            int type = (keycode >> 0x8) & 0xF;
+            if (type == 0x1) {
+                // Layer set "GOTO"
+                int when = (keycode >> 0x4) & 0x3;
+                int layer = keycode & 0xF;
+                action.code = ACTION_LAYER_SET(layer, when);
+            } else if (type == 0x2) {
+                // Momentary layer
+                int layer = keycode & 0xFF;
+                action.code = ACTION_LAYER_MOMENTARY(layer);
+            } else if (type == 0x3) {
+                // Set default layer
+                int layer = keycode & 0xFF;
+                action.code = ACTION_DEFAULT_LAYER_SET(layer);
+            } else if (type == 0x4) {
+                // Set default layer
+                int layer = keycode & 0xFF;
+                action.code = ACTION_LAYER_TOGGLE(layer);
+            }
+            break;
+    #ifdef MIDI_ENABLE
+        case 0x6000 ... 0x6FFF:
+            action.code =  ACTION_FUNCTION_OPT(keycode & 0xFF, (keycode & 0x0F00) >> 8);
+            break;
+    #endif
+        case 0x7000 ... 0x7FFF:
+            action.code = ACTION_MODS_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
+            break;
+        case 0x8000 ... 0x8FFF:
+            action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
+            break;
+    #ifdef UNICODE_ENABLE
+        case 0x8000000 ... 0x8FFFFFF:
+            uint16_t unicode = keycode & ~(0x8000);
+            action.code =  ACTION_FUNCTION_OPT(unicode & 0xFF, (unicode & 0xFF00) >> 8);
+            break;
+    #endif
         default:
             action.code = ACTION_NO;
             break;
@@ -278,7 +297,7 @@ static action_t keycode_to_action(uint16_t keycode)
 /* translates key to keycode */
 uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
 {
-	// Read entire word (16bits)
+    // Read entire word (16bits)
     return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]);
 }
 
@@ -290,6 +309,14 @@ action_t keymap_fn_to_action(uint16_t keycode)
 
 action_t keymap_func_to_action(uint16_t keycode)
 {
-	// For FUNC without 8bit limit
+    // For FUNC without 8bit limit
     return (action_t){ .code = pgm_read_word(&fn_actions[(int)keycode]) };
 }
+
+void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
+  if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
+    layer_on(layer3);
+  } else {
+    layer_off(layer3);
+  }
+}
diff --git a/quantum/keymap_common.h b/quantum/keymap_common.h
index 4a877d2a70..ce87e4770e 100644
--- a/quantum/keymap_common.h
+++ b/quantum/keymap_common.h
@@ -30,7 +30,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // #include "print.h"
 #include "debug.h"
 
-#ifdef BOOTMAGIC_ENABLE
 /* NOTE: Not portable. Bit field order depends on implementation */
 typedef union {
     uint16_t raw;
@@ -45,8 +44,6 @@ typedef union {
         bool nkro:1;
     };
 } keymap_config_t;
-keymap_config_t keymap_config;
-#endif
 
 
 /* translates key to keycode */
@@ -168,6 +165,30 @@ extern const uint16_t fn_actions[];
 #define RESET 0x5000
 #define DEBUG 0x5001
 
+// MAGIC keycodes
+#define MAGIC_SWAP_CONTROL_CAPSLOCK      0x5002
+#define MAGIC_UNSWAP_CONTROL_CAPSLOCK    0x5003
+#define MAGIC_CAPSLOCK_TO_CONTROL        0x5004
+#define MAGIC_UNCAPSLOCK_TO_CONTROL      0x5005
+#define MAGIC_SWAP_LALT_LGUI             0x5006
+#define MAGIC_UNSWAP_LALT_LGUI           0x5007
+#define MAGIC_SWAP_RALT_RGUI             0x5008
+#define MAGIC_UNSWAP_RALT_RGUI           0x5009
+#define MAGIC_NO_GUI                     0x500a
+#define MAGIC_UNNO_GUI                   0x500b
+#define MAGIC_SWAP_GRAVE_ESC             0x500c
+#define MAGIC_UNSWAP_GRAVE_ESC           0x500d
+#define MAGIC_SWAP_BACKSLASH_BACKSPACE   0x500e
+#define MAGIC_UNSWAP_BACKSLASH_BACKSPACE 0x500f
+#define MAGIC_HOST_NKRO                  0x5010
+#define MAGIC_UNHOST_NKRO                0x5011
+#define MAGIC_SWAP_ALT_GUI               0x5012
+#define MAGIC_UNSWAP_ALT_GUI             0x5013
+
+#define AG_SWAP MAGIC_SWAP_ALT_GUI
+#define AG_NORM MAGIC_UNSWAP_ALT_GUI
+
+
 // GOTO layer - 16 layers max
 // when:
 // ON_PRESS    = 1
@@ -208,5 +229,10 @@ extern const uint16_t fn_actions[];
 #define UNICODE(n) (n | 0x8000)
 #define UC(n) UNICODE(n)
 
+// For tri-layer
+void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
+#define IS_LAYER_ON(layer)  ((layer_state) & (1UL<<(layer)))
+#define IS_LAYER_OFF(layer) ((!layer_state) & (1UL<<(layer)))
+
 
 #endif
diff --git a/quantum/led.c b/quantum/led.c
index 9cdb8a5c20..208e348f34 100644
--- a/quantum/led.c
+++ b/quantum/led.c
@@ -24,6 +24,7 @@ void led_set_kb(uint8_t usb_led) {
 
 }
 
+__attribute__ ((weak))
 void led_set(uint8_t usb_led)
 {
 
diff --git a/quantum/musical_notes.h b/quantum/musical_notes.h
new file mode 100644
index 0000000000..b08d16a6fa
--- /dev/null
+++ b/quantum/musical_notes.h
@@ -0,0 +1,217 @@
+#ifndef MUSICAL_NOTES_H
+#define MUSICAL_NOTES_H
+
+// Tempo Placeholder
+#define TEMPO_DEFAULT 100
+
+
+#define SONG(notes...) { notes }
+
+
+// Note Types
+#define MUSICAL_NOTE(note, duration)   {(NOTE##note), duration}
+#define WHOLE_NOTE(note)               MUSICAL_NOTE(note, 64)
+#define HALF_NOTE(note)                MUSICAL_NOTE(note, 32)
+#define QUARTER_NOTE(note)             MUSICAL_NOTE(note, 16)
+#define EIGHTH_NOTE(note)              MUSICAL_NOTE(note,  8)
+#define SIXTEENTH_NOTE(note)           MUSICAL_NOTE(note,  4)
+
+#define WHOLE_DOT_NOTE(note)           MUSICAL_NOTE(note, 64+32)
+#define HALF_DOT_NOTE(note)            MUSICAL_NOTE(note, 32+16)
+#define QUARTER_DOT_NOTE(note)         MUSICAL_NOTE(note, 16+8)
+#define EIGHTH_DOT_NOTE(note)          MUSICAL_NOTE(note,  8+4)
+#define SIXTEENTH_DOT_NOTE(note)       MUSICAL_NOTE(note,  4+2)
+
+// Note Type Shortcuts
+#define M__NOTE(note, duration)        MUSICAL_NOTE(note, duration)
+#define W__NOTE(n)                     WHOLE_NOTE(n)
+#define H__NOTE(n)                     HALF_NOTE(n)
+#define Q__NOTE(n)                     QUARTER_NOTE(n)
+#define E__NOTE(n)                     EIGHTH_NOTE(n)
+#define S__NOTE(n)                     SIXTEENTH_NOTE(n)
+#define WD_NOTE(n)                     WHOLE_DOT_NOTE(n)
+#define HD_NOTE(n)                     HALF_DOT_NOTE(n)
+#define QD_NOTE(n)                     QUARTER_DOT_NOTE(n)
+#define ED_NOTE(n)                     EIGHTH_DOT_NOTE(n)
+#define SD_NOTE(n)                     SIXTEENTH_DOT_NOTE(n)
+
+// Note Styles
+// Staccato makes sure there is a rest between each note. Think: TA TA TA
+// Legato makes notes flow together. Think: TAAA
+#define STACCATO 0.01
+#define LEGATO   0
+
+// Note Timbre
+// Changes how the notes sound
+#define TIMBRE_12       0.125
+#define TIMBRE_25       0.250
+#define TIMBRE_50       0.500
+#define TIMBRE_75       0.750
+#define TIMBRE_DEFAULT  TIMBRE_50
+
+
+// Notes - # = Octave
+
+#define NOTE_REST         0.00
+
+/* These notes are currently bugged
+#define NOTE_C0          16.35
+#define NOTE_CS0         17.32
+#define NOTE_D0          18.35
+#define NOTE_DS0         19.45
+#define NOTE_E0          20.60
+#define NOTE_F0          21.83
+#define NOTE_FS0         23.12
+#define NOTE_G0          24.50
+#define NOTE_GS0         25.96
+#define NOTE_A0          27.50
+#define NOTE_AS0         29.14
+#define NOTE_B0          30.87
+#define NOTE_C1          32.70
+#define NOTE_CS1         34.65
+#define NOTE_D1          36.71
+#define NOTE_DS1         38.89
+#define NOTE_E1          41.20
+#define NOTE_F1          43.65
+#define NOTE_FS1         46.25
+#define NOTE_G1          49.00
+#define NOTE_GS1         51.91
+#define NOTE_A1          55.00
+#define NOTE_AS1         58.27
+*/
+
+#define NOTE_B1          61.74
+#define NOTE_C2          65.41
+#define NOTE_CS2         69.30
+#define NOTE_D2          73.42
+#define NOTE_DS2         77.78
+#define NOTE_E2          82.41
+#define NOTE_F2          87.31
+#define NOTE_FS2         92.50
+#define NOTE_G2          98.00
+#define NOTE_GS2        103.83
+#define NOTE_A2         110.00
+#define NOTE_AS2        116.54
+#define NOTE_B2         123.47
+#define NOTE_C3         130.81
+#define NOTE_CS3        138.59
+#define NOTE_D3         146.83
+#define NOTE_DS3        155.56
+#define NOTE_E3         164.81
+#define NOTE_F3         174.61
+#define NOTE_FS3        185.00
+#define NOTE_G3         196.00
+#define NOTE_GS3        207.65
+#define NOTE_A3         220.00
+#define NOTE_AS3        233.08
+#define NOTE_B3         246.94
+#define NOTE_C4         261.63
+#define NOTE_CS4        277.18
+#define NOTE_D4         293.66
+#define NOTE_DS4        311.13
+#define NOTE_E4         329.63
+#define NOTE_F4         349.23
+#define NOTE_FS4        369.99
+#define NOTE_G4         392.00
+#define NOTE_GS4        415.30
+#define NOTE_A4         440.00
+#define NOTE_AS4        466.16
+#define NOTE_B4         493.88
+#define NOTE_C5         523.25
+#define NOTE_CS5        554.37
+#define NOTE_D5         587.33
+#define NOTE_DS5        622.25
+#define NOTE_E5         659.26
+#define NOTE_F5         698.46
+#define NOTE_FS5        739.99
+#define NOTE_G5         783.99
+#define NOTE_GS5        830.61
+#define NOTE_A5         880.00
+#define NOTE_AS5        932.33
+#define NOTE_B5         987.77
+#define NOTE_C6        1046.50
+#define NOTE_CS6       1108.73
+#define NOTE_D6        1174.66
+#define NOTE_DS6       1244.51
+#define NOTE_E6        1318.51
+#define NOTE_F6        1396.91
+#define NOTE_FS6       1479.98
+#define NOTE_G6        1567.98
+#define NOTE_GS6       1661.22
+#define NOTE_A6        1760.00
+#define NOTE_AS6       1864.66
+#define NOTE_B6        1975.53
+#define NOTE_C7        2093.00
+#define NOTE_CS7       2217.46
+#define NOTE_D7        2349.32
+#define NOTE_DS7       2489.02
+#define NOTE_E7        2637.02
+#define NOTE_F7        2793.83
+#define NOTE_FS7       2959.96
+#define NOTE_G7        3135.96
+#define NOTE_GS7       3322.44
+#define NOTE_A7        3520.00
+#define NOTE_AS7       3729.31
+#define NOTE_B7        3951.07
+#define NOTE_C8        4186.01
+#define NOTE_CS8       4434.92
+#define NOTE_D8        4698.64
+#define NOTE_DS8       4978.03
+#define NOTE_E8        5274.04
+#define NOTE_F8        5587.65
+#define NOTE_FS8       5919.91
+#define NOTE_G8        6271.93
+#define NOTE_GS8       6644.88
+#define NOTE_A8        7040.00
+#define NOTE_AS8       7458.62
+#define NOTE_B8        7902.13
+
+// Flat Aliases
+#define NOTE_DF0 NOTE_CS0
+#define NOTE_EF0 NOTE_DS0
+#define NOTE_GF0 NOTE_FS0
+#define NOTE_AF0 NOTE_GS0
+#define NOTE_BF0 NOTE_AS0
+#define NOTE_DF1 NOTE_CS1
+#define NOTE_EF1 NOTE_DS1
+#define NOTE_GF1 NOTE_FS1
+#define NOTE_AF1 NOTE_GS1
+#define NOTE_BF1 NOTE_AS1
+#define NOTE_DF2 NOTE_CS2
+#define NOTE_EF2 NOTE_DS2
+#define NOTE_GF2 NOTE_FS2
+#define NOTE_AF2 NOTE_GS2
+#define NOTE_BF2 NOTE_AS2
+#define NOTE_DF3 NOTE_CS3
+#define NOTE_EF3 NOTE_DS3
+#define NOTE_GF3 NOTE_FS3
+#define NOTE_AF3 NOTE_GS3
+#define NOTE_BF3 NOTE_AS3
+#define NOTE_DF4 NOTE_CS4
+#define NOTE_EF4 NOTE_DS4
+#define NOTE_GF4 NOTE_FS4
+#define NOTE_AF4 NOTE_GS4
+#define NOTE_BF4 NOTE_AS4
+#define NOTE_DF5 NOTE_CS5
+#define NOTE_EF5 NOTE_DS5
+#define NOTE_GF5 NOTE_FS5
+#define NOTE_AF5 NOTE_GS5
+#define NOTE_BF5 NOTE_AS5
+#define NOTE_DF6 NOTE_CS6
+#define NOTE_EF6 NOTE_DS6
+#define NOTE_GF6 NOTE_FS6
+#define NOTE_AF6 NOTE_GS6
+#define NOTE_BF6 NOTE_AS6
+#define NOTE_DF7 NOTE_CS7
+#define NOTE_EF7 NOTE_DS7
+#define NOTE_GF7 NOTE_FS7
+#define NOTE_AF7 NOTE_GS7
+#define NOTE_BF7 NOTE_AS7
+#define NOTE_DF8 NOTE_CS8
+#define NOTE_EF8 NOTE_DS8
+#define NOTE_GF8 NOTE_FS8
+#define NOTE_AF8 NOTE_GS8
+#define NOTE_BF8 NOTE_AS8
+
+
+#endif
\ No newline at end of file
diff --git a/quantum/quantum.mk b/quantum/quantum.mk
index de93af7e8c..1fe7390eba 100644
--- a/quantum/quantum.mk
+++ b/quantum/quantum.mk
@@ -23,19 +23,19 @@ ifndef CUSTOM_MATRIX
 	SRC += $(QUANTUM_DIR)/matrix.c
 endif
 
-ifdef MIDI_ENABLE
+ifeq ($(strip $(MIDI_ENABLE)), yes)
 	SRC += $(QUANTUM_DIR)/keymap_midi.c
 endif
 
-ifdef AUDIO_ENABLE
+ifeq ($(strip $(AUDIO_ENABLE)), yes)
 	SRC += $(QUANTUM_DIR)/audio.c
 endif
 
-ifdef UNICODE_ENABLE
+ifeq ($(strip $(UNICODE_ENABLE)), yes)
 	SRC += $(QUANTUM_DIR)/keymap_unicode.c
 endif
 
-ifdef RGBLIGHT_ENABLE
+ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
 	SRC += $(QUANTUM_DIR)/light_ws2812.c
 	SRC += $(QUANTUM_DIR)/rgblight.c
 	OPT_DEFS += -DRGBLIGHT_ENABLE
@@ -46,6 +46,7 @@ endif
 
 # Search Path
 VPATH += $(TOP_DIR)/$(QUANTUM_DIR)
+VPATH += $(TOP_DIR)/$(QUANTUM_DIR)/keymap_extras
 
 include $(TMK_DIR)/protocol/lufa.mk
 
diff --git a/quantum/song_list.h b/quantum/song_list.h
new file mode 100644
index 0000000000..e992bd18a2
--- /dev/null
+++ b/quantum/song_list.h
@@ -0,0 +1,101 @@
+#include "musical_notes.h"
+
+#ifndef SONG_LIST_H
+#define SONG_LIST_H
+
+#define ODE_TO_JOY                                          \
+    Q__NOTE(_E4), Q__NOTE(_E4), Q__NOTE(_F4), Q__NOTE(_G4), \
+    Q__NOTE(_G4), Q__NOTE(_F4), Q__NOTE(_E4), Q__NOTE(_D4), \
+    Q__NOTE(_C4), Q__NOTE(_C4), Q__NOTE(_D4), Q__NOTE(_E4), \
+    QD_NOTE(_E4), E__NOTE(_D4), H__NOTE(_D4),
+
+#define ROCK_A_BYE_BABY                            \
+    QD_NOTE(_B4), E__NOTE(_D4), Q__NOTE(_B5),      \
+    H__NOTE(_A5), Q__NOTE(_G5),                    \
+    QD_NOTE(_B4), E__NOTE(_D5), Q__NOTE(_G5),      \
+    H__NOTE(_FS5),
+
+#define CLOSE_ENCOUNTERS_5_NOTE  \
+	Q__NOTE(_D5),                \
+	Q__NOTE(_E5),                \
+	Q__NOTE(_C5),                \
+	Q__NOTE(_C4),                \
+	Q__NOTE(_G4),
+
+#define DOE_A_DEER              \
+	QD_NOTE(_C4), E__NOTE(_D4), \
+	QD_NOTE(_E4), E__NOTE(_C4), \
+	Q__NOTE(_E4), Q__NOTE(_C4), \
+	Q__NOTE(_E4),
+
+#define GOODBYE_SOUND \
+    E__NOTE(_E7),     \
+    E__NOTE(_A6),     \
+    ED_NOTE(_E6),
+
+#define STARTUP_SOUND  \
+    ED_NOTE(_E7 ),     \
+    E__NOTE(_CS7),     \
+    E__NOTE(_E6 ),     \
+    E__NOTE(_A6 ),     \
+    M__NOTE(_CS7, 20),
+
+#define QWERTY_SOUND \
+    E__NOTE(_GS6 ),  \
+    E__NOTE(_A6  ),  \
+    S__NOTE(_REST),  \
+    Q__NOTE(_E7  ),
+
+#define COLEMAK_SOUND \
+    E__NOTE(_GS6 ),   \
+    E__NOTE(_A6  ),   \
+    S__NOTE(_REST),   \
+    ED_NOTE(_E7  ),   \
+    S__NOTE(_REST),   \
+    ED_NOTE(_GS7 ),
+
+#define DVORAK_SOUND \
+    E__NOTE(_GS6 ),  \
+    E__NOTE(_A6  ),  \
+    S__NOTE(_REST),  \
+    E__NOTE(_E7  ),  \
+    S__NOTE(_REST),  \
+    E__NOTE(_FS7 ),  \
+    S__NOTE(_REST),  \
+    E__NOTE(_E7  ),
+
+#define MUSIC_SCALE_SOUND \
+    E__NOTE(_A5 ),        \
+    E__NOTE(_B5 ),        \
+    E__NOTE(_CS6),        \
+    E__NOTE(_D6 ),        \
+    E__NOTE(_E6 ),        \
+    E__NOTE(_FS6),        \
+    E__NOTE(_GS6),        \
+    E__NOTE(_A6 ),
+
+#define CAPS_LOCK_ON_SOUND \
+    E__NOTE(_A3),          \
+    E__NOTE(_B3),
+
+#define CAPS_LOCK_OFF_SOUND \
+    E__NOTE(_B3),           \
+    E__NOTE(_A3),
+
+#define SCROLL_LOCK_ON_SOUND \
+    E__NOTE(_D4),            \
+    E__NOTE(_E4),
+
+#define SCROLL_LOCK_OFF_SOUND \
+    E__NOTE(_E4),             \
+    E__NOTE(_D4),
+
+#define NUM_LOCK_ON_SOUND \
+    E__NOTE(_D5),         \
+    E__NOTE(_E5),
+
+#define NUM_LOCK_OFF_SOUND \
+    E__NOTE(_E5),          \
+    E__NOTE(_D5),
+
+#endif
diff --git a/quantum/tools/README.md b/quantum/tools/README.md
new file mode 100644
index 0000000000..0702144238
--- /dev/null
+++ b/quantum/tools/README.md
@@ -0,0 +1,6 @@
+`eeprom_reset.hex` is to reset the eeprom on the Atmega32u4, like this:
+
+    dfu-programmer atmega32u4 erase
+    dfu-programmer atmega32u4 flash --eeprom eeprom-reset.bin
+
+ You'll need to reflash afterwards, because DFU requires the flash to be erased before messing with the eeprom.
\ No newline at end of file
diff --git a/quantum/tools/eeprom_reset.hex b/quantum/tools/eeprom_reset.hex
new file mode 100644
index 0000000000..a8a75389fe
--- /dev/null
+++ b/quantum/tools/eeprom_reset.hex
@@ -0,0 +1,9 @@
+:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
+:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
+:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
+:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
+:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
+:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
+:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
+:00000001FF