]> git.donarmstrong.com Git - qmk_firmware.git/blobdiff - quantum/quantum.c
rgblight.[ch] more configurable (#3582)
[qmk_firmware.git] / quantum / quantum.c
index 5a2a73d4a2bf4961cd9fb861046f64dbc37def13..9d352a94cf253f43a5d95548f25f87221df2028b 100644 (file)
@@ -147,8 +147,10 @@ void reset_keyboard(void) {
 #if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
   process_midi_all_notes_off();
 #endif
-#if defined(AUDIO_ENABLE) && !defined(NO_MUSIC_MODE)
-  music_all_notes_off();
+#ifdef AUDIO_ENABLE
+  #ifndef NO_MUSIC_MODE
+    music_all_notes_off();
+  #endif
   uint16_t timer_start = timer_read();
   PLAY_SONG(goodbye_song);
   shutdown_user();
@@ -156,6 +158,7 @@ void reset_keyboard(void) {
     wait_ms(1);
   stop_all_notes();
 #else
+  shutdown_user();
   wait_ms(250);
 #endif
 // this is also done later in bootloader.c - not sure if it's neccesary here
@@ -230,6 +233,9 @@ bool process_record_quantum(keyrecord_t *record) {
       process_clicky(keycode, record) &&
   #endif //AUDIO_CLICKY
     process_record_kb(keycode, record) &&
+  #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_KEYPRESSES)
+    process_rgb_matrix(keycode, record) &&
+  #endif
   #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)
     process_midi(keycode, record) &&
   #endif
@@ -307,10 +313,18 @@ bool process_record_quantum(keyrecord_t *record) {
     }
     return false;
   #endif
-  #ifdef RGBLIGHT_ENABLE
+  #if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
   case RGB_TOG:
+    // Split keyboards need to trigger on key-up for edge-case issue
+    #ifndef SPLIT_KEYBOARD
     if (record->event.pressed) {
+    #else
+    if (!record->event.pressed) {
+    #endif
       rgblight_toggle();
+      #ifdef SPLIT_KEYBOARD
+          RGB_DIRTY = true;
+      #endif
     }
     return false;
   case RGB_MODE_FORWARD:
@@ -322,6 +336,9 @@ bool process_record_quantum(keyrecord_t *record) {
       else {
         rgblight_step();
       }
+      #ifdef SPLIT_KEYBOARD
+          RGB_DIRTY = true;
+      #endif
     }
     return false;
   case RGB_MODE_REVERSE:
@@ -333,103 +350,194 @@ bool process_record_quantum(keyrecord_t *record) {
       else {
         rgblight_step_reverse();
       }
+      #ifdef SPLIT_KEYBOARD
+          RGB_DIRTY = true;
+      #endif
     }
     return false;
   case RGB_HUI:
+    // Split keyboards need to trigger on key-up for edge-case issue
+    #ifndef SPLIT_KEYBOARD
     if (record->event.pressed) {
+    #else
+    if (!record->event.pressed) {
+    #endif
       rgblight_increase_hue();
+      #ifdef SPLIT_KEYBOARD
+          RGB_DIRTY = true;
+      #endif
     }
     return false;
   case RGB_HUD:
+    // Split keyboards need to trigger on key-up for edge-case issue
+    #ifndef SPLIT_KEYBOARD
     if (record->event.pressed) {
+    #else
+    if (!record->event.pressed) {
+    #endif
       rgblight_decrease_hue();
+      #ifdef SPLIT_KEYBOARD
+          RGB_DIRTY = true;
+      #endif
     }
     return false;
   case RGB_SAI:
+    // Split keyboards need to trigger on key-up for edge-case issue
+    #ifndef SPLIT_KEYBOARD
     if (record->event.pressed) {
+    #else
+    if (!record->event.pressed) {
+    #endif
       rgblight_increase_sat();
+      #ifdef SPLIT_KEYBOARD
+          RGB_DIRTY = true;
+      #endif
     }
     return false;
   case RGB_SAD:
+    // Split keyboards need to trigger on key-up for edge-case issue
+    #ifndef SPLIT_KEYBOARD
     if (record->event.pressed) {
+    #else
+    if (!record->event.pressed) {
+    #endif
       rgblight_decrease_sat();
+      #ifdef SPLIT_KEYBOARD
+          RGB_DIRTY = true;
+      #endif
     }
     return false;
   case RGB_VAI:
+    // Split keyboards need to trigger on key-up for edge-case issue
+    #ifndef SPLIT_KEYBOARD
     if (record->event.pressed) {
+    #else
+    if (!record->event.pressed) {
+    #endif
       rgblight_increase_val();
+      #ifdef SPLIT_KEYBOARD
+          RGB_DIRTY = true;
+      #endif
     }
     return false;
   case RGB_VAD:
+    // Split keyboards need to trigger on key-up for edge-case issue
+    #ifndef SPLIT_KEYBOARD
     if (record->event.pressed) {
+    #else
+    if (!record->event.pressed) {
+    #endif
       rgblight_decrease_val();
+      #ifdef SPLIT_KEYBOARD
+          RGB_DIRTY = true;
+      #endif
+    }
+    return false;
+  case RGB_SPI:
+    if (record->event.pressed) {
+      rgblight_increase_speed();
+    }
+    return false;
+  case RGB_SPD:
+    if (record->event.pressed) {
+      rgblight_decrease_speed();
     }
     return false;
   case RGB_MODE_PLAIN:
     if (record->event.pressed) {
-      rgblight_mode(1);
+      rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
+      #ifdef SPLIT_KEYBOARD
+          RGB_DIRTY = true;
+      #endif
     }
     return false;
   case RGB_MODE_BREATHE:
+  #ifdef RGBLIGHT_EFFECT_BREATHING
     if (record->event.pressed) {
-      if ((2 <= rgblight_get_mode()) && (rgblight_get_mode() < 5)) {
+      if ((RGBLIGHT_MODE_BREATHING <= rgblight_get_mode()) &&
+          (rgblight_get_mode() < RGBLIGHT_MODE_BREATHING_end)) {
         rgblight_step();
       } else {
-        rgblight_mode(2);
+        rgblight_mode(RGBLIGHT_MODE_BREATHING);
       }
     }
+  #endif
     return false;
   case RGB_MODE_RAINBOW:
+  #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
     if (record->event.pressed) {
-      if ((6 <= rgblight_get_mode()) && (rgblight_get_mode() < 8)) {
+      if ((RGBLIGHT_MODE_RAINBOW_MOOD <= rgblight_get_mode()) &&
+          (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_MOOD_end)) {
         rgblight_step();
       } else {
-        rgblight_mode(6);
+        rgblight_mode(RGBLIGHT_MODE_RAINBOW_MOOD);
       }
     }
+  #endif
     return false;
   case RGB_MODE_SWIRL:
+  #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
     if (record->event.pressed) {
-      if ((9 <= rgblight_get_mode()) && (rgblight_get_mode() < 14)) {
+      if ((RGBLIGHT_MODE_RAINBOW_SWIRL <= rgblight_get_mode()) &&
+          (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_SWIRL_end)) {
         rgblight_step();
       } else {
-        rgblight_mode(9);
+        rgblight_mode(RGBLIGHT_MODE_RAINBOW_SWIRL);
       }
     }
+  #endif
     return false;
   case RGB_MODE_SNAKE:
+  #ifdef RGBLIGHT_EFFECT_SNAKE
     if (record->event.pressed) {
-      if ((15 <= rgblight_get_mode()) && (rgblight_get_mode() < 20)) {
+      if ((RGBLIGHT_MODE_SNAKE <= rgblight_get_mode()) &&
+          (rgblight_get_mode() < RGBLIGHT_MODE_SNAKE_end)) {
         rgblight_step();
       } else {
-        rgblight_mode(15);
+        rgblight_mode(RGBLIGHT_MODE_SNAKE);
       }
     }
+  #endif
     return false;
   case RGB_MODE_KNIGHT:
+  #ifdef RGBLIGHT_EFFECT_KNIGHT
     if (record->event.pressed) {
-      if ((21 <= rgblight_get_mode()) && (rgblight_get_mode() < 23)) {
+      if ((RGBLIGHT_MODE_KNIGHT <= rgblight_get_mode()) &&
+          (rgblight_get_mode() < RGBLIGHT_MODE_KNIGHT_end)) {
         rgblight_step();
       } else {
-        rgblight_mode(21);
+        rgblight_mode(RGBLIGHT_MODE_KNIGHT);
       }
     }
+  #endif
     return false;
   case RGB_MODE_XMAS:
+  #ifdef RGBLIGHT_EFFECT_CHRISTMAS
     if (record->event.pressed) {
-      rgblight_mode(24);
+      rgblight_mode(RGBLIGHT_MODE_CHRISTMAS);
     }
+  #endif
     return false;
   case RGB_MODE_GRADIENT:
+  #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
     if (record->event.pressed) {
-      if ((25 <= rgblight_get_mode()) && (rgblight_get_mode() < 34)) {
+      if ((RGBLIGHT_MODE_STATIC_GRADIENT <= rgblight_get_mode()) &&
+          (rgblight_get_mode() < RGBLIGHT_MODE_STATIC_GRADIENT_end)) {
         rgblight_step();
       } else {
-        rgblight_mode(25);
+        rgblight_mode(RGBLIGHT_MODE_STATIC_GRADIENT);
       }
     }
+  #endif
     return false;
+  case RGB_MODE_RGBTEST:
+  #ifdef RGBLIGHT_EFFECT_RGB_TEST
+    if (record->event.pressed) {
+      rgblight_mode(RGBLIGHT_MODE_RGB_TEST);
+    }
   #endif
+    return false;
+  #endif // defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
     #ifdef PROTOCOL_LUFA
     case OUT_AUTO:
       if (record->event.pressed) {
@@ -780,12 +888,14 @@ void set_single_persistent_default_layer(uint8_t default_layer) {
   default_layer_set(1U<<default_layer);
 }
 
+uint32_t update_tri_layer_state(uint32_t state, uint8_t layer1, uint8_t layer2, uint8_t layer3) {
+  uint32_t mask12 = (1UL << layer1) | (1UL << layer2);
+  uint32_t mask3 = 1UL << layer3;
+  return (state & mask12) == mask12 ? (state | mask3) : (state & ~mask3);
+}
+
 void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
-  if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
-    layer_on(layer3);
-  } else {
-    layer_off(layer3);
-  }
+  layer_state_set(update_tri_layer_state(layer_state, layer1, layer2, layer3));
 }
 
 void tap_random_base64(void) {
@@ -833,11 +943,20 @@ void matrix_init_quantum() {
   #ifdef AUDIO_ENABLE
     audio_init();
   #endif
+  #ifdef RGB_MATRIX_ENABLE
+    rgb_matrix_init();
+  #endif
   matrix_init_kb();
 }
 
+uint8_t rgb_matrix_task_counter = 0;
+
+#ifndef RGB_MATRIX_SKIP_FRAMES
+  #define RGB_MATRIX_SKIP_FRAMES 1
+#endif
+
 void matrix_scan_quantum() {
-  #if defined(AUDIO_ENABLE)
+  #if defined(AUDIO_ENABLE) && !defined(NO_MUSIC_MODE)
     matrix_scan_music();
   #endif
 
@@ -853,23 +972,45 @@ void matrix_scan_quantum() {
     backlight_task();
   #endif
 
+  #ifdef RGB_MATRIX_ENABLE
+    rgb_matrix_task();
+    if (rgb_matrix_task_counter == 0) {
+      rgb_matrix_update_pwm_buffers();
+    }
+    rgb_matrix_task_counter = ((rgb_matrix_task_counter + 1) % (RGB_MATRIX_SKIP_FRAMES + 1));
+  #endif
+
   matrix_scan_kb();
 }
-
 #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
 
 static const uint8_t backlight_pin = BACKLIGHT_PIN;
 
 // depending on the pin, we use a different output compare unit
 #if BACKLIGHT_PIN == B7
-#  define COM1x1 COM1C1
-#  define OCR1x  OCR1C
+#  define TCCRxA TCCR1A
+#  define TCCRxB TCCR1B
+#  define COMxx1 COM1C1
+#  define OCRxx  OCR1C
+#  define ICRx   ICR1
 #elif BACKLIGHT_PIN == B6
-#  define COM1x1 COM1B1
-#  define OCR1x  OCR1B
+#  define TCCRxA TCCR1A
+#  define TCCRxB TCCR1B
+#  define COMxx1 COM1B1
+#  define OCRxx  OCR1B
+#  define ICRx   ICR1
 #elif BACKLIGHT_PIN == B5
-#  define COM1x1 COM1A1
-#  define OCR1x  OCR1A
+#  define TCCRxA TCCR1A
+#  define TCCRxB TCCR1B
+#  define COMxx1 COM1A1
+#  define OCRxx  OCR1A
+#  define ICRx   ICR1
+#elif BACKLIGHT_PIN == C6
+#  define TCCRxA TCCR3A
+#  define TCCRxB TCCR3B
+#  define COMxx1 COM1A1
+#  define OCRxx  OCR3A
+#  define ICRx   ICR3
 #else
 #  define NO_HARDWARE_PWM
 #endif
@@ -951,7 +1092,7 @@ static uint16_t cie_lightness(uint16_t v) {
 
 // range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val.
 static inline void set_pwm(uint16_t val) {
-  OCR1x = val;
+       OCRxx = val;
 }
 
 #ifndef BACKLIGHT_CUSTOM_DRIVER
@@ -962,10 +1103,10 @@ void backlight_set(uint8_t level) {
 
   if (level == 0) {
     // Turn off PWM control on backlight pin
-    TCCR1A &= ~(_BV(COM1x1));
+    TCCRxA &= ~(_BV(COMxx1));
   } else {
     // Turn on PWM control of backlight pin
-    TCCR1A |= _BV(COM1x1);
+    TCCRxA |= _BV(COMxx1);
   }
   // Set the brightness
   set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS));
@@ -1113,11 +1254,10 @@ void backlight_init_ports(void)
   "In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]."
   "In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)."
   */
-
-  TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
-  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
+  TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010;
+  TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
   // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0.
-  ICR1 = TIMER_TOP;
+  ICRx = TIMER_TOP;
 
   backlight_init();
   #ifdef BACKLIGHT_BREATHING
@@ -1137,6 +1277,10 @@ void backlight_set(uint8_t level) {}
 
 #endif // backlight
 
+#ifdef HD44780_ENABLED
+#include "hd44780.h"
+#endif
+
 
 // Functions for spitting out values
 //