Kaynağa Gözat

Merge pull request #918 from jackhumbert/wu5y7

Adds Ergodox EZ RGB lights (both sides using I2C) and implements API base, Midi SysEx API
Erez Zukerman 8 yıl önce
ebeveyn
işleme
51ae6da99e
65 değiştirilmiş dosya ile 1761 ekleme ve 204 silme
  1. 1 2
      Dockerfile
  2. 14 0
      build_keyboard.mk
  3. 1 0
      common.mk
  4. 1 1
      keyboards/amj60/config.h
  5. 1 1
      keyboards/clueboard/rev1/config.h
  6. 1 1
      keyboards/clueboard/rev2/config.h
  7. 1 1
      keyboards/cluecard/config.h
  8. 1 1
      keyboards/cluecard/keymaps/rgb_effects/config.h
  9. 1 1
      keyboards/cluepad/config.h
  10. 6 1
      keyboards/ergodox/ez/Makefile
  11. 13 0
      keyboards/ergodox/ez/config.h
  12. 8 2
      keyboards/ergodox/ez/ez.c
  13. 1 1
      keyboards/ergodox/ez/matrix.c
  14. 2 0
      keyboards/ergodox/ez/rules.mk
  15. 2 0
      keyboards/ergodox/infinity/rules.mk
  16. 2 0
      keyboards/ergodox/keymaps/erez_experimental/Makefile
  17. 1 0
      keyboards/ergodox/keymaps/erez_experimental/config.h
  18. 33 9
      keyboards/ergodox/keymaps/erez_experimental/keymap.c
  19. 6 0
      keyboards/ergodox/keymaps/jack/Makefile
  20. 17 0
      keyboards/ergodox/keymaps/jack/config.h
  21. 16 6
      keyboards/ergodox/keymaps/jack/keymap.c
  22. 0 1
      keyboards/ergodox/rules.mk
  23. 1 1
      keyboards/gh60/keymaps/robotmaxtron/config.h
  24. 1 1
      keyboards/handwired/minorca/keymaps/rgb/config.h
  25. 1 1
      keyboards/jd40/config.h
  26. 1 1
      keyboards/kc60/keymaps/ws2812/config.h
  27. 2 1
      keyboards/lets_split/config.h
  28. 1 1
      keyboards/lets_split/keymaps/i2c/config.h
  29. 1 1
      keyboards/lets_split/keymaps/serial/config.h
  30. 1 1
      keyboards/phantom/config.h
  31. 4 4
      keyboards/planck/keymaps/default/Makefile
  32. 2 2
      keyboards/planck/keymaps/default/keymap.c
  33. 1 1
      keyboards/planck/keymaps/experimental/config.h
  34. 26 0
      keyboards/planck/keymaps/thermal_printer/Makefile
  35. 23 0
      keyboards/planck/keymaps/thermal_printer/config.h
  36. 314 0
      keyboards/planck/keymaps/thermal_printer/keymap.c
  37. 2 0
      keyboards/planck/keymaps/thermal_printer/readme.md
  38. 1 1
      keyboards/planck/keymaps/yang/config.h
  39. 1 0
      keyboards/planck/rules.mk
  40. 1 1
      keyboards/preonic/config.h
  41. 0 22
      keyboards/preonic/keymaps/default/Makefile
  42. 1 1
      keyboards/preonic/keymaps/kinesis/config.h
  43. 2 1
      keyboards/preonic/rules.mk
  44. 1 1
      keyboards/satan/config.h
  45. 1 1
      keyboards/tada68/config.h
  46. 178 0
      quantum/api.c
  47. 59 0
      quantum/api.h
  48. 29 0
      quantum/api/api_sysex.c
  49. 10 0
      quantum/api/api_sysex.h
  50. 51 50
      quantum/config_common.h
  51. 4 0
      quantum/keymap.h
  52. 146 5
      quantum/light_ws2812.c
  53. 18 3
      quantum/light_ws2812.h
  54. 254 0
      quantum/process_keycode/process_printer.c
  55. 8 0
      quantum/process_keycode/process_printer.h
  56. 260 0
      quantum/process_keycode/process_printer_bb.c
  57. 48 0
      quantum/quantum.c
  58. 11 0
      quantum/quantum.h
  59. 86 53
      quantum/rgblight.c
  60. 9 4
      quantum/rgblight.h
  61. 2 2
      readme.md
  62. 8 1
      tmk_core/common/host_driver.h
  63. 50 13
      tmk_core/protocol/lufa/lufa.c
  64. 11 2
      tmk_core/protocol/lufa/lufa.h
  65. 1 0
      tmk_core/protocol/midi.mk

+ 1 - 2
Dockerfile

@@ -25,5 +25,4 @@ ENV subproject=ez
 ENV keymap=default
 
 VOLUME /qmk
-WORKDIR /qmk
-CMD make clean ; make keyboard=${keyboard} subproject=${subproject} keymap=${keymap}
+WORKDIR /qmk

+ 14 - 0
build_keyboard.mk

@@ -131,6 +131,14 @@ ifndef CUSTOM_MATRIX
 	SRC += $(QUANTUM_DIR)/matrix.c
 endif
 
+ifeq ($(strip $(API_SYSEX_ENABLE)), yes)
+	OPT_DEFS += -DAPI_SYSEX_ENABLE
+	SRC += $(QUANTUM_DIR)/api/api_sysex.c
+	OPT_DEFS += -DAPI_ENABLE
+	SRC += $(QUANTUM_DIR)/api.c
+    MIDI_ENABLE=yes
+endif
+
 ifeq ($(strip $(MIDI_ENABLE)), yes)
     OPT_DEFS += -DMIDI_ENABLE
 	SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c
@@ -174,6 +182,12 @@ ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
 	SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c
 endif
 
+ifeq ($(strip $(PRINTING_ENABLE)), yes)
+	OPT_DEFS += -DPRINTING_ENABLE
+	SRC += $(QUANTUM_DIR)/process_keycode/process_printer.c
+	SRC += $(TMK_DIR)/protocol/serial_uart.c
+endif
+
 ifeq ($(strip $(SERIAL_LINK_ENABLE)), yes)
 	SRC += $(patsubst $(QUANTUM_PATH)/%,%,$(SERIAL_SRC))
 	OPT_DEFS += $(SERIAL_DEFS)

+ 1 - 0
common.mk

@@ -23,4 +23,5 @@ COMMON_VPATH += $(QUANTUM_PATH)
 COMMON_VPATH += $(QUANTUM_PATH)/keymap_extras
 COMMON_VPATH += $(QUANTUM_PATH)/audio
 COMMON_VPATH += $(QUANTUM_PATH)/process_keycode
+COMMON_VPATH += $(QUANTUM_PATH)/api
 COMMON_VPATH += $(SERIAL_PATH)

+ 1 - 1
keyboards/amj60/config.h

@@ -67,7 +67,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #define RGB_DI_PIN E2
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 8     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 1 - 1
keyboards/clueboard/rev1/config.h

@@ -26,7 +26,7 @@
 /* Underlight configuration
  */
 #define RGB_DI_PIN B2
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 14     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 1 - 1
keyboards/clueboard/rev2/config.h

@@ -30,7 +30,7 @@
 /* Underlight configuration
  */
 #define RGB_DI_PIN D7
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 14     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 1 - 1
keyboards/cluecard/config.h

@@ -140,7 +140,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 /* Underlight configuration
  */
 #define RGB_DI_PIN E6
-//#define RGBLIGHT_TIMER
+//#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 4     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 1 - 1
keyboards/cluecard/keymaps/rgb_effects/config.h

@@ -4,7 +4,7 @@
 #include "../../config.h"
 
 // place overrides here
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLIGHT_EFFECT_SNAKE_LENGTH 3
 #define RGBLIGHT_EFFECT_KNIGHT_LENGTH 2
 #define RGBLIGHT_EFFECT_KNIGHT_OFFSET 2

+ 1 - 1
keyboards/cluepad/config.h

@@ -70,7 +70,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 /* Underlight configuration
  */
 #define RGB_DI_PIN F6
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 4     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 6 - 1
keyboards/ergodox/ez/Makefile

@@ -1,3 +1,8 @@
+SLEEP_LED_ENABLE = no  # Breathing sleep LED during USB suspend
+COMMAND_ENABLE   = no  # Commands for debug and configuration
+RGBLIGHT_ENABLE ?= yes
+MIDI_ENABLE ?= yes
+
 ifndef MAKEFILE_INCLUDED
 	include ../../../Makefile
-endif
+endif

+ 13 - 0
keyboards/ergodox/ez/config.h

@@ -21,6 +21,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #include "../config.h"
 
+#include "config_common.h"
+
 /* USB Device descriptor parameter */
 #define VENDOR_ID       0xFEED
 #define PRODUCT_ID      0x1307
@@ -39,6 +41,17 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define LED_BRIGHTNESS_LO       15
 #define LED_BRIGHTNESS_HI       255
 
+/* ws2812 RGB LED */
+#define RGB_DI_PIN D7
+#define RGBLIGHT_ANIMATIONS
+#define RGBLED_NUM 15     // Number of LEDs
+#define RGBLIGHT_HUE_STEP 12
+#define RGBLIGHT_SAT_STEP 255
+#define RGBLIGHT_VAL_STEP 12
+
+#define RGB_MIDI
+#define RGBW_BB_TWI
+
 
 /* Set 0 if debouncing isn't needed */
 #define DEBOUNCE    5

+ 8 - 2
keyboards/ergodox/ez/ez.c

@@ -16,10 +16,10 @@ void matrix_init_kb(void) {
     // unused pins - C7, D4, D5, D7, E6
     // set as input with internal pull-ip enabled
     DDRC  &= ~(1<<7);
-    DDRD  &= ~(1<<7 | 1<<5 | 1<<4);
+    DDRD  &= ~(1<<5 | 1<<4);
     DDRE  &= ~(1<<6);
     PORTC |=  (1<<7);
-    PORTD |=  (1<<7 | 1<<5 | 1<<4);
+    PORTD |=  (1<<5 | 1<<4);
     PORTE |=  (1<<6);
 
     ergodox_blink_all_leds();
@@ -51,6 +51,10 @@ uint8_t init_mcp23018(void) {
     mcp23018_status = 0x20;
 
     // I2C subsystem
+
+    uint8_t sreg_prev;
+    sreg_prev=SREG;
+    cli();
     if (i2c_initialized == 0) {
         i2c_init();  // on pins D(1,0)
         i2c_initialized++;
@@ -79,6 +83,8 @@ uint8_t init_mcp23018(void) {
 out:
     i2c_stop();
 
+    SREG=sreg_prev;
+
     return mcp23018_status;
 }
 

+ 1 - 1
keyboards/ergodox/ez/matrix.c

@@ -121,7 +121,7 @@ void matrix_init(void)
     matrix_scan_count = 0;
 #endif
 
-    matrix_init_kb();
+    matrix_init_quantum();
 
 }
 

+ 2 - 0
keyboards/ergodox/ez/rules.mk

@@ -72,6 +72,8 @@ OPT_DEFS += -DBOOTLOADER_SIZE=512
 #
 
 SLEEP_LED_ENABLE = no
+API_SYSEX_ENABLE ?= yes
+RGBLIGHT_ENABLE ?= yes
 
 ifndef QUANTUM_DIR
 	include ../../../Makefile

+ 2 - 0
keyboards/ergodox/infinity/rules.mk

@@ -63,6 +63,8 @@ VISUALIZER_ENABLE ?= no #temporarily disabled to make everything compile
 LCD_ENABLE ?= yes
 LED_ENABLE ?= yes
 LCD_BACKLIGHT_ENABLE ?= yes
+MIDI_ENABLE = no
+RGBLIGHT_ENABLE = no
 
 ifndef QUANTUM_DIR
 	include ../../../Makefile

+ 2 - 0
keyboards/ergodox/keymaps/erez_experimental/Makefile

@@ -3,6 +3,8 @@
 
 SLEEP_LED_ENABLE = no  # Breathing sleep LED during USB suspend
 COMMAND_ENABLE   = no  # Commands for debug and configuration
+RGBLIGHT_ENABLE ?= yes
+MIDI_ENABLE ?= yes
 
 ifndef QUANTUM_DIR
 	include ../../../../Makefile

+ 1 - 0
keyboards/ergodox/keymaps/erez_experimental/config.h

@@ -8,5 +8,6 @@
 
 #undef LEADER_TIMEOUT
 #define LEADER_TIMEOUT 300
+ 
 
 #endif

+ 33 - 9
keyboards/ergodox/keymaps/erez_experimental/keymap.c

@@ -7,6 +7,12 @@
 #define SYMB 1 // symbols
 #define MDIA 2 // media keys
 
+enum custom_keycodes {
+  PLACEHOLDER = SAFE_RANGE, // can always be here
+  RGB_FF00BB // always start with RGB_
+};
+
+
 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 /* Keymap 0: Basic layer
  *
@@ -65,33 +71,33 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  *   |      |      |      |NxtTab|PrvTab|                                       |      |      |      |      |      |
  *   `----------------------------------'                                       `----------------------------------'
  *                                        ,-------------.       ,-------------.
- *                                        |      |      |       |      |      |
+ *                                        |      |      |       |TOG   |
  *                                 ,------|------|------|       |------+------+------.
- *                                 |      |      |      |       |      |      |      |
+ *                                 |VAI   |VAD   |HUI   |       |SAI   |TOG   |MOD   |
  *                                 |      |      |------|       |------|      |      |
- *                                 |      |      |      |       |      |      |      |
+ *                                 |      |      |HUD   |       |SAD   |      |      |
  *                                 `--------------------'       `--------------------'
  */
 // SYMBOLS
 [SYMB] = KEYMAP(
        // left hand
-       KC_TRNS, KC_F1,  KC_F2,  KC_F3,         KC_F4,        KC_F5,   KC_TRNS,
+       RGB_FF00BB, KC_F1,  KC_F2,  KC_F3,      KC_F4,        KC_F5,   KC_TRNS,
        KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,       KC_TRNS,      KC_TRNS, KC_TRNS,
        KC_TRNS, KC_1,   KC_2,   KC_3,          KC_4,         KC_5,
        KC_TRNS, KC_6,   KC_7,   KC_8,          KC_9,         KC_0,    KC_TRNS,
        KC_TRNS, KC_TRNS,KC_TRNS,LCTL(KC_PGUP), LCTL(KC_PGDN),
                                                                               KC_TRNS,KC_TRNS,
-                                                                                      KC_TRNS,
-                                                                      KC_TRNS,KC_TRNS,KC_TRNS,
+                                                                                      RGB_HUI,
+                                                                      RGB_VAI,RGB_VAD,RGB_HUD,
                // right hand
        KC_TRNS, KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,
        KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_F12,
                 KC_AMPR, KC_UNDS, KC_MINS, CM_SCLN, KC_PLUS, KC_TRNS,
        KC_TRNS, KC_PIPE, KC_AT,   KC_EQL,  KC_PERC,   KC_TRNS, KC_TRNS,
                          KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
-       KC_TRNS, KC_TRNS,
-       KC_TRNS,
-       KC_TRNS, KC_TRNS, KC_TRNS
+       RGB_TOG, KC_TRNS,
+       RGB_SAI,
+       RGB_SAD, KC_TRNS, RGB_MOD
 ),
 /* Keymap 2: Media and mouse keys
  *
@@ -152,6 +158,24 @@ void matrix_init_user(void) {
 
 };
 
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+  switch (keycode) {
+    // dynamically generate these.
+    case RGB_FF00BB:
+      if (record->event.pressed) {
+        #ifdef RGBLIGHT_ENABLE
+          rgblight_enable();
+          rgblight_mode(1);
+          rgblight_setrgb(0xff,0x00,0xbb);
+        #endif
+      }
+      return false;
+      break;
+  }
+  return true;
+}
+
 LEADER_EXTERNS();
 
 // Runs constantly in the background, in a loop.

+ 6 - 0
keyboards/ergodox/keymaps/jack/Makefile

@@ -0,0 +1,6 @@
+RGBLIGHT_ENABLE ?= yes
+MIDI_ENABLE ?= yes
+
+ifndef QUANTUM_DIR
+	include ../../../../Makefile
+endif

+ 17 - 0
keyboards/ergodox/keymaps/jack/config.h

@@ -0,0 +1,17 @@
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+/* ws2812 RGB LED */
+#define RGB_DI_PIN D7
+#define RGBLIGHT_ANIMATIONS
+#define RGBLED_NUM 15     // Number of LEDs
+#define RGBLIGHT_HUE_STEP 12
+#define RGBLIGHT_SAT_STEP 255
+#define RGBLIGHT_VAL_STEP 12
+
+#define RGB_MIDI
+#define RGBW_BB_TWI
+
+#endif

+ 16 - 6
keyboards/ergodox/keymaps/jack/keymap.c

@@ -19,14 +19,14 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
                                                               KC_HOME,
                                                KC_SPC,KC_SPC,KC_END,
         // right hand
-             KC_NO,     KC_6,   KC_7,   KC_8,   KC_9,   KC_0,             KC_NO,
-             KC_NO,     KC_Y,   KC_U,   KC_I,   KC_O,   KC_P,             KC_BSPC,
-                        KC_H,   KC_J,   KC_K,   KC_L,   KC_SCLN,          KC_QUOT,
+             KC_NO,     M(1),   KC_7,   KC_8,   KC_9,   KC_0,             KC_NO,
+             KC_NO,     RGB_TOG,   RGB_MOD,   RGB_HUI,   RGB_HUD,   KC_P,             KC_BSPC,
+                        RGB_SAI,   RGB_SAD,   RGB_VAI,   RGB_VAD,   KC_SCLN,          KC_QUOT,
              KC_NO,     KC_N,   KC_M,   KC_COMM,KC_DOT, KC_SLSH,          KC_ENT,
                                   MO(1), KC_LEFT,KC_DOWN,KC_UP,  KC_RGHT,  
-             KC_NO,        KC_NO,
-             KC_PGUP,
-             KC_PGDN, KC_SPC,KC_SPC
+             RGB_TOG,        RGB_HUI,
+             RGB_MOD,
+             M(2), KC_SPC,KC_SPC
     ),
 [SYMB] = KEYMAP(
        // left hand
@@ -84,6 +84,16 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
           unregister_code(KC_RSFT);
         }
         break;
+        case 1:
+        if (record->event.pressed) { // For resetting EEPROM
+          eeconfig_init();
+        }
+        break;
+        case 2:
+        if (record->event.pressed) { // For resetting EEPROM
+          api_send_unicode(0x0CA0);
+        }
+        break;
       }
     return MACRO_NONE;
 };

+ 0 - 1
keyboards/ergodox/rules.mk

@@ -24,6 +24,5 @@ COMMAND_ENABLE   ?= yes # Commands for debug and configuration
 CUSTOM_MATRIX    ?= yes # Custom matrix file for the ErgoDox EZ
 SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
 NKRO_ENABLE      ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
-MIDI_ENABLE      ?= no  # MIDI controls
 UNICODE_ENABLE   ?= yes # Unicode
 ONEHAND_ENABLE   ?= yes # Allow swapping hands of keyboard

+ 1 - 1
keyboards/gh60/keymaps/robotmaxtron/config.h

@@ -182,7 +182,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
 #define ws2812_pin PF4
 */ 
 #define RGB_DI_PIN F4
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 8         // Number of LEDs
 #define RGBLIGHT_HUE_STEP 8
 #define RGBLIGHT_SAT_STEP 8

+ 1 - 1
keyboards/handwired/minorca/keymaps/rgb/config.h

@@ -11,7 +11,7 @@
 
 /* ws2812 RGB LED */
 #define RGB_DI_PIN D5
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 13     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 1 - 1
keyboards/jd40/config.h

@@ -70,7 +70,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
 )
 
 #define RGB_DI_PIN D3
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 12         // Number of LEDs
 #define RGBLIGHT_HUE_STEP 8
 #define RGBLIGHT_SAT_STEP 8

+ 1 - 1
keyboards/kc60/keymaps/ws2812/config.h

@@ -2,7 +2,7 @@
 
 /* WS2812B RGB Underglow LED */
 #define RGB_DI_PIN F5   // Based on wiring depicted in ws2812_wiring.jpg
-#define RGBLIGHT_TIMER       
+#define RGBLIGHT_ANIMATIONS       
 #define RGBLED_NUM 16         // Number of LEDs. Change this to match your use case.
 #define RGBLIGHT_HUE_STEP 8
 #define RGBLIGHT_SAT_STEP 8

+ 2 - 1
keyboards/lets_split/config.h

@@ -49,6 +49,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define IS_COMMAND() ( \
     keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
 )
+
 /* disable debug print */
 //#define NO_DEBUG
 
@@ -68,4 +69,4 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifdef SUBPROJECT_rev2
     #include "rev2/config.h"
 #endif
-#endif
+#endif

+ 1 - 1
keyboards/lets_split/keymaps/i2c/config.h

@@ -75,7 +75,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 /* ws2812 RGB LED */
 #define RGB_DI_PIN D4
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 8     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 1 - 1
keyboards/lets_split/keymaps/serial/config.h

@@ -75,7 +75,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 /* ws2812 RGB LED */
 #define RGB_DI_PIN D4
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 8     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 1 - 1
keyboards/phantom/config.h

@@ -63,7 +63,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 /* Underlight configuration
  */
 #define RGB_DI_PIN E2
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 20     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 4 - 4
keyboards/planck/keymaps/default/Makefile

@@ -5,17 +5,17 @@
 #   the appropriate keymap folder that will get included automatically
 #
 BOOTMAGIC_ENABLE = no       # Virtual DIP switch configuration(+1000)
-MOUSEKEY_ENABLE = yes       # Mouse keys(+4700)
+MOUSEKEY_ENABLE = no       # Mouse keys(+4700)
 EXTRAKEY_ENABLE = yes       # Audio control and System control(+450)
 CONSOLE_ENABLE = no         # Console for debug(+400)
-COMMAND_ENABLE = yes        # Commands for debug and configuration
+COMMAND_ENABLE = no        # Commands for debug and configuration
 NKRO_ENABLE = yes            # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
 BACKLIGHT_ENABLE = yes      # Enable keyboard backlight functionality
-MIDI_ENABLE = no            # MIDI controls
+MIDI_ENABLE = yes            # MIDI controls
 AUDIO_ENABLE = yes           # Audio output on port C6
 UNICODE_ENABLE = no         # Unicode
 BLUETOOTH_ENABLE = no       # Enable Bluetooth with the Adafruit EZ-Key HID
-RGBLIGHT_ENABLE = no        # Enable WS2812 RGB underlight.  Do not enable this with audio at the same time.
+RGBLIGHT_ENABLE = no        # Enable WS2812 RGB underlight
 
 # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
 SLEEP_LED_ENABLE = no    # Breathing sleep LED during USB suspend

+ 2 - 2
keyboards/planck/keymaps/default/keymap.c

@@ -107,7 +107,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 [_LOWER] = {
   {KC_TILD, KC_EXLM, KC_AT,   KC_HASH, KC_DLR,  KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
   {KC_DEL,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
-  {_______, KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______},
+  {_______, KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,S(KC_NUHS),S(KC_NUBS),KC_HOME, KC_END, _______},
   {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
 },
 
@@ -125,7 +125,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
 [_RAISE] = {
   {KC_GRV,  KC_1,    KC_2,    KC_3,    KC_4,    KC_5,    KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    KC_BSPC},
   {KC_DEL,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_MINS, KC_EQL,  KC_LBRC, KC_RBRC, KC_BSLS},
-  {_______, KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  KC_NUHS, KC_NUBS, _______, _______, _______},
+  {_______, KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  KC_NUHS, KC_NUBS, KC_PGUP, KC_PGDN, _______},
   {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
 },
 

+ 1 - 1
keyboards/planck/keymaps/experimental/config.h

@@ -9,7 +9,7 @@
 
 /* ws2812 RGB LED */
 #define RGB_DI_PIN B1
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 8     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 26 - 0
keyboards/planck/keymaps/thermal_printer/Makefile

@@ -0,0 +1,26 @@
+
+
+# Build Options
+#   change to "no" to disable the options, or define them in the Makefile in 
+#   the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no       # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes       # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes       # Audio control and System control(+450)
+CONSOLE_ENABLE = no         # Console for debug(+400)
+COMMAND_ENABLE = yes        # Commands for debug and configuration
+NKRO_ENABLE = yes            # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes      # Enable keyboard backlight functionality
+MIDI_ENABLE = no            # MIDI controls
+AUDIO_ENABLE = yes           # Audio output on port C6
+UNICODE_ENABLE = no         # Unicode
+BLUETOOTH_ENABLE = no       # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no        # Enable WS2812 RGB underlight.  Do not enable this with audio at the same time.
+PRINTING_ENABLE = yes
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no    # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+	include ../../../../Makefile
+endif

+ 23 - 0
keyboards/planck/keymaps/thermal_printer/config.h

@@ -0,0 +1,23 @@
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+#      define SERIAL_UART_BAUD 19200
+#      define SERIAL_UART_DATA UDR1
+#      define SERIAL_UART_UBRR (F_CPU / (16UL * SERIAL_UART_BAUD) - 1)
+#      define SERIAL_UART_RXD_VECT USART1_RX_vect
+#      define SERIAL_UART_TXD_READY (UCSR1A & _BV(UDRE1))
+#      define SERIAL_UART_INIT() do { \
+            /* baud rate */ \
+            UBRR1L = SERIAL_UART_UBRR; \
+            /* baud rate */ \
+            UBRR1H = SERIAL_UART_UBRR >> 8; \
+            /* enable TX */ \
+            UCSR1B = _BV(TXEN1); \
+            /* 8-bit data */ \
+            UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); \
+            sei(); \
+        } while(0)
+
+ #endif

+ 314 - 0
keyboards/planck/keymaps/thermal_printer/keymap.c

@@ -0,0 +1,314 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "planck.h"
+#include "action_layer.h"
+#ifdef AUDIO_ENABLE
+  #include "audio.h"
+#endif
+#include "eeconfig.h"
+
+extern keymap_config_t keymap_config;
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QWERTY 0
+#define _COLEMAK 1
+#define _DVORAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _PLOVER 5
+#define _ADJUST 16
+
+enum planck_keycodes {
+  QWERTY = SAFE_RANGE,
+  COLEMAK,
+  DVORAK,
+  PLOVER,
+  LOWER,
+  RAISE,
+  BACKLIT,
+  EXT_PLV
+};
+
+// Fillers to make layering more clear
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab  |   Q  |   W  |   E  |   R  |   T  |   Y  |   U  |   I  |   O  |   P  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc  |   A  |   S  |   D  |   F  |   G  |   H  |   J  |   K  |   L  |   ;  |  "   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift|   Z  |   X  |   C  |   V  |   B  |   N  |   M  |   ,  |   .  |   /  |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_QWERTY] = {
+  {KC_TAB,  KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,    KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_BSPC},
+  {KC_ESC,  KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT},
+  {KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_N,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_ENT },
+  {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER,   KC_SPC,  KC_SPC,  RAISE,   KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT}
+},
+
+/* Colemak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab  |   Q  |   W  |   F  |   P  |   G  |   J  |   L  |   U  |   Y  |   ;  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc  |   A  |   R  |   S  |   T  |   D  |   H  |   N  |   E  |   I  |   O  |  "   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift|   Z  |   X  |   C  |   V  |   B  |   K  |   M  |   ,  |   .  |   /  |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_COLEMAK] = {
+  {KC_TAB,  KC_Q,    KC_W,    KC_F,    KC_P,    KC_G,    KC_J,    KC_L,    KC_U,    KC_Y,    KC_SCLN, KC_BSPC},
+  {KC_ESC,  KC_A,    KC_R,    KC_S,    KC_T,    KC_D,    KC_H,    KC_N,    KC_E,    KC_I,    KC_O,    KC_QUOT},
+  {KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_K,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_ENT },
+  {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER,   KC_SPC,  KC_SPC,  RAISE,   KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT}
+},
+
+/* Dvorak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab  |   "  |   ,  |   .  |   P  |   Y  |   F  |   G  |   C  |   R  |   L  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc  |   A  |   O  |   E  |   U  |   I  |   D  |   H  |   T  |   N  |   S  |  /   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift|   ;  |   Q  |   J  |   K  |   X  |   B  |   M  |   W  |   V  |   Z  |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_DVORAK] = {
+  {KC_TAB,  KC_QUOT, KC_COMM, KC_DOT,  KC_P,    KC_Y,    KC_F,    KC_G,    KC_C,    KC_R,    KC_L,    KC_BSPC},
+  {KC_ESC,  KC_A,    KC_O,    KC_E,    KC_U,    KC_I,    KC_D,    KC_H,    KC_T,    KC_N,    KC_S,    KC_SLSH},
+  {KC_LSFT, KC_SCLN, KC_Q,    KC_J,    KC_K,    KC_X,    KC_B,    KC_M,    KC_W,    KC_V,    KC_Z,    KC_ENT },
+  {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER,   KC_SPC,  KC_SPC,  RAISE,   KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT}
+},
+
+/* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * |   ~  |   !  |   @  |   #  |   $  |   %  |   ^  |   &  |   *  |   (  |   )  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del  |  F1  |  F2  |  F3  |  F4  |  F5  |  F6  |   _  |   +  |   {  |   }  |  |   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |  F7  |  F8  |  F9  |  F10 |  F11 |  F12 |ISO ~ |ISO | |      |      |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |      |      |      |      |      |             |      | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_LOWER] = {
+  {KC_TILD, KC_EXLM, KC_AT,   KC_HASH, KC_DLR,  KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+  {KC_DEL,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+  {_______, KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______},
+  {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * |   `  |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |   9  |   0  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del  |  F1  |  F2  |  F3  |  F4  |  F5  |  F6  |   -  |   =  |   [  |   ]  |  \   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |  F7  |  F8  |  F9  |  F10 |  F11 |  F12 |ISO # |ISO / |      |      |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |      |      |      |      |      |             |      | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_RAISE] = {
+  {KC_GRV,  KC_1,    KC_2,    KC_3,    KC_4,    KC_5,    KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    KC_BSPC},
+  {KC_DEL,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_MINS, KC_EQL,  KC_LBRC, KC_RBRC, KC_BSLS},
+  {_______, KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  KC_NUHS, KC_NUBS, _______, _______, _______},
+  {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Plover layer (http://opensteno.org)
+ * ,-----------------------------------------------------------------------------------.
+ * |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * |      |   S  |   T  |   P  |   H  |   *  |   *  |   F  |   P  |   L  |   T  |   D  |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |TogOut|   S  |   K  |   W  |   R  |   *  |   *  |   R  |   B  |   G  |   S  |   Z  |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Exit |      |      |   A  |   O  |             |   E  |   U  |      |      |      |
+ * `-----------------------------------------------------------------------------------'
+ */
+
+[_PLOVER] = {
+  {KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1   },
+  {XXXXXXX, KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,    KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_LBRC},
+  {XXXXXXX, KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT},
+  {EXT_PLV, XXXXXXX, XXXXXXX, KC_C,    KC_V,    XXXXXXX, XXXXXXX, KC_N,    KC_M,    XXXXXXX, XXXXXXX, XXXXXXX}
+},
+
+/* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * |      | Reset|      | Print|no prnt |    |      |      |      |      |      |  Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * |      |      |      |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak|Plover|      |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |Voice-|Voice+|Mus on|Musoff|MIDIon|MIDIof|      |      |      |      |      |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |      |      |      |      |      |             |      |      |      |      |      |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_ADJUST] = {
+  {_______, RESET,   _______, PRINT_ON, PRINT_OFF, _______, _______, _______, _______, _______, _______, KC_DEL},
+  {_______, _______, _______, AU_ON,   AU_OFF,  AG_NORM, AG_SWAP, QWERTY,  COLEMAK, DVORAK,  PLOVER,  _______},
+  {_______, MUV_DE,  MUV_IN,  MU_ON,   MU_OFF,  MI_ON,   MI_OFF,  _______, _______, _______, _______, _______},
+  {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
+}
+
+
+};
+
+#ifdef AUDIO_ENABLE
+
+float tone_startup[][2]    = SONG(STARTUP_SOUND);
+float tone_qwerty[][2]     = SONG(QWERTY_SOUND);
+float tone_dvorak[][2]     = SONG(DVORAK_SOUND);
+float tone_colemak[][2]    = SONG(COLEMAK_SOUND);
+float tone_plover[][2]     = SONG(PLOVER_SOUND);
+float tone_plover_gb[][2]  = SONG(PLOVER_GOODBYE_SOUND);
+float music_scale[][2]     = SONG(MUSIC_SCALE_SOUND);
+
+float tone_goodbye[][2] = SONG(GOODBYE_SOUND);
+#endif
+
+
+void persistant_default_layer_set(uint16_t default_layer) {
+  eeconfig_update_default_layer(default_layer);
+  default_layer_set(default_layer);
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+  switch (keycode) {
+    case QWERTY:
+      if (record->event.pressed) {
+        #ifdef AUDIO_ENABLE
+          PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
+        #endif
+        persistant_default_layer_set(1UL<<_QWERTY);
+      }
+      return false;
+      break;
+    case COLEMAK:
+      if (record->event.pressed) {
+        #ifdef AUDIO_ENABLE
+          PLAY_NOTE_ARRAY(tone_colemak, false, 0);
+        #endif
+        persistant_default_layer_set(1UL<<_COLEMAK);
+      }
+      return false;
+      break;
+    case DVORAK:
+      if (record->event.pressed) {
+        #ifdef AUDIO_ENABLE
+          PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
+        #endif
+        persistant_default_layer_set(1UL<<_DVORAK);
+      }
+      return false;
+      break;
+    case LOWER:
+      if (record->event.pressed) {
+        layer_on(_LOWER);
+        update_tri_layer(_LOWER, _RAISE, _ADJUST);
+      } else {
+        layer_off(_LOWER);
+        update_tri_layer(_LOWER, _RAISE, _ADJUST);
+      }
+      return false;
+      break;
+    case RAISE:
+      if (record->event.pressed) {
+        layer_on(_RAISE);
+        update_tri_layer(_LOWER, _RAISE, _ADJUST);
+      } else {
+        layer_off(_RAISE);
+        update_tri_layer(_LOWER, _RAISE, _ADJUST);
+      }
+      return false;
+      break;
+    case BACKLIT:
+      if (record->event.pressed) {
+        register_code(KC_RSFT);
+        #ifdef BACKLIGHT_ENABLE
+          backlight_step();
+        #endif
+      } else {
+        unregister_code(KC_RSFT);
+      }
+      return false;
+      break;
+    case PLOVER:
+      if (record->event.pressed) {
+        #ifdef AUDIO_ENABLE
+          stop_all_notes();
+          PLAY_NOTE_ARRAY(tone_plover, false, 0);
+        #endif
+        layer_off(_RAISE);
+        layer_off(_LOWER);
+        layer_off(_ADJUST);
+        layer_on(_PLOVER);
+        if (!eeconfig_is_enabled()) {
+            eeconfig_init();
+        }
+        keymap_config.raw = eeconfig_read_keymap();
+        keymap_config.nkro = 1;
+        eeconfig_update_keymap(keymap_config.raw);
+      }
+      return false;
+      break;
+    case EXT_PLV:
+      if (record->event.pressed) {
+        #ifdef AUDIO_ENABLE
+          PLAY_NOTE_ARRAY(tone_plover_gb, false, 0);
+        #endif
+        layer_off(_PLOVER);
+      }
+      return false;
+      break;
+  }
+  return true;
+}
+
+void matrix_init_user(void) {
+    #ifdef AUDIO_ENABLE
+        startup_user();
+    #endif
+}
+
+#ifdef AUDIO_ENABLE
+
+void startup_user()
+{
+    _delay_ms(20); // gets rid of tick
+    PLAY_NOTE_ARRAY(tone_startup, false, 0);
+}
+
+void shutdown_user()
+{
+    PLAY_NOTE_ARRAY(tone_goodbye, false, 0);
+    _delay_ms(150);
+    stop_all_notes();
+}
+
+void music_on_user(void)
+{
+    music_scale_user();
+}
+
+void music_scale_user(void)
+{
+    PLAY_NOTE_ARRAY(music_scale, false, 0);
+}
+
+#endif

+ 2 - 0
keyboards/planck/keymaps/thermal_printer/readme.md

@@ -0,0 +1,2 @@
+# The Default Planck Layout
+

+ 1 - 1
keyboards/planck/keymaps/yang/config.h

@@ -5,7 +5,7 @@
 
 /* ws2812 RGB LED */
 #define RGB_DI_PIN D1
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 28     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 1 - 0
keyboards/planck/rules.mk

@@ -62,6 +62,7 @@ AUDIO_ENABLE ?= no           # Audio output on port C6
 UNICODE_ENABLE ?= no         # Unicode
 BLUETOOTH_ENABLE ?= no       # Enable Bluetooth with the Adafruit EZ-Key HID
 RGBLIGHT_ENABLE ?= no        # Enable WS2812 RGB underlight.  Do not enable this with audio at the same time.
+API_SYSEX_ENABLE = yes
 
 # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
 SLEEP_LED_ENABLE ?= no    # Breathing sleep LED during USB suspend

+ 1 - 1
keyboards/preonic/config.h

@@ -63,7 +63,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 /* ws2812 RGB LED */
 #define RGB_DI_PIN D1
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 28     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 0 - 22
keyboards/preonic/keymaps/default/Makefile

@@ -1,25 +1,3 @@
-
-
-# Build Options
-#   change to "no" to disable the options, or define them in the Makefile in 
-#   the appropriate keymap folder that will get included automatically
-#
-BOOTMAGIC_ENABLE = no       # Virtual DIP switch configuration(+1000)
-MOUSEKEY_ENABLE = yes       # Mouse keys(+4700)
-EXTRAKEY_ENABLE = yes       # Audio control and System control(+450)
-CONSOLE_ENABLE = no         # Console for debug(+400)
-COMMAND_ENABLE = yes        # Commands for debug and configuration
-NKRO_ENABLE = yes            # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
-BACKLIGHT_ENABLE = yes      # Enable keyboard backlight functionality
-MIDI_ENABLE = no            # MIDI controls
-AUDIO_ENABLE = yes           # Audio output on port C6
-UNICODE_ENABLE = no         # Unicode
-BLUETOOTH_ENABLE = no       # Enable Bluetooth with the Adafruit EZ-Key HID
-RGBLIGHT_ENABLE = no        # Enable WS2812 RGB underlight.  Do not enable this with audio at the same time.
-
-# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
-SLEEP_LED_ENABLE = no    # Breathing sleep LED during USB suspend
-
 ifndef QUANTUM_DIR
 	include ../../../../Makefile
 endif

+ 1 - 1
keyboards/preonic/keymaps/kinesis/config.h

@@ -63,7 +63,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 /* ws2812 RGB LED */
 #define RGB_DI_PIN D1
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 28     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 2 - 1
keyboards/preonic/rules.mk

@@ -53,7 +53,7 @@ OPT_DEFS += -DBOOTLOADER_SIZE=4096
 #   the appropriate keymap folder that will get included automatically
 #
 BOOTMAGIC_ENABLE ?= no       # Virtual DIP switch configuration(+1000)
-MOUSEKEY_ENABLE ?= yes       # Mouse keys(+4700)
+MOUSEKEY_ENABLE ?= no       # Mouse keys(+4700)
 EXTRAKEY_ENABLE ?= yes       # Audio control and System control(+450)
 CONSOLE_ENABLE ?= no         # Console for debug(+400)
 COMMAND_ENABLE ?= yes        # Commands for debug and configuration
@@ -64,6 +64,7 @@ AUDIO_ENABLE ?= no           # Audio output on port C6
 UNICODE_ENABLE ?= no         # Unicode
 BLUETOOTH_ENABLE ?= no       # Enable Bluetooth with the Adafruit EZ-Key HID
 RGBLIGHT_ENABLE ?= no        # Enable WS2812 RGB underlight.  Do not enable this with audio at the same time.
+API_SYSEX_ENABLE ?= yes
 
 # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
 SLEEP_LED_ENABLE ?= no    # Breathing sleep LED during USB suspend

+ 1 - 1
keyboards/satan/config.h

@@ -67,7 +67,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #define RGB_DI_PIN E2
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 8     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 1 - 1
keyboards/tada68/config.h

@@ -67,7 +67,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 /*#define RGB_DI_PIN E2
-#define RGBLIGHT_TIMER
+#define RGBLIGHT_ANIMATIONS
 #define RGBLED_NUM 2     // Number of LEDs
 #define RGBLIGHT_HUE_STEP 10
 #define RGBLIGHT_SAT_STEP 17

+ 178 - 0
quantum/api.c

@@ -0,0 +1,178 @@
+#include "api.h"
+#include "quantum.h"
+
+void dword_to_bytes(uint32_t dword, uint8_t * bytes) {
+    bytes[0] = (dword >> 24) & 0xFF;
+    bytes[1] = (dword >> 16) & 0xFF; 
+    bytes[2] = (dword >> 8) & 0xFF; 
+    bytes[3] = (dword >> 0) & 0xFF; 
+}
+
+uint32_t bytes_to_dword(uint8_t * bytes, uint8_t index) {
+    return ((uint32_t)bytes[index + 0] << 24) | ((uint32_t)bytes[index + 1] << 16) | ((uint32_t)bytes[index + 2] << 8) | (uint32_t)bytes[index + 3];
+}
+
+__attribute__ ((weak))
+bool process_api_quantum(uint8_t length, uint8_t * data) {
+    return process_api_keyboard(length, data);
+}
+
+__attribute__ ((weak))
+bool process_api_keyboard(uint8_t length, uint8_t * data) {
+    return process_api_user(length, data);
+}
+
+__attribute__ ((weak))
+bool process_api_user(uint8_t length, uint8_t * data) {
+    return true;
+}
+
+void process_api(uint16_t length, uint8_t * data) {
+    // SEND_STRING("\nRX: ");
+    // for (uint8_t i = 0; i < length; i++) {
+    //     send_byte(data[i]);
+    //     SEND_STRING(" ");
+    // }
+    if (!process_api_quantum(length, data))
+        return;
+
+    switch (data[0]) {
+        case MT_SET_DATA:
+            switch (data[1]) {
+                case DT_DEFAULT_LAYER: {
+                    eeconfig_update_default_layer(data[2]);
+                    default_layer_set((uint32_t)(data[2]));
+                    break;
+                }
+                case DT_KEYMAP_OPTIONS: {
+                    eeconfig_update_keymap(data[2]);
+                    break;
+                }
+                case DT_RGBLIGHT: {
+                    #ifdef RGBLIGHT_ENABLE
+                        uint32_t rgblight = bytes_to_dword(data, 2);
+                        rgblight_update_dword(rgblight);
+                    #endif
+                    break;
+                }
+            }
+        case MT_GET_DATA:
+            switch (data[1]) {
+                case DT_HANDSHAKE: {
+                    MT_GET_DATA_ACK(DT_HANDSHAKE, NULL, 0);
+                    break;
+                }
+                case DT_DEBUG: {
+                    uint8_t debug_bytes[1] = { eeprom_read_byte(EECONFIG_DEBUG) };
+                    MT_GET_DATA_ACK(DT_DEBUG, debug_bytes, 1);
+                    break;
+                }
+                case DT_DEFAULT_LAYER: {
+                    uint8_t default_bytes[1] = { eeprom_read_byte(EECONFIG_DEFAULT_LAYER) };
+                    MT_GET_DATA_ACK(DT_DEFAULT_LAYER, default_bytes, 1);
+                    break;
+                }
+                case DT_CURRENT_LAYER: {
+                    uint8_t layer_state_bytes[4];
+                    dword_to_bytes(layer_state, layer_state_bytes);
+                    MT_GET_DATA_ACK(DT_CURRENT_LAYER, layer_state_bytes, 4);
+                    break;
+                }
+                case DT_AUDIO: {
+                    #ifdef AUDIO_ENABLE
+                        uint8_t audio_bytes[1] = { eeprom_read_byte(EECONFIG_AUDIO) };
+                        MT_GET_DATA_ACK(DT_AUDIO, audio_bytes, 1);
+                    #else
+                        MT_GET_DATA_ACK(DT_AUDIO, NULL, 0);
+                    #endif
+                    break;
+                }
+                case DT_BACKLIGHT: {
+                    #ifdef BACKLIGHT_ENABLE
+                        uint8_t backlight_bytes[1] = { eeprom_read_byte(EECONFIG_BACKLIGHT) };
+                        MT_GET_DATA_ACK(DT_BACKLIGHT, backlight_bytes, 1);
+                    #else
+                        MT_GET_DATA_ACK(DT_BACKLIGHT, NULL, 0);
+                    #endif
+                    break;
+                }
+                case DT_RGBLIGHT: {
+                    #ifdef RGBLIGHT_ENABLE
+                        uint8_t rgblight_bytes[4];
+                        dword_to_bytes(eeconfig_read_rgblight(), rgblight_bytes);
+                        MT_GET_DATA_ACK(DT_RGBLIGHT, rgblight_bytes, 4);
+                    #else
+                        MT_GET_DATA_ACK(DT_RGBLIGHT, NULL, 0);
+                    #endif
+                    break;
+                }
+                case DT_KEYMAP_OPTIONS: {
+                    uint8_t keymap_bytes[1] = { eeconfig_read_keymap() };
+                    MT_GET_DATA_ACK(DT_KEYMAP_OPTIONS, keymap_bytes, 1);
+                    break;
+                }
+                case DT_KEYMAP_SIZE: {
+                    uint8_t keymap_size[2] = {MATRIX_ROWS, MATRIX_COLS};
+                    MT_GET_DATA_ACK(DT_KEYMAP_SIZE, keymap_size, 2);
+                    break;
+                }
+                case DT_KEYMAP: {
+                    uint8_t keymap_data[MATRIX_ROWS * MATRIX_COLS * 4 + 3];
+                    keymap_data[0] = data[2];
+                    keymap_data[1] = MATRIX_ROWS;
+                    keymap_data[2] = MATRIX_COLS;
+                    for (int i = 0; i < MATRIX_ROWS; i++) {
+                        for (int j = 0; j < MATRIX_COLS; j++) {
+                            keymap_data[3 + (i*MATRIX_COLS*2) + (j*2)] = pgm_read_word(&keymaps[data[2]][i][j]) >> 8;
+                            keymap_data[3 + (i*MATRIX_COLS*2) + (j*2) + 1] = pgm_read_word(&keymaps[data[2]][i][j]) & 0xFF;
+                        }
+                    }
+                    MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, MATRIX_ROWS * MATRIX_COLS * 4 + 3);
+                    // uint8_t keymap_data[5];
+                    // keymap_data[0] = data[2];
+                    // keymap_data[1] = data[3];
+                    // keymap_data[2] = data[4];
+                    // keymap_data[3] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) >> 8;
+                    // keymap_data[4] = pgm_read_word(&keymaps[data[2]][data[3]][data[4]]) & 0xFF;
+
+                    // MT_GET_DATA_ACK(DT_KEYMAP, keymap_data, 5);
+                    break;
+                }
+                default:
+                    break;
+            }
+            break;
+        case MT_SET_DATA_ACK:
+        case MT_GET_DATA_ACK:
+            break;
+        case MT_SEND_DATA:
+            break;
+        case MT_SEND_DATA_ACK:
+            break;
+        case MT_EXE_ACTION:
+            break;
+        case MT_EXE_ACTION_ACK:
+            break;
+        case MT_TYPE_ERROR:
+            break;
+        default: ; // command not recognised
+            SEND_BYTES(MT_TYPE_ERROR, DT_NONE, data, length);
+            break;
+
+        // #ifdef RGBLIGHT_ENABLE
+        // case 0x27: ; // RGB LED functions
+        //     switch (*data++) {
+        //         case 0x00: ; // Update HSV
+        //             rgblight_sethsv((data[0] << 8 | data[1]) % 360, data[2], data[3]);
+        //             break;
+        //         case 0x01: ; // Update RGB
+        //             break;
+        //         case 0x02: ; // Update mode
+        //             rgblight_mode(data[0]);
+        //             break;
+        //     }
+        //     break;
+        // #endif
+    }
+
+}

+ 59 - 0
quantum/api.h

@@ -0,0 +1,59 @@
+#ifndef _API_H_
+#define _API_H_
+
+#include "lufa.h"
+
+enum MESSAGE_TYPE {
+    MT_GET_DATA =      0x10, // Get data from keyboard
+    MT_GET_DATA_ACK =  0x11, // returned data to process (ACK)
+    MT_SET_DATA =      0x20, // Set data on keyboard
+    MT_SET_DATA_ACK =  0x21, // returned data to confirm (ACK)
+    MT_SEND_DATA =     0x30, // Sending data/action from keyboard
+    MT_SEND_DATA_ACK = 0x31, // returned data/action confirmation (ACK)
+    MT_EXE_ACTION =    0x40, // executing actions on keyboard
+    MT_EXE_ACTION_ACK =0x41, // return confirmation/value (ACK)
+    MT_TYPE_ERROR =    0x80 // type not recofgnised (ACK)
+};
+
+enum DATA_TYPE {
+    DT_NONE = 0x00,
+    DT_HANDSHAKE,
+    DT_DEFAULT_LAYER,
+    DT_CURRENT_LAYER,
+    DT_KEYMAP_OPTIONS,
+    DT_BACKLIGHT,
+    DT_RGBLIGHT,
+    DT_UNICODE,
+    DT_DEBUG,
+    DT_AUDIO,
+    DT_QUANTUM_ACTION,
+    DT_KEYBOARD_ACTION,
+    DT_USER_ACTION,
+    DT_KEYMAP_SIZE,
+    DT_KEYMAP
+};
+
+void dword_to_bytes(uint32_t dword, uint8_t * bytes);
+uint32_t bytes_to_dword(uint8_t * bytes, uint8_t index);
+
+#define MT_GET_DATA(data_type, data, length) SEND_BYTES(MT_GET_DATA, data_type, data, length)
+#define MT_GET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_GET_DATA_ACK, data_type, data, length)
+#define MT_SET_DATA(data_type, data, length) SEND_BYTES(MT_SET_DATA, data_type, data, length)
+#define MT_SET_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SET_DATA_ACK, data_type, data, length)
+#define MT_SEND_DATA(data_type, data, length) SEND_BYTES(MT_SEND_DATA, data_type, data, length)
+#define MT_SEND_DATA_ACK(data_type, data, length) SEND_BYTES(MT_SEND_DATA_ACK, data_type, data, length)
+#define MT_EXE_ACTION(data_type, data, length) SEND_BYTES(MT_EXE_ACTION, data_type, data, length)
+#define MT_EXE_ACTION_ACK(data_type, data, length) SEND_BYTES(MT_EXE_ACTION_ACK, data_type, data, length)
+
+void process_api(uint16_t length, uint8_t * data);
+
+__attribute__ ((weak))
+bool process_api_quantum(uint8_t length, uint8_t * data);
+
+__attribute__ ((weak))
+bool process_api_keyboard(uint8_t length, uint8_t * data);
+
+__attribute__ ((weak))
+bool process_api_user(uint8_t length, uint8_t * data);
+
+#endif

+ 29 - 0
quantum/api/api_sysex.c

@@ -0,0 +1,29 @@
+#include "api_sysex.h"
+
+void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint16_t length) {
+    // SEND_STRING("\nTX: ");
+    // for (uint8_t i = 0; i < length; i++) {
+    //     send_byte(bytes[i]);
+    //     SEND_STRING(" ");
+    // }
+    uint8_t * precode = malloc(sizeof(uint8_t) * (length + 2));
+    precode[0] = message_type;
+    precode[1] = data_type;
+    memcpy(precode + 2, bytes, length);
+    uint8_t * encoded = malloc(sizeof(uint8_t) * (sysex_encoded_length(length + 2)));
+    uint16_t encoded_length = sysex_encode(encoded, precode, length + 2);
+    uint8_t * array = malloc(sizeof(uint8_t) * (encoded_length + 5));
+    array[0] = 0xF0;
+    array[1] = 0x00;
+    array[2] = 0x00;
+    array[3] = 0x00;
+    array[encoded_length + 4] = 0xF7;
+    memcpy(array + 4, encoded, encoded_length);
+    midi_send_array(&midi_device, encoded_length + 5, array);
+
+    // SEND_STRING("\nTD: ");
+    // for (uint8_t i = 0; i < encoded_length + 5; i++) {
+    //     send_byte(array[i]);
+    //     SEND_STRING(" ");
+    // }
+}

+ 10 - 0
quantum/api/api_sysex.h

@@ -0,0 +1,10 @@
+#ifndef _API_SYSEX_H_
+#define _API_SYSEX_H_
+
+#include "api.h"
+
+void send_bytes_sysex(uint8_t message_type, uint8_t data_type, uint8_t * bytes, uint16_t length);
+
+#define SEND_BYTES(mt, dt, b, l) send_bytes_sysex(mt, dt, b, l)
+
+#endif

+ 51 - 50
quantum/config_common.h

@@ -5,55 +5,56 @@
 #define COL2ROW 0
 #define ROW2COL 1
 /* I/O pins */
-#define B0 0x30
-#define B1 0x31
-#define B2 0x32
-#define B3 0x33
-#define B4 0x34
-#define B5 0x35
-#define B6 0x36
-#define B7 0x37
-#define C0 0x60
-#define C1 0x61
-#define C2 0x62
-#define C3 0x63
-#define C4 0x64
-#define C5 0x65
-#define C6 0x66
-#define C7 0x67
-#define D0 0x90
-#define D1 0x91
-#define D2 0x92
-#define D3 0x93
-#define D4 0x94
-#define D5 0x95
-#define D6 0x96
-#define D7 0x97
-#define E0 0xC0
-#define E1 0xC1
-#define E2 0xC2
-#define E3 0xC3
-#define E4 0xC4
-#define E5 0xC5
-#define E6 0xC6
-#define E7 0xC7
-#define F0 0xF0
-#define F1 0xF1
-#define F2 0xF2
-#define F3 0xF3
-#define F4 0xF4
-#define F5 0xF5
-#define F6 0xF6
-#define F7 0xF7
-#define A0 0x00
-#define A1 0x01
-#define A2 0x02
-#define A3 0x03
-#define A4 0x04
-#define A5 0x05
-#define A6 0x06
-#define A7 0x07
-
+#ifndef F0
+    #define B0 0x30
+    #define B1 0x31
+    #define B2 0x32
+    #define B3 0x33
+    #define B4 0x34
+    #define B5 0x35
+    #define B6 0x36
+    #define B7 0x37
+    #define C0 0x60
+    #define C1 0x61
+    #define C2 0x62
+    #define C3 0x63
+    #define C4 0x64
+    #define C5 0x65
+    #define C6 0x66
+    #define C7 0x67
+    #define D0 0x90
+    #define D1 0x91
+    #define D2 0x92
+    #define D3 0x93
+    #define D4 0x94
+    #define D5 0x95
+    #define D6 0x96
+    #define D7 0x97
+    #define E0 0xC0
+    #define E1 0xC1
+    #define E2 0xC2
+    #define E3 0xC3
+    #define E4 0xC4
+    #define E5 0xC5
+    #define E6 0xC6
+    #define E7 0xC7
+    #define F0 0xF0
+    #define F1 0xF1
+    #define F2 0xF2
+    #define F3 0xF3
+    #define F4 0xF4
+    #define F5 0xF5
+    #define F6 0xF6
+    #define F7 0xF7
+    #define A0 0x00
+    #define A1 0x01
+    #define A2 0x02
+    #define A3 0x03
+    #define A4 0x04
+    #define A5 0x05
+    #define A6 0x06
+    #define A7 0x07
+#endif
 
 /* USART configuration */
 #ifdef BLUETOOTH_ENABLE
@@ -79,4 +80,4 @@
 #   endif
 #endif
 
-#endif
+#endif

+ 4 - 0
quantum/keymap.h

@@ -178,6 +178,10 @@ enum quantum_keycodes {
     // Right shift, close paren
     KC_RSPC,
 
+    // Printing
+    PRINT_ON,
+    PRINT_OFF,
+
     // always leave at the end
     SAFE_RANGE
 };

+ 146 - 5
quantum/light_ws2812.c

@@ -16,14 +16,128 @@
 #include <util/delay.h>
 #include "debug.h"
 
+#ifdef RGBW_BB_TWI
+
+// Port for the I2C
+#define I2C_DDR DDRD
+#define I2C_PIN PIND
+#define I2C_PORT PORTD
+
+// Pins to be used in the bit banging
+#define I2C_CLK 0
+#define I2C_DAT 1
+
+#define I2C_DATA_HI()\
+I2C_DDR &= ~ (1 << I2C_DAT);\
+I2C_PORT |= (1 << I2C_DAT);
+#define I2C_DATA_LO()\
+I2C_DDR |= (1 << I2C_DAT);\
+I2C_PORT &= ~ (1 << I2C_DAT);
+
+#define I2C_CLOCK_HI()\
+I2C_DDR &= ~ (1 << I2C_CLK);\
+I2C_PORT |= (1 << I2C_CLK);
+#define I2C_CLOCK_LO()\
+I2C_DDR |= (1 << I2C_CLK);\
+I2C_PORT &= ~ (1 << I2C_CLK);
+
+#define I2C_DELAY 1
+
+void I2C_WriteBit(unsigned char c)
+{
+    if (c > 0)
+    {
+        I2C_DATA_HI();
+    }
+    else
+    {
+        I2C_DATA_LO();
+    }
+
+    I2C_CLOCK_HI();
+    _delay_us(I2C_DELAY);
+
+    I2C_CLOCK_LO();
+    _delay_us(I2C_DELAY);
+
+    if (c > 0)
+    {
+        I2C_DATA_LO();
+    }
+
+    _delay_us(I2C_DELAY);
+}
+
+// Inits bitbanging port, must be called before using the functions below
+//
+void I2C_Init()
+{
+    I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
+
+    I2C_CLOCK_HI();
+    I2C_DATA_HI();
+
+    _delay_us(I2C_DELAY);
+}
+
+// Send a START Condition
+//
+void I2C_Start()
+{
+    // set both to high at the same time
+    I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
+    _delay_us(I2C_DELAY);
+
+    I2C_DATA_LO();
+    _delay_us(I2C_DELAY);
+
+    I2C_CLOCK_LO();
+    _delay_us(I2C_DELAY);
+}
+
+// Send a STOP Condition
+//
+void I2C_Stop()
+{
+    I2C_CLOCK_HI();
+    _delay_us(I2C_DELAY);
+
+    I2C_DATA_HI();
+    _delay_us(I2C_DELAY);
+}
+
+// write a byte to the I2C slave device
+//
+unsigned char I2C_Write(unsigned char c)
+{
+    for (char i = 0; i < 8; i++)
+    {
+        I2C_WriteBit(c & 128);
+
+        c <<= 1;
+    }
+
+    
+    I2C_WriteBit(0);
+    _delay_us(I2C_DELAY);
+    _delay_us(I2C_DELAY);
+  
+    // _delay_us(I2C_DELAY);
+    //return I2C_ReadBit();
+    return 0;
+}
+
+
+#endif
+
 // Setleds for standard RGB
-void inline ws2812_setleds(struct cRGB *ledarray, uint16_t leds)
+void inline ws2812_setleds(LED_TYPE *ledarray, uint16_t leds)
 {
    // ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
    ws2812_setleds_pin(ledarray,leds, _BV(RGB_DI_PIN & 0xF));
 }
 
-void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask)
+void inline ws2812_setleds_pin(LED_TYPE *ledarray, uint16_t leds, uint8_t pinmask)
 {
   // ws2812_DDRREG |= pinmask; // Enable DDR
   // new universal format (DDR)
@@ -34,14 +148,41 @@ void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pin
 }
 
 // Setleds for SK6812RGBW
-void inline ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t leds)
+void inline ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t leds)
 {
+
+  #ifdef RGBW_BB_TWI
+    uint8_t sreg_prev, twcr_prev;
+    sreg_prev=SREG;
+    twcr_prev=TWCR;
+    cli();
+    TWCR &= ~(1<<TWEN);
+    I2C_Init();
+    I2C_Start();
+    I2C_Write(0x84);
+    uint16_t datlen = leds<<2;
+    uint8_t curbyte;
+    uint8_t * data = (uint8_t*)ledarray;
+    while (datlen--) {
+      curbyte=*data++;
+      I2C_Write(curbyte);
+    }
+    I2C_Stop();
+    SREG=sreg_prev;
+    TWCR=twcr_prev;
+  #endif
+
+
   // ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
   // new universal format (DDR)
   _SFR_IO8((RGB_DI_PIN >> 4) + 1) |= _BV(RGB_DI_PIN & 0xF);
 
   ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(RGB_DI_PIN & 0xF));
-  _delay_us(80);
+
+
+  #ifndef RGBW_BB_TWI
+    _delay_us(80);
+  #endif
 }
 
 void ws2812_sendarray(uint8_t *data,uint16_t datlen)
@@ -123,7 +264,7 @@ void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi)
   cli();
 
   while (datlen--) {
-    curbyte=*data++;
+    curbyte=(*data++);
 
     asm volatile(
     "       ldi   %0,8  \n\t"

+ 18 - 3
quantum/light_ws2812.h

@@ -16,6 +16,21 @@
 #include <avr/io.h>
 #include <avr/interrupt.h>
 //#include "ws2812_config.h"
+//#include "i2cmaster.h"
+
+#define LIGHT_I2C 1
+#define LIGHT_I2C_ADDR        0x84
+#define LIGHT_I2C_ADDR_WRITE  ( (LIGHT_I2C_ADDR<<1) | I2C_WRITE )
+#define LIGHT_I2C_ADDR_READ   ( (LIGHT_I2C_ADDR<<1) | I2C_READ  )
+
+#define RGBW 1
+
+#ifdef RGBW
+  #define LED_TYPE struct cRGBW
+#else
+  #define LED_TYPE struct cRGB
+#endif
+
 
 /*
  *  Structure of the LED array
@@ -42,9 +57,9 @@ struct cRGBW { uint8_t g; uint8_t r; uint8_t b; uint8_t w;};
  *         - Wait 50�s to reset the LEDs
  */
 
-void ws2812_setleds     (struct cRGB  *ledarray, uint16_t number_of_leds);
-void ws2812_setleds_pin (struct cRGB  *ledarray, uint16_t number_of_leds,uint8_t pinmask);
-void ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t number_of_leds);
+void ws2812_setleds     (LED_TYPE *ledarray, uint16_t number_of_leds);
+void ws2812_setleds_pin (LED_TYPE *ledarray, uint16_t number_of_leds,uint8_t pinmask);
+void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds);
 
 /*
  * Old interface / Internal functions

+ 254 - 0
quantum/process_keycode/process_printer.c

@@ -0,0 +1,254 @@
+#include "process_printer.h"
+#include "action_util.h"
+
+bool printing_enabled = false;
+uint8_t character_shift = 0;
+
+void enabled_printing() {
+	printing_enabled = true;
+	serial_init();
+}
+
+void disable_printing() {
+	printing_enabled = false;
+}
+
+uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29};
+
+// uint8_t keycode_to_ascii[0xFF][2];
+
+// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
+
+void print_char(char c) {
+	USB_Disable();
+	serial_send(c);
+	USB_Init();
+}
+
+void print_box_string(uint8_t text[]) {
+	uint8_t len = strlen(text);
+	uint8_t out[len * 3 + 8];
+	out[0] = 0xDA;
+	for (uint8_t i = 0; i < len; i++) {
+		out[i+1] = 0xC4;
+	}
+	out[len + 1] = 0xBF;
+	out[len + 2] = '\n';
+
+	out[len + 3] = 0xB3;
+	for (uint8_t i = 0; i < len; i++) {
+		out[len + 4 + i] = text[i];
+	}
+	out[len * 2 + 4] = 0xB3;
+	out[len * 2 + 5] = '\n';
+
+
+	out[len * 2 + 6] = 0xC0;
+	for (uint8_t i = 0; i < len; i++) {
+		out[len * 2 + 7 + i] = 0xC4;
+	}
+	out[len * 3 + 7] = 0xD9;
+	out[len * 3 + 8] = '\n';
+
+	print_string(out); 
+}
+
+void print_string(char c[]) {
+	for(uint8_t i = 0; i < strlen(c); i++)
+		print_char(c[i]);
+}
+
+bool process_printer(uint16_t keycode, keyrecord_t *record) {
+	if (keycode == PRINT_ON) {
+		enabled_printing();
+		return false;
+	}
+	if (keycode == PRINT_OFF) {
+		disable_printing();
+		return false;
+	}
+
+	if (printing_enabled) {
+		switch(keycode) {
+			case KC_EXLM ... KC_RPRN:
+			case KC_UNDS:
+			case KC_PLUS:
+			case KC_LCBR:
+			case KC_RCBR:
+			case KC_PIPE:
+			case KC_TILD:
+				keycode &= 0xFF;
+			case KC_LSFT:
+			case KC_RSFT:
+				if (record->event.pressed) {
+					character_shift++;
+				} else {
+					character_shift--;
+				}
+				return false;
+			break;
+		}
+
+		switch(keycode) {
+			case KC_F1:
+				if (record->event.pressed) {
+					print_box_string("This is a line of text!");
+				}
+				return false;
+			case KC_ESC:
+				if (record->event.pressed) {
+					print_char(0x1B);
+				}
+				return false;
+			break;
+			case KC_SPC:
+				if (record->event.pressed) {
+					print_char(0x20);
+				}
+				return false;
+			break;
+			case KC_A ... KC_Z:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x41 + (keycode - KC_A));
+					} else {
+						print_char(0x61 + (keycode - KC_A));
+					}
+				}
+				return false;
+			break;
+			case KC_1 ... KC_0:
+				if (record->event.pressed) {
+					if (character_shift) {
+							print_char(shifted_numbers[keycode - KC_1]);
+					} else {
+							print_char(0x30 + ((keycode - KC_1 + 1) % 10));
+					}
+				}
+				return false;
+			break;
+			case KC_ENT:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x0C);
+					} else {
+						print_char(0x0A);
+					}
+				}
+				return false;
+			break;
+			case KC_BSPC:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x18);
+					} else {
+						print_char(0x1A);
+					}
+				}
+				return false;
+			break;
+			case KC_DOT:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x3E);
+					} else {
+						print_char(0x2E);
+					}
+				}
+				return false;
+			break;
+			case KC_COMM:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x3C);
+					} else {
+						print_char(0x2C);
+					}
+				}
+				return false;
+			break;
+			case KC_SLSH:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x3F);
+					} else {
+						print_char(0x2F);
+					}
+				}
+				return false;
+			break;
+			case KC_QUOT:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x22);
+					} else {
+						print_char(0x27);
+					}
+				}
+				return false;
+			break;
+			case KC_GRV:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x7E);
+					} else {
+						print_char(0x60);
+					}
+				}
+				return false;
+			break;
+			case KC_MINS:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x5F);
+					} else {
+						print_char(0x2D);
+					}
+				}
+				return false;
+			break;
+			case KC_EQL:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x2B);
+					} else {
+						print_char(0x3D);
+					}
+				}
+				return false;
+			break;
+			case KC_LBRC:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x7B);
+					} else {
+						print_char(0x5B);
+					}
+				}
+				return false;
+			break;
+			case KC_RBRC:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x7D);
+					} else {
+						print_char(0x5D);
+					}
+				}
+				return false;
+			break;
+			case KC_BSLS:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x7C);
+					} else {
+						print_char(0x5C);
+					}
+				}
+				return false;
+			break;
+		}
+	}
+	return true;
+
+}

+ 8 - 0
quantum/process_keycode/process_printer.h

@@ -0,0 +1,8 @@
+#ifndef PROCESS_PRINTER_H
+#define PROCESS_PRINTER_H
+
+#include "quantum.h"
+
+#include "protocol/serial.h"
+
+#endif

+ 260 - 0
quantum/process_keycode/process_printer_bb.c

@@ -0,0 +1,260 @@
+#include "process_printer.h"
+#include "action_util.h"
+
+bool printing_enabled = false;
+uint8_t character_shift = 0;
+
+#define SERIAL_PIN_DDR DDRD
+#define SERIAL_PIN_PORT PORTD
+#define SERIAL_PIN_MASK _BV(PD3)
+#define SERIAL_DELAY 52
+
+inline static
+void serial_delay(void) {
+  _delay_us(SERIAL_DELAY);
+}
+
+inline static
+void serial_high(void) {
+  SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
+}
+
+inline static
+void serial_low(void) {
+  SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
+}
+
+inline static
+void serial_output(void) {
+  SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
+}
+
+
+void enabled_printing() {
+	printing_enabled = true;
+	serial_output();
+	serial_high();
+}
+
+void disable_printing() {
+	printing_enabled = false;
+}
+
+uint8_t shifted_numbers[10] = {0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29};
+
+// uint8_t keycode_to_ascii[0xFF][2];
+
+// keycode_to_ascii[KC_MINS] = {0x2D, 0x5F};
+
+void print_char(char c) {
+  uint8_t b = 8;
+  serial_output();
+  while( b-- ) {
+    if(c & (1 << b)) {
+      serial_high();
+    } else {
+      serial_low();
+    }
+    serial_delay();
+  }
+}
+
+void print_string(char c[]) {
+	for(uint8_t i = 0; i < strlen(c); i++)
+		print_char(c[i]);
+}
+
+bool process_printer(uint16_t keycode, keyrecord_t *record) {
+	if (keycode == PRINT_ON) {
+		enabled_printing();
+		return false;
+	}
+	if (keycode == PRINT_OFF) {
+		disable_printing();
+		return false;
+	}
+
+	if (printing_enabled) {
+		switch(keycode) {
+			case KC_EXLM ... KC_RPRN:
+			case KC_UNDS:
+			case KC_PLUS:
+			case KC_LCBR:
+			case KC_RCBR:
+			case KC_PIPE:
+			case KC_TILD:
+				keycode &= 0xFF;
+			case KC_LSFT:
+			case KC_RSFT:
+				if (record->event.pressed) {
+					character_shift++;
+				} else {
+					character_shift--;
+				}
+				return false;
+			break;
+		}
+
+		switch(keycode) {
+			case KC_F1:
+				if (record->event.pressed) {
+					print_string("This is a line of text!\n\n\n");
+				}
+				return false;
+			case KC_ESC:
+				if (record->event.pressed) {
+					print_char(0x1B);
+				}
+				return false;
+			break;
+			case KC_SPC:
+				if (record->event.pressed) {
+					print_char(0x20);
+				}
+				return false;
+			break;
+			case KC_A ... KC_Z:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x41 + (keycode - KC_A));
+					} else {
+						print_char(0x61 + (keycode - KC_A));
+					}
+				}
+				return false;
+			break;
+			case KC_1 ... KC_0:
+				if (record->event.pressed) {
+					if (character_shift) {
+							print_char(shifted_numbers[keycode - KC_1]);
+					} else {
+							print_char(0x30 + ((keycode - KC_1 + 1) % 10));
+					}
+				}
+				return false;
+			break;
+			case KC_ENT:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x0C);
+					} else {
+						print_char(0x0A);
+					}
+				}
+				return false;
+			break;
+			case KC_BSPC:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x18);
+					} else {
+						print_char(0x1A);
+					}
+				}
+				return false;
+			break;
+			case KC_DOT:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x3E);
+					} else {
+						print_char(0x2E);
+					}
+				}
+				return false;
+			break;
+			case KC_COMM:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x3C);
+					} else {
+						print_char(0x2C);
+					}
+				}
+				return false;
+			break;
+			case KC_SLSH:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x3F);
+					} else {
+						print_char(0x2F);
+					}
+				}
+				return false;
+			break;
+			case KC_QUOT:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x22);
+					} else {
+						print_char(0x27);
+					}
+				}
+				return false;
+			break;
+			case KC_GRV:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x7E);
+					} else {
+						print_char(0x60);
+					}
+				}
+				return false;
+			break;
+			case KC_MINS:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x5F);
+					} else {
+						print_char(0x2D);
+					}
+				}
+				return false;
+			break;
+			case KC_EQL:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x2B);
+					} else {
+						print_char(0x3D);
+					}
+				}
+				return false;
+			break;
+			case KC_LBRC:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x7B);
+					} else {
+						print_char(0x5B);
+					}
+				}
+				return false;
+			break;
+			case KC_RBRC:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x7D);
+					} else {
+						print_char(0x5D);
+					}
+				}
+				return false;
+			break;
+			case KC_BSLS:
+				if (record->event.pressed) {
+					if (character_shift) {
+						print_char(0x7C);
+					} else {
+						print_char(0x5C);
+					}
+				}
+				return false;
+			break;
+		}
+	}
+	return true;
+
+}

+ 48 - 0
quantum/quantum.c

@@ -134,6 +134,9 @@ bool process_record_quantum(keyrecord_t *record) {
   #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
@@ -806,6 +809,51 @@ 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;
+    }
+}
+
+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) {

+ 11 - 0
quantum/quantum.h

@@ -59,6 +59,10 @@ extern uint32_t default_layer_state;
 
 #include "process_tap_dance.h"
 
+#ifdef PRINTING_ENABLE
+	#include "process_printer.h"
+#endif
+
 #define SEND_STRING(str) send_string(PSTR(str))
 void send_string(const char *str);
 
@@ -106,8 +110,15 @@ void breathing_speed_dec(uint8_t value);
 #endif
 
 #endif
+void send_dword(uint32_t number);
+void send_word(uint16_t number);
+void send_byte(uint8_t number);
+void send_nibble(uint8_t number);
+
 
 void led_set_user(uint8_t usb_led);
 void led_set_kb(uint8_t usb_led);
 
+void api_send_unicode(uint32_t unicode);
+
 #endif

+ 86 - 53
quantum/rgblight.c

@@ -69,11 +69,12 @@ const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {100, 50, 20};
 
 rgblight_config_t rgblight_config;
 rgblight_config_t inmem_config;
-struct cRGB led[RGBLED_NUM];
-uint8_t rgblight_inited = 0;
 
+LED_TYPE led[RGBLED_NUM];
+uint8_t rgblight_inited = 0;
+bool rgblight_timer_enabled = false;
 
-void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) {
+void sethsv(uint16_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1) {
   uint8_t r = 0, g = 0, b = 0, base, color;
 
   if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
@@ -124,7 +125,7 @@ void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) {
   setrgb(r, g, b, led1);
 }
 
-void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1) {
+void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) {
   (*led1).r = r;
   (*led1).g = g;
   (*led1).b = b;
@@ -141,9 +142,9 @@ void eeconfig_update_rgblight_default(void) {
   dprintf("eeconfig_update_rgblight_default\n");
   rgblight_config.enable = 1;
   rgblight_config.mode = 1;
-  rgblight_config.hue = 200;
-  rgblight_config.sat = 204;
-  rgblight_config.val = 204;
+  rgblight_config.hue = 0;
+  rgblight_config.sat = 255;
+  rgblight_config.val = 255;
   eeconfig_update_rgblight(rgblight_config.raw);
 }
 void eeconfig_debug_rgblight(void) {
@@ -173,7 +174,7 @@ void rgblight_init(void) {
   }
   eeconfig_debug_rgblight(); // display current eeprom values
 
-  #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
+  #ifdef RGBLIGHT_ANIMATIONS
     rgblight_timer_init(); // setup the timer
   #endif
 
@@ -182,6 +183,19 @@ void rgblight_init(void) {
   }
 }
 
+void rgblight_update_dword(uint32_t dword) {
+  rgblight_config.raw = dword;
+  eeconfig_update_rgblight(rgblight_config.raw);
+  if (rgblight_config.enable)
+    rgblight_mode(rgblight_config.mode);
+  else {
+    #ifdef RGBLIGHT_ANIMATIONS
+      rgblight_timer_disable();
+    #endif
+      rgblight_set();
+  }
+}
+
 void rgblight_increase(void) {
   uint8_t mode = 0;
   if (rgblight_config.mode < RGBLIGHT_MODES) {
@@ -220,7 +234,7 @@ void rgblight_mode(uint8_t mode) {
   eeconfig_update_rgblight(rgblight_config.raw);
   xprintf("rgblight mode: %u\n", rgblight_config.mode);
   if (rgblight_config.mode == 1) {
-    #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
+    #ifdef RGBLIGHT_ANIMATIONS
       rgblight_timer_disable();
     #endif
   } else if (rgblight_config.mode >= 2 && rgblight_config.mode <= 23) {
@@ -230,7 +244,7 @@ void rgblight_mode(uint8_t mode) {
     // MODE 15-20, snake
     // MODE 21-23, knight
 
-    #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
+    #ifdef RGBLIGHT_ANIMATIONS
       rgblight_timer_enable();
     #endif
   }
@@ -244,7 +258,7 @@ void rgblight_toggle(void) {
   if (rgblight_config.enable) {
     rgblight_mode(rgblight_config.mode);
   } else {
-    #if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
+    #ifdef RGBLIGHT_ANIMATIONS
       rgblight_timer_disable();
     #endif
     _delay_ms(50);
@@ -252,6 +266,13 @@ void rgblight_toggle(void) {
   }
 }
 
+void rgblight_enable(void) {
+  rgblight_config.enable = 1;
+  eeconfig_update_rgblight(rgblight_config.raw);
+  xprintf("rgblight enable: rgblight_config.enable = %u\n", rgblight_config.enable);
+  rgblight_mode(rgblight_config.mode);
+}
+
 
 void rgblight_increase_hue(void) {
   uint16_t hue;
@@ -307,7 +328,7 @@ void rgblight_decrease_val(void) {
 void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) {
   inmem_config.raw = rgblight_config.raw;
   if (rgblight_config.enable) {
-    struct cRGB tmp_led;
+    LED_TYPE tmp_led;
     sethsv(hue, sat, val, &tmp_led);
     inmem_config.hue = hue;
     inmem_config.sat = sat;
@@ -351,66 +372,78 @@ void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b) {
 
 void rgblight_set(void) {
   if (rgblight_config.enable) {
-    ws2812_setleds(led, RGBLED_NUM);
+    #ifdef RGBW
+      ws2812_setleds_rgbw(led, RGBLED_NUM);
+    #else
+      ws2812_setleds(led, RGBLED_NUM);
+    #endif
   } else {
     for (uint8_t i = 0; i < RGBLED_NUM; i++) {
       led[i].r = 0;
       led[i].g = 0;
       led[i].b = 0;
     }
-    ws2812_setleds(led, RGBLED_NUM);
+    #ifdef RGBW
+      ws2812_setleds_rgbw(led, RGBLED_NUM);
+    #else
+      ws2812_setleds(led, RGBLED_NUM);
+    #endif
   }
 }
 
-#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
+#ifdef RGBLIGHT_ANIMATIONS
 
 // Animation timer -- AVR Timer3
 void rgblight_timer_init(void) {
-  static uint8_t rgblight_timer_is_init = 0;
-  if (rgblight_timer_is_init) {
-    return;
-  }
-  rgblight_timer_is_init = 1;
-  /* Timer 3 setup */
-  TCCR3B = _BV(WGM32) //CTC mode OCR3A as TOP
-        | _BV(CS30); //Clock selelct: clk/1
-  /* Set TOP value */
-  uint8_t sreg = SREG;
-  cli();
-  OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff;
-  OCR3AL = RGBLED_TIMER_TOP & 0xff;
-  SREG = sreg;
+  // static uint8_t rgblight_timer_is_init = 0;
+  // if (rgblight_timer_is_init) {
+  //   return;
+  // }
+  // rgblight_timer_is_init = 1;
+  // /* Timer 3 setup */
+  // TCCR3B = _BV(WGM32) // CTC mode OCR3A as TOP
+  //       | _BV(CS30); // Clock selelct: clk/1
+  // /* Set TOP value */
+  // uint8_t sreg = SREG;
+  // cli();
+  // OCR3AH = (RGBLED_TIMER_TOP >> 8) & 0xff;
+  // OCR3AL = RGBLED_TIMER_TOP & 0xff;
+  // SREG = sreg;
+
+  rgblight_timer_enabled = true;
 }
 void rgblight_timer_enable(void) {
-  TIMSK3 |= _BV(OCIE3A);
+  rgblight_timer_enabled = true;
   dprintf("TIMER3 enabled.\n");
 }
 void rgblight_timer_disable(void) {
-  TIMSK3 &= ~_BV(OCIE3A);
+  rgblight_timer_enabled = false;
   dprintf("TIMER3 disabled.\n");
 }
 void rgblight_timer_toggle(void) {
-  TIMSK3 ^= _BV(OCIE3A);
+  rgblight_timer_enabled ^= rgblight_timer_enabled;
   dprintf("TIMER3 toggled.\n");
 }
 
-ISR(TIMER3_COMPA_vect) {
-  // mode = 1, static light, do nothing here
-  if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
-    // mode = 2 to 5, breathing mode
-    rgblight_effect_breathing(rgblight_config.mode - 2);
-  } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 8) {
-    // mode = 6 to 8, rainbow mood mod
-    rgblight_effect_rainbow_mood(rgblight_config.mode - 6);
-  } else if (rgblight_config.mode >= 9 && rgblight_config.mode <= 14) {
-    // mode = 9 to 14, rainbow swirl mode
-    rgblight_effect_rainbow_swirl(rgblight_config.mode - 9);
-  } else if (rgblight_config.mode >= 15 && rgblight_config.mode <= 20) {
-    // mode = 15 to 20, snake mode
-    rgblight_effect_snake(rgblight_config.mode - 15);
-  } else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) {
-    // mode = 21 to 23, knight mode
-    rgblight_effect_knight(rgblight_config.mode - 21);
+void rgblight_task(void) {
+  if (rgblight_timer_enabled) {
+    // mode = 1, static light, do nothing here
+    if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
+      // mode = 2 to 5, breathing mode
+      rgblight_effect_breathing(rgblight_config.mode - 2);
+    } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 8) {
+      // mode = 6 to 8, rainbow mood mod
+      rgblight_effect_rainbow_mood(rgblight_config.mode - 6);
+    } else if (rgblight_config.mode >= 9 && rgblight_config.mode <= 14) {
+      // mode = 9 to 14, rainbow swirl mode
+      rgblight_effect_rainbow_swirl(rgblight_config.mode - 9);
+    } else if (rgblight_config.mode >= 15 && rgblight_config.mode <= 20) {
+      // mode = 15 to 20, snake mode
+      rgblight_effect_snake(rgblight_config.mode - 15);
+    } else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) {
+      // mode = 21 to 23, knight mode
+      rgblight_effect_knight(rgblight_config.mode - 21);
+    }
   }
 }
 
@@ -449,7 +482,7 @@ void rgblight_effect_rainbow_swirl(uint8_t interval) {
   last_timer = timer_read();
   for (i = 0; i < RGBLED_NUM; i++) {
     hue = (360 / RGBLED_NUM * i + current_hue) % 360;
-    sethsv(hue, rgblight_config.sat, rgblight_config.val, &led[i]);
+    sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
   }
   rgblight_set();
 
@@ -486,7 +519,7 @@ void rgblight_effect_snake(uint8_t interval) {
         k = k + RGBLED_NUM;
       }
       if (i == k) {
-        sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), &led[i]);
+        sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), (LED_TYPE *)&led[i]);
       }
     }
   }
@@ -506,7 +539,7 @@ void rgblight_effect_knight(uint8_t interval) {
   static uint16_t last_timer = 0;
   uint8_t i, j, cur;
   int8_t k;
-  struct cRGB preled[RGBLED_NUM];
+  LED_TYPE preled[RGBLED_NUM];
   static int8_t increment = -1;
   if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) {
     return;
@@ -525,7 +558,7 @@ void rgblight_effect_knight(uint8_t interval) {
         k = RGBLED_NUM - 1;
       }
       if (i == k) {
-        sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, &preled[i]);
+        sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&preled[i]);
       }
     }
   }

+ 9 - 4
quantum/rgblight.h

@@ -1,8 +1,7 @@
 #ifndef RGBLIGHT_H
 #define RGBLIGHT_H
 
-
-#if !defined(AUDIO_ENABLE) && defined(RGBLIGHT_TIMER)
+#ifdef RGBLIGHT_ANIMATIONS
 	#define RGBLIGHT_MODES 23
 #else
 	#define RGBLIGHT_MODES 1
@@ -34,6 +33,7 @@
 #endif
 
 #define RGBLED_TIMER_TOP F_CPU/(256*64)
+// #define RGBLED_TIMER_TOP 0xFF10
 
 #include <stdint.h>
 #include <stdbool.h>
@@ -61,9 +61,11 @@ void rgblight_init(void);
 void rgblight_increase(void);
 void rgblight_decrease(void);
 void rgblight_toggle(void);
+void rgblight_enable(void);
 void rgblight_step(void);
 void rgblight_mode(uint8_t mode);
 void rgblight_set(void);
+void rgblight_update_dword(uint32_t dword);
 void rgblight_increase_hue(void);
 void rgblight_decrease_hue(void);
 void rgblight_increase_sat(void);
@@ -78,10 +80,13 @@ void eeconfig_update_rgblight(uint32_t val);
 void eeconfig_update_rgblight_default(void);
 void eeconfig_debug_rgblight(void);
 
-void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1);
-void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1);
+void sethsv(uint16_t hue, uint8_t sat, uint8_t val, LED_TYPE *led1);
+void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1);
 void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val);
 
+
+void rgblight_task(void);
+
 void rgblight_timer_init(void);
 void rgblight_timer_enable(void);
 void rgblight_timer_disable(void);

+ 2 - 2
readme.md

@@ -1162,12 +1162,12 @@ For this mod, you need an unused pin wiring to DI of WS2812 strip. After wiring
 
     RGBLIGHT_ENABLE = yes
 
-In order to use the underglow timer functions, you need to have `#define RGBLIGHT_TIMER` in your `config.h`, and have audio disabled (`AUDIO_ENABLE = no` in your Makefile).
+In order to use the underglow animation functions, you need to have `#define RGBLIGHT_ANIMATIONS` in your `config.h`.
 
 Please add the following options into your config.h, and set them up according your hardware configuration. These settings are for the `F4` pin by default:
 
     #define RGB_DI_PIN F4     // The pin your RGB strip is wired to
-    #define RGBLIGHT_TIMER    // Require for fancier stuff (not compatible with audio)
+    #define RGBLIGHT_ANIMATIONS    // Require for fancier stuff (not compatible with audio)
     #define RGBLED_NUM 14     // Number of LEDs
     #define RGBLIGHT_HUE_STEP 10
     #define RGBLIGHT_SAT_STEP 17

+ 8 - 1
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

+ 50 - 13
tmk_core/protocol/lufa/lufa.c

@@ -51,6 +51,7 @@
 
 #include "descriptor.h"
 #include "lufa.h"
+#include "quantum.h"
 
 #ifdef NKRO_ENABLE
   #include "keycode_config.h"
@@ -71,6 +72,14 @@
     #include "virtser.h"
 #endif
 
+#if (defined(RGB_MIDI) | defined(RGBLIGHT_ANIMATIONS)) & defined(RGBLIGHT_ENABLE)
+    #include "rgblight.h"        
+#endif
+
+#ifdef MIDI_ENABLE
+  #include "sysex_tools.h"
+#endif
+
 uint8_t keyboard_idle = 0;
 /* 0: Boot Protocol, 1: Report Protocol(default) */
 uint8_t keyboard_protocol = 1;
@@ -79,9 +88,9 @@ static uint8_t keyboard_led_stats = 0;
 static report_keyboard_t keyboard_report_sent;
 
 #ifdef MIDI_ENABLE
-void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
-void usb_get_midi(MidiDevice * device);
-void midi_usb_init(MidiDevice * device);
+static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
+static void usb_get_midi(MidiDevice * device);
+static void midi_usb_init(MidiDevice * device);
 #endif
 
 /* Host driver */
@@ -709,7 +718,7 @@ int8_t sendchar(uint8_t c)
  ******************************************************************************/
 
 #ifdef MIDI_ENABLE
-void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
+static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
   MIDI_EventPacket_t event;
   event.Data1 = byte0;
   event.Data2 = byte1;
@@ -769,7 +778,7 @@ void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byt
   USB_USBTask();
 }
 
-void usb_get_midi(MidiDevice * device) {
+static void usb_get_midi(MidiDevice * device) {
   MIDI_EventPacket_t event;
   while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) {
 
@@ -799,12 +808,12 @@ void usb_get_midi(MidiDevice * device) {
   USB_USBTask();
 }
 
-void midi_usb_init(MidiDevice * device){
+static void midi_usb_init(MidiDevice * device){
   midi_device_init(device);
   midi_device_set_send_func(device, usb_send_func);
   midi_device_set_pre_input_process_func(device, usb_get_midi);
 
-  SetupHardware();
+  // SetupHardware();
   sei();
 }
 
@@ -1039,11 +1048,16 @@ int main(void)
         }
         #endif
 
+        keyboard_task();
+
 #ifdef MIDI_ENABLE
         midi_device_process(&midi_device);
         // MIDI_Task();
 #endif
-        keyboard_task();
+        
+#if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE)
+        rgblight_task();
+#endif
 
 #ifdef VIRTSER_ENABLE
         virtser_task();
@@ -1077,15 +1091,38 @@ void fallthrough_callback(MidiDevice * device,
 #endif
 }
 
+
 void cc_callback(MidiDevice * device,
     uint8_t chan, uint8_t num, uint8_t val) {
   //sending it back on the next channel
-  midi_send_cc(device, (chan + 1) % 16, num, val);
+  // midi_send_cc(device, (chan + 1) % 16, num, val);
 }
 
-void sysex_callback(MidiDevice * device,
-    uint16_t start, uint8_t length, uint8_t * data) {
-  for (int i = 0; i < length; i++)
-    midi_send_cc(device, 15, 0x7F & data[i], 0x7F & (start + i));
+uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0};
+
+void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) {
+    #ifdef API_SYSEX_ENABLE
+        // SEND_STRING("\n");
+        // send_word(start);
+        // SEND_STRING(": ");
+        for (uint8_t place = 0; place < length; place++) {
+            // send_byte(*data);
+            midi_buffer[start + place] = *data;
+            if (*data == 0xF7) {
+                // SEND_STRING("\nRD: ");
+                // for (uint8_t i = 0; i < start + place + 1; i++){
+                //     send_byte(midi_buffer[i]);
+                // SEND_STRING(" ");
+                // }
+                uint8_t * decoded = malloc(sizeof(uint8_t) * (sysex_decoded_length(start + place - 4)));
+                uint16_t decode_length = sysex_decode(decoded, midi_buffer + 4, start + place - 4);
+                process_api(decode_length, decoded);
+            }
+            // SEND_STRING(" ");
+            data++;
+        }
+    #endif
 }
+
+
 #endif

+ 11 - 2
tmk_core/protocol/lufa/lufa.h

@@ -68,8 +68,17 @@ typedef struct {
 } __attribute__ ((packed)) report_extra_t;
 
 #ifdef MIDI_ENABLE
-void MIDI_Task(void);
-MidiDevice midi_device;
+  void MIDI_Task(void);
+  MidiDevice midi_device;
+  #define MIDI_SYSEX_BUFFER 32 
+#endif
+
+#ifdef API_ENABLE
+  #include "api.h"
+#endif
+
+#ifdef API_SYSEX_ENABLE
+  #include "api_sysex.h"
 #endif
 
 // #if LUFA_VERSION_INTEGER < 0x120730

+ 1 - 0
tmk_core/protocol/midi.mk

@@ -4,6 +4,7 @@ SRC += midi.c \
 	   midi_device.c \
 	   bytequeue/bytequeue.c \
 	   bytequeue/interrupt_setting.c \
+	   sysex_tools.c \
 	   $(LUFA_SRC_USBCLASS)
 
 VPATH += $(TMK_PATH)/$(MIDI_DIR)