aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/config_options.md4
-rw-r--r--docs/faq_keymap.md2
-rw-r--r--docs/feature_backlight.md28
-rw-r--r--docs/hardware_avr.md3
-rw-r--r--keyboards/atomic/keymaps/pvc/keymap.c12
-rw-r--r--keyboards/bananasplit/config.h2
-rw-r--r--keyboards/bananasplit/keymaps/coloneljesus/config.h2
-rw-r--r--keyboards/bananasplit/keymaps/coloneljesus/keymap.c16
-rw-r--r--keyboards/jd45/keymaps/mjt/keymap.c8
-rw-r--r--keyboards/planck/keymaps/cbbrowne/keymap.c4
-rw-r--r--keyboards/planck/keymaps/experimental/keymap.c4
-rw-r--r--keyboards/planck/keymaps/khord/keymap.c4
-rw-r--r--keyboards/planck/keymaps/pvc/keymap.c12
-rw-r--r--keyboards/planck/keymaps/zach/zach_common_functions.c2
-rwxr-xr-xkeyboards/planck/keymaps/zrichard/keymap.c12
-rw-r--r--keyboards/preonic/keymaps/zach/zach_common_functions.c2
-rw-r--r--keyboards/vision_division/keymaps/default/keymap.c14
-rw-r--r--keyboards/xd75/keymaps/cbbrowne/keymap.c4
-rw-r--r--quantum/keymap_common.c7
-rw-r--r--quantum/quantum.c406
-rw-r--r--quantum/quantum.h9
-rw-r--r--quantum/quantum_keycodes.h22
-rw-r--r--tmk_core/common/action.c7
-rw-r--r--tmk_core/common/action_code.h6
-rw-r--r--tmk_core/common/backlight.c6
25 files changed, 277 insertions, 321 deletions
diff --git a/docs/config_options.md b/docs/config_options.md
index a9ff54995..1dd4cdbaa 100644
--- a/docs/config_options.md
+++ b/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
70 * pin of the backlight - B5, B6, B7 use PWM, others use softPWM 70 * pin of the backlight - B5, B6, B7 use PWM, others use softPWM
71* `#define BACKLIGHT_LEVELS 3` 71* `#define BACKLIGHT_LEVELS 3`
72 * number of levels your backlight will have (not including off) 72 * number of levels your backlight will have (not including off)
73* `#define BACKLIGHT_BREATHING`
74 * enables backlight breathing (only works with backlight pins B5, B6 and B7)
75* `#define BREATHING_PERIOD 6`
76 * the length of one backlight "breath" in seconds
73* `#define DEBOUNCING_DELAY 5` 77* `#define DEBOUNCING_DELAY 5`
74 * the delay when reading the value of the pin (5 is default) 78 * the delay when reading the value of the pin (5 is default)
75* `#define LOCKING_SUPPORT_ENABLE` 79* `#define LOCKING_SUPPORT_ENABLE`
diff --git a/docs/faq_keymap.md b/docs/faq_keymap.md
index 7093dec20..0fed0445f 100644
--- a/docs/faq_keymap.md
+++ b/docs/faq_keymap.md
@@ -127,7 +127,7 @@ https://github.com/tekezo/Karabiner/issues/403
127 127
128## Esc and <code>&#96;</code> on a Single Key 128## Esc and <code>&#96;</code> on a Single Key
129 129
130See the [Grave Escape](feature_grave_escape.md) feature. 130See the [Grave Escape](feature_grave_esc.md) feature.
131 131
132## Arrow on Right Modifier Keys with Dual-Role 132## Arrow on Right Modifier Keys with Dual-Role
133This 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**. 133This 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**.
diff --git a/docs/feature_backlight.md b/docs/feature_backlight.md
index aa747f90e..97421c043 100644
--- a/docs/feature_backlight.md
+++ b/docs/feature_backlight.md
@@ -10,8 +10,30 @@ These keycodes control the backlight. Most keyboards use this for single color i
10|---------|------------------------------------------| 10|---------|------------------------------------------|
11|`BL_TOGG`|Turn the backlight on or off | 11|`BL_TOGG`|Turn the backlight on or off |
12|`BL_STEP`|Cycle through backlight levels | 12|`BL_STEP`|Cycle through backlight levels |
13|`BL_x` |Set a specific backlight level between 0-9| 13|`BL_ON` |Set backlight to max brightness |
14|`BL_ON` |An alias for `BL_9` | 14|`BL_OFF` |Turn backlight off |
15|`BL_OFF` |An alias for `BL_0` |
16|`BL_INC` |Increase backlight level | 15|`BL_INC` |Increase backlight level |
17|`BL_DEC` |Decrease backlight level | 16|`BL_DEC` |Decrease backlight level |
17|`BL_BRTG`|Toggle backlight breathing |
18
19Note that for backlight breathing, you need to have `#define BACKLIGHT_BREATHING` in your config.h.
20
21## Configuration Options in `config.h`
22
23* `BACKLIGHT_PIN B7` defines the pin that controlls the LEDs. Unless you design your own keyboard, you don't need to set this.
24* `BACKLIGHT_LEVELS 3` defines the number of brightness levels (excluding OFF).
25* `BACKLIGHT_BREATHING` if defined, enables backlight breathing. Note that this is only available if `BACKLIGHT_PIN` is B5, B6 or B7.
26* `BREATHING_PERIOD 6` defines the length of one backlight "breath" in seconds.
27
28## Notes on Implementation
29
30To change the brightness when using pins B5, B6 or B7, the PWM (Pulse Width Modulation) functionality of the on-chip timer is used.
31The timer is a counter that counts up to a certain TOP value (`0xFFFF` set in ICR1) before resetting to 0.
32We also set an OCR1x register.
33When the counter reaches the value stored in that register, the PWM pin drops to low.
34The PWM pin is pulled high again when the counter resets to 0.
35Therefore, OCR1x basically sets the duty cycle of the LEDs and as such the brightness where `0` is the darkest and `0xFFFF` the brightest setting.
36
37To enable the breathing effect, we register an interrupt handler to be called whenever the counter resets (with `ISR(TIMER1_OVF_vect)`).
38In this handler, which gets called roughly 244 times per second, we compute the desired brightness using a precomputed brightness curve.
39To disable breathing, we can just disable the respective interrupt vector and reset the brightness to the desired level.
diff --git a/docs/hardware_avr.md b/docs/hardware_avr.md
index c6f3881dc..770817045 100644
--- a/docs/hardware_avr.md
+++ b/docs/hardware_avr.md
@@ -101,8 +101,9 @@ By default QMK supports backlighting on pins `B5`, `B6`, and `B7`. If you are us
101 101
102``` 102```
103#define BACKLIGHT_PIN B7 103#define BACKLIGHT_PIN B7
104#define BACKLIGHT_BREATHING
105#define BACKLIGHT_LEVELS 3 104#define BACKLIGHT_LEVELS 3
105#define BACKLIGHT_BREATHING
106#define BREATHING_PERIOD 6
106``` 107```
107 108
108{% hint style='info' %} 109{% hint style='info' %}
diff --git a/keyboards/atomic/keymaps/pvc/keymap.c b/keyboards/atomic/keymaps/pvc/keymap.c
index 4a7cc863e..2e78e64b1 100644
--- a/keyboards/atomic/keymaps/pvc/keymap.c
+++ b/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)
345 case MACRO_BREATH_SPEED_INC: 345 case MACRO_BREATH_SPEED_INC:
346 if (record->event.pressed) 346 if (record->event.pressed)
347 { 347 {
348 breathing_speed_inc(1); 348 breathing_period_inc();
349 } 349 }
350 break; 350 break;
351 351
352 case MACRO_BREATH_SPEED_DEC: 352 case MACRO_BREATH_SPEED_DEC:
353 if (record->event.pressed) 353 if (record->event.pressed)
354 { 354 {
355 breathing_speed_dec(1); 355 breathing_period_dec();
356 } 356 }
357 break; 357 break;
358 358
@@ -374,7 +374,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
374 if (record->event.pressed) 374 if (record->event.pressed)
375 { 375 {
376 layer_on(LAYER_UPPER); 376 layer_on(LAYER_UPPER);
377 breathing_speed_set(2); 377 breathing_period_set(2);
378 breathing_pulse(); 378 breathing_pulse();
379 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); 379 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
380 } 380 }
@@ -389,7 +389,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
389 if (record->event.pressed) 389 if (record->event.pressed)
390 { 390 {
391 layer_on(LAYER_LOWER); 391 layer_on(LAYER_LOWER);
392 breathing_speed_set(2); 392 breathing_period_set(2);
393 breathing_pulse(); 393 breathing_pulse();
394 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); 394 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
395 } 395 }
@@ -403,13 +403,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
403 case MACRO_FUNCTION: 403 case MACRO_FUNCTION:
404 if (record->event.pressed) 404 if (record->event.pressed)
405 { 405 {
406 breathing_speed_set(3); 406 breathing_period_set(3);
407 breathing_enable(); 407 breathing_enable();
408 layer_on(LAYER_FUNCTION); 408 layer_on(LAYER_FUNCTION);
409 } 409 }
410 else 410 else
411 { 411 {
412 breathing_speed_set(1); 412 breathing_period_set(1);
413 breathing_self_disable(); 413 breathing_self_disable();
414 layer_off(LAYER_FUNCTION); 414 layer_off(LAYER_FUNCTION);
415 } 415 }
diff --git a/keyboards/bananasplit/config.h b/keyboards/bananasplit/config.h
index 4bb5b85e0..5649ab4aa 100644
--- a/keyboards/bananasplit/config.h
+++ b/keyboards/bananasplit/config.h
@@ -42,7 +42,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
42//#define MATRIX_HAS_GHOST 42//#define MATRIX_HAS_GHOST
43 43
44/* number of backlight levels */ 44/* number of backlight levels */
45#define BACKLIGHT_LEVELS 1 45#define BACKLIGHT_LEVELS 3
46 46
47/* mapping backlight LEDs to correct Pin */ 47/* mapping backlight LEDs to correct Pin */
48#define BACKLIGHT_PIN B7 48#define BACKLIGHT_PIN B7
diff --git a/keyboards/bananasplit/keymaps/coloneljesus/config.h b/keyboards/bananasplit/keymaps/coloneljesus/config.h
index 5f2cd13fe..92a67f647 100644
--- a/keyboards/bananasplit/keymaps/coloneljesus/config.h
+++ b/keyboards/bananasplit/keymaps/coloneljesus/config.h
@@ -21,5 +21,7 @@
21 21
22// place overrides here 22// place overrides here
23#define GRAVE_ESC_CTRL_OVERRIDE 23#define GRAVE_ESC_CTRL_OVERRIDE
24#define BACKLIGHT_BREATHING
25#define BREATHING_PERIOD 8
24 26
25#endif 27#endif
diff --git a/keyboards/bananasplit/keymaps/coloneljesus/keymap.c b/keyboards/bananasplit/keymaps/coloneljesus/keymap.c
index ac7f1113a..b5889aa19 100644
--- a/keyboards/bananasplit/keymaps/coloneljesus/keymap.c
+++ b/keyboards/bananasplit/keymaps/coloneljesus/keymap.c
@@ -16,7 +16,7 @@
16#include "bananasplit.h" 16#include "bananasplit.h"
17 17
18enum custom_keycodes { 18enum custom_keycodes {
19 WIN_SWITCH_LAYOUT = SAFE_RANGE 19 WIN_SWITCH_LAYOUT = SAFE_RANGE,
20}; 20};
21 21
22const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { 22const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
@@ -57,7 +57,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
57 _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, \ 57 _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, \
58 KC_CAPS, KC_MPRV, KC_VOLU, KC_MNXT, KC_PGUP, KC_INS, KC_HOME, LCTL(KC_LEFT), LCTL(KC_RGHT), KC_END, _______, _______, _______, KC_PSCR, \ 58 KC_CAPS, KC_MPRV, KC_VOLU, KC_MNXT, KC_PGUP, KC_INS, KC_HOME, LCTL(KC_LEFT), LCTL(KC_RGHT), KC_END, _______, _______, _______, KC_PSCR, \
59 _______, KC_MUTE, KC_VOLD, KC_MPLY, KC_PGDN, KC_DEL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, _______, _______, _______, \ 59 _______, KC_MUTE, KC_VOLD, KC_MPLY, KC_PGDN, KC_DEL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, _______, _______, _______, \
60 _______, _______, _______, _______, _______,_______, LCTL(KC_BSPC), LCTL(KC_DEL), _______, _______, _______, _______, _______, \ 60 _______, BL_STEP, BL_BRTG, _______, _______,_______, LCTL(KC_BSPC), LCTL(KC_DEL), _______, _______, _______, _______, _______, \
61 _______, _______, _______, _______, _______,_______, _______, _______, _______, _______, RESET \ 61 _______, _______, _______, _______, _______,_______, _______, _______, _______, _______, RESET \
62), 62),
63}; 63};
@@ -76,19 +76,19 @@ void matrix_scan_user(void) {
76 76
77bool process_record_user(uint16_t keycode, keyrecord_t *record) { 77bool process_record_user(uint16_t keycode, keyrecord_t *record) {
78 switch (keycode) { 78 switch (keycode) {
79
79 case WIN_SWITCH_LAYOUT: { 80 case WIN_SWITCH_LAYOUT: {
80 // Sends Alt+Shift on both key down and key up. 81 // Sends Alt+Shift on both key down and key up.
81 // Designed to switch between two keyboard layouts on Windows using a locking switch. 82 // Designed to switch between two keyboard layouts on Windows using a locking switch.
82 // Does nothing if right shift is pressed for easy resync. 83 // Does nothing if right shift is pressed for easy resync.
83 if (!(get_mods() & MOD_BIT(KC_RSFT))) { 84 if (!(get_mods() & MOD_BIT(KC_RSFT)))
84 SEND_STRING(SS_DOWN(X_LALT)SS_TAP(X_LSHIFT)SS_UP(X_LALT)); 85 SEND_STRING(SS_DOWN(X_LALT)SS_TAP(X_LSHIFT)SS_UP(X_LALT));
85 return false; 86 return false;
86 }
87 else
88 return false;
89 } 87 }
88
89 default:
90 return true;
90 } 91 }
91 return true;
92} 92}
93 93
94void led_set_user(uint8_t usb_led) { 94void led_set_user(uint8_t usb_led) {
diff --git a/keyboards/jd45/keymaps/mjt/keymap.c b/keyboards/jd45/keymaps/mjt/keymap.c
index 1a7302216..610552ecf 100644
--- a/keyboards/jd45/keymaps/mjt/keymap.c
+++ b/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)
50 // action_function_tap may also handle this... 50 // action_function_tap may also handle this...
51 if (record->event.pressed) 51 if (record->event.pressed)
52 { 52 {
53 breathing_speed_set(3); 53 breathing_period_set(3);
54 breathing_enable(); 54 breathing_enable();
55 layer_on(1); 55 layer_on(1);
56 } 56 }
57 else 57 else
58 { 58 {
59 breathing_speed_set(1); 59 breathing_period_set(1);
60 breathing_self_disable(); 60 breathing_self_disable();
61 layer_off(1); 61 layer_off(1);
62 } 62 }
@@ -64,13 +64,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
64 case M_LAYER2: 64 case M_LAYER2:
65 if (record->event.pressed) 65 if (record->event.pressed)
66 { 66 {
67 breathing_speed_set(2); 67 breathing_period_set(2);
68 breathing_pulse(); 68 breathing_pulse();
69 layer_on(2); 69 layer_on(2);
70 } 70 }
71 else 71 else
72 { 72 {
73 breathing_speed_set(1); 73 breathing_period_set(1);
74 breathing_self_disable(); 74 breathing_self_disable();
75 layer_off(2); 75 layer_off(2);
76 } 76 }
diff --git a/keyboards/planck/keymaps/cbbrowne/keymap.c b/keyboards/planck/keymaps/cbbrowne/keymap.c
index d1214dda1..9bae6fb50 100644
--- a/keyboards/planck/keymaps/cbbrowne/keymap.c
+++ b/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)
220 { 220 {
221 layer_on(_RAISE); 221 layer_on(_RAISE);
222#ifdef BACKLIGHT_ENABLE 222#ifdef BACKLIGHT_ENABLE
223 breathing_speed_set(2); 223 breathing_period_set(2);
224 breathing_pulse(); 224 breathing_pulse();
225#endif 225#endif
226 update_tri_layer(_LOWER, _RAISE, _ADJUST); 226 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)
236 { 236 {
237 layer_on(_LOWER); 237 layer_on(_LOWER);
238#ifdef BACKLIGHT_ENABLE 238#ifdef BACKLIGHT_ENABLE
239 breathing_speed_set(2); 239 breathing_period_set(2);
240 breathing_pulse(); 240 breathing_pulse();
241#endif 241#endif
242 update_tri_layer(_LOWER, _RAISE, _ADJUST); 242 update_tri_layer(_LOWER, _RAISE, _ADJUST);
diff --git a/keyboards/planck/keymaps/experimental/keymap.c b/keyboards/planck/keymaps/experimental/keymap.c
index 272c09332..feeb137fa 100644
--- a/keyboards/planck/keymaps/experimental/keymap.c
+++ b/keyboards/planck/keymaps/experimental/keymap.c
@@ -242,7 +242,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
242 if (record->event.pressed) { 242 if (record->event.pressed) {
243 layer_on(_LOWER); 243 layer_on(_LOWER);
244 #ifdef BACKLIGHT_ENABLE 244 #ifdef BACKLIGHT_ENABLE
245 breathing_speed_set(2); 245 breathing_period_set(2);
246 breathing_pulse(); 246 breathing_pulse();
247 #endif 247 #endif
248 update_tri_layer(_LOWER, _RAISE, _ADJUST); 248 update_tri_layer(_LOWER, _RAISE, _ADJUST);
@@ -256,7 +256,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
256 if (record->event.pressed) { 256 if (record->event.pressed) {
257 layer_on(_RAISE); 257 layer_on(_RAISE);
258 #ifdef BACKLIGHT_ENABLE 258 #ifdef BACKLIGHT_ENABLE
259 breathing_speed_set(2); 259 breathing_period_set(2);
260 breathing_pulse(); 260 breathing_pulse();
261 #endif 261 #endif
262 update_tri_layer(_LOWER, _RAISE, _ADJUST); 262 update_tri_layer(_LOWER, _RAISE, _ADJUST);
diff --git a/keyboards/planck/keymaps/khord/keymap.c b/keyboards/planck/keymaps/khord/keymap.c
index c8022a389..c515a0d36 100644
--- a/keyboards/planck/keymaps/khord/keymap.c
+++ b/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) {
128 break; 128 break;
129 case MACRO_BREATH_SPEED_INC: 129 case MACRO_BREATH_SPEED_INC:
130 if (record->event.pressed) { 130 if (record->event.pressed) {
131 breathing_speed_inc(1); 131 breathing_period_inc();
132 } 132 }
133 break; 133 break;
134 case MACRO_BREATH_SPEED_DEC: 134 case MACRO_BREATH_SPEED_DEC:
135 if (record->event.pressed) { 135 if (record->event.pressed) {
136 breathing_speed_dec(1); 136 breathing_period_dec();
137 } 137 }
138 break; 138 break;
139 case MACRO_BREATH_DEFAULT: 139 case MACRO_BREATH_DEFAULT:
diff --git a/keyboards/planck/keymaps/pvc/keymap.c b/keyboards/planck/keymaps/pvc/keymap.c
index 60f6d925a..820018af6 100644
--- a/keyboards/planck/keymaps/pvc/keymap.c
+++ b/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)
323 case MACRO_BREATH_SPEED_INC: 323 case MACRO_BREATH_SPEED_INC:
324 if (record->event.pressed) 324 if (record->event.pressed)
325 { 325 {
326 breathing_speed_inc(1); 326 breathing_period_inc();
327 } 327 }
328 break; 328 break;
329 329
330 case MACRO_BREATH_SPEED_DEC: 330 case MACRO_BREATH_SPEED_DEC:
331 if (record->event.pressed) 331 if (record->event.pressed)
332 { 332 {
333 breathing_speed_dec(1); 333 breathing_period_dec();
334 } 334 }
335 break; 335 break;
336 336
@@ -352,7 +352,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
352 if (record->event.pressed) 352 if (record->event.pressed)
353 { 353 {
354 layer_on(LAYER_UPPER); 354 layer_on(LAYER_UPPER);
355 breathing_speed_set(2); 355 breathing_period_set(2);
356 breathing_pulse(); 356 breathing_pulse();
357 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); 357 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
358 } 358 }
@@ -367,7 +367,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
367 if (record->event.pressed) 367 if (record->event.pressed)
368 { 368 {
369 layer_on(LAYER_LOWER); 369 layer_on(LAYER_LOWER);
370 breathing_speed_set(2); 370 breathing_period_set(2);
371 breathing_pulse(); 371 breathing_pulse();
372 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); 372 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
373 } 373 }
@@ -381,13 +381,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
381 case MACRO_FUNCTION: 381 case MACRO_FUNCTION:
382 if (record->event.pressed) 382 if (record->event.pressed)
383 { 383 {
384 breathing_speed_set(3); 384 breathing_period_set(3);
385 breathing_enable(); 385 breathing_enable();
386 layer_on(LAYER_FUNCTION); 386 layer_on(LAYER_FUNCTION);
387 } 387 }
388 else 388 else
389 { 389 {
390 breathing_speed_set(1); 390 breathing_period_set(1);
391 breathing_self_disable(); 391 breathing_self_disable();
392 layer_off(LAYER_FUNCTION); 392 layer_off(LAYER_FUNCTION);
393 } 393 }
diff --git a/keyboards/planck/keymaps/zach/zach_common_functions.c b/keyboards/planck/keymaps/zach/zach_common_functions.c
index f824b4033..e6aeaa50a 100644
--- a/keyboards/planck/keymaps/zach/zach_common_functions.c
+++ b/keyboards/planck/keymaps/zach/zach_common_functions.c
@@ -270,7 +270,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
270 PLAY_SONG(tone_ctrl_mod); 270 PLAY_SONG(tone_ctrl_mod);
271 #endif 271 #endif
272 #ifdef BACKLIGHT_BREATHING 272 #ifdef BACKLIGHT_BREATHING
273 breathing_speed_set(2); 273 breathing_period_set(2);
274 breathing_pulse(); 274 breathing_pulse();
275 #endif 275 #endif
276 } 276 }
diff --git a/keyboards/planck/keymaps/zrichard/keymap.c b/keyboards/planck/keymaps/zrichard/keymap.c
index c40492f5e..cf4478cee 100755
--- a/keyboards/planck/keymaps/zrichard/keymap.c
+++ b/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)
332 case MACRO_BREATH_SPEED_INC: 332 case MACRO_BREATH_SPEED_INC:
333 if (record->event.pressed) 333 if (record->event.pressed)
334 { 334 {
335 breathing_speed_inc(1); 335 breathing_period_inc();
336 } 336 }
337 break; 337 break;
338 338
339 case MACRO_BREATH_SPEED_DEC: 339 case MACRO_BREATH_SPEED_DEC:
340 if (record->event.pressed) 340 if (record->event.pressed)
341 { 341 {
342 breathing_speed_dec(1); 342 breathing_period_dec();
343 } 343 }
344 break; 344 break;
345 345
@@ -361,7 +361,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
361 if (record->event.pressed) 361 if (record->event.pressed)
362 { 362 {
363 layer_on(LAYER_UPPER); 363 layer_on(LAYER_UPPER);
364 breathing_speed_set(2); 364 breathing_period_set(2);
365 breathing_pulse(); 365 breathing_pulse();
366 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); 366 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
367 } 367 }
@@ -376,7 +376,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
376 if (record->event.pressed) 376 if (record->event.pressed)
377 { 377 {
378 layer_on(LAYER_LOWER); 378 layer_on(LAYER_LOWER);
379 breathing_speed_set(2); 379 breathing_period_set(2);
380 breathing_pulse(); 380 breathing_pulse();
381 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); 381 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
382 } 382 }
@@ -390,13 +390,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
390 case MACRO_FUNCTION: 390 case MACRO_FUNCTION:
391 if (record->event.pressed) 391 if (record->event.pressed)
392 { 392 {
393 breathing_speed_set(3); 393 breathing_period_set(3);
394 breathing_enable(); 394 breathing_enable();
395 layer_on(LAYER_FUNCTION); 395 layer_on(LAYER_FUNCTION);
396 } 396 }
397 else 397 else
398 { 398 {
399 breathing_speed_set(1); 399 breathing_period_set(1);
400 breathing_self_disable(); 400 breathing_self_disable();
401 layer_off(LAYER_FUNCTION); 401 layer_off(LAYER_FUNCTION);
402 } 402 }
diff --git a/keyboards/preonic/keymaps/zach/zach_common_functions.c b/keyboards/preonic/keymaps/zach/zach_common_functions.c
index f824b4033..e6aeaa50a 100644
--- a/keyboards/preonic/keymaps/zach/zach_common_functions.c
+++ b/keyboards/preonic/keymaps/zach/zach_common_functions.c
@@ -270,7 +270,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
270 PLAY_SONG(tone_ctrl_mod); 270 PLAY_SONG(tone_ctrl_mod);
271 #endif 271 #endif
272 #ifdef BACKLIGHT_BREATHING 272 #ifdef BACKLIGHT_BREATHING
273 breathing_speed_set(2); 273 breathing_period_set(2);
274 breathing_pulse(); 274 breathing_pulse();
275 #endif 275 #endif
276 } 276 }
diff --git a/keyboards/vision_division/keymaps/default/keymap.c b/keyboards/vision_division/keymaps/default/keymap.c
index c40bf1ef6..31b107661 100644
--- a/keyboards/vision_division/keymaps/default/keymap.c
+++ b/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)
406 case MACRO_BREATH_SPEED_INC: 406 case MACRO_BREATH_SPEED_INC:
407 if (record->event.pressed) 407 if (record->event.pressed)
408 { 408 {
409 breathing_speed_inc(1); 409 breathing_period_inc();
410 } 410 }
411 break; 411 break;
412 412
413 case MACRO_BREATH_SPEED_DEC: 413 case MACRO_BREATH_SPEED_DEC:
414 if (record->event.pressed) 414 if (record->event.pressed)
415 { 415 {
416 breathing_speed_dec(1); 416 breathing_period_dec();
417 } 417 }
418 break; 418 break;
419 419
420 case MACRO_BREATH_DEFAULT: 420 case MACRO_BREATH_DEFAULT:
421 if (record->event.pressed) 421 if (record->event.pressed)
422 { 422 {
423 breathing_defaults(); 423 breathing_period_default();
424 } 424 }
425 break; 425 break;
426 426
@@ -435,7 +435,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
435 if (record->event.pressed) 435 if (record->event.pressed)
436 { 436 {
437 layer_on(LAYER_UPPER); 437 layer_on(LAYER_UPPER);
438 breathing_speed_set(2); 438 breathing_period_set(2);
439 breathing_pulse(); 439 breathing_pulse();
440 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); 440 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
441 } 441 }
@@ -450,7 +450,7 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
450 if (record->event.pressed) 450 if (record->event.pressed)
451 { 451 {
452 layer_on(LAYER_LOWER); 452 layer_on(LAYER_LOWER);
453 breathing_speed_set(2); 453 breathing_period_set(2);
454 breathing_pulse(); 454 breathing_pulse();
455 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST); 455 update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
456 } 456 }
@@ -464,13 +464,13 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
464 case MACRO_FUNCTION: 464 case MACRO_FUNCTION:
465 if (record->event.pressed) 465 if (record->event.pressed)
466 { 466 {
467 breathing_speed_set(3); 467 breathing_period_set(3);
468 breathing_enable(); 468 breathing_enable();
469 layer_on(LAYER_FUNCTION); 469 layer_on(LAYER_FUNCTION);
470 } 470 }
471 else 471 else
472 { 472 {
473 breathing_speed_set(1); 473 breathing_period_set(1);
474 breathing_self_disable(); 474 breathing_self_disable();
475 layer_off(LAYER_FUNCTION); 475 layer_off(LAYER_FUNCTION);
476 } 476 }
diff --git a/keyboards/xd75/keymaps/cbbrowne/keymap.c b/keyboards/xd75/keymaps/cbbrowne/keymap.c
index 5496ed40d..ec98b6d5a 100644
--- a/keyboards/xd75/keymaps/cbbrowne/keymap.c
+++ b/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)
265 { 265 {
266 layer_on(_RAISE); 266 layer_on(_RAISE);
267#ifdef BACKLIGHT_ENABLE 267#ifdef BACKLIGHT_ENABLE
268 breathing_speed_set(2); 268 breathing_period_set(2);
269 breathing_pulse(); 269 breathing_pulse();
270#endif 270#endif
271 update_tri_layer(_LOWER, _RAISE, _ADJUST); 271 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)
281 { 281 {
282 layer_on(_LOWER); 282 layer_on(_LOWER);
283#ifdef BACKLIGHT_ENABLE 283#ifdef BACKLIGHT_ENABLE
284 breathing_speed_set(2); 284 breathing_period_set(2);
285 breathing_pulse(); 285 breathing_pulse();
286#endif 286#endif
287 update_tri_layer(_LOWER, _RAISE, _ADJUST); 287 update_tri_layer(_LOWER, _RAISE, _ADJUST);
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index b1460c53c..a0d4c1ddb 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -127,8 +127,11 @@ action_t action_for_key(uint8_t layer, keypos_t key)
127 action.code = ACTION_MODS_TAP_KEY(mod, keycode & 0xFF); 127 action.code = ACTION_MODS_TAP_KEY(mod, keycode & 0xFF);
128 break; 128 break;
129 #ifdef BACKLIGHT_ENABLE 129 #ifdef BACKLIGHT_ENABLE
130 case BL_0 ... BL_15: 130 case BL_ON:
131 action.code = ACTION_BACKLIGHT_LEVEL(keycode - BL_0); 131 action.code = ACTION_BACKLIGHT_ON();
132 break;
133 case BL_OFF:
134 action.code = ACTION_BACKLIGHT_OFF();
132 break; 135 break;
133 case BL_DEC: 136 case BL_DEC:
134 action.code = ACTION_BACKLIGHT_DECREASE(); 137 action.code = ACTION_BACKLIGHT_DECREASE();
diff --git a/quantum/quantum.c b/quantum/quantum.c
index c80975f21..88617412c 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -23,6 +23,10 @@
23#define TAPPING_TERM 200 23#define TAPPING_TERM 200
24#endif 24#endif
25 25
26#ifndef BREATHING_PERIOD
27#define BREATHING_PERIOD 6
28#endif
29
26#include "backlight.h" 30#include "backlight.h"
27extern backlight_config_t backlight_config; 31extern backlight_config_t backlight_config;
28 32
@@ -618,7 +622,17 @@ bool process_record_quantum(keyrecord_t *record) {
618 } 622 }
619 623
620 send_keyboard_report(); 624 send_keyboard_report();
625 return false;
621 } 626 }
627
628#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_BREATHING)
629 case BL_BRTG: {
630 if (record->event.pressed)
631 breathing_toggle();
632 return false;
633 }
634#endif
635
622 default: { 636 default: {
623 shift_interrupted[0] = true; 637 shift_interrupted[0] = true;
624 shift_interrupted[1] = true; 638 shift_interrupted[1] = true;
@@ -831,6 +845,7 @@ void matrix_scan_quantum() {
831 845
832static const uint8_t backlight_pin = BACKLIGHT_PIN; 846static const uint8_t backlight_pin = BACKLIGHT_PIN;
833 847
848// depending on the pin, we use a different output compare unit
834#if BACKLIGHT_PIN == B7 849#if BACKLIGHT_PIN == B7
835# define COM1x1 COM1C1 850# define COM1x1 COM1C1
836# define OCR1x OCR1C 851# define OCR1x OCR1C
@@ -841,17 +856,18 @@ static const uint8_t backlight_pin = BACKLIGHT_PIN;
841# define COM1x1 COM1A1 856# define COM1x1 COM1A1
842# define OCR1x OCR1A 857# define OCR1x OCR1A
843#else 858#else
844# define NO_BACKLIGHT_CLOCK 859# define NO_HARDWARE_PWM
845#endif 860#endif
846 861
847#ifndef BACKLIGHT_ON_STATE 862#ifndef BACKLIGHT_ON_STATE
848#define BACKLIGHT_ON_STATE 0 863#define BACKLIGHT_ON_STATE 0
849#endif 864#endif
850 865
866#ifdef NO_HARDWARE_PWM // pwm through software
867
851__attribute__ ((weak)) 868__attribute__ ((weak))
852void backlight_init_ports(void) 869void backlight_init_ports(void)
853{ 870{
854
855 // Setup backlight pin as output and output to on state. 871 // Setup backlight pin as output and output to on state.
856 // DDRx |= n 872 // DDRx |= n
857 _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF); 873 _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF);
@@ -862,83 +878,15 @@ void backlight_init_ports(void)
862 // PORTx |= n 878 // PORTx |= n
863 _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF); 879 _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
864 #endif 880 #endif
865
866 #ifndef NO_BACKLIGHT_CLOCK
867 // Use full 16-bit resolution.
868 ICR1 = 0xFFFF;
869
870 // I could write a wall of text here to explain... but TL;DW
871 // Go read the ATmega32u4 datasheet.
872 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
873
874 // Pin PB7 = OCR1C (Timer 1, Channel C)
875 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
876 // (i.e. start high, go low when counter matches.)
877 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
878 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
879
880 TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
881 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
882 #endif
883
884 backlight_init();
885 #ifdef BACKLIGHT_BREATHING
886 breathing_defaults();
887 #endif
888} 881}
889 882
890__attribute__ ((weak)) 883__attribute__ ((weak))
891void backlight_set(uint8_t level) 884void backlight_set(uint8_t level) {}
892{
893 // Prevent backlight blink on lowest level
894 // #if BACKLIGHT_ON_STATE == 0
895 // // PORTx &= ~n
896 // _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
897 // #else
898 // // PORTx |= n
899 // _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
900 // #endif
901
902 if ( level == 0 ) {
903 #ifndef NO_BACKLIGHT_CLOCK
904 // Turn off PWM control on backlight pin, revert to output low.
905 TCCR1A &= ~(_BV(COM1x1));
906 OCR1x = 0x0;
907 #else
908 // #if BACKLIGHT_ON_STATE == 0
909 // // PORTx |= n
910 // _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
911 // #else
912 // // PORTx &= ~n
913 // _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
914 // #endif
915 #endif
916 }
917 #ifndef NO_BACKLIGHT_CLOCK
918 else if ( level == BACKLIGHT_LEVELS ) {
919 // Turn on PWM control of backlight pin
920 TCCR1A |= _BV(COM1x1);
921 // Set the brightness
922 OCR1x = 0xFFFF;
923 }
924 else {
925 // Turn on PWM control of backlight pin
926 TCCR1A |= _BV(COM1x1);
927 // Set the brightness
928 OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
929 }
930 #endif
931
932 #ifdef BACKLIGHT_BREATHING
933 breathing_intensity_default();
934 #endif
935}
936 885
937uint8_t backlight_tick = 0; 886uint8_t backlight_tick = 0;
938 887
939void backlight_task(void) { 888void backlight_task(void) {
940 #ifdef NO_BACKLIGHT_CLOCK 889 if ((0xFFFF >> ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) {
941 if ((0xFFFF >> ((BACKLIGHT_LEVELS - backlight_config.level) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) {
942 #if BACKLIGHT_ON_STATE == 0 890 #if BACKLIGHT_ON_STATE == 0
943 // PORTx &= ~n 891 // PORTx &= ~n
944 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); 892 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
@@ -955,232 +903,216 @@ void backlight_task(void) {
955 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF); 903 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
956 #endif 904 #endif
957 } 905 }
958 backlight_tick = (backlight_tick + 1) % 16; 906 backlight_tick = backlight_tick + 1 % 16;
959 #endif
960} 907}
961 908
962#ifdef BACKLIGHT_BREATHING 909#ifdef BACKLIGHT_BREATHING
910#error "Backlight breathing only available with hardware PWM. Please disable."
911#endif
963 912
964#ifdef NO_BACKLIGHT_CLOCK 913#else // pwm through timer
965void breathing_defaults(void) {} 914
966void breathing_intensity_default(void) {} 915#define TIMER_TOP 0xFFFFU
967#else 916
917// See http://jared.geek.nz/2013/feb/linear-led-pwm
918static uint16_t cie_lightness(uint16_t v) {
919 if (v <= 5243) // if below 8% of max
920 return v / 9; // same as dividing by 900%
921 else {
922 uint32_t y = (((uint32_t) v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
923 // to get a useful result with integer division, we shift left in the expression above
924 // and revert what we've done again after squaring.
925 y = y * y * y >> 8;
926 if (y > 0xFFFFUL) // prevent overflow
927 return 0xFFFFU;
928 else
929 return (uint16_t) y;
930 }
931}
932
933// range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val.
934static inline void set_pwm(uint16_t val) {
935 OCR1x = val;
936}
937
938__attribute__ ((weak))
939void backlight_set(uint8_t level) {
940 if (level > BACKLIGHT_LEVELS)
941 level = BACKLIGHT_LEVELS;
942
943 if (level == 0) {
944 // Turn off PWM control on backlight pin
945 TCCR1A &= ~(_BV(COM1x1));
946 } else {
947 // Turn on PWM control of backlight pin
948 TCCR1A |= _BV(COM1x1);
949 }
950 // Set the brightness
951 set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS));
952}
953
954void backlight_task(void) {}
955
956#ifdef BACKLIGHT_BREATHING
968 957
969#define BREATHING_NO_HALT 0 958#define BREATHING_NO_HALT 0
970#define BREATHING_HALT_OFF 1 959#define BREATHING_HALT_OFF 1
971#define BREATHING_HALT_ON 2 960#define BREATHING_HALT_ON 2
961#define BREATHING_STEPS 128
972 962
973static uint8_t breath_intensity; 963static uint8_t breathing_period = BREATHING_PERIOD;
974static uint8_t breath_speed; 964static uint8_t breathing_halt = BREATHING_NO_HALT;
975static uint16_t breathing_index; 965static uint16_t breathing_counter = 0;
976static uint8_t breathing_halt;
977 966
978void breathing_enable(void) 967bool is_breathing(void) {
979{ 968 return !!(TIMSK1 & _BV(TOIE1));
980 if (get_backlight_level() == 0) 969}
981 {
982 breathing_index = 0;
983 }
984 else
985 {
986 // Set breathing_index to be at the midpoint (brightest point)
987 breathing_index = 0x20 << breath_speed;
988 }
989 970
990 breathing_halt = BREATHING_NO_HALT; 971#define breathing_interrupt_enable() do {TIMSK1 |= _BV(TOIE1);} while (0)
972#define breathing_interrupt_disable() do {TIMSK1 &= ~_BV(TOIE1);} while (0)
973#define breathing_min() do {breathing_counter = 0;} while (0)
974#define breathing_max() do {breathing_counter = breathing_period * 244 / 2;} while (0)
991 975
992 // Enable breathing interrupt 976void breathing_enable(void)
993 TIMSK1 |= _BV(OCIE1A); 977{
978 breathing_counter = 0;
979 breathing_halt = BREATHING_NO_HALT;
980 breathing_interrupt_enable();
994} 981}
995 982
996void breathing_pulse(void) 983void breathing_pulse(void)
997{ 984{
998 if (get_backlight_level() == 0) 985 if (get_backlight_level() == 0)
999 { 986 breathing_min();
1000 breathing_index = 0;
1001 }
1002 else 987 else
1003 { 988 breathing_max();
1004 // Set breathing_index to be at the midpoint + 1 (brightest point)
1005 breathing_index = 0x21 << breath_speed;
1006 }
1007
1008 breathing_halt = BREATHING_HALT_ON; 989 breathing_halt = BREATHING_HALT_ON;
1009 990 breathing_interrupt_enable();
1010 // Enable breathing interrupt
1011 TIMSK1 |= _BV(OCIE1A);
1012} 991}
1013 992
1014void breathing_disable(void) 993void breathing_disable(void)
1015{ 994{
1016 // Disable breathing interrupt 995 breathing_interrupt_disable();
1017 TIMSK1 &= ~_BV(OCIE1A); 996 // Restore backlight level
1018 backlight_set(get_backlight_level()); 997 backlight_set(get_backlight_level());
1019} 998}
1020 999
1021void breathing_self_disable(void) 1000void breathing_self_disable(void)
1022{ 1001{
1023 if (get_backlight_level() == 0) 1002 if (get_backlight_level() == 0)
1024 { 1003 breathing_halt = BREATHING_HALT_OFF;
1025 breathing_halt = BREATHING_HALT_OFF; 1004 else
1026 } 1005 breathing_halt = BREATHING_HALT_ON;
1027 else
1028 {
1029 breathing_halt = BREATHING_HALT_ON;
1030 }
1031
1032 //backlight_set(get_backlight_level());
1033} 1006}
1034 1007
1035void breathing_toggle(void) 1008void breathing_toggle(void) {
1036{ 1009 if (is_breathing())
1037 if (!is_breathing()) 1010 breathing_disable();
1038 { 1011 else
1039 if (get_backlight_level() == 0) 1012 breathing_enable();
1040 {
1041 breathing_index = 0;
1042 }
1043 else
1044 {
1045 // Set breathing_index to be at the midpoint + 1 (brightest point)
1046 breathing_index = 0x21 << breath_speed;
1047 }
1048
1049 breathing_halt = BREATHING_NO_HALT;
1050 }
1051
1052 // Toggle breathing interrupt
1053 TIMSK1 ^= _BV(OCIE1A);
1054
1055 // Restore backlight level
1056 if (!is_breathing())
1057 {
1058 backlight_set(get_backlight_level());
1059 }
1060} 1013}
1061 1014
1062bool is_breathing(void) 1015void breathing_period_set(uint8_t value)
1063{ 1016{
1064 return (TIMSK1 && _BV(OCIE1A)); 1017 if (!value)
1018 value = 1;
1019 breathing_period = value;
1065} 1020}
1066 1021
1067void breathing_intensity_default(void) 1022void breathing_period_default(void) {
1068{ 1023 breathing_period_set(BREATHING_PERIOD);
1069 //breath_intensity = (uint8_t)((uint16_t)100 * (uint16_t)get_backlight_level() / (uint16_t)BACKLIGHT_LEVELS);
1070 breath_intensity = ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2));
1071} 1024}
1072 1025
1073void breathing_intensity_set(uint8_t value) 1026void breathing_period_inc(void)
1074{ 1027{
1075 breath_intensity = value; 1028 breathing_period_set(breathing_period+1);
1076} 1029}
1077 1030
1078void breathing_speed_default(void) 1031void breathing_period_dec(void)
1079{ 1032{
1080 breath_speed = 4; 1033 breathing_period_set(breathing_period-1);
1081} 1034}
1082 1035
1083void breathing_speed_set(uint8_t value) 1036/* To generate breathing curve in python:
1084{ 1037 * from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
1085 bool is_breathing_now = is_breathing(); 1038 */
1086 uint8_t old_breath_speed = breath_speed; 1039static 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};
1087
1088 if (is_breathing_now)
1089 {
1090 // Disable breathing interrupt
1091 TIMSK1 &= ~_BV(OCIE1A);
1092 }
1093
1094 breath_speed = value;
1095
1096 if (is_breathing_now)
1097 {
1098 // Adjust index to account for new speed
1099 breathing_index = (( (uint8_t)( (breathing_index) >> old_breath_speed ) ) & 0x3F) << breath_speed;
1100
1101 // Enable breathing interrupt
1102 TIMSK1 |= _BV(OCIE1A);
1103 }
1104
1105}
1106 1040
1107void breathing_speed_inc(uint8_t value) 1041// Use this before the cie_lightness function.
1108{ 1042static inline uint16_t scale_backlight(uint16_t v) {
1109 if ((uint16_t)(breath_speed - value) > 10 ) 1043 return v / BACKLIGHT_LEVELS * get_backlight_level();
1110 {
1111 breathing_speed_set(0);
1112 }
1113 else
1114 {
1115 breathing_speed_set(breath_speed - value);
1116 }
1117} 1044}
1118 1045
1119void breathing_speed_dec(uint8_t value) 1046/* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run
1047 * about 244 times per second.
1048 */
1049ISR(TIMER1_OVF_vect)
1120{ 1050{
1121 if ((uint16_t)(breath_speed + value) > 10 ) 1051 uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS;
1122 { 1052 // resetting after one period to prevent ugly reset at overflow.
1123 breathing_speed_set(10); 1053 breathing_counter = (breathing_counter + 1) % (breathing_period * 244);
1124 } 1054 uint8_t index = breathing_counter / interval % BREATHING_STEPS;
1125 else 1055
1126 { 1056 if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) ||
1127 breathing_speed_set(breath_speed + value); 1057 ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1)))
1128 } 1058 {
1129} 1059 breathing_interrupt_disable();
1060 }
1130 1061
1131void breathing_defaults(void) 1062 set_pwm(cie_lightness(scale_backlight((uint16_t) pgm_read_byte(&breathing_table[index]) * 0x0101U)));
1132{
1133 breathing_intensity_default();
1134 breathing_speed_default();
1135 breathing_halt = BREATHING_NO_HALT;
1136} 1063}
1137 1064
1138/* Breathing Sleep LED brighness(PWM On period) table 1065#endif // BACKLIGHT_BREATHING
1139 * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
1140 *
1141 * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
1142 * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
1143 */
1144static const uint8_t breathing_table[64] PROGMEM = {
1145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
1146 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
1147255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
1148 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1149};
1150 1066
1151ISR(TIMER1_COMPA_vect) 1067__attribute__ ((weak))
1068void backlight_init_ports(void)
1152{ 1069{
1153 // OCR1x = (pgm_read_byte(&breathing_table[ ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F ] )) * breath_intensity; 1070 // Setup backlight pin as output and output to on state.
1154 1071 // DDRx |= n
1155 1072 _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF);
1156 uint8_t local_index = ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F; 1073 #if BACKLIGHT_ON_STATE == 0
1157 1074 // PORTx &= ~n
1158 if (((breathing_halt == BREATHING_HALT_ON) && (local_index == 0x20)) || ((breathing_halt == BREATHING_HALT_OFF) && (local_index == 0x3F))) 1075 _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
1159 { 1076 #else
1160 // Disable breathing interrupt 1077 // PORTx |= n
1161 TIMSK1 &= ~_BV(OCIE1A); 1078 _SFR_IO8((backlight_pin >> 4) + 2) |= _BV(backlight_pin & 0xF);
1162 } 1079 #endif
1163 1080 // I could write a wall of text here to explain... but TL;DW
1164 OCR1x = (uint16_t)(((uint16_t)pgm_read_byte(&breathing_table[local_index]) * 257)) >> breath_intensity; 1081 // Go read the ATmega32u4 datasheet.
1082 // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
1083
1084 // Pin PB7 = OCR1C (Timer 1, Channel C)
1085 // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
1086 // (i.e. start high, go low when counter matches.)
1087 // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
1088 // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
1089
1090 /*
1091 14.8.3:
1092 "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 [..]."
1093 "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)."
1094 */
1095
1096 TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
1097 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
1098 // Use full 16-bit resolution. Counter counts to ICR1 before reset to 0.
1099 ICR1 = TIMER_TOP;
1165 1100
1101 backlight_init();
1102 #ifdef BACKLIGHT_BREATHING
1103 breathing_enable();
1104 #endif
1166} 1105}
1167 1106
1168#endif // NO_BACKLIGHT_CLOCK 1107#endif // NO_HARDWARE_PWM
1169#endif // breathing
1170 1108
1171#else // backlight 1109#else // backlight
1172 1110
1173__attribute__ ((weak)) 1111__attribute__ ((weak))
1174void backlight_init_ports(void) 1112void backlight_init_ports(void) {}
1175{
1176
1177}
1178 1113
1179__attribute__ ((weak)) 1114__attribute__ ((weak))
1180void backlight_set(uint8_t level) 1115void backlight_set(uint8_t level) {}
1181{
1182
1183}
1184 1116
1185#endif // backlight 1117#endif // backlight
1186 1118
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 056d37292..6ca5ecb5c 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -173,12 +173,11 @@ void breathing_self_disable(void);
173void breathing_toggle(void); 173void breathing_toggle(void);
174bool is_breathing(void); 174bool is_breathing(void);
175 175
176void breathing_defaults(void);
177void breathing_intensity_default(void); 176void breathing_intensity_default(void);
178void breathing_speed_default(void); 177void breathing_period_default(void);
179void breathing_speed_set(uint8_t value); 178void breathing_period_set(uint8_t value);
180void breathing_speed_inc(uint8_t value); 179void breathing_period_inc(void);
181void breathing_speed_dec(uint8_t value); 180void breathing_period_dec(void);
182#endif 181#endif
183 182
184#endif 183#endif
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 65bf9e141..1b9a7534c 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -380,26 +380,13 @@ enum quantum_keycodes {
380#endif // MIDI_ADVANCED 380#endif // MIDI_ADVANCED
381 381
382 // Backlight functionality 382 // Backlight functionality
383 BL_0, 383 BL_ON,
384 BL_1, 384 BL_OFF,
385 BL_2,
386 BL_3,
387 BL_4,
388 BL_5,
389 BL_6,
390 BL_7,
391 BL_8,
392 BL_9,
393 BL_10,
394 BL_11,
395 BL_12,
396 BL_13,
397 BL_14,
398 BL_15,
399 BL_DEC, 385 BL_DEC,
400 BL_INC, 386 BL_INC,
401 BL_TOGG, 387 BL_TOGG,
402 BL_STEP, 388 BL_STEP,
389 BL_BRTG,
403 390
404 // RGB functionality 391 // RGB functionality
405 RGB_TOG, 392 RGB_TOG,
@@ -579,9 +566,6 @@ enum quantum_keycodes {
579#define AG_SWAP MAGIC_SWAP_ALT_GUI 566#define AG_SWAP MAGIC_SWAP_ALT_GUI
580#define AG_NORM MAGIC_UNSWAP_ALT_GUI 567#define AG_NORM MAGIC_UNSWAP_ALT_GUI
581 568
582#define BL_ON BL_9
583#define BL_OFF BL_0
584
585// GOTO layer - 16 layers max 569// GOTO layer - 16 layers max
586// when: 570// when:
587// ON_PRESS = 1 571// ON_PRESS = 1
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index b39aa4cbc..dd3a5b3ee 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -512,8 +512,11 @@ void process_action(keyrecord_t *record, action_t action)
512 case BACKLIGHT_STEP: 512 case BACKLIGHT_STEP:
513 backlight_step(); 513 backlight_step();
514 break; 514 break;
515 case BACKLIGHT_LEVEL: 515 case BACKLIGHT_ON:
516 backlight_level(action.backlight.level); 516 backlight_level(BACKLIGHT_LEVELS);
517 break;
518 case BACKLIGHT_OFF:
519 backlight_level(0);
517 break; 520 break;
518 } 521 }
519 } 522 }
diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h
index b15aaa0eb..05bc84573 100644
--- a/tmk_core/common/action_code.h
+++ b/tmk_core/common/action_code.h
@@ -304,7 +304,8 @@ enum backlight_opt {
304 BACKLIGHT_DECREASE = 1, 304 BACKLIGHT_DECREASE = 1,
305 BACKLIGHT_TOGGLE = 2, 305 BACKLIGHT_TOGGLE = 2,
306 BACKLIGHT_STEP = 3, 306 BACKLIGHT_STEP = 3,
307 BACKLIGHT_LEVEL = 4, 307 BACKLIGHT_ON = 4,
308 BACKLIGHT_OFF = 5,
308}; 309};
309 310
310/* Macro */ 311/* Macro */
@@ -316,7 +317,8 @@ enum backlight_opt {
316#define ACTION_BACKLIGHT_DECREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8) 317#define ACTION_BACKLIGHT_DECREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8)
317#define ACTION_BACKLIGHT_TOGGLE() ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8) 318#define ACTION_BACKLIGHT_TOGGLE() ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8)
318#define ACTION_BACKLIGHT_STEP() ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8) 319#define ACTION_BACKLIGHT_STEP() ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8)
319#define ACTION_BACKLIGHT_LEVEL(level) ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | (level)) 320#define ACTION_BACKLIGHT_ON() ACTION(ACT_BACKLIGHT, BACKLIGHT_ON << 8)
321#define ACTION_BACKLIGHT_OFF() ACTION(ACT_BACKLIGHT, BACKLIGHT_OFF << 8)
320/* Command */ 322/* Command */
321#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (id)) 323#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (id))
322/* Function */ 324/* Function */
diff --git a/tmk_core/common/backlight.c b/tmk_core/common/backlight.c
index d03bfe931..4d2491b98 100644
--- a/tmk_core/common/backlight.c
+++ b/tmk_core/common/backlight.c
@@ -61,6 +61,8 @@ void backlight_decrease(void)
61void backlight_toggle(void) 61void backlight_toggle(void)
62{ 62{
63 backlight_config.enable ^= 1; 63 backlight_config.enable ^= 1;
64 if (backlight_config.raw == 1) // enabled but level = 0
65 backlight_config.level = 1;
64 eeconfig_update_backlight(backlight_config.raw); 66 eeconfig_update_backlight(backlight_config.raw);
65 dprintf("backlight toggle: %u\n", backlight_config.enable); 67 dprintf("backlight toggle: %u\n", backlight_config.enable);
66 backlight_set(backlight_config.enable ? backlight_config.level : 0); 68 backlight_set(backlight_config.enable ? backlight_config.level : 0);
@@ -81,7 +83,9 @@ void backlight_step(void)
81 83
82void backlight_level(uint8_t level) 84void backlight_level(uint8_t level)
83{ 85{
84 backlight_config.level ^= level; 86 if (level > BACKLIGHT_LEVELS)
87 level = BACKLIGHT_LEVELS;
88 backlight_config.level = level;
85 backlight_config.enable = !!backlight_config.level; 89 backlight_config.enable = !!backlight_config.level;
86 eeconfig_update_backlight(backlight_config.raw); 90 eeconfig_update_backlight(backlight_config.raw);
87 backlight_set(backlight_config.level); 91 backlight_set(backlight_config.level);