aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/config_options.md2
-rw-r--r--docs/feature_backlight.md47
-rw-r--r--docs/getting_started_make_guide.md2
-rw-r--r--docs/hardware_avr.md4
-rw-r--r--docs/porting_your_keyboard_to_qmk_(arm_and_other_chibios_cpus).md2
-rw-r--r--quantum/quantum.c239
6 files changed, 168 insertions, 128 deletions
diff --git a/docs/config_options.md b/docs/config_options.md
index 3be294db8..d2ae56179 100644
--- a/docs/config_options.md
+++ b/docs/config_options.md
@@ -76,7 +76,7 @@ This is a C header file that is one of the first things included, and will persi
76* `#define B7_AUDIO` 76* `#define B7_AUDIO`
77 * enables audio on pin B7 (duophony is enables if one of B[5-7]\_AUDIO is enabled along with one of C[4-6]\_AUDIO) 77 * enables audio on pin B7 (duophony is enables if one of B[5-7]\_AUDIO is enabled along with one of C[4-6]\_AUDIO)
78* `#define BACKLIGHT_PIN B7` 78* `#define BACKLIGHT_PIN B7`
79 * pin of the backlight - `B5`, `B6`, `B7` and `C6` (and `D4` on ATmega32A) use hardware PWM, others use software implementation 79 * pin of the backlight
80* `#define BACKLIGHT_LEVELS 3` 80* `#define BACKLIGHT_LEVELS 3`
81 * number of levels your backlight will have (maximum 15 excluding off) 81 * number of levels your backlight will have (maximum 15 excluding off)
82* `#define BACKLIGHT_BREATHING` 82* `#define BACKLIGHT_BREATHING`
diff --git a/docs/feature_backlight.md b/docs/feature_backlight.md
index 64c663076..2d9eea67b 100644
--- a/docs/feature_backlight.md
+++ b/docs/feature_backlight.md
@@ -30,32 +30,31 @@ You should then be able to use the keycodes below to change the backlight level.
30 30
31This feature is distinct from both the [RGB underglow](feature_rgblight.md) and [RGB matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously use multiple different coloured LEDs on a keyboard. 31This feature is distinct from both the [RGB underglow](feature_rgblight.md) and [RGB matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously use multiple different coloured LEDs on a keyboard.
32 32
33Hardware PWM is only supported on certain pins of the MCU, so if the backlighting is not connected to one of them, a software PWM implementation triggered by hardware timer interrupts will be used.
34
35Hardware PWM is supported according to the following table: 33Hardware PWM is supported according to the following table:
36 34
37| Backlight Pin | Hardware timer | 35|Backlight Pin|AT90USB64/128|ATmega16/32U4|ATmega16/32U2|ATmega32A|
38|---------------|-------------------------| 36|-------------|-------------|-------------|-------------|---------|
39|`B5` | Timer 1 | 37|`B5` |Timer 1 |Timer 1 | | |
40|`B6` | Timer 1 | 38|`B6` |Timer 1 |Timer 1 | | |
41|`B7` | Timer 1 | 39|`B7` |Timer 1 |Timer 1 |Timer 1 | |
42|`C6` | Timer 3 | 40|`C4` |Timer 3 | | | |
43|`D4` | Timer 1 (ATmega32A only)| 41|`C5` |Timer 3 | |Timer 1 | |
44| other | Software PWM | 42|`C6` |Timer 3 |Timer 3 |Timer 1 | |
45 43|`D4` | | | |Timer 1 |
46The [audio feature](feature_audio.md) also uses hardware timers. Please refer to the following table to know what hardware timer the software PWM will use depending on the audio configuration: 44|`D5` | | | |Timer 1 |
47 45
48| Audio Pin(s) | Audio Timer | Software PWM Timer | 46All other pins will use software PWM. If the [Audio](feature_audio.md) feature is disabled or only using one timer, the backlight PWM can be triggered by a hardware timer:
49|--------------|-------------|--------------------| 47
50| `C4` | Timer 3 | Timer 1 | 48|Audio Pin|Audio Timer|Software PWM Timer|
51| `C5` | Timer 3 | Timer 1 | 49|---------|-----------|------------------|
52| `C6` | Timer 3 | Timer 1 | 50|`C4` |Timer 3 |Timer 1 |
53| `B5` | Timer 1 | Timer 3 | 51|`C5` |Timer 3 |Timer 1 |
54| `B6` | Timer 1 | Timer 3 | 52|`C6` |Timer 3 |Timer 1 |
55| `B7` | Timer 1 | Timer 3 | 53|`B5` |Timer 1 |Timer 3 |
56| `Bx` & `Cx` | Timer 1 & 3 | None | 54|`B6` |Timer 1 |Timer 3 |
57 55|`B7` |Timer 1 |Timer 3 |
58When all timers are in use for [audio](feature_audio.md), the backlight software PWM will not use a hardware timer, but instead will be triggered during the matrix scan. In this case the backlight doesn't support breathing and might show lighting artifacts (for instance flickering), because the PWM computation might not be called with enough timing precision. 56
57When both timers are in use for Audio, the backlight PWM will not use a hardware timer, but will instead be triggered during the matrix scan. In this case, breathing is not supported, and the backlight might flicker, because the PWM computation may not be called with enough timing precision.
59 58
60## Configuration 59## Configuration
61 60
diff --git a/docs/getting_started_make_guide.md b/docs/getting_started_make_guide.md
index 75eafd42c..4fe3f184d 100644
--- a/docs/getting_started_make_guide.md
+++ b/docs/getting_started_make_guide.md
@@ -83,7 +83,7 @@ This allows the keyboard to tell the host OS that up to 248 keys are held down a
83 83
84`BACKLIGHT_ENABLE` 84`BACKLIGHT_ENABLE`
85 85
86This enables your backlight on Timer1 and ports B5, B6, or B7 (for now). You can specify your port by putting this in your `config.h`: 86This enables the in-switch LED backlighting. You can specify the backlight pin by putting this in your `config.h`:
87 87
88 #define BACKLIGHT_PIN B7 88 #define BACKLIGHT_PIN B7
89 89
diff --git a/docs/hardware_avr.md b/docs/hardware_avr.md
index 7c28ab6db..c6987d1bd 100644
--- a/docs/hardware_avr.md
+++ b/docs/hardware_avr.md
@@ -125,7 +125,7 @@ To configure a keyboard where each switch is connected to a separate pin and gro
125 125
126### Backlight Configuration 126### Backlight Configuration
127 127
128By default QMK supports backlighting on pins `B5`, `B6`, and `B7`. If you are using one of those you can simply enable it here. For more details see the [Backlight Documentation](feature_backlight.md). 128QMK supports backlighting on most GPIO pins. A select few of these can be driven by the MCU in hardware. For more details see the [Backlight Documentation](feature_backlight.md).
129 129
130```c 130```c
131#define BACKLIGHT_PIN B7 131#define BACKLIGHT_PIN B7
@@ -134,8 +134,6 @@ By default QMK supports backlighting on pins `B5`, `B6`, and `B7`. If you are us
134#define BREATHING_PERIOD 6 134#define BREATHING_PERIOD 6
135``` 135```
136 136
137?> You can use backlighting on any pin you like, but you will have to do more work to support that. See the [Backlight Documentation](feature_backlight.md) for more details.
138
139### Other Configuration Options 137### Other Configuration Options
140 138
141There are a lot of features that can be configured or tuned in `config.h`. You should see the [Config Options](config_options.md) page for more details. 139There are a lot of features that can be configured or tuned in `config.h`. You should see the [Config Options](config_options.md) page for more details.
diff --git a/docs/porting_your_keyboard_to_qmk_(arm_and_other_chibios_cpus).md b/docs/porting_your_keyboard_to_qmk_(arm_and_other_chibios_cpus).md
index 979eafbc8..bce9f9dc9 100644
--- a/docs/porting_your_keyboard_to_qmk_(arm_and_other_chibios_cpus).md
+++ b/docs/porting_your_keyboard_to_qmk_(arm_and_other_chibios_cpus).md
@@ -34,7 +34,7 @@ For the `DIODE_DIRECTION`, most hand-wiring guides will instruct you to wire the
34 34
35To configure a keyboard where each switch is connected to a separate pin and ground instead of sharing row and column pins, use `DIRECT_PINS`. The mapping defines the pins of each switch in rows and columns, from left to right. Must conform to the sizes within `MATRIX_ROWS` and `MATRIX_COLS`, use `NO_PIN` to fill in blank spaces. Overrides the behaviour of `DIODE_DIRECTION`, `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`. 35To configure a keyboard where each switch is connected to a separate pin and ground instead of sharing row and column pins, use `DIRECT_PINS`. The mapping defines the pins of each switch in rows and columns, from left to right. Must conform to the sizes within `MATRIX_ROWS` and `MATRIX_COLS`, use `NO_PIN` to fill in blank spaces. Overrides the behaviour of `DIODE_DIRECTION`, `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`.
36 36
37`BACKLIGHT_PIN` is the pin that your PWM-controlled backlight (if one exists) is hooked-up to. Currently only B5, B6, and B7 are supported. 37`BACKLIGHT_PIN` is the pin that your PWM-controlled backlight (if one exists) is hooked-up to.
38 38
39`BACKLIGHT_BREATHING` is a fancier backlight feature that adds breathing/pulsing/fading effects to the backlight. It uses the same timer as the normal backlight. These breathing effects must be called by code in your keymap. 39`BACKLIGHT_BREATHING` is a fancier backlight feature that adds breathing/pulsing/fading effects to the backlight. It uses the same timer as the normal backlight. These breathing effects must be called by code in your keymap.
40 40
diff --git a/quantum/quantum.c b/quantum/quantum.c
index d98c601d9..77cbbb2e7 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -1034,104 +1034,147 @@ void matrix_scan_quantum() {
1034} 1034}
1035#if defined(BACKLIGHT_ENABLE) && (defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS)) 1035#if defined(BACKLIGHT_ENABLE) && (defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS))
1036 1036
1037// The logic is a bit complex, we support 3 setups: 1037// This logic is a bit complex, we support 3 setups:
1038// 1. hardware PWM when backlight is wired to a PWM pin 1038//
1039// depending on this pin, we use a different output compare unit 1039// 1. Hardware PWM when backlight is wired to a PWM pin.
1040// 2. software PWM with hardware timers, but the used timer depends 1040// Depending on this pin, we use a different output compare unit.
1041// on the audio setup (audio wins other backlight) 1041// 2. Software PWM with hardware timers, but the used timer
1042// 3. full software PWM 1042// depends on the Audio setup (Audio wins over Backlight).
1043 1043// 3. Full software PWM, driven by the matrix scan, if both timers are used by Audio.
1044#if BACKLIGHT_PIN == B7 1044
1045# define HARDWARE_PWM 1045#if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) \
1046# define TCCRxA TCCR1A 1046 || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) \
1047# define TCCRxB TCCR1B 1047 || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) \
1048# define COMxx1 COM1C1 1048 && (BACKLIGHT_PIN == B5 || BACKLIGHT_PIN == B6 || BACKLIGHT_PIN == B7)
1049# define OCRxx OCR1C 1049 #define HARDWARE_PWM
1050# define TIMERx_OVF_vect TIMER1_OVF_vect 1050 #define ICRx ICR1
1051# define TOIEx TOIE1 1051 #define TCCRxA TCCR1A
1052# define ICRx ICR1 1052 #define TCCRxB TCCR1B
1053# define TIMSKx TIMSK1 1053 #define TIMERx_OVF_vect TIMER1_OVF_vect
1054#elif BACKLIGHT_PIN == B6 1054 #define TIMSKx TIMSK1
1055# define HARDWARE_PWM 1055 #define TOIEx TOIE1
1056# define TCCRxA TCCR1A 1056
1057# define TCCRxB TCCR1B 1057 #if BACKLIGHT_PIN == B5
1058# define COMxx1 COM1B1 1058 #define COMxx1 COM1A1
1059# define OCRxx OCR1B 1059 #define OCRxx OCR1A
1060# define TIMERx_OVF_vect TIMER1_OVF_vect 1060 #elif BACKLIGHT_PIN == B6
1061# define TOIEx TOIE1 1061 #define COMxx1 COM1B1
1062# define ICRx ICR1 1062 #define OCRxx OCR1B
1063# define TIMSKx TIMSK1 1063 #elif BACKLIGHT_PIN == B7
1064#elif BACKLIGHT_PIN == B5 1064 #define COMxx1 COM1C1
1065# define HARDWARE_PWM 1065 #define OCRxx OCR1C
1066# define TCCRxA TCCR1A 1066 #endif
1067# define TCCRxB TCCR1B 1067#elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) \
1068# define COMxx1 COM1A1 1068 || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) \
1069# define OCRxx OCR1A 1069 || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) \
1070# define TIMERx_OVF_vect TIMER1_OVF_vect 1070 && (BACKLIGHT_PIN == C4 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6)
1071# define TOIEx TOIE1 1071 #define HARDWARE_PWM
1072# define ICRx ICR1 1072 #define ICRx ICR3
1073# define TIMSKx TIMSK1 1073 #define TCCRxA TCCR3A
1074#elif BACKLIGHT_PIN == C6 1074 #define TCCRxB TCCR3B
1075# define HARDWARE_PWM 1075 #define TIMERx_OVF_vect TIMER3_OVF_vect
1076# define TCCRxA TCCR3A 1076 #define TIMSKx TIMSK3
1077# define TCCRxB TCCR3B 1077 #define TOIEx TOIE3
1078# define COMxx1 COM3A1 1078
1079# define OCRxx OCR3A 1079 #if BACKLIGHT_PIN == C4
1080# define TIMERx_OVF_vect TIMER3_OVF_vect 1080 #if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
1081# define TOIEx TOIE3 1081 #error This MCU has no C4 pin!
1082# define ICRx ICR3 1082 #else
1083# define TIMSKx TIMSK3 1083 #define COMxx1 COM3C1
1084#elif defined(__AVR_ATmega32A__) && BACKLIGHT_PIN == D4 1084 #define OCRxx OCR3C
1085# define TCCRxA TCCR1A 1085 #endif
1086# define TCCRxB TCCR1B 1086 #elif BACKLIGHT_PIN == C5
1087# define COMxx1 COM1B1 1087 #if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
1088# define OCRxx OCR1B 1088 #error This MCU has no C5 pin!
1089# define TIMERx_OVF_vect TIMER1_OVF_vect 1089 #else
1090# define TOIEx TOIE1 1090 #define COMxx1 COM3B1
1091# define ICRx ICR1 1091 #define OCRxx OCR3B
1092# define TIMSKx TIMSK1 1092 #endif
1093 #elif BACKLIGHT_PIN == C6
1094 #define COMxx1 COM3A1
1095 #define OCRxx OCR3A
1096 #endif
1097#elif (defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__)) \
1098 && (BACKLIGHT_PIN == B7 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6)
1099 #define HARDWARE_PWM
1100 #define ICRx ICR1
1101 #define TCCRxA TCCR1A
1102 #define TCCRxB TCCR1B
1103 #define TIMERx_OVF_vect TIMER1_OVF_vect
1104 #define TIMSKx TIMSK1
1105 #define TOIEx TOIE1
1106
1107 #if BACKLIGHT_PIN == B7
1108 #define COMxx1 COM1C1
1109 #define OCRxx OCR1C
1110 #elif BACKLIGHT_PIN == C5
1111 #define COMxx1 COM1B1
1112 #define OCRxx OCR1B
1113 #elif BACKLIGHT_PIN == C6
1114 #define COMxx1 COM1A1
1115 #define OCRxx OCR1A
1116 #endif
1117#elif defined(__AVR_ATmega32A__) \
1118 && (BACKLIGHT_PIN == D4 || BACKLIGHT_PIN == D5)
1119 #define HARDWARE_PWM
1120 #define ICRx ICR1
1121 #define TCCRxA TCCR1A
1122 #define TCCRxB TCCR1B
1123 #define TIMERx_OVF_vect TIMER1_OVF_vect
1124 #define TIMSKx TIMSK
1125 #define TOIEx TOIE1
1126
1127 #if BACKLIGHT_PIN == D4
1128 #define COMxx1 COM1B1
1129 #define OCRxx OCR1B
1130 #elif BACKLIGHT_PIN == D5
1131 #define COMxx1 COM1A1
1132 #define OCRxx OCR1A
1133 #endif
1093#else 1134#else
1094# if !defined(BACKLIGHT_CUSTOM_DRIVER) 1135 #if !defined(BACKLIGHT_CUSTOM_DRIVER)
1095# if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO) 1136 #if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO)
1096 // timer 1 is not used by audio , backlight can use it 1137 // Timer 1 is not in use by Audio feature, Backlight can use it
1097#pragma message "Using hardware timer 1 with software PWM" 1138 #pragma message "Using hardware timer 1 with software PWM"
1098# define HARDWARE_PWM 1139 #define HARDWARE_PWM
1099# define BACKLIGHT_PWM_TIMER 1140 #define BACKLIGHT_PWM_TIMER
1100# define TCCRxA TCCR1A 1141 #define ICRx ICR1
1101# define TCCRxB TCCR1B 1142 #define TCCRxA TCCR1A
1102# define OCRxx OCR1A 1143 #define TCCRxB TCCR1B
1103# define TIMERx_COMPA_vect TIMER1_COMPA_vect 1144 #define TIMERx_COMPA_vect TIMER1_COMPA_vect
1104# define TIMERx_OVF_vect TIMER1_OVF_vect 1145 #define TIMERx_OVF_vect TIMER1_OVF_vect
1105# define OCIExA OCIE1A 1146 #if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register
1106# define TOIEx TOIE1 1147 #define TIMSKx TIMSK
1107# define ICRx ICR1 1148 #else
1108# if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register 1149 #define TIMSKx TIMSK1
1109# define TIMSKx TIMSK 1150 #endif
1110# else 1151 #define TOIEx TOIE1
1111# define TIMSKx TIMSK1 1152
1112# endif 1153 #define OCIExA OCIE1A
1113# elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO) 1154 #define OCRxx OCR1A
1114#pragma message "Using hardware timer 3 with software PWM" 1155 #elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO)
1115// timer 3 is not used by audio, backlight can use it 1156 #pragma message "Using hardware timer 3 with software PWM"
1116# define HARDWARE_PWM 1157 // Timer 3 is not in use by Audio feature, Backlight can use it
1117# define BACKLIGHT_PWM_TIMER 1158 #define HARDWARE_PWM
1118# define TCCRxA TCCR3A 1159 #define BACKLIGHT_PWM_TIMER
1119# define TCCRxB TCCR3B 1160 #define ICRx ICR1
1120# define OCRxx OCR3A 1161 #define TCCRxA TCCR3A
1121# define TIMERx_COMPA_vect TIMER3_COMPA_vect 1162 #define TCCRxB TCCR3B
1122# define TIMERx_OVF_vect TIMER3_OVF_vect 1163 #define TIMERx_COMPA_vect TIMER3_COMPA_vect
1123# define OCIExA OCIE3A 1164 #define TIMERx_OVF_vect TIMER3_OVF_vect
1124# define TOIEx TOIE3 1165 #define TIMSKx TIMSK3
1125# define ICRx ICR1 1166 #define TOIEx TOIE3
1126# define TIMSKx TIMSK3 1167
1127# else 1168 #define OCIExA OCIE3A
1128#pragma message "Audio in use - using pure software PWM" 1169 #define OCRxx OCR3A
1129#define NO_HARDWARE_PWM 1170 #else
1130# endif 1171 #pragma message "Audio in use - using pure software PWM"
1131# else 1172 #define NO_HARDWARE_PWM
1132#pragma message "Custom driver defined - using pure software PWM" 1173 #endif
1133#define NO_HARDWARE_PWM 1174 #else
1134# endif 1175 #pragma message "Custom driver defined - using pure software PWM"
1176 #define NO_HARDWARE_PWM
1177 #endif
1135#endif 1178#endif
1136 1179
1137#ifndef BACKLIGHT_ON_STATE 1180#ifndef BACKLIGHT_ON_STATE
@@ -1300,7 +1343,7 @@ static uint16_t cie_lightness(uint16_t v) {
1300 1343
1301// range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val. 1344// range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val.
1302static inline void set_pwm(uint16_t val) { 1345static inline void set_pwm(uint16_t val) {
1303 OCRxx = val; 1346 OCRxx = val;
1304} 1347}
1305 1348
1306#ifndef BACKLIGHT_CUSTOM_DRIVER 1349#ifndef BACKLIGHT_CUSTOM_DRIVER