Ver código fonte

backlight breathing overhaul (#2187)

* add breathing to bananasplit

* backlight breathing overhaul

* fix the backlight_tick thing.

* fix for vision_division backlight

* fix a few keymaps and probably break breathing for some weirdly set-up boards.

* remove BL_x keycodes because they made unreasonable assumptions

* some fixes for BL keycodes

* integer cie lightness scaling

* use cie lightness for non-breathing backlight and make breathing able to reach true max brightness
Balz Guenat 8 anos atrás
pai
commit
4931510ad3

+ 4 - 0
docs/config_options.md

@@ -70,6 +70,10 @@ This is a C header file that is one of the first things included, and will persi
   * pin of the backlight - B5, B6, B7 use PWM, others use softPWM
 * `#define BACKLIGHT_LEVELS 3`
   * number of levels your backlight will have (not including off)
+* `#define BACKLIGHT_BREATHING`
+  * enables backlight breathing (only works with backlight pins B5, B6 and B7)
+* `#define BREATHING_PERIOD 6`
+  * the length of one backlight "breath" in seconds
 * `#define DEBOUNCING_DELAY 5`
   * the delay when reading the value of the pin (5 is default)
 * `#define LOCKING_SUPPORT_ENABLE`

+ 1 - 1
docs/faq_keymap.md

@@ -127,7 +127,7 @@ https://github.com/tekezo/Karabiner/issues/403
 
 ## Esc and <code>&#96;</code> on a Single Key
 
-See the [Grave Escape](feature_grave_escape.md) feature.
+See the [Grave Escape](feature_grave_esc.md) feature.
 
 ## Arrow on Right Modifier Keys with Dual-Role
 This turns right modifier keys into arrow keys when the keys are tapped while still modifiers when the keys are hold. In TMK the dual-role function is dubbed **TAP**.

+ 25 - 3
docs/feature_backlight.md

@@ -10,8 +10,30 @@ These keycodes control the backlight. Most keyboards use this for single color i
 |---------|------------------------------------------|
 |`BL_TOGG`|Turn the backlight on or off              |
 |`BL_STEP`|Cycle through backlight levels            |
-|`BL_x`   |Set a specific backlight level between 0-9|
-|`BL_ON`  |An alias for `BL_9`                       |
-|`BL_OFF` |An alias for `BL_0`                       |
+|`BL_ON`  |Set backlight to max brightness           |
+|`BL_OFF` |Turn backlight off                        |
 |`BL_INC` |Increase backlight level                  |
 |`BL_DEC` |Decrease backlight level                  |
+|`BL_BRTG`|Toggle backlight breathing				 |
+
+Note that for backlight breathing, you need to have `#define BACKLIGHT_BREATHING` in your config.h.
+
+## Configuration Options in `config.h`
+
+* `BACKLIGHT_PIN B7` defines the pin that controlls the LEDs. Unless you design your own keyboard, you don't need to set this.
+* `BACKLIGHT_LEVELS 3` defines the number of brightness levels (excluding OFF).
+* `BACKLIGHT_BREATHING` if defined, enables backlight breathing. Note that this is only available if `BACKLIGHT_PIN` is B5, B6 or B7.
+* `BREATHING_PERIOD 6` defines the length of one backlight "breath" in seconds.
+
+## Notes on Implementation
+
+To change the brightness when using pins B5, B6 or B7, the PWM (Pulse Width Modulation) functionality of the on-chip timer is used.
+The timer is a counter that counts up to a certain TOP value (`0xFFFF` set in ICR1) before resetting to 0.
+We also set an OCR1x register.
+When the counter reaches the value stored in that register, the PWM pin drops to low.
+The PWM pin is pulled high again when the counter resets to 0.
+Therefore, OCR1x basically sets the duty cycle of the LEDs and as such the brightness where `0` is the darkest and `0xFFFF` the brightest setting.
+
+To enable the breathing effect, we register an interrupt handler to be called whenever the counter resets (with `ISR(TIMER1_OVF_vect)`).
+In this handler, which gets called roughly 244 times per second, we compute the desired brightness using a precomputed brightness curve.
+To disable breathing, we can just disable the respective interrupt vector and reset the brightness to the desired level.

+ 2 - 1
docs/hardware_avr.md

@@ -101,8 +101,9 @@ By default QMK supports backlighting on pins `B5`, `B6`, and `B7`. If you are us
 
 ```
 #define BACKLIGHT_PIN B7
-#define BACKLIGHT_BREATHING
 #define BACKLIGHT_LEVELS 3
+#define BACKLIGHT_BREATHING
+#define BREATHING_PERIOD 6
 ```
 
 {% hint style='info' %}

+ 6 - 6
keyboards/atomic/keymaps/pvc/keymap.c

@@ -345,14 +345,14 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
         case MACRO_BREATH_SPEED_INC:
             if (record->event.pressed)
             {
-                breathing_speed_inc(1);
+                breathing_period_inc();
             }
             break;
 
         case MACRO_BREATH_SPEED_DEC:
             if (record->event.pressed)
             {
-                breathing_speed_dec(1);
+                breathing_period_dec();
             }
             break;
 
@@ -374,7 +374,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
             if (record->event.pressed)
             {
                 layer_on(LAYER_UPPER);
-                breathing_speed_set(2);
+                breathing_period_set(2);
                 breathing_pulse();
                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
             }
@@ -389,7 +389,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
             if (record->event.pressed)
             {
                 layer_on(LAYER_LOWER);
-                breathing_speed_set(2);
+                breathing_period_set(2);
                 breathing_pulse();
                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
             }
@@ -403,13 +403,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
         case MACRO_FUNCTION:
             if (record->event.pressed)
             {
-                breathing_speed_set(3);
+                breathing_period_set(3);
                 breathing_enable();
                 layer_on(LAYER_FUNCTION);
             }
             else
             {
-                breathing_speed_set(1);
+                breathing_period_set(1);
                 breathing_self_disable();
                 layer_off(LAYER_FUNCTION);
             }

+ 1 - 1
keyboards/bananasplit/config.h

@@ -42,7 +42,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 //#define MATRIX_HAS_GHOST
 
 /* number of backlight levels */
-#define BACKLIGHT_LEVELS  1
+#define BACKLIGHT_LEVELS 3
 
 /* mapping backlight LEDs to correct Pin */
 #define BACKLIGHT_PIN B7

+ 2 - 0
keyboards/bananasplit/keymaps/coloneljesus/config.h

@@ -21,5 +21,7 @@
 
 // place overrides here
 #define GRAVE_ESC_CTRL_OVERRIDE
+#define BACKLIGHT_BREATHING
+#define BREATHING_PERIOD 8
 
 #endif

+ 8 - 8
keyboards/bananasplit/keymaps/coloneljesus/keymap.c

@@ -16,7 +16,7 @@
 #include "bananasplit.h"
 
 enum custom_keycodes {
-  WIN_SWITCH_LAYOUT = SAFE_RANGE
+  WIN_SWITCH_LAYOUT = SAFE_RANGE,
 };
 
 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
@@ -57,7 +57,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
     _______, KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,  KC_F6,   KC_F7,         KC_F8,         KC_F9,   KC_F10,  KC_F11,  KC_F12,  _______, \
     KC_CAPS, KC_MPRV, KC_VOLU, KC_MNXT, KC_PGUP, KC_INS, KC_HOME, LCTL(KC_LEFT), LCTL(KC_RGHT), KC_END,  _______, _______, _______, KC_PSCR, \
     _______, KC_MUTE, KC_VOLD, KC_MPLY, KC_PGDN, KC_DEL, KC_LEFT, KC_DOWN,       KC_UP,         KC_RGHT, _______, _______, _______, \
-    _______,          _______, _______, _______, _______,_______, LCTL(KC_BSPC), LCTL(KC_DEL),  _______, _______, _______, _______, _______, \
+    _______,          BL_STEP, BL_BRTG, _______, _______,_______, LCTL(KC_BSPC), LCTL(KC_DEL),  _______, _______, _______, _______, _______, \
     _______, _______, _______,          _______, _______,_______,                _______,       _______, _______, _______, RESET \
 ),
 };
@@ -76,19 +76,19 @@ void matrix_scan_user(void) {
 
 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
   switch (keycode) {
+
     case WIN_SWITCH_LAYOUT: {
       // Sends Alt+Shift on both key down and key up. 
       // Designed to switch between two keyboard layouts on Windows using a locking switch.
       // Does nothing if right shift is pressed for easy resync.
-      if (!(get_mods() & MOD_BIT(KC_RSFT))) {
+      if (!(get_mods() & MOD_BIT(KC_RSFT)))
         SEND_STRING(SS_DOWN(X_LALT)SS_TAP(X_LSHIFT)SS_UP(X_LALT));
-        return false;
-      }
-      else
-        return false;
+      return false;
     }
+
+    default:
+      return true;
   }
-  return true;
 }
 
 void led_set_user(uint8_t usb_led) {

+ 4 - 4
keyboards/jd45/keymaps/mjt/keymap.c

@@ -50,13 +50,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
             // action_function_tap may also handle this...
             if (record->event.pressed)
             {
-                breathing_speed_set(3);
+                breathing_period_set(3);
                 breathing_enable();
                 layer_on(1);
             }
             else
             {
-                breathing_speed_set(1);
+                breathing_period_set(1);
                 breathing_self_disable();
                 layer_off(1);
             }
@@ -64,13 +64,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
         case M_LAYER2:
             if (record->event.pressed)
             {
-                breathing_speed_set(2);
+                breathing_period_set(2);
                 breathing_pulse();
                 layer_on(2);
             }
             else
             {
-                breathing_speed_set(1);
+                breathing_period_set(1);
                 breathing_self_disable();
                 layer_off(2);
             }

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

@@ -220,7 +220,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
       {
 	layer_on(_RAISE);
 #ifdef BACKLIGHT_ENABLE
-	breathing_speed_set(2);
+	breathing_period_set(2);
 	breathing_pulse();
 #endif
 	update_tri_layer(_LOWER, _RAISE, _ADJUST);
@@ -236,7 +236,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
       {
 	layer_on(_LOWER);
 #ifdef BACKLIGHT_ENABLE
-	breathing_speed_set(2);
+	breathing_period_set(2);
 	breathing_pulse();
 #endif
 	update_tri_layer(_LOWER, _RAISE, _ADJUST);

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

@@ -242,7 +242,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
           if (record->event.pressed) {
             layer_on(_LOWER);
             #ifdef BACKLIGHT_ENABLE
-                breathing_speed_set(2);
+                breathing_period_set(2);
                 breathing_pulse();
             #endif
             update_tri_layer(_LOWER, _RAISE, _ADJUST);
@@ -256,7 +256,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
           if (record->event.pressed) {
             layer_on(_RAISE);
             #ifdef BACKLIGHT_ENABLE
-                breathing_speed_set(2);
+                breathing_period_set(2);
                 breathing_pulse();
             #endif
             update_tri_layer(_LOWER, _RAISE, _ADJUST);

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

@@ -128,12 +128,12 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
       break;
     case MACRO_BREATH_SPEED_INC:
       if (record->event.pressed) {
-        breathing_speed_inc(1);
+        breathing_period_inc();
       }
       break;
     case MACRO_BREATH_SPEED_DEC:
       if (record->event.pressed) {
-        breathing_speed_dec(1);
+        breathing_period_dec();
       }
       break;
     case MACRO_BREATH_DEFAULT:

+ 6 - 6
keyboards/planck/keymaps/pvc/keymap.c

@@ -323,14 +323,14 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
         case MACRO_BREATH_SPEED_INC:
             if (record->event.pressed)
             {
-                breathing_speed_inc(1);
+                breathing_period_inc();
             }
             break;
 
         case MACRO_BREATH_SPEED_DEC:
             if (record->event.pressed)
             {
-                breathing_speed_dec(1);
+                breathing_period_dec();
             }
             break;
 
@@ -352,7 +352,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
             if (record->event.pressed)
             {
                 layer_on(LAYER_UPPER);
-                breathing_speed_set(2);
+                breathing_period_set(2);
                 breathing_pulse();
                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
             }
@@ -367,7 +367,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
             if (record->event.pressed)
             {
                 layer_on(LAYER_LOWER);
-                breathing_speed_set(2);
+                breathing_period_set(2);
                 breathing_pulse();
                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
             }
@@ -381,13 +381,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
         case MACRO_FUNCTION:
             if (record->event.pressed)
             {
-                breathing_speed_set(3);
+                breathing_period_set(3);
                 breathing_enable();
                 layer_on(LAYER_FUNCTION);
             }
             else
             {
-                breathing_speed_set(1);
+                breathing_period_set(1);
                 breathing_self_disable();
                 layer_off(LAYER_FUNCTION);
             }

+ 1 - 1
keyboards/planck/keymaps/zach/zach_common_functions.c

@@ -270,7 +270,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
                     PLAY_SONG(tone_ctrl_mod);
                 #endif
                 #ifdef BACKLIGHT_BREATHING
-                    breathing_speed_set(2);
+                    breathing_period_set(2);
                     breathing_pulse();
                 #endif
             }

+ 6 - 6
keyboards/planck/keymaps/zrichard/keymap.c

@@ -332,14 +332,14 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
         case MACRO_BREATH_SPEED_INC:
             if (record->event.pressed)
             {
-                breathing_speed_inc(1);
+                breathing_period_inc();
             }
             break;
 
         case MACRO_BREATH_SPEED_DEC:
             if (record->event.pressed)
             {
-                breathing_speed_dec(1);
+                breathing_period_dec();
             }
             break;
 
@@ -361,7 +361,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
             if (record->event.pressed)
             {
                 layer_on(LAYER_UPPER);
-                breathing_speed_set(2);
+                breathing_period_set(2);
                 breathing_pulse();
                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
             }
@@ -376,7 +376,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
             if (record->event.pressed)
             {
                 layer_on(LAYER_LOWER);
-                breathing_speed_set(2);
+                breathing_period_set(2);
                 breathing_pulse();
                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
             }
@@ -390,13 +390,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
         case MACRO_FUNCTION:
             if (record->event.pressed)
             {
-                breathing_speed_set(3);
+                breathing_period_set(3);
                 breathing_enable();
                 layer_on(LAYER_FUNCTION);
             }
             else
             {
-                breathing_speed_set(1);
+                breathing_period_set(1);
                 breathing_self_disable();
                 layer_off(LAYER_FUNCTION);
             }

+ 1 - 1
keyboards/preonic/keymaps/zach/zach_common_functions.c

@@ -270,7 +270,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
                     PLAY_SONG(tone_ctrl_mod);
                 #endif
                 #ifdef BACKLIGHT_BREATHING
-                    breathing_speed_set(2);
+                    breathing_period_set(2);
                     breathing_pulse();
                 #endif
             }

+ 7 - 7
keyboards/vision_division/keymaps/default/keymap.c

@@ -406,21 +406,21 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
   case MACRO_BREATH_SPEED_INC:
     if (record->event.pressed)
     {
-      breathing_speed_inc(1);
+      breathing_period_inc();
     }
     break;
 
   case MACRO_BREATH_SPEED_DEC:
     if (record->event.pressed)
     {
-      breathing_speed_dec(1);
+      breathing_period_dec();
     }
     break;
 
   case MACRO_BREATH_DEFAULT:
     if (record->event.pressed)
     {
-      breathing_defaults();
+      breathing_period_default();
     }
     break;
 
@@ -435,7 +435,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
     if (record->event.pressed)
     {
       layer_on(LAYER_UPPER);
-      breathing_speed_set(2);
+      breathing_period_set(2);
       breathing_pulse();
       update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
     }
@@ -450,7 +450,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
     if (record->event.pressed)
     {
       layer_on(LAYER_LOWER);
-      breathing_speed_set(2);
+      breathing_period_set(2);
       breathing_pulse();
       update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
     }
@@ -464,13 +464,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
   case MACRO_FUNCTION:
     if (record->event.pressed)
     {
-      breathing_speed_set(3);
+      breathing_period_set(3);
       breathing_enable();
       layer_on(LAYER_FUNCTION);
     }
     else
     {
-      breathing_speed_set(1);
+      breathing_period_set(1);
       breathing_self_disable();
       layer_off(LAYER_FUNCTION);
     }

+ 2 - 2
keyboards/xd75/keymaps/cbbrowne/keymap.c

@@ -265,7 +265,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
       {
 	layer_on(_RAISE);
 #ifdef BACKLIGHT_ENABLE
-	breathing_speed_set(2);
+	breathing_period_set(2);
 	breathing_pulse();
 #endif
 	update_tri_layer(_LOWER, _RAISE, _ADJUST);
@@ -281,7 +281,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
       {
 	layer_on(_LOWER);
 #ifdef BACKLIGHT_ENABLE
-	breathing_speed_set(2);
+	breathing_period_set(2);
 	breathing_pulse();
 #endif
 	update_tri_layer(_LOWER, _RAISE, _ADJUST);

+ 5 - 2
quantum/keymap_common.c

@@ -127,8 +127,11 @@ action_t action_for_key(uint8_t layer, keypos_t key)
             action.code = ACTION_MODS_TAP_KEY(mod, keycode & 0xFF);
             break;
     #ifdef BACKLIGHT_ENABLE
-        case BL_0 ... BL_15:
-            action.code = ACTION_BACKLIGHT_LEVEL(keycode - BL_0);
+        case BL_ON:
+            action.code = ACTION_BACKLIGHT_ON();
+            break;
+        case BL_OFF:
+            action.code = ACTION_BACKLIGHT_OFF();
             break;
         case BL_DEC:
             action.code = ACTION_BACKLIGHT_DECREASE();

Diferenças do arquivo suprimidas por serem muito extensas
+ 169 - 237
quantum/quantum.c


+ 4 - 5
quantum/quantum.h

@@ -173,12 +173,11 @@ void breathing_self_disable(void);
 void breathing_toggle(void);
 bool is_breathing(void);
 
-void breathing_defaults(void);
 void breathing_intensity_default(void);
-void breathing_speed_default(void);
-void breathing_speed_set(uint8_t value);
-void breathing_speed_inc(uint8_t value);
-void breathing_speed_dec(uint8_t value);
+void breathing_period_default(void);
+void breathing_period_set(uint8_t value);
+void breathing_period_inc(void);
+void breathing_period_dec(void);
 #endif
 
 #endif

+ 3 - 19
quantum/quantum_keycodes.h

@@ -380,26 +380,13 @@ enum quantum_keycodes {
 #endif // MIDI_ADVANCED
 
     // Backlight functionality
-    BL_0,
-    BL_1,
-    BL_2,
-    BL_3,
-    BL_4,
-    BL_5,
-    BL_6,
-    BL_7,
-    BL_8,
-    BL_9,
-    BL_10,
-    BL_11,
-    BL_12,
-    BL_13,
-    BL_14,
-    BL_15,
+    BL_ON,
+    BL_OFF,
     BL_DEC,
     BL_INC,
     BL_TOGG,
     BL_STEP,
+    BL_BRTG,
 
     // RGB functionality
     RGB_TOG,
@@ -579,9 +566,6 @@ enum quantum_keycodes {
 #define AG_SWAP MAGIC_SWAP_ALT_GUI
 #define AG_NORM MAGIC_UNSWAP_ALT_GUI
 
-#define BL_ON  BL_9
-#define BL_OFF BL_0
-
 // GOTO layer - 16 layers max
 // when:
 // ON_PRESS    = 1

+ 5 - 2
tmk_core/common/action.c

@@ -512,8 +512,11 @@ void process_action(keyrecord_t *record, action_t action)
                     case BACKLIGHT_STEP:
                         backlight_step();
                         break;
-                    case BACKLIGHT_LEVEL:
-                        backlight_level(action.backlight.level);
+                    case BACKLIGHT_ON:
+                        backlight_level(BACKLIGHT_LEVELS);
+                        break;
+                    case BACKLIGHT_OFF:
+                        backlight_level(0);
                         break;
                 }
             }

+ 4 - 2
tmk_core/common/action_code.h

@@ -304,7 +304,8 @@ enum backlight_opt {
     BACKLIGHT_DECREASE = 1,
     BACKLIGHT_TOGGLE   = 2,
     BACKLIGHT_STEP     = 3,
-    BACKLIGHT_LEVEL    = 4,
+    BACKLIGHT_ON       = 4,
+    BACKLIGHT_OFF      = 5,
 };
 
 /* Macro */
@@ -316,7 +317,8 @@ enum backlight_opt {
 #define ACTION_BACKLIGHT_DECREASE()     ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8)
 #define ACTION_BACKLIGHT_TOGGLE()       ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8)
 #define ACTION_BACKLIGHT_STEP()         ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8)
-#define ACTION_BACKLIGHT_LEVEL(level)   ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | (level))
+#define ACTION_BACKLIGHT_ON()           ACTION(ACT_BACKLIGHT, BACKLIGHT_ON << 8)
+#define ACTION_BACKLIGHT_OFF()          ACTION(ACT_BACKLIGHT, BACKLIGHT_OFF << 8)
 /* Command */
 #define ACTION_COMMAND(id, opt)         ACTION(ACT_COMMAND,  (opt)<<8 | (id))
 /* Function */

+ 5 - 1
tmk_core/common/backlight.c

@@ -61,6 +61,8 @@ void backlight_decrease(void)
 void backlight_toggle(void)
 {
     backlight_config.enable ^= 1;
+    if (backlight_config.raw == 1) // enabled but level = 0
+        backlight_config.level = 1;
     eeconfig_update_backlight(backlight_config.raw);
     dprintf("backlight toggle: %u\n", backlight_config.enable);
     backlight_set(backlight_config.enable ? backlight_config.level : 0);
@@ -81,7 +83,9 @@ void backlight_step(void)
 
 void backlight_level(uint8_t level)
 {
-    backlight_config.level ^= level;
+    if (level > BACKLIGHT_LEVELS)
+        level = BACKLIGHT_LEVELS;
+    backlight_config.level = level;
     backlight_config.enable = !!backlight_config.level;
     eeconfig_update_backlight(backlight_config.raw);
     backlight_set(backlight_config.level);