summary refs log tree commit diff
path: root/tmk_core/common
diff options
context:
space:
mode:
authorJosh Colbeck <skrymir@gmail.com>2017-02-21 20:31:16 -0600
committerJosh Colbeck <skrymir@gmail.com>2017-02-21 20:31:16 -0600
commite51001efcc3ff8b64f8264e8bd4c2dbea15f3364 (patch)
treebdf5a0a4b44d5e63ba1376b70d94f64c77f3c90c /tmk_core/common
parentc56693f858cb3409e4a68a8e65a1370c022a51ed (diff)
parent7ff41df32c29bca4e3a6efc3047b8fa93bb99b92 (diff)
Merge remote-tracking branch 'qmk/master'
Diffstat (limited to 'tmk_core/common')
-rw-r--r--tmk_core/common/action.c118
-rw-r--r--tmk_core/common/action.h18
-rw-r--r--tmk_core/common/action_code.h38
-rw-r--r--tmk_core/common/action_layer.c14
-rw-r--r--tmk_core/common/action_layer.h5
-rw-r--r--tmk_core/common/action_macro.h26
-rw-r--r--tmk_core/common/action_util.c10
-rw-r--r--tmk_core/common/avr/bootloader.c20
-rw-r--r--tmk_core/common/avr/suspend.c11
-rw-r--r--tmk_core/common/avr/timer.c69
-rw-r--r--tmk_core/common/avr/xprintf.S1000
-rw-r--r--tmk_core/common/avr/xprintf.h222
-rw-r--r--tmk_core/common/backlight.c4
-rw-r--r--tmk_core/common/bootmagic.c4
-rw-r--r--tmk_core/common/command.c23
-rw-r--r--tmk_core/common/host.c5
-rw-r--r--tmk_core/common/host.h4
-rw-r--r--tmk_core/common/host_driver.h9
-rw-r--r--tmk_core/common/keyboard.c13
-rw-r--r--tmk_core/common/keycode.h2
-rw-r--r--tmk_core/common/magic.c4
-rw-r--r--tmk_core/common/matrix.h2
-rw-r--r--tmk_core/common/mbed/xprintf.cpp2
-rw-r--r--tmk_core/common/mbed/xprintf.h2
-rw-r--r--tmk_core/common/print.h172
-rw-r--r--tmk_core/common/raw_hid.h8
-rw-r--r--tmk_core/common/report.h7
-rw-r--r--tmk_core/common/virtser.h10
28 files changed, 1091 insertions, 731 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index be6dea2b79..94de36918d 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -33,6 +33,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "nodebug.h"
 #endif
 
+#ifdef FAUXCLICKY_ENABLE
+#include <fauxclicky.h>
+#endif
 
 void action_exec(keyevent_t event)
 {
@@ -41,8 +44,31 @@ void action_exec(keyevent_t event)
         dprint("EVENT: "); debug_event(event); dprintln();
     }
 
+#ifdef FAUXCLICKY_ENABLE
+    if (IS_PRESSED(event)) {
+        FAUXCLICKY_ACTION_PRESS;
+    }
+    if (IS_RELEASED(event)) {
+        FAUXCLICKY_ACTION_RELEASE;
+    }
+    fauxclicky_check();
+#endif
+
+#ifdef ONEHAND_ENABLE
+    if (!IS_NOEVENT(event)) {
+        process_hand_swap(&event);
+    }
+#endif
+
     keyrecord_t record = { .event = event };
 
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+    if (has_oneshot_layer_timed_out()) {
+        dprintf("Oneshot layer: timeout\n");
+        clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+    }
+#endif
+
 #ifndef NO_ACTION_TAPPING
     action_tapping_process(record);
 #else
@@ -53,6 +79,26 @@ void action_exec(keyevent_t event)
 #endif
 }
 
+#ifdef ONEHAND_ENABLE
+bool swap_hands = false;
+
+void process_hand_swap(keyevent_t *event) {
+    static swap_state_row_t swap_state[MATRIX_ROWS];
+
+    keypos_t pos = event->key;
+    swap_state_row_t col_bit = (swap_state_row_t)1<<pos.col;
+    bool do_swap = event->pressed ? swap_hands :
+                                    swap_state[pos.row] & (col_bit);
+
+    if (do_swap) {
+        event->key = hand_swap_config[pos.row][pos.col];
+        swap_state[pos.row] |= col_bit;
+    } else {
+        swap_state[pos.row] &= ~(col_bit);
+    }
+}
+#endif
+
 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
 bool disable_action_cache = false;
 
@@ -74,7 +120,7 @@ bool process_record_quantum(keyrecord_t *record) {
     return true;
 }
 
-void process_record(keyrecord_t *record) 
+void process_record(keyrecord_t *record)
 {
     if (IS_NOEVENT(record->event)) { return; }
 
@@ -100,13 +146,6 @@ void process_action(keyrecord_t *record, action_t action)
     uint8_t tap_count = record->tap.count;
 #endif
 
-#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
-    if (has_oneshot_layer_timed_out()) {
-        dprintf("Oneshot layer: timeout\n");
-        clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
-    }
-#endif
-
     if (event.pressed) {
         // clear the potential weak mods left by previously pressed keys
         clear_weak_mods();
@@ -129,9 +168,10 @@ void process_action(keyrecord_t *record, action_t action)
                                                                 action.key.mods<<4;
                 if (event.pressed) {
                     if (mods) {
-                        if (IS_MOD(action.key.code)) {
+                        if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
                             // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
-                            // this also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT)
+                            // This also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT).
+                            // Same applies for some keys like KC_MEH which are declared as MEH(KC_NO).
                             add_mods(mods);
                         } else {
                             add_weak_mods(mods);
@@ -142,7 +182,7 @@ void process_action(keyrecord_t *record, action_t action)
                 } else {
                     unregister_code(action.key.code);
                     if (mods) {
-                        if (IS_MOD(action.key.code)) {
+                        if (IS_MOD(action.key.code) || action.key.code == KC_NO) {
                             del_mods(mods);
                         } else {
                             del_weak_mods(mods);
@@ -440,6 +480,54 @@ void process_action(keyrecord_t *record, action_t action)
 #endif
         case ACT_COMMAND:
             break;
+#ifdef ONEHAND_ENABLE
+        case ACT_SWAP_HANDS:
+            switch (action.swap.code) {
+                case OP_SH_TOGGLE:
+                    if (event.pressed) {
+                        swap_hands = !swap_hands;
+                    }
+                    break;
+                case OP_SH_ON_OFF:
+                    swap_hands = event.pressed;
+                    break;
+                case OP_SH_OFF_ON:
+                    swap_hands = !event.pressed;
+                    break;
+                case OP_SH_ON:
+                    if (!event.pressed) {
+                        swap_hands = true;
+                    }
+                    break;
+                case OP_SH_OFF:
+                    if (!event.pressed) {
+                        swap_hands = false;
+                    }
+                    break;
+    #ifndef NO_ACTION_TAPPING
+                case OP_SH_TAP_TOGGLE:
+                    /* tap toggle */
+                    if (tap_count > 0) {
+                        if (!event.pressed) {
+                            swap_hands = !swap_hands;
+                        }
+                    } else {
+                        swap_hands = event.pressed;
+                    }
+                    break;
+                default:
+                    if (tap_count > 0) {
+                        if (event.pressed) {
+                            register_code(action.swap.code);
+                        } else {
+                            unregister_code(action.swap.code);
+                        }
+                    } else {
+                        swap_hands = event.pressed;
+                    }
+    #endif
+            }
+#endif
 #ifndef NO_ACTION_FUNCTION
         case ACT_FUNCTION:
             action_function(record, action.func.id, action.func.opt);
@@ -652,6 +740,13 @@ bool is_tap_key(keypos_t key)
                     return true;
             }
             return false;
+        case ACT_SWAP_HANDS:
+            switch (action.swap.code) {
+                case 0x00 ... 0xdf:
+                case OP_SH_TAP_TOGGLE:
+                    return true;
+            }
+            return false;
         case ACT_MACRO:
         case ACT_FUNCTION:
             if (action.func.opt & FUNC_TAP) { return true; }
@@ -692,6 +787,7 @@ void debug_action(action_t action)
         case ACT_MACRO:             dprint("ACT_MACRO");             break;
         case ACT_COMMAND:           dprint("ACT_COMMAND");           break;
         case ACT_FUNCTION:          dprint("ACT_FUNCTION");          break;
+        case ACT_SWAP_HANDS:        dprint("ACT_SWAP_HANDS");        break;
         default:                    dprint("UNKNOWN");               break;
     }
     dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h
index e8aa12a7cb..b9bdfe642c 100644
--- a/tmk_core/common/action.h
+++ b/tmk_core/common/action.h
@@ -65,6 +65,24 @@ bool process_record_quantum(keyrecord_t *record);
 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
 extern bool disable_action_cache;
 #endif
+
+/* Code for handling one-handed key modifiers. */
+#ifdef ONEHAND_ENABLE
+extern bool swap_hands;
+extern const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS];
+#if (MATRIX_COLS <= 8)
+typedef  uint8_t    swap_state_row_t;
+#elif (MATRIX_COLS <= 16)
+typedef  uint16_t   swap_state_row_t;
+#elif (MATRIX_COLS <= 32)
+typedef  uint32_t   swap_state_row_t;
+#else
+#error "MATRIX_COLS: invalid value"
+#endif
+
+void process_hand_swap(keyevent_t *record);
+#endif
+
 void process_record_nocache(keyrecord_t *record);
 void process_record(keyrecord_t *record);
 void process_action(keyrecord_t *record, action_t action);
diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h
index ca729aaece..b15aaa0eb3 100644
--- a/tmk_core/common/action_code.h
+++ b/tmk_core/common/action_code.h
@@ -47,10 +47,15 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * 0100|10| usage(10)     (reserved)
  * 0100|11| usage(10)     (reserved)
  *
- * ACT_MOUSEKEY(0110): TODO: Not needed?
+ *
+ * ACT_MOUSEKEY(0101): TODO: Merge these two actions to conserve space?
  * 0101|xxxx| keycode     Mouse key
  *
- * 011x|xxxx xxxx xxxx    (reseved)
+ * ACT_SWAP_HANDS(0110):
+ * 0110|xxxx| keycode     Swap hands (keycode on tap, or options)
+ *
+ *
+ * 0111|xxxx xxxx xxxx    (reserved)
  *
  *
  * Layer Actions(10xx)
@@ -67,7 +72,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *   ee:    on event(01:press, 10:release, 11:both)
  *
  * 1001|xxxx|xxxx xxxx   (reserved)
- * 1001|oopp|BBBB BBBB   8-bit Bitwise Operation???
  *
  * ACT_LAYER_TAP(101x):
  * 101E|LLLL| keycode    On/Off with tap key    (0x00-DF)[TAP]
@@ -108,6 +112,8 @@ enum action_kind_id {
     /* Other Keys */
     ACT_USAGE           = 0b0100,
     ACT_MOUSEKEY        = 0b0101,
+    /* One-hand Support */
+    ACT_SWAP_HANDS      = 0b0110,
     /* Layer Actions */
     ACT_LAYER           = 0b1000,
     ACT_LAYER_TAP       = 0b1010, /* Layer  0-15 */
@@ -178,6 +184,11 @@ typedef union {
         uint8_t  opt    :4;
         uint8_t  kind   :4;
     } func;
+    struct action_swap {
+        uint8_t  code   :8;
+        uint8_t  opt   :4;
+        uint8_t  kind   :4;
+    } swap;
 } action_t;
 
 
@@ -295,6 +306,7 @@ enum backlight_opt {
     BACKLIGHT_STEP     = 3,
     BACKLIGHT_LEVEL    = 4,
 };
+
 /* Macro */
 #define ACTION_MACRO(id)                ACTION(ACT_MACRO, (id))
 #define ACTION_MACRO_TAP(id)            ACTION(ACT_MACRO, FUNC_TAP<<8 | (id))
@@ -306,7 +318,7 @@ enum backlight_opt {
 #define ACTION_BACKLIGHT_STEP()         ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8)
 #define ACTION_BACKLIGHT_LEVEL(level)   ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | (level))
 /* Command */
-#define ACTION_COMMAND(id, opt)         ACTION(ACT_COMMAND,  (opt)<<8 | (addr))
+#define ACTION_COMMAND(id, opt)         ACTION(ACT_COMMAND,  (opt)<<8 | (id))
 /* Function */
 enum function_opts {
     FUNC_TAP = 0x8,     /* indciates function is tappable */
@@ -314,5 +326,23 @@ enum function_opts {
 #define ACTION_FUNCTION(id)             ACTION(ACT_FUNCTION, (id))
 #define ACTION_FUNCTION_TAP(id)         ACTION(ACT_FUNCTION, FUNC_TAP<<8 | (id))
 #define ACTION_FUNCTION_OPT(id, opt)    ACTION(ACT_FUNCTION, (opt)<<8 | (id))
+/* OneHand Support */
+enum swap_hands_pram_tap_op {
+    OP_SH_TOGGLE = 0xF0,
+    OP_SH_TAP_TOGGLE,
+    OP_SH_ON_OFF,
+    OP_SH_OFF_ON,
+    OP_SH_OFF,
+    OP_SH_ON,
+};
+
+#define ACTION_SWAP_HANDS()             ACTION_SWAP_HANDS_ON_OFF()
+#define ACTION_SWAP_HANDS_TOGGLE()      ACTION(ACT_SWAP_HANDS, OP_SH_TOGGLE)
+#define ACTION_SWAP_HANDS_TAP_TOGGLE()  ACTION(ACT_SWAP_HANDS, OP_SH_TAP_TOGGLE)
+#define ACTION_SWAP_HANDS_TAP_KEY(key)  ACTION(ACT_SWAP_HANDS, key)
+#define ACTION_SWAP_HANDS_ON_OFF()      ACTION(ACT_SWAP_HANDS, OP_SH_ON_OFF)
+#define ACTION_SWAP_HANDS_OFF_ON()      ACTION(ACT_SWAP_HANDS, OP_SH_OFF_ON)
+#define ACTION_SWAP_HANDS_ON()          ACTION(ACT_SWAP_HANDS, OP_SH_ON)
+#define ACTION_SWAP_HANDS_OFF()         ACTION(ACT_SWAP_HANDS, OP_SH_OFF)
 
 #endif /* ACTION_CODE_H */
diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c
index 63fa2b5ae4..58d919a04d 100644
--- a/tmk_core/common/action_layer.c
+++ b/tmk_core/common/action_layer.c
@@ -16,8 +16,14 @@
  */
 uint32_t default_layer_state = 0;
 
+__attribute__((weak))
+uint32_t default_layer_state_set_kb(uint32_t state) {
+    return state;
+}
+
 static void default_layer_state_set(uint32_t state)
 {
+    state = default_layer_state_set_kb(state);
     debug("default_layer_state: ");
     default_layer_debug(); debug(" to ");
     default_layer_state = state;
@@ -57,8 +63,14 @@ void default_layer_xor(uint32_t state)
  */
 uint32_t layer_state = 0;
 
+__attribute__((weak))
+uint32_t layer_state_set_kb(uint32_t state) {
+    return state;
+}
+
 static void layer_state_set(uint32_t state)
 {
+    state = layer_state_set_kb(state);
     dprint("layer_state: ");
     layer_debug(); dprint(" to ");
     layer_state = state;
@@ -111,7 +123,7 @@ void layer_debug(void)
 #endif
 
 #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
-uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {0};
+uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}};
 
 void update_source_layers_cache(keypos_t key, uint8_t layer)
 {
diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h
index 025cf5420f..d89ed6e5ce 100644
--- a/tmk_core/common/action_layer.h
+++ b/tmk_core/common/action_layer.h
@@ -29,6 +29,9 @@ extern uint32_t default_layer_state;
 void default_layer_debug(void);
 void default_layer_set(uint32_t state);
 
+__attribute__((weak))
+uint32_t default_layer_state_set_kb(uint32_t state);
+
 #ifndef NO_ACTION_LAYER
 /* bitwise operation */
 void default_layer_or(uint32_t state);
@@ -69,6 +72,8 @@ void layer_xor(uint32_t state);
 #define layer_xor(state)
 #define layer_debug()
 
+__attribute__((weak))
+uint32_t layer_state_set_kb(uint32_t state);
 #endif
 
 /* pressed actions cache */
diff --git a/tmk_core/common/action_macro.h b/tmk_core/common/action_macro.h
index aedc32ec6b..f373f5068e 100644
--- a/tmk_core/common/action_macro.h
+++ b/tmk_core/common/action_macro.h
@@ -20,11 +20,33 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "progmem.h"
 
 
-#define MACRO_NONE      0
+
+typedef uint8_t macro_t;
+
+#define MACRO_NONE      (macro_t*)0
 #define MACRO(...)      ({ static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; })
 #define MACRO_GET(p)    pgm_read_byte(p)
 
-typedef uint8_t macro_t;
+// Sends press when the macro key is pressed, release when release, or tap_macro when the key has been tapped
+#define MACRO_TAP_HOLD(record, press, release, tap_macro) ( ((record)->event.pressed) ? \
+     ( ((record)->tap.count <= 0 || (record)->tap.interrupted) ? (press) : MACRO_NONE ) : \
+     ( ((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (tap_macro) : (release) ) )
+
+// Holds down the modifier mod when the macro key is held, or sends macro instead when tapped
+#define MACRO_TAP_HOLD_MOD(record, macro, mod) MACRO_TAP_HOLD(record, (MACRO(D(mod), END)), MACRO(U(mod), END), macro)
+
+// Holds down the modifier mod when the macro key is held, or pressed a shifted key when tapped (eg: shift+3 for #)
+#define MACRO_TAP_SHFT_KEY_HOLD_MOD(record, key, mod) MACRO_TAP_HOLD_MOD(record, (MACRO(I(10), D(LSFT), T(key), U(LSFT), END)), mod)
+
+
+// Momentary switch layer when held, sends macro if tapped
+#define MACRO_TAP_HOLD_LAYER(record, macro, layer) ( ((record)->event.pressed) ? \
+     ( ((record)->tap.count <= 0 || (record)->tap.interrupted) ? ({layer_on((layer)); MACRO_NONE; }) : MACRO_NONE ) : \
+     ( ((record)->tap.count > 0 && !((record)->tap.interrupted)) ? (macro) : ({layer_off((layer)); MACRO_NONE; }) ) )
+
+// Momentary switch layer when held, presses a shifted key when tapped (eg: shift+3 for #)
+#define MACRO_TAP_SHFT_KEY_HOLD_LAYER(record, key, layer) MACRO_TAP_HOLD_LAYER(record, MACRO(I(10), D(LSFT), T(key), U(LSFT), END), layer)
+     
 
 
 #ifndef NO_ACTION_MACRO
diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c
index 61ff202bef..cb4b252648 100644
--- a/tmk_core/common/action_util.c
+++ b/tmk_core/common/action_util.c
@@ -20,6 +20,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "action_util.h"
 #include "action_layer.h"
 #include "timer.h"
+#include "keycode_config.h"
+
+extern keymap_config_t keymap_config;
+
 
 static inline void add_key_byte(uint8_t code);
 static inline void del_key_byte(uint8_t code);
@@ -139,7 +143,7 @@ void send_keyboard_report(void) {
 void add_key(uint8_t key)
 {
 #ifdef NKRO_ENABLE
-    if (keyboard_protocol && keyboard_nkro) {
+    if (keyboard_protocol && keymap_config.nkro) {
         add_key_bit(key);
         return;
     }
@@ -150,7 +154,7 @@ void add_key(uint8_t key)
 void del_key(uint8_t key)
 {
 #ifdef NKRO_ENABLE
-    if (keyboard_protocol && keyboard_nkro) {
+    if (keyboard_protocol && keymap_config.nkro) {
         del_key_bit(key);
         return;
     }
@@ -231,7 +235,7 @@ uint8_t has_anymod(void)
 uint8_t get_first_key(void)
 {
 #ifdef NKRO_ENABLE
-    if (keyboard_protocol && keyboard_nkro) {
+    if (keyboard_protocol && keymap_config.nkro) {
         uint8_t i = 0;
         for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
             ;
diff --git a/tmk_core/common/avr/bootloader.c b/tmk_core/common/avr/bootloader.c
index fb9bf2d1c3..34db8d0b0a 100644
--- a/tmk_core/common/avr/bootloader.c
+++ b/tmk_core/common/avr/bootloader.c
@@ -1,6 +1,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <avr/io.h>
+#include <avr/eeprom.h>
 #include <avr/interrupt.h>
 #include <avr/wdt.h>
 #include <util/delay.h>
@@ -38,7 +39,7 @@
  *          |               |                        |               |
  *          =               =                        =               =
  *          |               | 32KB-4KB               |               | 128KB-8KB
- * 0x6000   +---------------+               0x1FC00  +---------------+
+ * 0x7000   +---------------+               0x1E000  +---------------+
  *          |  Bootloader   | 4KB                    |  Bootloader   | 8KB
  * 0x7FFF   +---------------+               0x1FFFF  +---------------+
  *
@@ -64,8 +65,8 @@
 #define BOOTLOADER_START    (FLASH_SIZE - BOOTLOADER_SIZE)
 
 
-/* 
- * Entering the Bootloader via Software 
+/*
+ * Entering the Bootloader via Software
  * http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
  */
 #define BOOTLOADER_RESET_KEY 0xB007B007
@@ -89,6 +90,12 @@ void bootloader_jump(void) {
             _delay_ms(5);
         #endif
 
+        #ifdef BOOTLOADHID_BOOTLOADER
+            // force bootloadHID to stay in bootloader mode, so that it waits
+            // for a new firmware to be flashed
+            eeprom_write_byte((uint8_t *)1, 0x00);
+        #endif
+
         // watchdog reset
         reset_key = BOOTLOADER_RESET_KEY;
         wdt_enable(WDTO_250MS);
@@ -114,6 +121,11 @@ void bootloader_jump(void) {
     #endif
 }
 
+#ifdef __AVR_ATmega32A__
+// MCUSR is actually called MCUCSR in ATmega32A
+#define MCUSR MCUCSR
+#endif
+
 /* this runs before main() */
 void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3")));
 void bootloader_jump_after_watchdog_reset(void)
@@ -137,7 +149,7 @@ void bootloader_jump_after_watchdog_reset(void)
 #if 0
 /* Jumping To The Bootloader
  * http://www.pjrc.com/teensy/jump_to_bootloader.html
- * 
+ *
  * This method doen't work when using LUFA. idk why.
  * - needs to initialize more regisers or interrupt setting?
  */
diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c
index 8a7272bbc5..0c81e83612 100644
--- a/tmk_core/common/avr/suspend.c
+++ b/tmk_core/common/avr/suspend.c
@@ -47,6 +47,7 @@ void suspend_idle(uint8_t time)
     sleep_disable();
 }
 
+#ifndef NO_SUSPEND_POWER_DOWN
 /* Power down MCU with watchdog timer
  * wdto: watchdog timer timeout defined in <avr/wdt.h>
  *          WDTO_15MS
@@ -61,6 +62,7 @@ void suspend_idle(uint8_t time)
  *          WDTO_8S
  */
 static uint8_t wdt_timeout = 0;
+
 static void power_down(uint8_t wdto)
 {
 #ifdef PROTOCOL_LUFA
@@ -98,19 +100,19 @@ static void power_down(uint8_t wdto)
     // Disable watchdog after sleep
     wdt_disable();
 }
+#endif
 
 void suspend_power_down(void)
 {
+#ifndef NO_SUSPEND_POWER_DOWN
     power_down(WDTO_15MS);
+#endif
 }
 
 __attribute__ ((weak)) void matrix_power_up(void) {}
 __attribute__ ((weak)) void matrix_power_down(void) {}
 bool suspend_wakeup_condition(void)
 {
-#ifdef BACKLIGHT_ENABLE
-    backlight_set(0);
-#endif
     matrix_power_up();
     matrix_scan();
     matrix_power_down();
@@ -126,10 +128,9 @@ void suspend_wakeup_init(void)
     // clear keyboard state
     clear_keyboard();
 #ifdef BACKLIGHT_ENABLE
-    backlight_set(0);
     backlight_init();
 #endif
-led_set(host_keyboard_leds());
+	led_set(host_keyboard_leds());
 }
 
 #ifndef NO_SUSPEND_POWER_DOWN
diff --git a/tmk_core/common/avr/timer.c b/tmk_core/common/avr/timer.c
index 292b41c3a6..369015200d 100644
--- a/tmk_core/common/avr/timer.c
+++ b/tmk_core/common/avr/timer.c
@@ -17,6 +17,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <avr/io.h>
 #include <avr/interrupt.h>
+#include <util/atomic.h>
 #include <stdint.h>
 #include "timer_avr.h"
 #include "timer.h"
@@ -24,38 +25,47 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 // counter resolution 1ms
 // NOTE: union { uint32_t timer32; struct { uint16_t dummy; uint16_t timer16; }}
-volatile uint32_t timer_count = 0;
+volatile uint32_t timer_count;
 
 void timer_init(void)
 {
-    // Timer0 CTC mode
-    TCCR0A = 0x02;
-
 #if TIMER_PRESCALER == 1
-    TCCR0B = 0x01;
+    uint8_t prescaler = 0x01;
 #elif TIMER_PRESCALER == 8
-    TCCR0B = 0x02;
+    uint8_t prescaler = 0x02;
 #elif TIMER_PRESCALER == 64
-    TCCR0B = 0x03;
+    uint8_t prescaler = 0x03;
 #elif TIMER_PRESCALER == 256
-    TCCR0B = 0x04;
+    uint8_t prescaler = 0x04;
 #elif TIMER_PRESCALER == 1024
-    TCCR0B = 0x05;
+    uint8_t prescaler = 0x05;
 #else
 #   error "Timer prescaler value is NOT vaild."
 #endif
 
+#ifndef __AVR_ATmega32A__
+    // Timer0 CTC mode
+    TCCR0A = 0x02;
+
+    TCCR0B = prescaler;
+
     OCR0A = TIMER_RAW_TOP;
     TIMSK0 = (1<<OCIE0A);
+#else
+    // Timer0 CTC mode
+    TCCR0 = (1 << WGM01) | prescaler;
+
+    OCR0 = TIMER_RAW_TOP;
+    TIMSK = (1 << OCIE0);
+#endif
 }
 
 inline
 void timer_clear(void)
 {
-    uint8_t sreg = SREG;
-    cli();
+  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
     timer_count = 0;
-    SREG = sreg;
+  }
 }
 
 inline
@@ -63,10 +73,9 @@ uint16_t timer_read(void)
 {
     uint32_t t;
 
-    uint8_t sreg = SREG;
-    cli();
-    t = timer_count;
-    SREG = sreg;
+    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+      t = timer_count;
+    }
 
     return (t & 0xFFFF);
 }
@@ -76,10 +85,9 @@ uint32_t timer_read32(void)
 {
     uint32_t t;
 
-    uint8_t sreg = SREG;
-    cli();
-    t = timer_count;
-    SREG = sreg;
+    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+      t = timer_count;
+    }
 
     return t;
 }
@@ -89,10 +97,9 @@ uint16_t timer_elapsed(uint16_t last)
 {
     uint32_t t;
 
-    uint8_t sreg = SREG;
-    cli();
-    t = timer_count;
-    SREG = sreg;
+    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+      t = timer_count;
+    }
 
     return TIMER_DIFF_16((t & 0xFFFF), last);
 }
@@ -102,16 +109,20 @@ uint32_t timer_elapsed32(uint32_t last)
 {
     uint32_t t;
 
-    uint8_t sreg = SREG;
-    cli();
-    t = timer_count;
-    SREG = sreg;
+    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+      t = timer_count;
+    }
 
     return TIMER_DIFF_32(t, last);
 }
 
 // excecuted once per 1ms.(excess for just timer count?)
-ISR(TIMER0_COMPA_vect)
+#ifndef __AVR_ATmega32A__
+#define TIMER_INTERRUPT_VECTOR TIMER0_COMPA_vect
+#else
+#define TIMER_INTERRUPT_VECTOR TIMER0_COMP_vect
+#endif
+ISR(TIMER_INTERRUPT_VECTOR, ISR_NOBLOCK)
 {
     timer_count++;
 }
diff --git a/tmk_core/common/avr/xprintf.S b/tmk_core/common/avr/xprintf.S
index 0cec70ce22..06434b98d9 100644
--- a/tmk_core/common/avr/xprintf.S
+++ b/tmk_core/common/avr/xprintf.S
@@ -1,500 +1,500 @@
-;---------------------------------------------------------------------------;

-; Extended itoa, puts, printf and atoi                     (C)ChaN, 2011

-;---------------------------------------------------------------------------;

-

-				// Base size is 152 bytes

-#define	CR_CRLF		0	// Convert \n to \r\n (+10 bytes)

-#define USE_XPRINTF	1	// Enable xprintf function (+194 bytes)

-#define USE_XSPRINTF	0	// Add xsprintf function (+78 bytes)

-#define USE_XFPRINTF	0	// Add xfprintf function (+54 bytes)

-#define USE_XATOI	0	// Enable xatoi function (+182 bytes)

-

-

-#if FLASHEND > 0x1FFFF

-#error xitoa module does not support 256K devices

-#endif

-

-.nolist

-#include <avr/io.h>	// Include device specific definitions.

-.list

-

-#ifdef SPM_PAGESIZE	// Recent devices have "lpm Rd,Z+" and "movw".

-.macro	_LPMI	reg

-	lpm	\reg, Z+

-.endm

-.macro	_MOVW	dh,dl, sh,sl

-	movw	\dl, \sl

-.endm

-#else			// Earlier devices do not have "lpm Rd,Z+" nor "movw".

-.macro	_LPMI	reg

-	lpm

-	mov	\reg, r0

-	adiw	ZL, 1

-.endm

-.macro	_MOVW	dh,dl, sh,sl

-	mov	\dl, \sl

-	mov	\dh, \sh

-.endm

-#endif

-

-

-

-;---------------------------------------------------------------------------

-; Stub function to forward to user output function

-;

-;Prototype: void xputc (char chr	// a character to be output

-;			);

-;Size: 12/12 words

-

-.section .bss

-.global xfunc_out	; xfunc_out must be initialized before using this module.

-xfunc_out:	.ds.w	1

-.section .text

-

-

-.func xputc

-.global xputc

-xputc:

-#if CR_CRLF

-	cpi	r24, 10		;LF --> CRLF

-	brne	1f		;

-	ldi	r24, 13		;

-	rcall	1f		;

-	ldi	r24, 10		;/

-1:

-#endif

-	push	ZH

-	push	ZL

-	lds	ZL, xfunc_out+0	;Pointer to the registered output function.

-	lds	ZH, xfunc_out+1	;/

-	sbiw	ZL, 0		;Skip if null

-	breq	2f		;/

-	icall

-2:	pop	ZL

-	pop	ZH

-	ret

-.endfunc

-

-

-

-;---------------------------------------------------------------------------

-; Direct ROM string output

-;

-;Prototype: void xputs (const char *str_p // rom string to be output

-;			);

-

-.func xputs

-.global xputs

-xputs:

-	_MOVW	ZH,ZL, r25,r24	; Z = pointer to rom string

-1:	_LPMI	r24

-	cpi	r24, 0

-	breq	2f

-	rcall	xputc

-	rjmp	1b

-2:	ret

-.endfunc

-

-

-;---------------------------------------------------------------------------

-; Extended direct numeral string output (32bit version)

-;

-;Prototype: void xitoa (long value,	// value to be output

-;                       char radix,	// radix

-;                       char width);	// minimum width

-;

-

-.func xitoa

-.global xitoa

-xitoa:

-				;r25:r22 = value, r20 = base, r18 = digits

-	clr	r31		;r31 = stack level

-	ldi	r30, ' '	;r30 = sign

-	ldi	r19, ' '	;r19 = filler

-	sbrs	r20, 7		;When base indicates signd format and the value

-	rjmp	0f		;is minus, add a '-'.

-	neg	r20		;

-	sbrs	r25, 7		;

-	rjmp	0f		;

-	ldi	r30, '-'	;

-	com	r22		;

-	com	r23		;

-	com	r24		;

-	com	r25		;

-	adc	r22, r1		;

-	adc	r23, r1		;

-	adc	r24, r1		;

-	adc	r25, r1		;/

-0:	sbrs	r18, 7		;When digits indicates zero filled,

-	rjmp	1f		;filler is '0'.

-	neg	r18		;

-	ldi	r19, '0'	;/

-				;----- string conversion loop

-1:	ldi	r21, 32		;r26 = r25:r22 % r20

-	clr	r26		;r25:r22 /= r20

-2:	lsl	r22		;

-	rol	r23		;

-	rol	r24		;

-	rol	r25		;

-	rol	r26		;

-	cp	r26, r20	;

-	brcs	3f		;

-	sub	r26, r20	;

-	inc	r22		;

-3:	dec	r21		;

-	brne	2b		;/

-	cpi	r26, 10		;r26 is a numeral digit '0'-'F'

-	brcs	4f		;

-	subi	r26, -7		;

-4:	subi	r26, -'0'	;/

-	push	r26		;Stack it

-	inc	r31		;/

-	cp	r22, r1		;Repeat until r25:r22 gets zero

-	cpc	r23, r1		;

-	cpc	r24, r1		;

-	cpc	r25, r1		;

-	brne	1b		;/

-

-	cpi	r30, '-'	;Minus sign if needed

-	brne	5f		;

-	push	r30		;

-	inc	r31		;/

-5:	cp	r31, r18	;Filler

-	brcc	6f		;

-	push	r19		;

-	inc	r31		;

-	rjmp	5b		;/

-

-6:	pop	r24		;Flush stacked digits and exit

-	rcall	xputc		;

-	dec	r31		;

-	brne	6b		;/

-

-	ret

-.endfunc

-

-

-

-;---------------------------------------------------------------------------;

-; Formatted string output (16/32bit version)

-;

-;Prototype:

-; void __xprintf (const char *format_p, ...);

-; void __xsprintf(char*, const char *format_p, ...);

-; void __xfprintf(void(*func)(char), const char *format_p, ...);

-;

-

-#if USE_XPRINTF

-

-.func xvprintf

-xvprintf:

-	ld	ZL, Y+		;Z = pointer to format string

-	ld	ZH, Y+		;/

-

-0:	_LPMI	r24		;Get a format char

-	cpi	r24, 0		;End of format string?

-	breq	90f		;/

-	cpi	r24, '%'	;Is format?

-	breq	20f		;/

-1:	rcall	xputc		;Put a normal character

-	rjmp	0b		;/

-90:	ret

-

-20:	ldi	r18, 0		;r18: digits

-	clt			;T: filler

-	_LPMI	r21		;Get flags

-	cpi	r21, '%'	;Is a %?

-	breq	1b		;/

-	cpi	r21, '0'	;Zero filled?

-	brne	23f		;

-	set			;/

-22:	_LPMI	r21		;Get width

-23:	cpi	r21, '9'+1	;

-	brcc	24f		;

-	subi	r21, '0'	;

-	brcs	90b		;

-	lsl	r18		;

-	mov	r0, r18		;

-	lsl	r18		;

-	lsl	r18		;

-	add	r18, r0		;

-	add	r18, r21	;

-	rjmp	22b		;/

-

-24:	brtc	25f		;get value (low word)

-	neg	r18		;

-25:	ld	r24, Y+		;

-	ld	r25, Y+		;/

-	cpi	r21, 'c'	;Is type character?

-	breq	1b		;/

-	cpi	r21, 's'	;Is type RAM string?

-	breq	50f		;/

-	cpi	r21, 'S'	;Is type ROM string?

-	breq	60f		;/

-	_MOVW	r23,r22,r25,r24	;r25:r22 = value

-	clr	r24		;

-	clr	r25		;

-	clt			;/

-	cpi	r21, 'l'	;Is long int?

-	brne	26f		;

-	ld	r24, Y+		;get value (high word)

-	ld	r25, Y+		;

-	set			;

-	_LPMI	r21		;/

-26:	cpi	r21, 'd'	;Is type signed decimal?

-	brne	27f		;/

-	ldi	r20, -10	;

-	brts	40f		;

-	sbrs	r23, 7		;

-	rjmp	40f		;

-	ldi	r24, -1		;

-	ldi	r25, -1		;

-	rjmp	40f		;/

-27:	cpi	r21, 'u'	;Is type unsigned decimal?

-	ldi	r20, 10		;

-	breq	40f		;/

-	cpi	r21, 'X'	;Is type hexdecimal?

-	ldi	r20, 16		;

-	breq	40f		;/

-	cpi	r21, 'b'	;Is type binary?

-	ldi	r20, 2		;

-	breq	40f		;/

-	ret			;abort

-40:	push	ZH		;Output the value

-	push	ZL		;

-	rcall	xitoa		;

-42:	pop	ZL		;

-	pop	ZH		;

-	rjmp	0b		;/

-

-50:	push	ZH		;Put a string on the RAM

-	push	ZL

-	_MOVW	ZH,ZL, r25,r24

-51:	ld	r24, Z+

-	cpi	r24, 0

-	breq	42b

-	rcall	xputc

-	rjmp	51b

-

-60:	push	ZH		;Put a string on the ROM

-	push	ZL

-	rcall	xputs

-	rjmp	42b

-.endfunc

-

-

-.func __xprintf

-.global __xprintf

-__xprintf:

-	push	YH

-	push	YL

-	in	YL, _SFR_IO_ADDR(SPL)

-#ifdef SPH

-	in	YH, _SFR_IO_ADDR(SPH)

-#else

-	clr	YH

-#endif

-	adiw	YL, 5		;Y = pointer to arguments

-	rcall	xvprintf

-	pop	YL

-	pop	YH

-	ret

-.endfunc

-

-

-#if USE_XSPRINTF

-

-.func __xsprintf

-putram:

-	_MOVW	ZH,ZL, r15,r14

-	st	Z+, r24

-	_MOVW	r15,r14, ZH,ZL

-	ret

-.global __xsprintf

-__xsprintf:

-	push	YH

-	push	YL

-	in	YL, _SFR_IO_ADDR(SPL)

-#ifdef SPH

-	in	YH, _SFR_IO_ADDR(SPH)

-#else

-	clr	YH

-#endif

-	adiw	YL, 5		;Y = pointer to arguments

-	lds	ZL, xfunc_out+0	;Save registered output function

-	lds	ZH, xfunc_out+1	;

-	push	ZL		;

-	push	ZH		;/

-	ldi	ZL, lo8(pm(putram));Set local output function

-	ldi	ZH, hi8(pm(putram));

-	sts	xfunc_out+0, ZL	;

-	sts	xfunc_out+1, ZH	;/

-	push	r15		;Initialize pointer to string buffer

-	push	r14		;

-	ld	r14, Y+		;

-	ld	r15, Y+		;/

-	rcall	xvprintf

-	_MOVW	ZH,ZL, r15,r14	;Terminate string

-	st	Z, r1		;

-	pop	r14		;

-	pop	r15		;/

-	pop	ZH		;Restore registered output function

-	pop	ZL		;

-	sts	xfunc_out+0, ZL	;

-	sts	xfunc_out+1, ZH	;/

-	pop	YL

-	pop	YH

-	ret

-.endfunc

-#endif

-

-

-#if USE_XFPRINTF

-.func __xfprintf

-.global __xfprintf

-__xfprintf:

-	push	YH

-	push	YL

-	in	YL, _SFR_IO_ADDR(SPL)

-#ifdef SPH

-	in	YH, _SFR_IO_ADDR(SPH)

-#else

-	clr	YH

-#endif

-	adiw	YL, 5		;Y = pointer to arguments

-	lds	ZL, xfunc_out+0	;Save registered output function

-	lds	ZH, xfunc_out+1	;

-	push	ZL		;

-	push	ZH		;/

-	ld	ZL, Y+		;Set output function

-	ld	ZH, Y+		;

-	sts	xfunc_out+0, ZL	;

-	sts	xfunc_out+1, ZH	;/

-	rcall	xvprintf

-	pop	ZH		;Restore registered output function

-	pop	ZL		;

-	sts	xfunc_out+0, ZL	;

-	sts	xfunc_out+1, ZH	;/

-	pop	YL

-	pop	YH

-	ret

-.endfunc

-#endif

-

-#endif

-

-

-

-;---------------------------------------------------------------------------

-; Extended numeral string input

-;

-;Prototype:

-; char xatoi (           /* 1: Successful, 0: Failed */

-;      const char **str, /* pointer to pointer to source string */

-;      long *res         /* result */

-; );

-;

-

-

-#if USE_XATOI

-.func xatoi

-.global xatoi

-xatoi:

-	_MOVW	r1, r0, r23, r22

-	_MOVW	XH, XL, r25, r24

-	ld	ZL, X+

-	ld	ZH, X+

-	clr	r18		;r21:r18 = 0;

-	clr	r19		;

-	clr	r20		;

-	clr	r21		;/

-	clt			;T = 0;

-

-	ldi	r25, 10		;r25 = 10;

-	rjmp	41f		;/

-40:	adiw	ZL, 1		;Z++;

-41:	ld	r22, Z		;r22 = *Z;

-	cpi	r22, ' '	;if(r22 == ' ') continue

-	breq	40b		;/

-	brcs	70f		;if(r22 < ' ') error;

-	cpi	r22, '-'	;if(r22 == '-') {

-	brne	42f		; T = 1;

-	set			; continue;

-	rjmp	40b		;}

-42:	cpi	r22, '9'+1	;if(r22 > '9') error;

-	brcc	70f		;/

-	cpi	r22, '0'	;if(r22 < '0') error;

-	brcs	70f		;/

-	brne	51f		;if(r22 > '0') cv_start;

-	ldi	r25, 8		;r25 = 8;

-	adiw	ZL, 1		;r22 = *(++Z);

-	ld	r22, Z		;/

-	cpi	r22, ' '+1	;if(r22 <= ' ') exit;

-	brcs	80f		;/

-	cpi	r22, 'b'	;if(r22 == 'b') {

-	brne	43f		; r25 = 2;

-	ldi	r25, 2		; cv_start;

-	rjmp	50f		;}

-43:	cpi	r22, 'x'	;if(r22 != 'x') error;

-	brne	51f		;/

-	ldi	r25, 16		;r25 = 16;

-

-50:	adiw	ZL, 1		;Z++;

-	ld	r22, Z		;r22 = *Z;

-51:	cpi	r22, ' '+1	;if(r22 <= ' ') break;

-	brcs	80f		;/

-	cpi	r22, 'a'	;if(r22 >= 'a') r22 =- 0x20;

-	brcs	52f		;

-	subi	r22, 0x20	;/

-52:	subi	r22, '0'	;if((r22 -= '0') < 0) error;

-	brcs	70f		;/

-	cpi	r22, 10		;if(r22 >= 10) {

-	brcs	53f		; r22 -= 7;

-	subi	r22, 7		; if(r22 < 10) 

-	cpi	r22, 10		;

-	brcs	70f		;}

-53:	cp	r22, r25	;if(r22 >= r25) error;

-	brcc	70f		;/

-60:	ldi	r24, 33		;r21:r18 *= r25;

-	sub	r23, r23	;

-61:	brcc	62f		;

-	add	r23, r25	;

-62:	lsr	r23		;

-	ror	r21		;

-	ror	r20		;

-	ror	r19		;

-	ror	r18		;

-	dec	r24		;

-	brne	61b		;/

-	add	r18, r22	;r21:r18 += r22;

-	adc	r19, r24	;

-	adc	r20, r24	;

-	adc	r21, r24	;/

-	rjmp	50b		;repeat

-

-70:	ldi	r24, 0

-	rjmp	81f

-80:	ldi	r24, 1

-81:	brtc	82f

-	clr	r22

-	com	r18

-	com	r19

-	com	r20

-	com	r21

-	adc	r18, r22

-	adc	r19, r22

-	adc	r20, r22

-	adc	r21, r22

-82:	st	-X, ZH

-	st	-X, ZL

-	_MOVW	XH, XL, r1, r0

-	st	X+, r18

-	st	X+, r19

-	st	X+, r20

-	st	X+, r21

-	clr	r1

-	ret

-.endfunc

-#endif

-

-

+;---------------------------------------------------------------------------;
+; Extended itoa, puts, printf and atoi                     (C)ChaN, 2011
+;---------------------------------------------------------------------------;
+
+				// Base size is 152 bytes
+#define	CR_CRLF		0	// Convert \n to \r\n (+10 bytes)
+#define USE_XPRINTF	1	// Enable xprintf function (+194 bytes)
+#define USE_XSPRINTF	0	// Add xsprintf function (+78 bytes)
+#define USE_XFPRINTF	0	// Add xfprintf function (+54 bytes)
+#define USE_XATOI	0	// Enable xatoi function (+182 bytes)
+
+
+#if FLASHEND > 0x1FFFF
+#error xitoa module does not support 256K devices
+#endif
+
+.nolist
+#include <avr/io.h>	// Include device specific definitions.
+.list
+
+#ifdef SPM_PAGESIZE	// Recent devices have "lpm Rd,Z+" and "movw".
+.macro	_LPMI	reg
+	lpm	\reg, Z+
+.endm
+.macro	_MOVW	dh,dl, sh,sl
+	movw	\dl, \sl
+.endm
+#else			// Earlier devices do not have "lpm Rd,Z+" nor "movw".
+.macro	_LPMI	reg
+	lpm
+	mov	\reg, r0
+	adiw	ZL, 1
+.endm
+.macro	_MOVW	dh,dl, sh,sl
+	mov	\dl, \sl
+	mov	\dh, \sh
+.endm
+#endif
+
+
+
+;---------------------------------------------------------------------------
+; Stub function to forward to user output function
+;
+;Prototype: void xputc (char chr	// a character to be output
+;			);
+;Size: 12/12 words
+
+.section .bss
+.global xfunc_out	; xfunc_out must be initialized before using this module.
+xfunc_out:	.ds.w	1
+.section .text
+
+
+.func xputc
+.global xputc
+xputc:
+#if CR_CRLF
+	cpi	r24, 10		;LF --> CRLF
+	brne	1f		;
+	ldi	r24, 13		;
+	rcall	1f		;
+	ldi	r24, 10		;/
+1:
+#endif
+	push	ZH
+	push	ZL
+	lds	ZL, xfunc_out+0	;Pointer to the registered output function.
+	lds	ZH, xfunc_out+1	;/
+	sbiw	ZL, 0		;Skip if null
+	breq	2f		;/
+	icall
+2:	pop	ZL
+	pop	ZH
+	ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------
+; Direct ROM string output
+;
+;Prototype: void xputs (const char *str_p // rom string to be output
+;			);
+
+.func xputs
+.global xputs
+xputs:
+	_MOVW	ZH,ZL, r25,r24	; Z = pointer to rom string
+1:	_LPMI	r24
+	cpi	r24, 0
+	breq	2f
+	rcall	xputc
+	rjmp	1b
+2:	ret
+.endfunc
+
+
+;---------------------------------------------------------------------------
+; Extended direct numeral string output (32bit version)
+;
+;Prototype: void xitoa (long value,	// value to be output
+;                       char radix,	// radix
+;                       char width);	// minimum width
+;
+
+.func xitoa
+.global xitoa
+xitoa:
+				;r25:r22 = value, r20 = base, r18 = digits
+	clr	r31		;r31 = stack level
+	ldi	r30, ' '	;r30 = sign
+	ldi	r19, ' '	;r19 = filler
+	sbrs	r20, 7		;When base indicates signd format and the value
+	rjmp	0f		;is minus, add a '-'.
+	neg	r20		;
+	sbrs	r25, 7		;
+	rjmp	0f		;
+	ldi	r30, '-'	;
+	com	r22		;
+	com	r23		;
+	com	r24		;
+	com	r25		;
+	adc	r22, r1		;
+	adc	r23, r1		;
+	adc	r24, r1		;
+	adc	r25, r1		;/
+0:	sbrs	r18, 7		;When digits indicates zero filled,
+	rjmp	1f		;filler is '0'.
+	neg	r18		;
+	ldi	r19, '0'	;/
+				;----- string conversion loop
+1:	ldi	r21, 32		;r26 = r25:r22 % r20
+	clr	r26		;r25:r22 /= r20
+2:	lsl	r22		;
+	rol	r23		;
+	rol	r24		;
+	rol	r25		;
+	rol	r26		;
+	cp	r26, r20	;
+	brcs	3f		;
+	sub	r26, r20	;
+	inc	r22		;
+3:	dec	r21		;
+	brne	2b		;/
+	cpi	r26, 10		;r26 is a numeral digit '0'-'F'
+	brcs	4f		;
+	subi	r26, -7		;
+4:	subi	r26, -'0'	;/
+	push	r26		;Stack it
+	inc	r31		;/
+	cp	r22, r1		;Repeat until r25:r22 gets zero
+	cpc	r23, r1		;
+	cpc	r24, r1		;
+	cpc	r25, r1		;
+	brne	1b		;/
+
+	cpi	r30, '-'	;Minus sign if needed
+	brne	5f		;
+	push	r30		;
+	inc	r31		;/
+5:	cp	r31, r18	;Filler
+	brcc	6f		;
+	push	r19		;
+	inc	r31		;
+	rjmp	5b		;/
+
+6:	pop	r24		;Flush stacked digits and exit
+	rcall	xputc		;
+	dec	r31		;
+	brne	6b		;/
+
+	ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------;
+; Formatted string output (16/32bit version)
+;
+;Prototype:
+; void __xprintf (const char *format_p, ...);
+; void __xsprintf(char*, const char *format_p, ...);
+; void __xfprintf(void(*func)(char), const char *format_p, ...);
+;
+
+#if USE_XPRINTF
+
+.func xvprintf
+xvprintf:
+	ld	ZL, Y+		;Z = pointer to format string
+	ld	ZH, Y+		;/
+
+0:	_LPMI	r24		;Get a format char
+	cpi	r24, 0		;End of format string?
+	breq	90f		;/
+	cpi	r24, '%'	;Is format?
+	breq	20f		;/
+1:	rcall	xputc		;Put a normal character
+	rjmp	0b		;/
+90:	ret
+
+20:	ldi	r18, 0		;r18: digits
+	clt			;T: filler
+	_LPMI	r21		;Get flags
+	cpi	r21, '%'	;Is a %?
+	breq	1b		;/
+	cpi	r21, '0'	;Zero filled?
+	brne	23f		;
+	set			;/
+22:	_LPMI	r21		;Get width
+23:	cpi	r21, '9'+1	;
+	brcc	24f		;
+	subi	r21, '0'	;
+	brcs	90b		;
+	lsl	r18		;
+	mov	r0, r18		;
+	lsl	r18		;
+	lsl	r18		;
+	add	r18, r0		;
+	add	r18, r21	;
+	rjmp	22b		;/
+
+24:	brtc	25f		;get value (low word)
+	neg	r18		;
+25:	ld	r24, Y+		;
+	ld	r25, Y+		;/
+	cpi	r21, 'c'	;Is type character?
+	breq	1b		;/
+	cpi	r21, 's'	;Is type RAM string?
+	breq	50f		;/
+	cpi	r21, 'S'	;Is type ROM string?
+	breq	60f		;/
+	_MOVW	r23,r22,r25,r24	;r25:r22 = value
+	clr	r24		;
+	clr	r25		;
+	clt			;/
+	cpi	r21, 'l'	;Is long int?
+	brne	26f		;
+	ld	r24, Y+		;get value (high word)
+	ld	r25, Y+		;
+	set			;
+	_LPMI	r21		;/
+26:	cpi	r21, 'd'	;Is type signed decimal?
+	brne	27f		;/
+	ldi	r20, -10	;
+	brts	40f		;
+	sbrs	r23, 7		;
+	rjmp	40f		;
+	ldi	r24, -1		;
+	ldi	r25, -1		;
+	rjmp	40f		;/
+27:	cpi	r21, 'u'	;Is type unsigned decimal?
+	ldi	r20, 10		;
+	breq	40f		;/
+	cpi	r21, 'X'	;Is type hexdecimal?
+	ldi	r20, 16		;
+	breq	40f		;/
+	cpi	r21, 'b'	;Is type binary?
+	ldi	r20, 2		;
+	breq	40f		;/
+	ret			;abort
+40:	push	ZH		;Output the value
+	push	ZL		;
+	rcall	xitoa		;
+42:	pop	ZL		;
+	pop	ZH		;
+	rjmp	0b		;/
+
+50:	push	ZH		;Put a string on the RAM
+	push	ZL
+	_MOVW	ZH,ZL, r25,r24
+51:	ld	r24, Z+
+	cpi	r24, 0
+	breq	42b
+	rcall	xputc
+	rjmp	51b
+
+60:	push	ZH		;Put a string on the ROM
+	push	ZL
+	rcall	xputs
+	rjmp	42b
+.endfunc
+
+
+.func __xprintf
+.global __xprintf
+__xprintf:
+	push	YH
+	push	YL
+	in	YL, _SFR_IO_ADDR(SPL)
+#ifdef SPH
+	in	YH, _SFR_IO_ADDR(SPH)
+#else
+	clr	YH
+#endif
+	adiw	YL, 5		;Y = pointer to arguments
+	rcall	xvprintf
+	pop	YL
+	pop	YH
+	ret
+.endfunc
+
+
+#if USE_XSPRINTF
+
+.func __xsprintf
+putram:
+	_MOVW	ZH,ZL, r15,r14
+	st	Z+, r24
+	_MOVW	r15,r14, ZH,ZL
+	ret
+.global __xsprintf
+__xsprintf:
+	push	YH
+	push	YL
+	in	YL, _SFR_IO_ADDR(SPL)
+#ifdef SPH
+	in	YH, _SFR_IO_ADDR(SPH)
+#else
+	clr	YH
+#endif
+	adiw	YL, 5		;Y = pointer to arguments
+	lds	ZL, xfunc_out+0	;Save registered output function
+	lds	ZH, xfunc_out+1	;
+	push	ZL		;
+	push	ZH		;/
+	ldi	ZL, lo8(pm(putram));Set local output function
+	ldi	ZH, hi8(pm(putram));
+	sts	xfunc_out+0, ZL	;
+	sts	xfunc_out+1, ZH	;/
+	push	r15		;Initialize pointer to string buffer
+	push	r14		;
+	ld	r14, Y+		;
+	ld	r15, Y+		;/
+	rcall	xvprintf
+	_MOVW	ZH,ZL, r15,r14	;Terminate string
+	st	Z, r1		;
+	pop	r14		;
+	pop	r15		;/
+	pop	ZH		;Restore registered output function
+	pop	ZL		;
+	sts	xfunc_out+0, ZL	;
+	sts	xfunc_out+1, ZH	;/
+	pop	YL
+	pop	YH
+	ret
+.endfunc
+#endif
+
+
+#if USE_XFPRINTF
+.func __xfprintf
+.global __xfprintf
+__xfprintf:
+	push	YH
+	push	YL
+	in	YL, _SFR_IO_ADDR(SPL)
+#ifdef SPH
+	in	YH, _SFR_IO_ADDR(SPH)
+#else
+	clr	YH
+#endif
+	adiw	YL, 5		;Y = pointer to arguments
+	lds	ZL, xfunc_out+0	;Save registered output function
+	lds	ZH, xfunc_out+1	;
+	push	ZL		;
+	push	ZH		;/
+	ld	ZL, Y+		;Set output function
+	ld	ZH, Y+		;
+	sts	xfunc_out+0, ZL	;
+	sts	xfunc_out+1, ZH	;/
+	rcall	xvprintf
+	pop	ZH		;Restore registered output function
+	pop	ZL		;
+	sts	xfunc_out+0, ZL	;
+	sts	xfunc_out+1, ZH	;/
+	pop	YL
+	pop	YH
+	ret
+.endfunc
+#endif
+
+#endif
+
+
+
+;---------------------------------------------------------------------------
+; Extended numeral string input
+;
+;Prototype:
+; char xatoi (           /* 1: Successful, 0: Failed */
+;      const char **str, /* pointer to pointer to source string */
+;      long *res         /* result */
+; );
+;
+
+
+#if USE_XATOI
+.func xatoi
+.global xatoi
+xatoi:
+	_MOVW	r1, r0, r23, r22
+	_MOVW	XH, XL, r25, r24
+	ld	ZL, X+
+	ld	ZH, X+
+	clr	r18		;r21:r18 = 0;
+	clr	r19		;
+	clr	r20		;
+	clr	r21		;/
+	clt			;T = 0;
+
+	ldi	r25, 10		;r25 = 10;
+	rjmp	41f		;/
+40:	adiw	ZL, 1		;Z++;
+41:	ld	r22, Z		;r22 = *Z;
+	cpi	r22, ' '	;if(r22 == ' ') continue
+	breq	40b		;/
+	brcs	70f		;if(r22 < ' ') error;
+	cpi	r22, '-'	;if(r22 == '-') {
+	brne	42f		; T = 1;
+	set			; continue;
+	rjmp	40b		;}
+42:	cpi	r22, '9'+1	;if(r22 > '9') error;
+	brcc	70f		;/
+	cpi	r22, '0'	;if(r22 < '0') error;
+	brcs	70f		;/
+	brne	51f		;if(r22 > '0') cv_start;
+	ldi	r25, 8		;r25 = 8;
+	adiw	ZL, 1		;r22 = *(++Z);
+	ld	r22, Z		;/
+	cpi	r22, ' '+1	;if(r22 <= ' ') exit;
+	brcs	80f		;/
+	cpi	r22, 'b'	;if(r22 == 'b') {
+	brne	43f		; r25 = 2;
+	ldi	r25, 2		; cv_start;
+	rjmp	50f		;}
+43:	cpi	r22, 'x'	;if(r22 != 'x') error;
+	brne	51f		;/
+	ldi	r25, 16		;r25 = 16;
+
+50:	adiw	ZL, 1		;Z++;
+	ld	r22, Z		;r22 = *Z;
+51:	cpi	r22, ' '+1	;if(r22 <= ' ') break;
+	brcs	80f		;/
+	cpi	r22, 'a'	;if(r22 >= 'a') r22 =- 0x20;
+	brcs	52f		;
+	subi	r22, 0x20	;/
+52:	subi	r22, '0'	;if((r22 -= '0') < 0) error;
+	brcs	70f		;/
+	cpi	r22, 10		;if(r22 >= 10) {
+	brcs	53f		; r22 -= 7;
+	subi	r22, 7		; if(r22 < 10) 
+	cpi	r22, 10		;
+	brcs	70f		;}
+53:	cp	r22, r25	;if(r22 >= r25) error;
+	brcc	70f		;/
+60:	ldi	r24, 33		;r21:r18 *= r25;
+	sub	r23, r23	;
+61:	brcc	62f		;
+	add	r23, r25	;
+62:	lsr	r23		;
+	ror	r21		;
+	ror	r20		;
+	ror	r19		;
+	ror	r18		;
+	dec	r24		;
+	brne	61b		;/
+	add	r18, r22	;r21:r18 += r22;
+	adc	r19, r24	;
+	adc	r20, r24	;
+	adc	r21, r24	;/
+	rjmp	50b		;repeat
+
+70:	ldi	r24, 0
+	rjmp	81f
+80:	ldi	r24, 1
+81:	brtc	82f
+	clr	r22
+	com	r18
+	com	r19
+	com	r20
+	com	r21
+	adc	r18, r22
+	adc	r19, r22
+	adc	r20, r22
+	adc	r21, r22
+82:	st	-X, ZH
+	st	-X, ZL
+	_MOVW	XH, XL, r1, r0
+	st	X+, r18
+	st	X+, r19
+	st	X+, r20
+	st	X+, r21
+	clr	r1
+	ret
+.endfunc
+#endif
+
+
diff --git a/tmk_core/common/avr/xprintf.h b/tmk_core/common/avr/xprintf.h
index 59c6f25312..08d9f93a0c 100644
--- a/tmk_core/common/avr/xprintf.h
+++ b/tmk_core/common/avr/xprintf.h
@@ -1,111 +1,111 @@
-/*---------------------------------------------------------------------------

-   Extended itoa, puts and printf                    (C)ChaN, 2011

------------------------------------------------------------------------------*/

-

-#ifndef XPRINTF_H

-#define XPRINTF_H

-

-#include <inttypes.h>

-#include <avr/pgmspace.h>

-

-#ifdef __cplusplus

-extern "C" {

-#endif

-

-extern void (*xfunc_out)(uint8_t);

-#define xdev_out(func) xfunc_out = (void(*)(uint8_t))(func)

-

-/* This is a pointer to user defined output function. It must be initialized

-   before using this modle.

-*/

-

-void xputc(char chr);

-

-/* This is a stub function to forward outputs to user defined output function.

-   All outputs from this module are output via this function.

-*/

-

-

-/*-----------------------------------------------------------------------------*/

-void xputs(const char *string_p);

-

-/*  The string placed in the ROM is forwarded to xputc() directly.

-*/

-

-

-/*-----------------------------------------------------------------------------*/

-void xitoa(long value, char radix, char width);

-

-/* Extended itoa().

-

-      value  radix  width   output

-        100     10      6   "   100"

-        100     10     -6   "000100"

-        100     10      0   "100"

- 4294967295     10      0   "4294967295"

- 4294967295    -10      0   "-1"

-     655360     16     -8   "000A0000"

-       1024     16      0   "400"

-       0x55      2     -8   "01010101"

-*/

-

-

-/*-----------------------------------------------------------------------------*/

-#define xprintf(format, ...)            __xprintf(PSTR(format), ##__VA_ARGS__)

-#define xsprintf(str, format, ...)      __xsprintf(str, PSTR(format), ##__VA_ARGS__)

-#define xfprintf(func, format, ...)     __xfprintf(func, PSTR(format), ##__VA_ARGS__)

-

-void __xprintf(const char *format_p, ...);	/* Send formatted string to the registered device */

-void __xsprintf(char*, const char *format_p, ...);	/* Put formatted string to the memory */

-void __xfprintf(void(*func)(uint8_t), const char *format_p, ...); /* Send formatted string to the specified device */

-

-/* Format string is placed in the ROM. The format flags is similar to printf().

-

-   %[flag][width][size]type

-

-   flag

-     A '0' means filled with '0' when output is shorter than width.

-     ' ' is used in default. This is effective only numeral type.

-   width

-     Minimum width in decimal number. This is effective only numeral type.

-     Default width is zero.

-   size

-     A 'l' means the argument is long(32bit). Default is short(16bit).

-     This is effective only numeral type.

-   type

-     'c' : Character, argument is the value

-     's' : String placed on the RAM, argument is the pointer

-     'S' : String placed on the ROM, argument is the pointer

-     'd' : Signed decimal, argument is the value

-     'u' : Unsigned decimal, argument is the value

-     'X' : Hexdecimal, argument is the value

-     'b' : Binary, argument is the value

-     '%' : '%'

-

-*/

-

-

-/*-----------------------------------------------------------------------------*/

-char xatoi(char **str, long *ret);

-

-/* Get value of the numeral string. 

-

-  str

-    Pointer to pointer to source string

-

-    "0b11001010" binary

-    "0377" octal

-    "0xff800" hexdecimal

-    "1250000" decimal

-    "-25000" decimal

-

-  ret

-    Pointer to return value

-*/

-

-#ifdef __cplusplus

-}

-#endif

-

-#endif

-

+/*---------------------------------------------------------------------------
+   Extended itoa, puts and printf                    (C)ChaN, 2011
+-----------------------------------------------------------------------------*/
+
+#ifndef XPRINTF_H
+#define XPRINTF_H
+
+#include <inttypes.h>
+#include <avr/pgmspace.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void (*xfunc_out)(uint8_t);
+#define xdev_out(func) xfunc_out = (void(*)(uint8_t))(func)
+
+/* This is a pointer to user defined output function. It must be initialized
+   before using this modle.
+*/
+
+void xputc(char chr);
+
+/* This is a stub function to forward outputs to user defined output function.
+   All outputs from this module are output via this function.
+*/
+
+
+/*-----------------------------------------------------------------------------*/
+void xputs(const char *string_p);
+
+/*  The string placed in the ROM is forwarded to xputc() directly.
+*/
+
+
+/*-----------------------------------------------------------------------------*/
+void xitoa(long value, char radix, char width);
+
+/* Extended itoa().
+
+      value  radix  width   output
+        100     10      6   "   100"
+        100     10     -6   "000100"
+        100     10      0   "100"
+ 4294967295     10      0   "4294967295"
+ 4294967295    -10      0   "-1"
+     655360     16     -8   "000A0000"
+       1024     16      0   "400"
+       0x55      2     -8   "01010101"
+*/
+
+
+/*-----------------------------------------------------------------------------*/
+#define xprintf(format, ...)            __xprintf(PSTR(format), ##__VA_ARGS__)
+#define xsprintf(str, format, ...)      __xsprintf(str, PSTR(format), ##__VA_ARGS__)
+#define xfprintf(func, format, ...)     __xfprintf(func, PSTR(format), ##__VA_ARGS__)
+
+void __xprintf(const char *format_p, ...);	/* Send formatted string to the registered device */
+// void __xsprintf(char*, const char *format_p, ...);	/* Put formatted string to the memory */
+// void __xfprintf(void(*func)(uint8_t), const char *format_p, ...); /* Send formatted string to the specified device */
+
+/* Format string is placed in the ROM. The format flags is similar to printf().
+
+   %[flag][width][size]type
+
+   flag
+     A '0' means filled with '0' when output is shorter than width.
+     ' ' is used in default. This is effective only numeral type.
+   width
+     Minimum width in decimal number. This is effective only numeral type.
+     Default width is zero.
+   size
+     A 'l' means the argument is long(32bit). Default is short(16bit).
+     This is effective only numeral type.
+   type
+     'c' : Character, argument is the value
+     's' : String placed on the RAM, argument is the pointer
+     'S' : String placed on the ROM, argument is the pointer
+     'd' : Signed decimal, argument is the value
+     'u' : Unsigned decimal, argument is the value
+     'X' : Hexdecimal, argument is the value
+     'b' : Binary, argument is the value
+     '%' : '%'
+
+*/
+
+
+/*-----------------------------------------------------------------------------*/
+char xatoi(char **str, long *ret);
+
+/* Get value of the numeral string.
+
+  str
+    Pointer to pointer to source string
+
+    "0b11001010" binary
+    "0377" octal
+    "0xff800" hexdecimal
+    "1250000" decimal
+    "-25000" decimal
+
+  ret
+    Pointer to return value
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tmk_core/common/backlight.c b/tmk_core/common/backlight.c
index c9e8fd3fd2..0e0ad2d154 100644
--- a/tmk_core/common/backlight.c
+++ b/tmk_core/common/backlight.c
@@ -36,9 +36,9 @@ void backlight_increase(void)
     if(backlight_config.level < BACKLIGHT_LEVELS)
     {
         backlight_config.level++;
-        backlight_config.enable = 1;
-        eeconfig_update_backlight(backlight_config.raw);
     }
+    backlight_config.enable = 1;
+    eeconfig_update_backlight(backlight_config.raw);
     dprintf("backlight increase: %u\n", backlight_config.level);
     backlight_set(backlight_config.level);
 }
diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c
index 6730a2a4aa..2c6bcbae56 100644
--- a/tmk_core/common/bootmagic.c
+++ b/tmk_core/common/bootmagic.c
@@ -83,10 +83,6 @@ void bootmagic(void)
     }
     eeconfig_update_keymap(keymap_config.raw);
 
-#ifdef NKRO_ENABLE
-    keyboard_nkro = keymap_config.nkro;
-#endif
-
     /* default layer */
     uint8_t default_layer = 0;
     if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { default_layer |= (1<<0); }
diff --git a/tmk_core/common/command.c b/tmk_core/common/command.c
index 084c9fe155..f79d5a257b 100644
--- a/tmk_core/common/command.c
+++ b/tmk_core/common/command.c
@@ -34,6 +34,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "command.h"
 #include "backlight.h"
 #include "quantum.h"
+#include "version.h"
 
 #ifdef MOUSEKEY_ENABLE
 #include "mousekey.h"
@@ -180,7 +181,7 @@ static void print_version(void)
     print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
           "PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
           "VER: " STR(DEVICE_VER) "\n");
-    print("BUILD: " STR(VERSION) " (" __TIME__ " " __DATE__ ")\n");
+    print("BUILD: " STR(QMK_VERSION) " (" __TIME__ " " __DATE__ ")\n");
 
     /* build options */
     print("OPTIONS:"
@@ -234,10 +235,13 @@ static void print_status(void)
     print("\n\t- Status -\n");
 
     print_val_hex8(host_keyboard_leds());
+#ifndef PROTOCOL_VUSB
+    // these aren't set on the V-USB protocol, so we just ignore them for now
     print_val_hex8(keyboard_protocol);
     print_val_hex8(keyboard_idle);
+#endif
 #ifdef NKRO_ENABLE
-    print_val_hex8(keyboard_nkro);
+    print_val_hex8(keymap_config.nkro);
 #endif
     print_val_hex32(timer_read32());
 
@@ -260,7 +264,10 @@ static void print_status(void)
 #ifdef BOOTMAGIC_ENABLE
 static void print_eeconfig(void)
 {
-#ifndef NO_PRINT
+
+// Print these variables if NO_PRINT or USER_PRINT are not defined.
+#if !defined(NO_PRINT) && !defined(USER_PRINT)
+
     print("default_layer: "); print_dec(eeconfig_read_default_layer()); print("\n");
 
     debug_config_t dc;
@@ -375,9 +382,6 @@ static bool command_common(uint8_t code)
             debug_enable = !debug_enable;
             if (debug_enable) {
                 print("\ndebug: on\n");
-                debug_matrix   = true;
-                debug_keyboard = true;
-                debug_mouse    = true;
             } else {
                 print("\ndebug: off\n");
                 debug_matrix   = false;
@@ -434,8 +438,8 @@ static bool command_common(uint8_t code)
 		// NKRO toggle
         case MAGIC_KC(MAGIC_KEY_NKRO):
             clear_keyboard(); // clear to prevent stuck keys
-            keyboard_nkro = !keyboard_nkro;
-            if (keyboard_nkro) {
+            keymap_config.nkro = !keymap_config.nkro;
+            if (keymap_config.nkro) {
                 print("NKRO: on\n");
             } else {
                 print("NKRO: off\n");
@@ -570,7 +574,8 @@ static uint8_t mousekey_param = 0;
 
 static void mousekey_param_print(void)
 {
-#ifndef NO_PRINT
+// Print these variables if NO_PRINT or USER_PRINT are not defined.
+#if !defined(NO_PRINT) && !defined(USER_PRINT)
     print("\n\t- Values -\n");
     print("1: delay(*10ms): "); pdec(mk_delay); print("\n");
     print("2: interval(ms): "); pdec(mk_interval); print("\n");
diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c
index 11a05c2ddd..e12b622165 100644
--- a/tmk_core/common/host.c
+++ b/tmk_core/common/host.c
@@ -22,11 +22,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "util.h"
 #include "debug.h"
 
-
-#ifdef NKRO_ENABLE
-bool keyboard_nkro = true;
-#endif
-
 static host_driver_t *driver;
 static uint16_t last_system_report = 0;
 static uint16_t last_consumer_report = 0;
diff --git a/tmk_core/common/host.h b/tmk_core/common/host.h
index 9814b10d2d..aeabba7107 100644
--- a/tmk_core/common/host.h
+++ b/tmk_core/common/host.h
@@ -28,10 +28,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 extern "C" {
 #endif
 
-#ifdef NKRO_ENABLE
-extern bool keyboard_nkro;
-#endif
-
 extern uint8_t keyboard_idle;
 extern uint8_t keyboard_protocol;
 
diff --git a/tmk_core/common/host_driver.h b/tmk_core/common/host_driver.h
index edb9e5dd9c..588d1c0be8 100644
--- a/tmk_core/common/host_driver.h
+++ b/tmk_core/common/host_driver.h
@@ -20,7 +20,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include <stdint.h>
 #include "report.h"
-
+#ifdef MIDI_ENABLE
+	#include "midi.h"
+#endif
 
 typedef struct {
     uint8_t (*keyboard_leds)(void);
@@ -28,6 +30,11 @@ typedef struct {
     void (*send_mouse)(report_mouse_t *);
     void (*send_system)(uint16_t);
     void (*send_consumer)(uint16_t);
+#ifdef MIDI_ENABLE
+    void (*usb_send_func)(MidiDevice *, uint16_t, uint8_t, uint8_t, uint8_t);
+    void (*usb_get_midi)(MidiDevice *);
+    void (*midi_usb_init)(MidiDevice *);
+#endif
 } host_driver_t;
 
 #endif
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c
index c46a701b3b..eac1f1dd81 100644
--- a/tmk_core/common/keyboard.c
+++ b/tmk_core/common/keyboard.c
@@ -14,6 +14,7 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
+
 #include <stdint.h>
 #include "keyboard.h"
 #include "matrix.h"
@@ -50,6 +51,9 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifdef RGBLIGHT_ENABLE
 #   include "rgblight.h"
 #endif
+#ifdef FAUXCLICKY_ENABLE
+#   include "fauxclicky.h"
+#endif
 #ifdef SERIAL_LINK_ENABLE
 #   include "serial_link/system/serial_link.h"
 #endif
@@ -57,6 +61,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #   include "visualizer/visualizer.h"
 #endif
 
+
+
 #ifdef MATRIX_HAS_GHOST
 static bool has_ghost_in_row(uint8_t row)
 {
@@ -105,8 +111,11 @@ void keyboard_init(void) {
 #ifdef RGBLIGHT_ENABLE
     rgblight_init();
 #endif
+#ifdef FAUXCLICKY_ENABLE
+    fauxclicky_init();
+#endif
 #if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
-	keyboard_nkro = true;
+    keymap_config.nkro = 1;
 #endif
 }
 
@@ -186,7 +195,7 @@ MATRIX_LOOP_END:
 #endif
 
 #ifdef VISUALIZER_ENABLE
-    visualizer_update(default_layer_state, layer_state, host_keyboard_leds());
+    visualizer_update(default_layer_state, layer_state, visualizer_get_mods(), host_keyboard_leds());
 #endif
 
     // update LED
diff --git a/tmk_core/common/keycode.h b/tmk_core/common/keycode.h
index 2f208c54e0..54e9c322c1 100644
--- a/tmk_core/common/keycode.h
+++ b/tmk_core/common/keycode.h
@@ -85,7 +85,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define KC_LCAP KC_LOCKING_CAPS
 #define KC_LNUM KC_LOCKING_NUM
 #define KC_LSCR KC_LOCKING_SCROLL
-#define KC_ERAS KC_ALT_ERASE,
+#define KC_ERAS KC_ALT_ERASE
 #define KC_CLR  KC_CLEAR
 /* Japanese specific */
 #define KC_ZKHK KC_GRAVE
diff --git a/tmk_core/common/magic.c b/tmk_core/common/magic.c
index 194e4cc026..49617a3d10 100644
--- a/tmk_core/common/magic.c
+++ b/tmk_core/common/magic.c
@@ -27,10 +27,6 @@ void magic(void)
     /* keymap config */
     keymap_config.raw = eeconfig_read_keymap();
 
-#ifdef NKRO_ENABLE
-    keyboard_nkro = keymap_config.nkro;
-#endif
-
     uint8_t default_layer = 0;
     default_layer = eeconfig_read_default_layer();
     default_layer_set((uint32_t)default_layer);
diff --git a/tmk_core/common/matrix.h b/tmk_core/common/matrix.h
index cee3593eee..2543f5abce 100644
--- a/tmk_core/common/matrix.h
+++ b/tmk_core/common/matrix.h
@@ -50,7 +50,7 @@ void matrix_init(void);
 uint8_t matrix_scan(void);
 /* whether modified from previous scan. used after matrix_scan. */
 bool matrix_is_modified(void) __attribute__ ((deprecated));
-/* whether a swtich is on */
+/* whether a switch is on */
 bool matrix_is_on(uint8_t row, uint8_t col);
 /* matrix state on row */
 matrix_row_t matrix_get_row(uint8_t row);
diff --git a/tmk_core/common/mbed/xprintf.cpp b/tmk_core/common/mbed/xprintf.cpp
index 3647ece751..b1aac2c99d 100644
--- a/tmk_core/common/mbed/xprintf.cpp
+++ b/tmk_core/common/mbed/xprintf.cpp
@@ -7,7 +7,7 @@
 #define STRING_STACK_LIMIT    120
 
 //TODO
-int xprintf(const char* format, ...) { return 0; }
+int __xprintf(const char* format, ...) { return 0; }
 
 #if 0
 /* mbed Serial */
diff --git a/tmk_core/common/mbed/xprintf.h b/tmk_core/common/mbed/xprintf.h
index 26bc529e5b..1e7a48c06d 100644
--- a/tmk_core/common/mbed/xprintf.h
+++ b/tmk_core/common/mbed/xprintf.h
@@ -7,7 +7,7 @@
 extern "C" {
 #endif
 
-int xprintf(const char *format, ...);
+int __xprintf(const char *format, ...);
 
 #ifdef __cplusplus
 }
diff --git a/tmk_core/common/print.h b/tmk_core/common/print.h
index 0368bcd4a1..8836c0fc7c 100644
--- a/tmk_core/common/print.h
+++ b/tmk_core/common/print.h
@@ -29,45 +29,147 @@
 #include <stdbool.h>
 #include "util.h"
 
-
+#if defined(PROTOCOL_CHIBIOS)
+#define PSTR(x) x
+#endif
 
 
 #ifndef NO_PRINT
 
+#if defined(__AVR__) /* __AVR__ */
+
+#  include "avr/xprintf.h"
+
+#  ifdef USER_PRINT /* USER_PRINT */
+
+// Remove normal print defines
+#    define print(s)
+#    define println(s)
+#    undef xprintf
+#    define xprintf(fmt, ...)
+
+// Create user print defines
+#    define uprint(s)          xputs(PSTR(s))
+#    define uprintln(s)        xputs(PSTR(s "\r\n"))
+#    define uprintf(fmt, ...)  __xprintf(PSTR(fmt), ##__VA_ARGS__)
+
+#  else /* NORMAL PRINT */
 
-#if defined(__AVR__)
+// Create user & normal print defines
+#    define print(s)           xputs(PSTR(s))
+#    define println(s)         xputs(PSTR(s "\r\n"))
+#    define uprint(s)          print(s)
+#    define uprintln(s)        println(s)
+#    define uprintf(fmt, ...)  xprintf(fmt, ...)
 
-#include "avr/xprintf.h"
-#define print(s)    xputs(PSTR(s))
-#define println(s)  xputs(PSTR(s "\r\n"))
+#  endif /* USER_PRINT / NORMAL PRINT */
 
-#ifdef __cplusplus
+#  ifdef __cplusplus
 extern "C"
-#endif
+#  endif
+
 /* function pointer of sendchar to be used by print utility */
 void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
 
-#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
+#elif defined(PROTOCOL_CHIBIOS) /* PROTOCOL_CHIBIOS */
+
+#  include "chibios/printf.h"
+
+#  ifdef USER_PRINT /* USER_PRINT */
+
+// Remove normal print defines
+#    define print(s)
+#    define println(s)
+#    define xprintf(fmt, ...)
+
+// Create user print defines
+#    define uprint(s)    printf(s)
+#    define uprintln(s)  printf(s "\r\n")
+#    define uprintf      printf
+
+#  else /* NORMAL PRINT */
 
-#include "chibios/printf.h"
+// Create user & normal print defines
+#    define print(s)     printf(s)
+#    define println(s)   printf(s "\r\n")
+#    define xprintf      printf
+#    define uprint(s)    printf(s)
+#    define uprintln(s)  printf(s "\r\n")
+#    define uprintf      printf
 
-#define print(s)    printf(s)
-#define println(s)  printf(s "\r\n")
-#define xprintf  printf
+#  endif /* USER_PRINT / NORMAL PRINT */
 
-#elif defined(__arm__) /* __AVR__ */
+#elif defined(__arm__) /* __arm__ */
 
-#include "mbed/xprintf.h"
+#  include "mbed/xprintf.h"
 
-#define print(s)    xprintf(s)
-#define println(s)  xprintf(s "\r\n")
+#  ifdef USER_PRINT /* USER_PRINT */
+
+// Remove normal print defines
+#    define print(s)
+#    define println(s)
+#    define xprintf(fmt, ...)
+
+// Create user print defines
+#    define uprintf(fmt, ...)  __xprintf(fmt, ...)
+#    define uprint(s)          xprintf(s)
+#    define uprintln(s)        xprintf(s "\r\n")
+
+#  else /* NORMAL PRINT */
+
+// Create user & normal print defines
+#    define xprintf(fmt, ...)  __xprintf(fmt, ...)
+#    define print(s)           xprintf(s)
+#    define println(s)         xprintf(s "\r\n")
+#    define uprint(s)          print(s)
+#    define uprintln(s)        println(s)
+#    define uprintf(fmt, ...)  xprintf(fmt, ...)
+
+#  endif /* USER_PRINT / NORMAL PRINT */
 
 /* TODO: to select output destinations: UART/USBSerial */
-#define print_set_sendchar(func)
+#  define print_set_sendchar(func)
+
+#endif /* __AVR__ / PROTOCOL_CHIBIOS / __arm__ */
 
-#endif /* __AVR__ */
+// User print disables the normal print messages in the body of QMK/TMK code and
+// is meant as a lightweight alternative to NOPRINT. Use it when you only want to do
+// a spot of debugging but lack flash resources for allowing all of the codebase to
+// print (and store their wasteful strings).
+//
+// !!! DO NOT USE USER PRINT CALLS IN THE BODY OF QMK/TMK !!!
+//
+#ifdef USER_PRINT
+
+// Disable normal print
+#define print_dec(data)
+#define print_decs(data)
+#define print_hex4(data)
+#define print_hex8(data)
+#define print_hex16(data)
+#define print_hex32(data)
+#define print_bin4(data)
+#define print_bin8(data)
+#define print_bin16(data)
+#define print_bin32(data)
+#define print_bin_reverse8(data)
+#define print_bin_reverse16(data)
+#define print_bin_reverse32(data)
+#define print_val_dec(v)
+#define print_val_decs(v)
+#define print_val_hex8(v)
+#define print_val_hex16(v)
+#define print_val_hex32(v)
+#define print_val_bin8(v)
+#define print_val_bin16(v)
+#define print_val_bin32(v)
+#define print_val_bin_reverse8(v)
+#define print_val_bin_reverse16(v)
+#define print_val_bin_reverse32(v)
 
+#else /* NORMAL_PRINT */
 
+//Enable normal print
 /* decimal */
 #define print_dec(i)                xprintf("%u", i)
 #define print_decs(i)               xprintf("%d", i)
@@ -97,6 +199,39 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
 #define print_val_bin_reverse16(v)  xprintf(#v ": %016b\n", bitrev16(v))
 #define print_val_bin_reverse32(v)  xprintf(#v ": %032lb\n", bitrev32(v))
 
+#endif /* USER_PRINT / NORMAL_PRINT */
+
+// User Print
+
+/* decimal */
+#define uprint_dec(i)               uprintf("%u", i)
+#define uprint_decs(i)              uprintf("%d", i)
+/* hex */
+#define uprint_hex4(i)              uprintf("%X", i)
+#define uprint_hex8(i)              uprintf("%02X", i)
+#define uprint_hex16(i)             uprintf("%04X", i)
+#define uprint_hex32(i)             uprintf("%08lX", i)
+/* binary */
+#define uprint_bin4(i)              uprintf("%04b", i)
+#define uprint_bin8(i)              uprintf("%08b", i)
+#define uprint_bin16(i)             uprintf("%016b", i)
+#define uprint_bin32(i)             uprintf("%032lb", i)
+#define uprint_bin_reverse8(i)      uprintf("%08b", bitrev(i))
+#define uprint_bin_reverse16(i)     uprintf("%016b", bitrev16(i))
+#define uprint_bin_reverse32(i)     uprintf("%032lb", bitrev32(i))
+/* print value utility */
+#define uprint_val_dec(v)           uprintf(#v ": %u\n", v)
+#define uprint_val_decs(v)          uprintf(#v ": %d\n", v)
+#define uprint_val_hex8(v)          uprintf(#v ": %X\n", v)
+#define uprint_val_hex16(v)         uprintf(#v ": %02X\n", v)
+#define uprint_val_hex32(v)         uprintf(#v ": %04lX\n", v)
+#define uprint_val_bin8(v)          uprintf(#v ": %08b\n", v)
+#define uprint_val_bin16(v)         uprintf(#v ": %016b\n", v)
+#define uprint_val_bin32(v)         uprintf(#v ": %032lb\n", v)
+#define uprint_val_bin_reverse8(v)  uprintf(#v ": %08b\n", bitrev(v))
+#define uprint_val_bin_reverse16(v) uprintf(#v ": %016b\n", bitrev16(v))
+#define uprint_val_bin_reverse32(v) uprintf(#v ": %032lb\n", bitrev32(v))
+
 #else   /* NO_PRINT */
 
 #define xprintf(fmt, ...)
@@ -141,5 +276,4 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
 #define pbin_reverse(data)      print_bin_reverse8(data)
 #define pbin_reverse16(data)    print_bin_reverse16(data)
 
-
 #endif
diff --git a/tmk_core/common/raw_hid.h b/tmk_core/common/raw_hid.h
new file mode 100644
index 0000000000..86da02fd15
--- /dev/null
+++ b/tmk_core/common/raw_hid.h
@@ -0,0 +1,8 @@
+#ifndef _RAW_HID_H_
+#define _RAW_HID_H_
+
+void raw_hid_receive( uint8_t *data, uint8_t length );
+
+void raw_hid_send( uint8_t *data, uint8_t length );
+
+#endif
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h
index 0c799eca39..8fb28b6ce3 100644
--- a/tmk_core/common/report.h
+++ b/tmk_core/common/report.h
@@ -134,13 +134,6 @@ typedef union {
     } nkro;
 #endif
 } __attribute__ ((packed)) report_keyboard_t;
-/*
-typedef struct {
-    uint8_t mods;
-    uint8_t reserved;
-    uint8_t keys[REPORT_KEYS];
-} __attribute__ ((packed)) report_keyboard_t;
-*/
 
 typedef struct {
     uint8_t buttons;
diff --git a/tmk_core/common/virtser.h b/tmk_core/common/virtser.h
new file mode 100644
index 0000000000..74891b6ae0
--- /dev/null
+++ b/tmk_core/common/virtser.h
@@ -0,0 +1,10 @@
+#ifndef _VIRTSER_H_
+#define _VIRTSER_H_
+
+/* Define this function in your code to process incoming bytes */
+void virtser_recv(const uint8_t ch);
+
+/* Call this to send a character over the Virtual Serial Device */
+void virtser_send(const uint8_t byte);
+
+#endif