forked from mfulz_github/qmk_firmware
		
	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
This commit is contained in:
		
							parent
							
								
									d6215ad6af
								
							
						
					
					
						commit
						4931510ad3
					
				| @ -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 |   * pin of the backlight - B5, B6, B7 use PWM, others use softPWM | ||||||
| * `#define BACKLIGHT_LEVELS 3` | * `#define BACKLIGHT_LEVELS 3` | ||||||
|   * number of levels your backlight will have (not including off) |   * 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` | * `#define DEBOUNCING_DELAY 5` | ||||||
|   * the delay when reading the value of the pin (5 is default) |   * the delay when reading the value of the pin (5 is default) | ||||||
| * `#define LOCKING_SUPPORT_ENABLE` | * `#define LOCKING_SUPPORT_ENABLE` | ||||||
|  | |||||||
| @ -127,7 +127,7 @@ https://github.com/tekezo/Karabiner/issues/403 | |||||||
| 
 | 
 | ||||||
| ## Esc and <code>`</code> on a Single Key | ## Esc and <code>`</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 | ## 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**. | 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**. | ||||||
|  | |||||||
| @ -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_TOGG`|Turn the backlight on or off              | | ||||||
| |`BL_STEP`|Cycle through backlight levels            | | |`BL_STEP`|Cycle through backlight levels            | | ||||||
| |`BL_x`   |Set a specific backlight level between 0-9| | |`BL_ON`  |Set backlight to max brightness           | | ||||||
| |`BL_ON`  |An alias for `BL_9`                       | | |`BL_OFF` |Turn backlight off                        | | ||||||
| |`BL_OFF` |An alias for `BL_0`                       | |  | ||||||
| |`BL_INC` |Increase backlight level                  | | |`BL_INC` |Increase backlight level                  | | ||||||
| |`BL_DEC` |Decrease 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. | ||||||
|  | |||||||
| @ -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_PIN B7 | ||||||
| #define BACKLIGHT_BREATHING |  | ||||||
| #define BACKLIGHT_LEVELS 3 | #define BACKLIGHT_LEVELS 3 | ||||||
|  | #define BACKLIGHT_BREATHING | ||||||
|  | #define BREATHING_PERIOD 6 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| {% hint style='info' %} | {% hint style='info' %} | ||||||
|  | |||||||
| @ -345,14 +345,14 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|         case MACRO_BREATH_SPEED_INC: |         case MACRO_BREATH_SPEED_INC: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_inc(1); |                 breathing_period_inc(); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case MACRO_BREATH_SPEED_DEC: |         case MACRO_BREATH_SPEED_DEC: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_dec(1); |                 breathing_period_dec(); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
| @ -374,7 +374,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 layer_on(LAYER_UPPER); |                 layer_on(LAYER_UPPER); | ||||||
|                 breathing_speed_set(2); |                 breathing_period_set(2); | ||||||
|                 breathing_pulse(); |                 breathing_pulse(); | ||||||
|                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); |                 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) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 layer_on(LAYER_LOWER); |                 layer_on(LAYER_LOWER); | ||||||
|                 breathing_speed_set(2); |                 breathing_period_set(2); | ||||||
|                 breathing_pulse(); |                 breathing_pulse(); | ||||||
|                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); |                 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: |         case MACRO_FUNCTION: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_set(3); |                 breathing_period_set(3); | ||||||
|                 breathing_enable(); |                 breathing_enable(); | ||||||
|                 layer_on(LAYER_FUNCTION); |                 layer_on(LAYER_FUNCTION); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 breathing_speed_set(1); |                 breathing_period_set(1); | ||||||
|                 breathing_self_disable(); |                 breathing_self_disable(); | ||||||
|                 layer_off(LAYER_FUNCTION); |                 layer_off(LAYER_FUNCTION); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -42,7 +42,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||||||
| //#define MATRIX_HAS_GHOST
 | //#define MATRIX_HAS_GHOST
 | ||||||
| 
 | 
 | ||||||
| /* number of backlight levels */ | /* number of backlight levels */ | ||||||
| #define BACKLIGHT_LEVELS  1 | #define BACKLIGHT_LEVELS 3 | ||||||
| 
 | 
 | ||||||
| /* mapping backlight LEDs to correct Pin */ | /* mapping backlight LEDs to correct Pin */ | ||||||
| #define BACKLIGHT_PIN B7 | #define BACKLIGHT_PIN B7 | ||||||
|  | |||||||
| @ -21,5 +21,7 @@ | |||||||
| 
 | 
 | ||||||
| // place overrides here
 | // place overrides here
 | ||||||
| #define GRAVE_ESC_CTRL_OVERRIDE | #define GRAVE_ESC_CTRL_OVERRIDE | ||||||
|  | #define BACKLIGHT_BREATHING | ||||||
|  | #define BREATHING_PERIOD 8 | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -16,7 +16,7 @@ | |||||||
| #include "bananasplit.h" | #include "bananasplit.h" | ||||||
| 
 | 
 | ||||||
| enum custom_keycodes { | enum custom_keycodes { | ||||||
|   WIN_SWITCH_LAYOUT = SAFE_RANGE |   WIN_SWITCH_LAYOUT = SAFE_RANGE, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { | 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_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_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, _______, _______, _______, \ |     _______, 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 \ |     _______, _______, _______,          _______, _______,_______,                _______,       _______, _______, _______, RESET \ | ||||||
| ), | ), | ||||||
| }; | }; | ||||||
| @ -76,20 +76,20 @@ void matrix_scan_user(void) { | |||||||
| 
 | 
 | ||||||
| bool process_record_user(uint16_t keycode, keyrecord_t *record) { | bool process_record_user(uint16_t keycode, keyrecord_t *record) { | ||||||
|   switch (keycode) { |   switch (keycode) { | ||||||
|  | 
 | ||||||
|     case WIN_SWITCH_LAYOUT: { |     case WIN_SWITCH_LAYOUT: { | ||||||
|       // Sends Alt+Shift on both key down and key up. 
 |       // Sends Alt+Shift on both key down and key up. 
 | ||||||
|       // Designed to switch between two keyboard layouts on Windows using a locking switch.
 |       // Designed to switch between two keyboard layouts on Windows using a locking switch.
 | ||||||
|       // Does nothing if right shift is pressed for easy resync.
 |       // 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)); |         SEND_STRING(SS_DOWN(X_LALT)SS_TAP(X_LSHIFT)SS_UP(X_LALT)); | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
|       else | 
 | ||||||
|         return false; |     default: | ||||||
|     } |  | ||||||
|   } |  | ||||||
|       return true; |       return true; | ||||||
|   } |   } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void led_set_user(uint8_t usb_led) { | void led_set_user(uint8_t usb_led) { | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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...
 |             // action_function_tap may also handle this...
 | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_set(3); |                 breathing_period_set(3); | ||||||
|                 breathing_enable(); |                 breathing_enable(); | ||||||
|                 layer_on(1); |                 layer_on(1); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 breathing_speed_set(1); |                 breathing_period_set(1); | ||||||
|                 breathing_self_disable(); |                 breathing_self_disable(); | ||||||
|                 layer_off(1); |                 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: |         case M_LAYER2: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_set(2); |                 breathing_period_set(2); | ||||||
|                 breathing_pulse(); |                 breathing_pulse(); | ||||||
|                 layer_on(2); |                 layer_on(2); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 breathing_speed_set(1); |                 breathing_period_set(1); | ||||||
|                 breathing_self_disable(); |                 breathing_self_disable(); | ||||||
|                 layer_off(2); |                 layer_off(2); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -220,7 +220,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|       { |       { | ||||||
| 	layer_on(_RAISE); | 	layer_on(_RAISE); | ||||||
| #ifdef BACKLIGHT_ENABLE | #ifdef BACKLIGHT_ENABLE | ||||||
| 	breathing_speed_set(2); | 	breathing_period_set(2); | ||||||
| 	breathing_pulse(); | 	breathing_pulse(); | ||||||
| #endif | #endif | ||||||
| 	update_tri_layer(_LOWER, _RAISE, _ADJUST); | 	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); | 	layer_on(_LOWER); | ||||||
| #ifdef BACKLIGHT_ENABLE | #ifdef BACKLIGHT_ENABLE | ||||||
| 	breathing_speed_set(2); | 	breathing_period_set(2); | ||||||
| 	breathing_pulse(); | 	breathing_pulse(); | ||||||
| #endif | #endif | ||||||
| 	update_tri_layer(_LOWER, _RAISE, _ADJUST); | 	update_tri_layer(_LOWER, _RAISE, _ADJUST); | ||||||
|  | |||||||
| @ -242,7 +242,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { | |||||||
|           if (record->event.pressed) { |           if (record->event.pressed) { | ||||||
|             layer_on(_LOWER); |             layer_on(_LOWER); | ||||||
|             #ifdef BACKLIGHT_ENABLE |             #ifdef BACKLIGHT_ENABLE | ||||||
|                 breathing_speed_set(2); |                 breathing_period_set(2); | ||||||
|                 breathing_pulse(); |                 breathing_pulse(); | ||||||
|             #endif |             #endif | ||||||
|             update_tri_layer(_LOWER, _RAISE, _ADJUST); |             update_tri_layer(_LOWER, _RAISE, _ADJUST); | ||||||
| @ -256,7 +256,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { | |||||||
|           if (record->event.pressed) { |           if (record->event.pressed) { | ||||||
|             layer_on(_RAISE); |             layer_on(_RAISE); | ||||||
|             #ifdef BACKLIGHT_ENABLE |             #ifdef BACKLIGHT_ENABLE | ||||||
|                 breathing_speed_set(2); |                 breathing_period_set(2); | ||||||
|                 breathing_pulse(); |                 breathing_pulse(); | ||||||
|             #endif |             #endif | ||||||
|             update_tri_layer(_LOWER, _RAISE, _ADJUST); |             update_tri_layer(_LOWER, _RAISE, _ADJUST); | ||||||
|  | |||||||
| @ -128,12 +128,12 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) { | |||||||
|       break; |       break; | ||||||
|     case MACRO_BREATH_SPEED_INC: |     case MACRO_BREATH_SPEED_INC: | ||||||
|       if (record->event.pressed) { |       if (record->event.pressed) { | ||||||
|         breathing_speed_inc(1); |         breathing_period_inc(); | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|     case MACRO_BREATH_SPEED_DEC: |     case MACRO_BREATH_SPEED_DEC: | ||||||
|       if (record->event.pressed) { |       if (record->event.pressed) { | ||||||
|         breathing_speed_dec(1); |         breathing_period_dec(); | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|     case MACRO_BREATH_DEFAULT: |     case MACRO_BREATH_DEFAULT: | ||||||
|  | |||||||
| @ -323,14 +323,14 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|         case MACRO_BREATH_SPEED_INC: |         case MACRO_BREATH_SPEED_INC: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_inc(1); |                 breathing_period_inc(); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case MACRO_BREATH_SPEED_DEC: |         case MACRO_BREATH_SPEED_DEC: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_dec(1); |                 breathing_period_dec(); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
| @ -352,7 +352,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 layer_on(LAYER_UPPER); |                 layer_on(LAYER_UPPER); | ||||||
|                 breathing_speed_set(2); |                 breathing_period_set(2); | ||||||
|                 breathing_pulse(); |                 breathing_pulse(); | ||||||
|                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); |                 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) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 layer_on(LAYER_LOWER); |                 layer_on(LAYER_LOWER); | ||||||
|                 breathing_speed_set(2); |                 breathing_period_set(2); | ||||||
|                 breathing_pulse(); |                 breathing_pulse(); | ||||||
|                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); |                 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: |         case MACRO_FUNCTION: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_set(3); |                 breathing_period_set(3); | ||||||
|                 breathing_enable(); |                 breathing_enable(); | ||||||
|                 layer_on(LAYER_FUNCTION); |                 layer_on(LAYER_FUNCTION); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 breathing_speed_set(1); |                 breathing_period_set(1); | ||||||
|                 breathing_self_disable(); |                 breathing_self_disable(); | ||||||
|                 layer_off(LAYER_FUNCTION); |                 layer_off(LAYER_FUNCTION); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -270,7 +270,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { | |||||||
|                     PLAY_SONG(tone_ctrl_mod); |                     PLAY_SONG(tone_ctrl_mod); | ||||||
|                 #endif |                 #endif | ||||||
|                 #ifdef BACKLIGHT_BREATHING |                 #ifdef BACKLIGHT_BREATHING | ||||||
|                     breathing_speed_set(2); |                     breathing_period_set(2); | ||||||
|                     breathing_pulse(); |                     breathing_pulse(); | ||||||
|                 #endif |                 #endif | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -332,14 +332,14 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|         case MACRO_BREATH_SPEED_INC: |         case MACRO_BREATH_SPEED_INC: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_inc(1); |                 breathing_period_inc(); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case MACRO_BREATH_SPEED_DEC: |         case MACRO_BREATH_SPEED_DEC: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_dec(1); |                 breathing_period_dec(); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
| @ -361,7 +361,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 layer_on(LAYER_UPPER); |                 layer_on(LAYER_UPPER); | ||||||
|                 breathing_speed_set(2); |                 breathing_period_set(2); | ||||||
|                 breathing_pulse(); |                 breathing_pulse(); | ||||||
|                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); |                 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) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 layer_on(LAYER_LOWER); |                 layer_on(LAYER_LOWER); | ||||||
|                 breathing_speed_set(2); |                 breathing_period_set(2); | ||||||
|                 breathing_pulse(); |                 breathing_pulse(); | ||||||
|                 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); |                 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: |         case MACRO_FUNCTION: | ||||||
|             if (record->event.pressed) |             if (record->event.pressed) | ||||||
|             { |             { | ||||||
|                 breathing_speed_set(3); |                 breathing_period_set(3); | ||||||
|                 breathing_enable(); |                 breathing_enable(); | ||||||
|                 layer_on(LAYER_FUNCTION); |                 layer_on(LAYER_FUNCTION); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 breathing_speed_set(1); |                 breathing_period_set(1); | ||||||
|                 breathing_self_disable(); |                 breathing_self_disable(); | ||||||
|                 layer_off(LAYER_FUNCTION); |                 layer_off(LAYER_FUNCTION); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -270,7 +270,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { | |||||||
|                     PLAY_SONG(tone_ctrl_mod); |                     PLAY_SONG(tone_ctrl_mod); | ||||||
|                 #endif |                 #endif | ||||||
|                 #ifdef BACKLIGHT_BREATHING |                 #ifdef BACKLIGHT_BREATHING | ||||||
|                     breathing_speed_set(2); |                     breathing_period_set(2); | ||||||
|                     breathing_pulse(); |                     breathing_pulse(); | ||||||
|                 #endif |                 #endif | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -406,21 +406,21 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|   case MACRO_BREATH_SPEED_INC: |   case MACRO_BREATH_SPEED_INC: | ||||||
|     if (record->event.pressed) |     if (record->event.pressed) | ||||||
|     { |     { | ||||||
|       breathing_speed_inc(1); |       breathing_period_inc(); | ||||||
|     } |     } | ||||||
|     break; |     break; | ||||||
| 
 | 
 | ||||||
|   case MACRO_BREATH_SPEED_DEC: |   case MACRO_BREATH_SPEED_DEC: | ||||||
|     if (record->event.pressed) |     if (record->event.pressed) | ||||||
|     { |     { | ||||||
|       breathing_speed_dec(1); |       breathing_period_dec(); | ||||||
|     } |     } | ||||||
|     break; |     break; | ||||||
| 
 | 
 | ||||||
|   case MACRO_BREATH_DEFAULT: |   case MACRO_BREATH_DEFAULT: | ||||||
|     if (record->event.pressed) |     if (record->event.pressed) | ||||||
|     { |     { | ||||||
|       breathing_defaults(); |       breathing_period_default(); | ||||||
|     } |     } | ||||||
|     break; |     break; | ||||||
| 
 | 
 | ||||||
| @ -435,7 +435,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|     if (record->event.pressed) |     if (record->event.pressed) | ||||||
|     { |     { | ||||||
|       layer_on(LAYER_UPPER); |       layer_on(LAYER_UPPER); | ||||||
|       breathing_speed_set(2); |       breathing_period_set(2); | ||||||
|       breathing_pulse(); |       breathing_pulse(); | ||||||
|       update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); |       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) |     if (record->event.pressed) | ||||||
|     { |     { | ||||||
|       layer_on(LAYER_LOWER); |       layer_on(LAYER_LOWER); | ||||||
|       breathing_speed_set(2); |       breathing_period_set(2); | ||||||
|       breathing_pulse(); |       breathing_pulse(); | ||||||
|       update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); |       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: |   case MACRO_FUNCTION: | ||||||
|     if (record->event.pressed) |     if (record->event.pressed) | ||||||
|     { |     { | ||||||
|       breathing_speed_set(3); |       breathing_period_set(3); | ||||||
|       breathing_enable(); |       breathing_enable(); | ||||||
|       layer_on(LAYER_FUNCTION); |       layer_on(LAYER_FUNCTION); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|       breathing_speed_set(1); |       breathing_period_set(1); | ||||||
|       breathing_self_disable(); |       breathing_self_disable(); | ||||||
|       layer_off(LAYER_FUNCTION); |       layer_off(LAYER_FUNCTION); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -265,7 +265,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) | |||||||
|       { |       { | ||||||
| 	layer_on(_RAISE); | 	layer_on(_RAISE); | ||||||
| #ifdef BACKLIGHT_ENABLE | #ifdef BACKLIGHT_ENABLE | ||||||
| 	breathing_speed_set(2); | 	breathing_period_set(2); | ||||||
| 	breathing_pulse(); | 	breathing_pulse(); | ||||||
| #endif | #endif | ||||||
| 	update_tri_layer(_LOWER, _RAISE, _ADJUST); | 	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); | 	layer_on(_LOWER); | ||||||
| #ifdef BACKLIGHT_ENABLE | #ifdef BACKLIGHT_ENABLE | ||||||
| 	breathing_speed_set(2); | 	breathing_period_set(2); | ||||||
| 	breathing_pulse(); | 	breathing_pulse(); | ||||||
| #endif | #endif | ||||||
| 	update_tri_layer(_LOWER, _RAISE, _ADJUST); | 	update_tri_layer(_LOWER, _RAISE, _ADJUST); | ||||||
|  | |||||||
| @ -127,8 +127,11 @@ action_t action_for_key(uint8_t layer, keypos_t key) | |||||||
|             action.code = ACTION_MODS_TAP_KEY(mod, keycode & 0xFF); |             action.code = ACTION_MODS_TAP_KEY(mod, keycode & 0xFF); | ||||||
|             break; |             break; | ||||||
|     #ifdef BACKLIGHT_ENABLE |     #ifdef BACKLIGHT_ENABLE | ||||||
|         case BL_0 ... BL_15: |         case BL_ON: | ||||||
|             action.code = ACTION_BACKLIGHT_LEVEL(keycode - BL_0); |             action.code = ACTION_BACKLIGHT_ON(); | ||||||
|  |             break; | ||||||
|  |         case BL_OFF: | ||||||
|  |             action.code = ACTION_BACKLIGHT_OFF(); | ||||||
|             break; |             break; | ||||||
|         case BL_DEC: |         case BL_DEC: | ||||||
|             action.code = ACTION_BACKLIGHT_DECREASE(); |             action.code = ACTION_BACKLIGHT_DECREASE(); | ||||||
|  | |||||||
| @ -23,6 +23,10 @@ | |||||||
| #define TAPPING_TERM 200 | #define TAPPING_TERM 200 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifndef BREATHING_PERIOD | ||||||
|  | #define BREATHING_PERIOD 6 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #include "backlight.h" | #include "backlight.h" | ||||||
| extern backlight_config_t backlight_config; | extern backlight_config_t backlight_config; | ||||||
| 
 | 
 | ||||||
| @ -618,7 +622,17 @@ bool process_record_quantum(keyrecord_t *record) { | |||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       send_keyboard_report(); |       send_keyboard_report(); | ||||||
|  |       return false; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  | #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_BREATHING) | ||||||
|  |     case BL_BRTG: { | ||||||
|  |       if (record->event.pressed) | ||||||
|  |         breathing_toggle(); | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|     default: { |     default: { | ||||||
|       shift_interrupted[0] = true; |       shift_interrupted[0] = true; | ||||||
|       shift_interrupted[1] = true; |       shift_interrupted[1] = true; | ||||||
| @ -831,6 +845,7 @@ void matrix_scan_quantum() { | |||||||
| 
 | 
 | ||||||
| static const uint8_t backlight_pin = 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 | #if BACKLIGHT_PIN == B7 | ||||||
| #  define COM1x1 COM1C1 | #  define COM1x1 COM1C1 | ||||||
| #  define OCR1x  OCR1C | #  define OCR1x  OCR1C | ||||||
| @ -841,17 +856,18 @@ static const uint8_t backlight_pin = BACKLIGHT_PIN; | |||||||
| #  define COM1x1 COM1A1 | #  define COM1x1 COM1A1 | ||||||
| #  define OCR1x  OCR1A | #  define OCR1x  OCR1A | ||||||
| #else | #else | ||||||
| #  define NO_BACKLIGHT_CLOCK | #  define NO_HARDWARE_PWM | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifndef BACKLIGHT_ON_STATE | #ifndef BACKLIGHT_ON_STATE | ||||||
| #define BACKLIGHT_ON_STATE 0 | #define BACKLIGHT_ON_STATE 0 | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef NO_HARDWARE_PWM // pwm through software
 | ||||||
|  | 
 | ||||||
| __attribute__ ((weak)) | __attribute__ ((weak)) | ||||||
| void backlight_init_ports(void) | void backlight_init_ports(void) | ||||||
| { | { | ||||||
| 
 |  | ||||||
|   // Setup backlight pin as output and output to on state.
 |   // Setup backlight pin as output and output to on state.
 | ||||||
|   // DDRx |= n
 |   // DDRx |= n
 | ||||||
|   _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF); |   _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF); | ||||||
| @ -862,83 +878,15 @@ void backlight_init_ports(void) | |||||||
|     // PORTx |= n
 |     // PORTx |= n
 | ||||||
|     _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); |     _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); | ||||||
|   #endif |   #endif | ||||||
| 
 |  | ||||||
|   #ifndef NO_BACKLIGHT_CLOCK |  | ||||||
|     // Use full 16-bit resolution.
 |  | ||||||
|     ICR1 = 0xFFFF; |  | ||||||
| 
 |  | ||||||
|     // I could write a wall of text here to explain... but TL;DW
 |  | ||||||
|     // Go read the ATmega32u4 datasheet.
 |  | ||||||
|     // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
 |  | ||||||
| 
 |  | ||||||
|     // Pin PB7 = OCR1C (Timer 1, Channel C)
 |  | ||||||
|     // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
 |  | ||||||
|     // (i.e. start high, go low when counter matches.)
 |  | ||||||
|     // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
 |  | ||||||
|     // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
 |  | ||||||
| 
 |  | ||||||
|     TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
 |  | ||||||
|     TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
 |  | ||||||
|   #endif |  | ||||||
| 
 |  | ||||||
|   backlight_init(); |  | ||||||
|   #ifdef BACKLIGHT_BREATHING |  | ||||||
|     breathing_defaults(); |  | ||||||
|   #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| __attribute__ ((weak)) | __attribute__ ((weak)) | ||||||
| void backlight_set(uint8_t level) | void backlight_set(uint8_t level) {} | ||||||
| { |  | ||||||
|   // Prevent backlight blink on lowest level
 |  | ||||||
|   // #if BACKLIGHT_ON_STATE == 0
 |  | ||||||
|   //   // PORTx &= ~n
 |  | ||||||
|   //   _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
 |  | ||||||
|   // #else
 |  | ||||||
|   //   // PORTx |= n
 |  | ||||||
|   //   _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
 |  | ||||||
|   // #endif
 |  | ||||||
| 
 |  | ||||||
|   if ( level == 0 ) { |  | ||||||
|     #ifndef NO_BACKLIGHT_CLOCK |  | ||||||
|       // Turn off PWM control on backlight pin, revert to output low.
 |  | ||||||
|       TCCR1A &= ~(_BV(COM1x1)); |  | ||||||
|       OCR1x = 0x0; |  | ||||||
|     #else |  | ||||||
|       // #if BACKLIGHT_ON_STATE == 0
 |  | ||||||
|       //   // PORTx |= n
 |  | ||||||
|       //   _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
 |  | ||||||
|       // #else
 |  | ||||||
|       //   // PORTx &= ~n
 |  | ||||||
|       //   _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
 |  | ||||||
|       // #endif
 |  | ||||||
|     #endif |  | ||||||
|   } |  | ||||||
|   #ifndef NO_BACKLIGHT_CLOCK |  | ||||||
|     else if ( level == BACKLIGHT_LEVELS ) { |  | ||||||
|       // Turn on PWM control of backlight pin
 |  | ||||||
|       TCCR1A |= _BV(COM1x1); |  | ||||||
|       // Set the brightness
 |  | ||||||
|       OCR1x = 0xFFFF; |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|       // Turn on PWM control of backlight pin
 |  | ||||||
|       TCCR1A |= _BV(COM1x1); |  | ||||||
|       // Set the brightness
 |  | ||||||
|       OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2)); |  | ||||||
|     } |  | ||||||
|   #endif |  | ||||||
| 
 |  | ||||||
|   #ifdef BACKLIGHT_BREATHING |  | ||||||
|     breathing_intensity_default(); |  | ||||||
|   #endif |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| uint8_t backlight_tick = 0; | uint8_t backlight_tick = 0; | ||||||
| 
 | 
 | ||||||
| void backlight_task(void) { | void backlight_task(void) { | ||||||
|   #ifdef NO_BACKLIGHT_CLOCK |   if ((0xFFFF >> ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) { | ||||||
|   if ((0xFFFF >> ((BACKLIGHT_LEVELS - backlight_config.level) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) { |  | ||||||
|     #if BACKLIGHT_ON_STATE == 0 |     #if BACKLIGHT_ON_STATE == 0 | ||||||
|       // PORTx &= ~n
 |       // PORTx &= ~n
 | ||||||
|       _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); |       _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); | ||||||
| @ -955,232 +903,216 @@ void backlight_task(void) { | |||||||
|       _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); |       _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); | ||||||
|     #endif |     #endif | ||||||
|   } |   } | ||||||
|   backlight_tick = (backlight_tick + 1) % 16; |   backlight_tick = backlight_tick + 1 % 16; | ||||||
|   #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #ifdef BACKLIGHT_BREATHING | #ifdef BACKLIGHT_BREATHING | ||||||
|  | #error "Backlight breathing only available with hardware PWM. Please disable." | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef NO_BACKLIGHT_CLOCK | #else // pwm through timer
 | ||||||
| void breathing_defaults(void) {} | 
 | ||||||
| void breathing_intensity_default(void) {} | #define TIMER_TOP 0xFFFFU | ||||||
| #else | 
 | ||||||
|  | // See http://jared.geek.nz/2013/feb/linear-led-pwm
 | ||||||
|  | static uint16_t cie_lightness(uint16_t v) { | ||||||
|  |   if (v <= 5243) // if below 8% of max
 | ||||||
|  |     return v / 9; // same as dividing by 900%
 | ||||||
|  |   else { | ||||||
|  |     uint32_t y = (((uint32_t) v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
 | ||||||
|  |     // to get a useful result with integer division, we shift left in the expression above
 | ||||||
|  |     // and revert what we've done again after squaring.
 | ||||||
|  |     y = y * y * y >> 8; | ||||||
|  |     if (y > 0xFFFFUL) // prevent overflow
 | ||||||
|  |       return 0xFFFFU; | ||||||
|  |     else | ||||||
|  |       return (uint16_t) y; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // 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; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | __attribute__ ((weak)) | ||||||
|  | void backlight_set(uint8_t level) { | ||||||
|  |   if (level > BACKLIGHT_LEVELS) | ||||||
|  |     level = BACKLIGHT_LEVELS; | ||||||
|  | 
 | ||||||
|  |   if (level == 0) { | ||||||
|  |     // Turn off PWM control on backlight pin
 | ||||||
|  |     TCCR1A &= ~(_BV(COM1x1)); | ||||||
|  |   } else { | ||||||
|  |     // Turn on PWM control of backlight pin
 | ||||||
|  |     TCCR1A |= _BV(COM1x1); | ||||||
|  |   } | ||||||
|  |   // Set the brightness
 | ||||||
|  |   set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void backlight_task(void) {} | ||||||
|  | 
 | ||||||
|  | #ifdef BACKLIGHT_BREATHING | ||||||
| 
 | 
 | ||||||
| #define BREATHING_NO_HALT  0 | #define BREATHING_NO_HALT  0 | ||||||
| #define BREATHING_HALT_OFF 1 | #define BREATHING_HALT_OFF 1 | ||||||
| #define BREATHING_HALT_ON  2 | #define BREATHING_HALT_ON  2 | ||||||
|  | #define BREATHING_STEPS 128 | ||||||
| 
 | 
 | ||||||
| static uint8_t breath_intensity; | static uint8_t breathing_period = BREATHING_PERIOD; | ||||||
| static uint8_t breath_speed; | static uint8_t breathing_halt = BREATHING_NO_HALT; | ||||||
| static uint16_t breathing_index; | static uint16_t breathing_counter = 0; | ||||||
| static uint8_t breathing_halt; | 
 | ||||||
|  | bool is_breathing(void) { | ||||||
|  |     return !!(TIMSK1 & _BV(TOIE1)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define breathing_interrupt_enable() do {TIMSK1 |= _BV(TOIE1);} while (0) | ||||||
|  | #define breathing_interrupt_disable() do {TIMSK1 &= ~_BV(TOIE1);} while (0) | ||||||
|  | #define breathing_min() do {breathing_counter = 0;} while (0) | ||||||
|  | #define breathing_max() do {breathing_counter = breathing_period * 244 / 2;} while (0) | ||||||
| 
 | 
 | ||||||
| void breathing_enable(void) | void breathing_enable(void) | ||||||
| { | { | ||||||
|     if (get_backlight_level() == 0) |   breathing_counter = 0; | ||||||
|     { |  | ||||||
|         breathing_index = 0; |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         // Set breathing_index to be at the midpoint (brightest point)
 |  | ||||||
|         breathing_index = 0x20 << breath_speed; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|   breathing_halt = BREATHING_NO_HALT; |   breathing_halt = BREATHING_NO_HALT; | ||||||
| 
 |   breathing_interrupt_enable(); | ||||||
|     // Enable breathing interrupt
 |  | ||||||
|     TIMSK1 |= _BV(OCIE1A); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void breathing_pulse(void) | void breathing_pulse(void) | ||||||
| { | { | ||||||
|     if (get_backlight_level() == 0) |     if (get_backlight_level() == 0) | ||||||
|     { |       breathing_min(); | ||||||
|         breathing_index = 0; |  | ||||||
|     } |  | ||||||
|     else |     else | ||||||
|     { |       breathing_max(); | ||||||
|         // Set breathing_index to be at the midpoint + 1 (brightest point)
 |  | ||||||
|         breathing_index = 0x21 << breath_speed; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     breathing_halt = BREATHING_HALT_ON; |     breathing_halt = BREATHING_HALT_ON; | ||||||
| 
 |     breathing_interrupt_enable(); | ||||||
|     // Enable breathing interrupt
 |  | ||||||
|     TIMSK1 |= _BV(OCIE1A); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void breathing_disable(void) | void breathing_disable(void) | ||||||
| { | { | ||||||
|     // Disable breathing interrupt
 |     breathing_interrupt_disable(); | ||||||
|     TIMSK1 &= ~_BV(OCIE1A); |     // Restore backlight level
 | ||||||
|     backlight_set(get_backlight_level()); |     backlight_set(get_backlight_level()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void breathing_self_disable(void) | void breathing_self_disable(void) | ||||||
| { | { | ||||||
|   if (get_backlight_level() == 0) |   if (get_backlight_level() == 0) | ||||||
|     { |  | ||||||
|     breathing_halt = BREATHING_HALT_OFF; |     breathing_halt = BREATHING_HALT_OFF; | ||||||
|     } |  | ||||||
|   else |   else | ||||||
|     { |  | ||||||
|     breathing_halt = BREATHING_HALT_ON; |     breathing_halt = BREATHING_HALT_ON; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|     //backlight_set(get_backlight_level());
 | void breathing_toggle(void) { | ||||||
| } |   if (is_breathing()) | ||||||
| 
 |     breathing_disable(); | ||||||
| void breathing_toggle(void) |  | ||||||
| { |  | ||||||
|     if (!is_breathing()) |  | ||||||
|     { |  | ||||||
|         if (get_backlight_level() == 0) |  | ||||||
|         { |  | ||||||
|             breathing_index = 0; |  | ||||||
|         } |  | ||||||
|   else |   else | ||||||
|  |     breathing_enable(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void breathing_period_set(uint8_t value) | ||||||
| { | { | ||||||
|             // Set breathing_index to be at the midpoint + 1 (brightest point)
 |   if (!value) | ||||||
|             breathing_index = 0x21 << breath_speed; |     value = 1; | ||||||
|  |   breathing_period = value; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|         breathing_halt = BREATHING_NO_HALT; | void breathing_period_default(void) { | ||||||
|  |   breathing_period_set(BREATHING_PERIOD); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|     // Toggle breathing interrupt
 | void breathing_period_inc(void) | ||||||
|     TIMSK1 ^= _BV(OCIE1A); |  | ||||||
| 
 |  | ||||||
|     // Restore backlight level
 |  | ||||||
|     if (!is_breathing()) |  | ||||||
| { | { | ||||||
|         backlight_set(get_backlight_level()); |   breathing_period_set(breathing_period+1); | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool is_breathing(void) | void breathing_period_dec(void) | ||||||
| { | { | ||||||
|     return (TIMSK1 && _BV(OCIE1A)); |   breathing_period_set(breathing_period-1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void breathing_intensity_default(void) | /* To generate breathing curve in python:
 | ||||||
| { |  * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)] | ||||||
|     //breath_intensity = (uint8_t)((uint16_t)100 * (uint16_t)get_backlight_level() / (uint16_t)BACKLIGHT_LEVELS);
 |  | ||||||
|     breath_intensity = ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void breathing_intensity_set(uint8_t value) |  | ||||||
| { |  | ||||||
|     breath_intensity = value; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void breathing_speed_default(void) |  | ||||||
| { |  | ||||||
|     breath_speed = 4; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void breathing_speed_set(uint8_t value) |  | ||||||
| { |  | ||||||
|     bool is_breathing_now = is_breathing(); |  | ||||||
|     uint8_t old_breath_speed = breath_speed; |  | ||||||
| 
 |  | ||||||
|     if (is_breathing_now) |  | ||||||
|     { |  | ||||||
|         // Disable breathing interrupt
 |  | ||||||
|         TIMSK1 &= ~_BV(OCIE1A); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     breath_speed = value; |  | ||||||
| 
 |  | ||||||
|     if (is_breathing_now) |  | ||||||
|     { |  | ||||||
|         // Adjust index to account for new speed
 |  | ||||||
|         breathing_index = (( (uint8_t)( (breathing_index) >> old_breath_speed ) ) & 0x3F) << breath_speed; |  | ||||||
| 
 |  | ||||||
|         // Enable breathing interrupt
 |  | ||||||
|         TIMSK1 |= _BV(OCIE1A); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void breathing_speed_inc(uint8_t value) |  | ||||||
| { |  | ||||||
|     if ((uint16_t)(breath_speed - value) > 10 ) |  | ||||||
|     { |  | ||||||
|         breathing_speed_set(0); |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         breathing_speed_set(breath_speed - value); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void breathing_speed_dec(uint8_t value) |  | ||||||
| { |  | ||||||
|     if ((uint16_t)(breath_speed + value) > 10 ) |  | ||||||
|     { |  | ||||||
|         breathing_speed_set(10); |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         breathing_speed_set(breath_speed + value); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void breathing_defaults(void) |  | ||||||
| { |  | ||||||
|     breathing_intensity_default(); |  | ||||||
|     breathing_speed_default(); |  | ||||||
|     breathing_halt = BREATHING_NO_HALT; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Breathing Sleep LED brighness(PWM On period) table
 |  | ||||||
|  * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle |  | ||||||
|  * |  | ||||||
|  * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
 |  | ||||||
|  * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i } |  | ||||||
|  */ |  */ | ||||||
| static const uint8_t breathing_table[64] PROGMEM = { | static const uint8_t breathing_table[BREATHING_STEPS] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||||||
|   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   4,   6,  10, |  | ||||||
|  15,  23,  32,  44,  58,  74,  93, 113, 135, 157, 179, 199, 218, 233, 245, 252, |  | ||||||
| 255, 252, 245, 233, 218, 199, 179, 157, 135, 113,  93,  74,  58,  44,  32,  23, |  | ||||||
|  15,  10,   6,   4,   2,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| ISR(TIMER1_COMPA_vect) | // Use this before the cie_lightness function.
 | ||||||
| { | static inline uint16_t scale_backlight(uint16_t v) { | ||||||
|     // OCR1x = (pgm_read_byte(&breathing_table[ ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F ] )) * breath_intensity;
 |   return v / BACKLIGHT_LEVELS * get_backlight_level(); | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     uint8_t local_index = ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F; |  | ||||||
| 
 |  | ||||||
|     if (((breathing_halt == BREATHING_HALT_ON) && (local_index == 0x20)) || ((breathing_halt == BREATHING_HALT_OFF) && (local_index == 0x3F))) |  | ||||||
|     { |  | ||||||
|         // Disable breathing interrupt
 |  | ||||||
|         TIMSK1 &= ~_BV(OCIE1A); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|     OCR1x = (uint16_t)(((uint16_t)pgm_read_byte(&breathing_table[local_index]) * 257)) >> breath_intensity; | /* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run
 | ||||||
|  |  * about 244 times per second. | ||||||
|  |  */ | ||||||
|  | ISR(TIMER1_OVF_vect) | ||||||
|  | { | ||||||
|  |   uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS; | ||||||
|  |   // resetting after one period to prevent ugly reset at overflow.
 | ||||||
|  |   breathing_counter = (breathing_counter + 1) % (breathing_period * 244); | ||||||
|  |   uint8_t index = breathing_counter / interval % BREATHING_STEPS; | ||||||
| 
 | 
 | ||||||
|  |   if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) || | ||||||
|  |       ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1))) | ||||||
|  |   { | ||||||
|  |       breathing_interrupt_disable(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| #endif // NO_BACKLIGHT_CLOCK
 |   set_pwm(cie_lightness(scale_backlight((uint16_t) pgm_read_byte(&breathing_table[index]) * 0x0101U))); | ||||||
| #endif // breathing
 | } | ||||||
| 
 | 
 | ||||||
| #else // backlight
 | #endif // BACKLIGHT_BREATHING
 | ||||||
| 
 | 
 | ||||||
| __attribute__ ((weak)) | __attribute__ ((weak)) | ||||||
| void backlight_init_ports(void) | void backlight_init_ports(void) | ||||||
| { | { | ||||||
|  |   // Setup backlight pin as output and output to on state.
 | ||||||
|  |   // DDRx |= n
 | ||||||
|  |   _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF); | ||||||
|  |   #if BACKLIGHT_ON_STATE == 0 | ||||||
|  |     // PORTx &= ~n
 | ||||||
|  |     _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); | ||||||
|  |   #else | ||||||
|  |     // PORTx |= n
 | ||||||
|  |     _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); | ||||||
|  |   #endif | ||||||
|  |   // I could write a wall of text here to explain... but TL;DW
 | ||||||
|  |   // Go read the ATmega32u4 datasheet.
 | ||||||
|  |   // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
 | ||||||
| 
 | 
 | ||||||
|  |   // Pin PB7 = OCR1C (Timer 1, Channel C)
 | ||||||
|  |   // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
 | ||||||
|  |   // (i.e. start high, go low when counter matches.)
 | ||||||
|  |   // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
 | ||||||
|  |   // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
 | ||||||
|  | 
 | ||||||
|  |   /*
 | ||||||
|  |   14.8.3: | ||||||
|  |   "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;
 | ||||||
|  |   // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0.
 | ||||||
|  |   ICR1 = TIMER_TOP; | ||||||
|  | 
 | ||||||
|  |   backlight_init(); | ||||||
|  |   #ifdef BACKLIGHT_BREATHING | ||||||
|  |     breathing_enable(); | ||||||
|  |   #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #endif // NO_HARDWARE_PWM
 | ||||||
|  | 
 | ||||||
|  | #else // backlight
 | ||||||
|  | 
 | ||||||
| __attribute__ ((weak)) | __attribute__ ((weak)) | ||||||
| void backlight_set(uint8_t level) | void backlight_init_ports(void) {} | ||||||
| { |  | ||||||
| 
 | 
 | ||||||
| } | __attribute__ ((weak)) | ||||||
|  | void backlight_set(uint8_t level) {} | ||||||
| 
 | 
 | ||||||
| #endif // backlight
 | #endif // backlight
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -173,12 +173,11 @@ void breathing_self_disable(void); | |||||||
| void breathing_toggle(void); | void breathing_toggle(void); | ||||||
| bool is_breathing(void); | bool is_breathing(void); | ||||||
| 
 | 
 | ||||||
| void breathing_defaults(void); |  | ||||||
| void breathing_intensity_default(void); | void breathing_intensity_default(void); | ||||||
| void breathing_speed_default(void); | void breathing_period_default(void); | ||||||
| void breathing_speed_set(uint8_t value); | void breathing_period_set(uint8_t value); | ||||||
| void breathing_speed_inc(uint8_t value); | void breathing_period_inc(void); | ||||||
| void breathing_speed_dec(uint8_t value); | void breathing_period_dec(void); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -380,26 +380,13 @@ enum quantum_keycodes { | |||||||
| #endif // MIDI_ADVANCED
 | #endif // MIDI_ADVANCED
 | ||||||
| 
 | 
 | ||||||
|     // Backlight functionality
 |     // Backlight functionality
 | ||||||
|     BL_0, |     BL_ON, | ||||||
|     BL_1, |     BL_OFF, | ||||||
|     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_DEC, |     BL_DEC, | ||||||
|     BL_INC, |     BL_INC, | ||||||
|     BL_TOGG, |     BL_TOGG, | ||||||
|     BL_STEP, |     BL_STEP, | ||||||
|  |     BL_BRTG, | ||||||
| 
 | 
 | ||||||
|     // RGB functionality
 |     // RGB functionality
 | ||||||
|     RGB_TOG, |     RGB_TOG, | ||||||
| @ -579,9 +566,6 @@ enum quantum_keycodes { | |||||||
| #define AG_SWAP MAGIC_SWAP_ALT_GUI | #define AG_SWAP MAGIC_SWAP_ALT_GUI | ||||||
| #define AG_NORM MAGIC_UNSWAP_ALT_GUI | #define AG_NORM MAGIC_UNSWAP_ALT_GUI | ||||||
| 
 | 
 | ||||||
| #define BL_ON  BL_9 |  | ||||||
| #define BL_OFF BL_0 |  | ||||||
| 
 |  | ||||||
| // GOTO layer - 16 layers max
 | // GOTO layer - 16 layers max
 | ||||||
| // when:
 | // when:
 | ||||||
| // ON_PRESS    = 1
 | // ON_PRESS    = 1
 | ||||||
|  | |||||||
| @ -512,8 +512,11 @@ void process_action(keyrecord_t *record, action_t action) | |||||||
|                     case BACKLIGHT_STEP: |                     case BACKLIGHT_STEP: | ||||||
|                         backlight_step(); |                         backlight_step(); | ||||||
|                         break; |                         break; | ||||||
|                     case BACKLIGHT_LEVEL: |                     case BACKLIGHT_ON: | ||||||
|                         backlight_level(action.backlight.level); |                         backlight_level(BACKLIGHT_LEVELS); | ||||||
|  |                         break; | ||||||
|  |                     case BACKLIGHT_OFF: | ||||||
|  |                         backlight_level(0); | ||||||
|                         break; |                         break; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -304,7 +304,8 @@ enum backlight_opt { | |||||||
|     BACKLIGHT_DECREASE = 1, |     BACKLIGHT_DECREASE = 1, | ||||||
|     BACKLIGHT_TOGGLE   = 2, |     BACKLIGHT_TOGGLE   = 2, | ||||||
|     BACKLIGHT_STEP     = 3, |     BACKLIGHT_STEP     = 3, | ||||||
|     BACKLIGHT_LEVEL    = 4, |     BACKLIGHT_ON       = 4, | ||||||
|  |     BACKLIGHT_OFF      = 5, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* Macro */ | /* Macro */ | ||||||
| @ -316,7 +317,8 @@ enum backlight_opt { | |||||||
| #define ACTION_BACKLIGHT_DECREASE()     ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8) | #define ACTION_BACKLIGHT_DECREASE()     ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8) | ||||||
| #define ACTION_BACKLIGHT_TOGGLE()       ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8) | #define ACTION_BACKLIGHT_TOGGLE()       ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8) | ||||||
| #define ACTION_BACKLIGHT_STEP()         ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 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 */ | /* Command */ | ||||||
| #define ACTION_COMMAND(id, opt)         ACTION(ACT_COMMAND,  (opt)<<8 | (id)) | #define ACTION_COMMAND(id, opt)         ACTION(ACT_COMMAND,  (opt)<<8 | (id)) | ||||||
| /* Function */ | /* Function */ | ||||||
|  | |||||||
| @ -61,6 +61,8 @@ void backlight_decrease(void) | |||||||
| void backlight_toggle(void) | void backlight_toggle(void) | ||||||
| { | { | ||||||
|     backlight_config.enable ^= 1; |     backlight_config.enable ^= 1; | ||||||
|  |     if (backlight_config.raw == 1) // enabled but level = 0
 | ||||||
|  |         backlight_config.level = 1; | ||||||
|     eeconfig_update_backlight(backlight_config.raw); |     eeconfig_update_backlight(backlight_config.raw); | ||||||
|     dprintf("backlight toggle: %u\n", backlight_config.enable); |     dprintf("backlight toggle: %u\n", backlight_config.enable); | ||||||
|     backlight_set(backlight_config.enable ? backlight_config.level : 0); |     backlight_set(backlight_config.enable ? backlight_config.level : 0); | ||||||
| @ -81,7 +83,9 @@ void backlight_step(void) | |||||||
| 
 | 
 | ||||||
| void backlight_level(uint8_t level) | 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; |     backlight_config.enable = !!backlight_config.level; | ||||||
|     eeconfig_update_backlight(backlight_config.raw); |     eeconfig_update_backlight(backlight_config.raw); | ||||||
|     backlight_set(backlight_config.level); |     backlight_set(backlight_config.level); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Balz Guenat
						Balz Guenat