]> git.donarmstrong.com Git - qmk_firmware.git/blobdiff - quantum/quantum.c
add support for pedal cc messages
[qmk_firmware.git] / quantum / quantum.c
index 9c0f9691ff117699829b7cc30491a70bd481735f..4a6d0355fabe1590226aa5672ea89d41fe385545 100644 (file)
@@ -1,4 +1,82 @@
 #include "quantum.h"
+#ifdef PROTOCOL_LUFA
+#include "outputselect.h"
+#endif
+
+#ifndef TAPPING_TERM
+#define TAPPING_TERM 200
+#endif
+
+#ifdef FAUXCLICKY_ENABLE
+#include "fauxclicky.h"
+#endif
+
+static void do_code16 (uint16_t code, void (*f) (uint8_t)) {
+  switch (code) {
+  case QK_MODS ... QK_MODS_MAX:
+    break;
+  default:
+    return;
+  }
+
+  if (code & QK_LCTL)
+    f(KC_LCTL);
+  if (code & QK_LSFT)
+    f(KC_LSFT);
+  if (code & QK_LALT)
+    f(KC_LALT);
+  if (code & QK_LGUI)
+    f(KC_LGUI);
+
+  if (code < QK_RMODS_MIN) return;
+
+  if (code & QK_RCTL)
+    f(KC_RCTL);
+  if (code & QK_RSFT)
+    f(KC_RSFT);
+  if (code & QK_RALT)
+    f(KC_RALT);
+  if (code & QK_RGUI)
+    f(KC_RGUI);
+}
+
+static inline void qk_register_weak_mods(uint8_t kc) {
+    add_weak_mods(MOD_BIT(kc));
+    send_keyboard_report();
+}
+
+static inline void qk_unregister_weak_mods(uint8_t kc) {
+    del_weak_mods(MOD_BIT(kc));
+    send_keyboard_report();
+}
+
+static inline void qk_register_mods(uint8_t kc) {
+    add_weak_mods(MOD_BIT(kc));
+    send_keyboard_report();
+}
+
+static inline void qk_unregister_mods(uint8_t kc) {
+    del_weak_mods(MOD_BIT(kc));
+    send_keyboard_report();
+}
+
+void register_code16 (uint16_t code) {
+  if (IS_MOD(code) || code == KC_NO) {
+      do_code16 (code, qk_register_mods);
+  } else {
+      do_code16 (code, qk_register_weak_mods);
+  }
+  register_code (code);
+}
+
+void unregister_code16 (uint16_t code) {
+  unregister_code (code);
+  if (IS_MOD(code) || code == KC_NO) {
+      do_code16 (code, qk_unregister_mods);
+  } else {
+      do_code16 (code, qk_unregister_weak_mods);
+  }
+}
 
 __attribute__ ((weak))
 bool process_action_kb(keyrecord_t *record) {
@@ -15,53 +93,18 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
   return true;
 }
 
-__attribute__ ((weak))
-void leader_start(void) {}
-
-__attribute__ ((weak))
-void leader_end(void) {}
-
-uint8_t starting_note = 0x0C;
-int offset = 7;
-
-
+void reset_keyboard(void) {
+  clear_keyboard();
 #ifdef AUDIO_ENABLE
-  bool music_activated = false;
-
-  // music sequencer
-  static bool music_sequence_recording = false;
-  static bool music_sequence_playing = false;
-  static float music_sequence[16] = {0};
-  static uint8_t music_sequence_count = 0;
-  static uint8_t music_sequence_position = 0;
-
-  static uint16_t music_sequence_timer = 0;
-  static uint16_t music_sequence_interval = 100;
-
+  stop_all_notes();
+  shutdown_user();
 #endif
-
-#ifdef MIDI_ENABLE
-  bool midi_activated = false;
-#endif
-
-// Leader key stuff
-bool leading = false;
-uint16_t leader_time = 0;
-
-uint16_t leader_sequence[5] = {0, 0, 0, 0, 0};
-uint8_t leader_sequence_size = 0;
-
-// Chording stuff
-#define CHORDING_MAX 4
-bool chording = false;
-
-uint8_t chord_keys[CHORDING_MAX] = {0};
-uint8_t chord_key_count = 0;
-uint8_t chord_key_down = 0;
-
-#ifdef UNICODE_ENABLE
-  static uint8_t input_mode;
+  wait_ms(250);
+#ifdef CATERINA_BOOTLOADER
+  *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
 #endif
+  bootloader_jump();
+}
 
 // Shift / paren setup
 
@@ -73,48 +116,7 @@ uint8_t chord_key_down = 0;
 #endif
 
 static bool shift_interrupted[2] = {0, 0};
-
-bool keys_chord(uint8_t keys[]) {
-  uint8_t keys_size = sizeof(keys)/sizeof(keys[0]);
-  bool pass = true;
-  uint8_t in = 0;
-  for (uint8_t i = 0; i < chord_key_count; i++) {
-    bool found = false;
-    for (uint8_t j = 0; j < keys_size; j++) {
-      if (chord_keys[i] == (keys[j] & 0xFF)) {
-        in++; // detects key in chord
-        found = true;
-        break;
-      }
-    }
-    if (found)
-      continue;
-    if (chord_keys[i] != 0)  {
-      pass = false; // makes sure rest are blank
-    }
-  }
-  return (pass && (in == keys_size));
-}
-
-#ifdef UNICODE_ENABLE
-
-uint16_t hex_to_keycode(uint8_t hex)
-{
-  if (hex == 0x0) {
-    return KC_0;
-  } else if (hex < 0xA) {
-    return KC_1 + (hex - 0x1);
-  } else {
-    return KC_A + (hex - 0xA);
-  }
-}
-
-void set_unicode_mode(uint8_t os_target)
-{
-  input_mode = os_target;
-}
-
-#endif
+static uint16_t scs_timer = 0;
 
 bool process_record_quantum(keyrecord_t *record) {
 
@@ -123,21 +125,20 @@ bool process_record_quantum(keyrecord_t *record) {
   uint16_t keycode;
 
   #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
-    uint8_t layer;
+    /* TODO: Use store_or_get_action() or a similar function. */
+    if (!disable_action_cache) {
+      uint8_t layer;
 
-    if (record->event.pressed) {
-      layer = layer_switch_get_layer(key);
-      update_source_layers_cache(key, layer);
-    } else {
-      layer = read_source_layers_cache(key);
-    }
-    keycode = keymap_key_to_keycode(layer, key);
-  #else
-    keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
+      if (record->event.pressed) {
+        layer = layer_switch_get_layer(key);
+        update_source_layers_cache(key, layer);
+      } else {
+        layer = read_source_layers_cache(key);
+      }
+      keycode = keymap_key_to_keycode(layer, key);
+    } else
   #endif
-
-  if (!process_record_kb(keycode, record))
-    return false;
+    keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
 
     // This is how you use actions here
     // if (keycode == KC_LEAD) {
@@ -147,304 +148,159 @@ bool process_record_quantum(keyrecord_t *record) {
     //   return false;
     // }
 
+  if (!(
+    process_record_kb(keycode, record) &&
   #ifdef MIDI_ENABLE
-    if (keycode == MI_ON && record->event.pressed) {
-      midi_activated = true;
-      music_scale_user();
-      return false;
-    }
+    process_midi(keycode, record) &&
+  #endif
+  #ifdef AUDIO_ENABLE
+    process_music(keycode, record) &&
+  #endif
+  #ifdef TAP_DANCE_ENABLE
+    process_tap_dance(keycode, record) &&
+  #endif
+  #ifndef DISABLE_LEADER
+    process_leader(keycode, record) &&
+  #endif
+  #ifndef DISABLE_CHORDING
+    process_chording(keycode, record) &&
+  #endif
+  #ifdef COMBO_ENABLE
+    process_combo(keycode, record) &&
+  #endif
+  #ifdef UNICODE_ENABLE
+    process_unicode(keycode, record) &&
+  #endif
+  #ifdef UCIS_ENABLE
+    process_ucis(keycode, record) &&
+  #endif
+  #ifdef PRINTING_ENABLE
+    process_printer(keycode, record) &&
+  #endif
+  #ifdef UNICODEMAP_ENABLE
+    process_unicode_map(keycode, record) &&
+  #endif
+      true)) {
+    return false;
+  }
 
-    if (keycode == MI_OFF && record->event.pressed) {
-      midi_activated = false;
-      midi_send_cc(&midi_device, 0, 0x7B, 0);
-      return false;
-    }
+  // Shift / paren setup
 
-    if (midi_activated) {
-      if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) {
-          if (record->event.pressed) {
-              starting_note++; // Change key
-              midi_send_cc(&midi_device, 0, 0x7B, 0);
-          }
-          return false;
-      }
-      if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) {
-          if (record->event.pressed) {
-              starting_note--; // Change key
-              midi_send_cc(&midi_device, 0, 0x7B, 0);
-          }
-          return false;
-      }
-      if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
-          offset++; // Change scale
-          midi_send_cc(&midi_device, 0, 0x7B, 0);
-          return false;
-      }
-      if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
-          offset--; // Change scale
-          midi_send_cc(&midi_device, 0, 0x7B, 0);
-          return false;
+  switch(keycode) {
+    case RESET:
+      if (record->event.pressed) {
+        reset_keyboard();
       }
-      // basic
-      // uint8_t note = (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row);
-      // advanced
-      // uint8_t note = (starting_note + record->event.key.col + offset)+12*(MATRIX_ROWS - record->event.key.row);
-      // guitar
-      uint8_t note = (starting_note + record->event.key.col + offset)+5*(MATRIX_ROWS - record->event.key.row);
-      // violin
-      // uint8_t note = (starting_note + record->event.key.col + offset)+7*(MATRIX_ROWS - record->event.key.row);
-
+         return false;
+      break;
+    case DEBUG:
       if (record->event.pressed) {
-        // midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
-        midi_send_noteon(&midi_device, 0, note, 127);
-      } else {
-        // midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
-        midi_send_noteoff(&midi_device, 0, note, 127);
+          print("\nDEBUG: enabled.\n");
+          debug_enable = true;
       }
-
-      if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
-        return false;
-    }
-  #endif
-
-  #ifdef AUDIO_ENABLE
-    if (keycode == AU_ON && record->event.pressed) {
-      audio_on();
-      return false;
-    }
-
-    if (keycode == AU_OFF && record->event.pressed) {
-      audio_off();
-      return false;
-    }
-
-    if (keycode == AU_TOG && record->event.pressed) {
-        if (is_audio_on())
-        {
-            audio_off();
-        }
-        else
-        {
-            audio_on();
-        }
-      return false;
-    }
-
-    if (keycode == MU_ON && record->event.pressed) {
-        music_on();
-        return false;
-    }
-
-    if (keycode == MU_OFF && record->event.pressed) {
-        music_off();
-        return false;
-    }
-
-    if (keycode == MU_TOG && record->event.pressed) {
-        if (music_activated)
-        {
-            music_off();
-        }
-        else
-        {
-            music_on();
-        }
-        return false;
+         return false;
+      break;
+  #ifdef FAUXCLICKY_ENABLE
+  case FC_TOG:
+    if (record->event.pressed) {
+      FAUXCLICKY_TOGGLE;
     }
-
-    if (keycode == MUV_IN && record->event.pressed) {
-        voice_iterate();
-        music_scale_user();
-        return false;
+    return false;
+    break;
+  case FC_ON:
+    if (record->event.pressed) {
+      FAUXCLICKY_ON;
     }
-
-    if (keycode == MUV_DE && record->event.pressed) {
-        voice_deiterate();
-        music_scale_user();
-        return false;
+    return false;
+    break;
+  case FC_OFF:
+    if (record->event.pressed) {
+      FAUXCLICKY_OFF;
     }
-
-    if (music_activated) {
-
-      if (keycode == KC_LCTL && record->event.pressed) { // Start recording
-        stop_all_notes();
-        music_sequence_recording = true;
-        music_sequence_playing = false;
-        music_sequence_count = 0;
-        return false;
+    return false;
+    break;
+  #endif
+       #ifdef RGBLIGHT_ENABLE
+       case RGB_TOG:
+               if (record->event.pressed) {
+                       rgblight_toggle();
       }
-
-      if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing
-        stop_all_notes();
-        music_sequence_recording = false;
-        music_sequence_playing = false;
-        return false;
+         return false;
+      break;
+       case RGB_MOD:
+               if (record->event.pressed) {
+                       rgblight_step();
       }
-
-      if (keycode == KC_LGUI && record->event.pressed) { // Start playing
-        stop_all_notes();
-        music_sequence_recording = false;
-        music_sequence_playing = true;
-        music_sequence_position = 0;
-        music_sequence_timer = 0;
-        return false;
+         return false;
+      break;
+       case RGB_HUI:
+               if (record->event.pressed) {
+                       rgblight_increase_hue();
       }
-
-      if (keycode == KC_UP) {
-        if (record->event.pressed)
-            music_sequence_interval-=10;
-        return false;
+         return false;
+      break;
+       case RGB_HUD:
+               if (record->event.pressed) {
+                       rgblight_decrease_hue();
       }
-
-      if (keycode == KC_DOWN) {
-        if (record->event.pressed)
-            music_sequence_interval+=10;
-        return false;
+         return false;
+      break;
+       case RGB_SAI:
+               if (record->event.pressed) {
+                       rgblight_increase_sat();
       }
-
-      float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row));
+         return false;
+      break;
+       case RGB_SAD:
+               if (record->event.pressed) {
+                       rgblight_decrease_sat();
+      }
+         return false;
+      break;
+       case RGB_VAI:
+               if (record->event.pressed) {
+                       rgblight_increase_val();
+      }
+         return false;
+      break;
+       case RGB_VAD:
+               if (record->event.pressed) {
+                       rgblight_decrease_val();
+      }
+         return false;
+      break;
+       #endif
+    #ifdef PROTOCOL_LUFA
+    case OUT_AUTO:
       if (record->event.pressed) {
-        play_note(freq, 0xF);
-        if (music_sequence_recording) {
-          music_sequence[music_sequence_count] = freq;
-          music_sequence_count++;
-        }
-      } else {
-        stop_note(freq);
+        set_output(OUTPUT_AUTO);
       }
-
-      if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
-        return false;
-    }
-  #endif
-
-#ifndef DISABLE_LEADER
-  // Leader key set-up
-  if (record->event.pressed) {
-    if (!leading && keycode == KC_LEAD) {
-      leader_start();
-      leading = true;
-      leader_time = timer_read();
-      leader_sequence_size = 0;
-      leader_sequence[0] = 0;
-      leader_sequence[1] = 0;
-      leader_sequence[2] = 0;
-      leader_sequence[3] = 0;
-      leader_sequence[4] = 0;
       return false;
-    }
-    if (leading && timer_elapsed(leader_time) < LEADER_TIMEOUT) {
-      leader_sequence[leader_sequence_size] = keycode;
-      leader_sequence_size++;
-      return false;
-    }
-  }
-#endif
-
-#define DISABLE_CHORDING
-#ifndef DISABLE_CHORDING
-
-  if (keycode >= QK_CHORDING && keycode <= QK_CHORDING_MAX) {
-    if (record->event.pressed) {
-      if (!chording) {
-        chording = true;
-        for (uint8_t i = 0; i < CHORDING_MAX; i++)
-          chord_keys[i] = 0;
-        chord_key_count = 0;
-        chord_key_down = 0;
+      break;
+    case OUT_USB:
+      if (record->event.pressed) {
+        set_output(OUTPUT_USB);
       }
-      chord_keys[chord_key_count] = (keycode & 0xFF);
-      chord_key_count++;
-      chord_key_down++;
       return false;
-    } else {
-      if (chording) {
-        chord_key_down--;
-        if (chord_key_down == 0) {
-          chording = false;
-          // Chord Dictionary
-          if (keys_chord((uint8_t[]){KC_ENTER, KC_SPACE})) {
-            register_code(KC_A);
-            unregister_code(KC_A);
-            return false;
-          }
-          for (uint8_t i = 0; i < chord_key_count; i++) {
-            register_code(chord_keys[i]);
-            unregister_code(chord_keys[i]);
-            return false;
-          }
-        }
-      }
-    }
-  }
-
-#endif
-
-#ifdef UNICODE_ENABLE
-
-  if (keycode > QK_UNICODE && record->event.pressed) {
-    uint16_t unicode = keycode & 0x7FFF;
-    switch(input_mode) {
-      case UC_OSX:
-        register_code(KC_LALT);
-        break;
-      case UC_LNX:
-        register_code(KC_LCTL);
-        register_code(KC_LSFT);
-        register_code(KC_U);
-        unregister_code(KC_U);
-        break;
-      case UC_WIN:
-        register_code(KC_LALT);
-        register_code(KC_PPLS);
-        unregister_code(KC_PPLS);
-        break;
-    }
-    for(int i = 3; i >= 0; i--) {
-        uint8_t digit = ((unicode >> (i*4)) & 0xF);
-        register_code(hex_to_keycode(digit));
-        unregister_code(hex_to_keycode(digit));
-    }
-    switch(input_mode) {
-      case UC_OSX:
-      case UC_WIN:
-        unregister_code(KC_LALT);
-        break;
-      case UC_LNX:
-        unregister_code(KC_LCTL);
-        unregister_code(KC_LSFT);
-        break;
-    }
-  }
-
-#endif
-
-  // Shift / paren setup
-
-  switch(keycode) {
-    case RESET:
+      break;
+    #ifdef BLUETOOTH_ENABLE
+    case OUT_BT:
       if (record->event.pressed) {
-        clear_keyboard();
-        #ifdef AUDIO_ENABLE
-          stop_all_notes();
-          shutdown_user();
-        #endif
-        _delay_ms(250);
-        #ifdef ATREUS_ASTAR
-            *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
-        #endif
-        bootloader_jump();
-        return false;
+        set_output(OUTPUT_BLUETOOTH);
       }
+      return false;
       break;
-    case DEBUG:
+    #endif
+    #ifdef ADAFRUIT_BLE_ENABLE
+    case OUT_BLE:
       if (record->event.pressed) {
-          print("\nDEBUG: enabled.\n");
-          debug_enable = true;
-          return false;
+        set_output(OUTPUT_ADAFRUIT_BLE);
       }
+      return false;
       break;
-    case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_UNSWAP_ALT_GUI:
+    #endif
+    #endif
+    case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_TOGGLE_NKRO:
       if (record->event.pressed) {
         // MAGIC actions (BOOTMAGIC without the boot)
         if (!eeconfig_is_enabled()) {
@@ -452,81 +308,120 @@ bool process_record_quantum(keyrecord_t *record) {
         }
         /* 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;
+        switch (keycode)
+        {
+          case MAGIC_SWAP_CONTROL_CAPSLOCK:
+            keymap_config.swap_control_capslock = true;
+            break;
+          case MAGIC_CAPSLOCK_TO_CONTROL:
+            keymap_config.capslock_to_control = true;
+            break;
+          case MAGIC_SWAP_LALT_LGUI:
+            keymap_config.swap_lalt_lgui = true;
+            break;
+          case MAGIC_SWAP_RALT_RGUI:
+            keymap_config.swap_ralt_rgui = true;
+            break;
+          case MAGIC_NO_GUI:
+            keymap_config.no_gui = true;
+            break;
+          case MAGIC_SWAP_GRAVE_ESC:
+            keymap_config.swap_grave_esc = true;
+            break;
+          case MAGIC_SWAP_BACKSLASH_BACKSPACE:
+            keymap_config.swap_backslash_backspace = true;
+            break;
+          case MAGIC_HOST_NKRO:
+            keymap_config.nkro = true;
+            break;
+          case MAGIC_SWAP_ALT_GUI:
+            keymap_config.swap_lalt_lgui = true;
+            keymap_config.swap_ralt_rgui = true;
+            break;
+          case MAGIC_UNSWAP_CONTROL_CAPSLOCK:
+            keymap_config.swap_control_capslock = false;
+            break;
+          case MAGIC_UNCAPSLOCK_TO_CONTROL:
+            keymap_config.capslock_to_control = false;
+            break;
+          case MAGIC_UNSWAP_LALT_LGUI:
+            keymap_config.swap_lalt_lgui = false;
+            break;
+          case MAGIC_UNSWAP_RALT_RGUI:
+            keymap_config.swap_ralt_rgui = false;
+            break;
+          case MAGIC_UNNO_GUI:
+            keymap_config.no_gui = false;
+            break;
+          case MAGIC_UNSWAP_GRAVE_ESC:
+            keymap_config.swap_grave_esc = false;
+            break;
+          case MAGIC_UNSWAP_BACKSLASH_BACKSPACE:
+            keymap_config.swap_backslash_backspace = false;
+            break;
+          case MAGIC_UNHOST_NKRO:
+            keymap_config.nkro = false;
+            break;
+          case MAGIC_UNSWAP_ALT_GUI:
+            keymap_config.swap_lalt_lgui = false;
+            keymap_config.swap_ralt_rgui = false;
+            break;
+          case MAGIC_TOGGLE_NKRO:
+            keymap_config.nkro = !keymap_config.nkro;
+            break;
+          default:
+            break;
         }
         eeconfig_update_keymap(keymap_config.raw);
+        clear_keyboard(); // clear to prevent stuck keys
+
         return false;
       }
       break;
     case KC_LSPO: {
       if (record->event.pressed) {
         shift_interrupted[0] = false;
+        scs_timer = timer_read ();
         register_mods(MOD_BIT(KC_LSFT));
       }
       else {
-        if (!shift_interrupted[0]) {
+        #ifdef DISABLE_SPACE_CADET_ROLLOVER
+          if (get_mods() & MOD_BIT(KC_RSFT)) {
+            shift_interrupted[0] = true;
+            shift_interrupted[1] = true;
+          }
+        #endif
+        if (!shift_interrupted[0] && timer_elapsed(scs_timer) < TAPPING_TERM) {
           register_code(LSPO_KEY);
           unregister_code(LSPO_KEY);
         }
         unregister_mods(MOD_BIT(KC_LSFT));
       }
       return false;
-      break;
+      // break;
     }
 
     case KC_RSPC: {
       if (record->event.pressed) {
         shift_interrupted[1] = false;
+        scs_timer = timer_read ();
         register_mods(MOD_BIT(KC_RSFT));
       }
       else {
-        if (!shift_interrupted[1]) {
+        #ifdef DISABLE_SPACE_CADET_ROLLOVER
+          if (get_mods() & MOD_BIT(KC_LSFT)) {
+            shift_interrupted[0] = true;
+            shift_interrupted[1] = true;
+          }
+        #endif
+        if (!shift_interrupted[1] && timer_elapsed(scs_timer) < TAPPING_TERM) {
           register_code(RSPC_KEY);
           unregister_code(RSPC_KEY);
         }
         unregister_mods(MOD_BIT(KC_RSFT));
       }
       return false;
-      break;
+      // break;
     }
     default: {
       shift_interrupted[0] = true;
@@ -648,6 +543,44 @@ void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
   }
 }
 
+void tap_random_base64(void) {
+  #if defined(__AVR_ATmega32U4__)
+    uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64;
+  #else
+    uint8_t key = rand() % 64;
+  #endif
+  switch (key) {
+    case 0 ... 25:
+      register_code(KC_LSFT);
+      register_code(key + KC_A);
+      unregister_code(key + KC_A);
+      unregister_code(KC_LSFT);
+      break;
+    case 26 ... 51:
+      register_code(key - 26 + KC_A);
+      unregister_code(key - 26 + KC_A);
+      break;
+    case 52:
+      register_code(KC_0);
+      unregister_code(KC_0);
+      break;
+    case 53 ... 61:
+      register_code(key - 53 + KC_1);
+      unregister_code(key - 53 + KC_1);
+      break;
+    case 62:
+      register_code(KC_LSFT);
+      register_code(KC_EQL);
+      unregister_code(KC_EQL);
+      unregister_code(KC_LSFT);
+      break;
+    case 63:
+      register_code(KC_SLSH);
+      unregister_code(KC_SLSH);
+      break;
+  }
+}
+
 void matrix_init_quantum() {
   #ifdef BACKLIGHT_ENABLE
     backlight_init_ports();
@@ -657,46 +590,20 @@ void matrix_init_quantum() {
 
 void matrix_scan_quantum() {
   #ifdef AUDIO_ENABLE
-  if (music_sequence_playing) {
-    if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) {
-      music_sequence_timer = timer_read();
-      stop_note(music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]);
-      play_note(music_sequence[music_sequence_position], 0xF);
-      music_sequence_position = (music_sequence_position + 1) % music_sequence_count;
-    }
-  }
+    matrix_scan_music();
+  #endif
+
+  #ifdef TAP_DANCE_ENABLE
+    matrix_scan_tap_dance();
+  #endif
 
+  #ifdef COMBO_ENABLE
+    matrix_scan_combo();
   #endif
 
   matrix_scan_kb();
 }
 
-#ifdef AUDIO_ENABLE
-  bool is_music_on(void) {
-      return (music_activated != 0);
-  }
-
-  void music_toggle(void) {
-      if (!music_activated) {
-          music_on();
-      } else {
-          music_off();
-      }
-  }
-
-  void music_on(void) {
-      music_activated = 1;
-      music_on_user();
-  }
-
-  void music_off(void) {
-      music_activated = 0;
-      stop_all_notes();
-  }
-
-#endif
-
-
 #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
 
 static const uint8_t backlight_pin = BACKLIGHT_PIN;
@@ -711,34 +618,45 @@ static const uint8_t backlight_pin = BACKLIGHT_PIN;
 #  define COM1x1 COM1A1
 #  define OCR1x  OCR1A
 #else
-#  error "Backlight pin not supported - use B5, B6, or B7"
+#  define NO_BACKLIGHT_CLOCK
+#endif
+
+#ifndef BACKLIGHT_ON_STATE
+#define BACKLIGHT_ON_STATE 0
 #endif
 
 __attribute__ ((weak))
 void backlight_init_ports(void)
 {
 
-  // Setup backlight pin as output and output low.
+  // Setup backlight pin as output and output to on state.
   // DDRx |= n
   _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF);
-  // PORTx &= ~n
-  _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
+  #if BACKLIGHT_ON_STATE == 0
+    // PORTx &= ~n
+    _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
+  #else
+    // PORTx |= n
+    _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
+  #endif
 
-  // Use full 16-bit resolution.
-  ICR1 = 0xFFFF;
+  #ifndef NO_BACKLIGHT_CLOCK
+    // Use full 16-bit resolution.
+    ICR1 = 0xFFFF;
 
-  // I could write a wall of text here to explain... but TL;DW
-  // Go read the ATmega32u4 datasheet.
-  // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
+    // I could write a wall of text here to explain... but TL;DW
+    // Go read the ATmega32u4 datasheet.
+    // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
 
-  // Pin PB7 = OCR1C (Timer 1, Channel C)
-  // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
-  // (i.e. start high, go low when counter matches.)
-  // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
-  // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
+    // Pin PB7 = OCR1C (Timer 1, Channel C)
+    // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
+    // (i.e. start high, go low when counter matches.)
+    // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
+    // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
 
-  TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
-  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
+    TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
+    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
+  #endif
 
   backlight_init();
   #ifdef BACKLIGHT_BREATHING
@@ -750,24 +668,43 @@ __attribute__ ((weak))
 void backlight_set(uint8_t level)
 {
   // Prevent backlight blink on lowest level
-  // PORTx &= ~n
-  _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
+  #if BACKLIGHT_ON_STATE == 0
+    // PORTx &= ~n
+    _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
+  #else
+    // PORTx |= n
+    _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
+  #endif
 
   if ( level == 0 ) {
-    // Turn off PWM control on backlight pin, revert to output low.
-    TCCR1A &= ~(_BV(COM1x1));
-    OCR1x = 0x0;
-  } else if ( level == BACKLIGHT_LEVELS ) {
-    // Turn on PWM control of backlight pin
-    TCCR1A |= _BV(COM1x1);
-    // Set the brightness
-    OCR1x = 0xFFFF;
-  } else {
-    // Turn on PWM control of backlight pin
-    TCCR1A |= _BV(COM1x1);
-    // Set the brightness
-    OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
-  }
+    #ifndef NO_BACKLIGHT_CLOCK
+      // Turn off PWM control on backlight pin, revert to output low.
+      TCCR1A &= ~(_BV(COM1x1));
+      OCR1x = 0x0;
+    #else
+      #if BACKLIGHT_ON_STATE == 0
+        // PORTx |= n
+        _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
+      #else
+        // PORTx &= ~n
+        _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
+      #endif
+    #endif
+  } 
+  #ifndef NO_BACKLIGHT_CLOCK
+    else if ( level == BACKLIGHT_LEVELS ) {
+      // Turn on PWM control of backlight pin
+      TCCR1A |= _BV(COM1x1);
+      // Set the brightness
+      OCR1x = 0xFFFF;
+    } 
+    else {
+      // Turn on PWM control of backlight pin
+      TCCR1A |= _BV(COM1x1);
+      // Set the brightness
+      OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
+    }
+  #endif
 
   #ifdef BACKLIGHT_BREATHING
     breathing_intensity_default();
@@ -997,6 +934,64 @@ void backlight_set(uint8_t level)
 #endif // backlight
 
 
+// Functions for spitting out values
+//
+
+void send_dword(uint32_t number) { // this might not actually work
+    uint16_t word = (number >> 16);
+    send_word(word);
+    send_word(number & 0xFFFFUL);
+}
+
+void send_word(uint16_t number) {
+    uint8_t byte = number >> 8;
+    send_byte(byte);
+    send_byte(number & 0xFF);
+}
+
+void send_byte(uint8_t number) {
+    uint8_t nibble = number >> 4;
+    send_nibble(nibble);
+    send_nibble(number & 0xF);
+}
+
+void send_nibble(uint8_t number) {
+    switch (number) {
+        case 0:
+            register_code(KC_0);
+            unregister_code(KC_0);
+            break;
+        case 1 ... 9:
+            register_code(KC_1 + (number - 1));
+            unregister_code(KC_1 + (number - 1));
+            break;
+        case 0xA ... 0xF:
+            register_code(KC_A + (number - 0xA));
+            unregister_code(KC_A + (number - 0xA));
+            break;
+    }
+}
+
+
+__attribute__((weak))
+uint16_t hex_to_keycode(uint8_t hex)
+{
+  if (hex == 0x0) {
+    return KC_0;
+  } else if (hex < 0xA) {
+    return KC_1 + (hex - 0x1);
+  } else {
+    return KC_A + (hex - 0xA);
+  }
+}
+
+void api_send_unicode(uint32_t unicode) {
+#ifdef API_ENABLE
+    uint8_t chunk[4];
+    dword_to_bytes(unicode, chunk);
+    MT_SEND_DATA(DT_UNICODE, chunk, 5);
+#endif
+}
 
 __attribute__ ((weak))
 void led_set_user(uint8_t usb_led) {
@@ -1048,13 +1043,4 @@ void startup_user() {}
 __attribute__ ((weak))
 void shutdown_user() {}
 
-__attribute__ ((weak))
-void music_on_user() {}
-
-__attribute__ ((weak))
-void audio_on_user() {}
-
-__attribute__ ((weak))
-void music_scale_user() {}
-
 //------------------------------------------------------------------------------