diff options
| author | fauxpark <fauxpark@gmail.com> | 2019-06-18 12:37:17 +1000 |
|---|---|---|
| committer | Drashna Jaelre <drashna@live.com> | 2019-06-17 19:37:17 -0700 |
| commit | 6bdcbfb25ae068d9f5351af0f7c6a03385020661 (patch) | |
| tree | c5c3e95ba361d1dc90600ecddff5550c07206965 | |
| parent | c6850bad74ccec3cec0af1c74eb20b139d0ca481 (diff) | |
| download | qmk_firmware-6bdcbfb25ae068d9f5351af0f7c6a03385020661.tar.gz qmk_firmware-6bdcbfb25ae068d9f5351af0f7c6a03385020661.zip | |
Fix backlight breathing on C6 (#6102)
* Fix backlight breathing on C6
* Account for ATmega32A's single TIMSK register (MT40)
* Document hardware PWM on D4 for ATmega32A
* Add C6 and D4 to BACKLIGHT_PIN description
| -rw-r--r-- | docs/config_options.md | 2 | ||||
| -rw-r--r-- | docs/feature_backlight.md | 15 | ||||
| -rw-r--r-- | quantum/quantum.c | 48 |
3 files changed, 38 insertions, 27 deletions
diff --git a/docs/config_options.md b/docs/config_options.md index f4035809a..55d25d4c8 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 use PWM, others use softPWM | 79 | * pin of the backlight - `B5`, `B6`, `B7` and `C6` (and `D4` on ATmega32A) use hardware PWM, others use software implementation |
| 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 048d75390..5a21a6790 100644 --- a/docs/feature_backlight.md +++ b/docs/feature_backlight.md | |||
| @@ -34,13 +34,14 @@ Hardware PWM is only supported on certain pins of the MCU, so if the backlightin | |||
| 34 | 34 | ||
| 35 | Hardware PWM is supported according to the following table: | 35 | Hardware PWM is supported according to the following table: |
| 36 | 36 | ||
| 37 | | Backlight Pin | Hardware timer | | 37 | | Backlight Pin | Hardware timer | |
| 38 | |---------------|----------------| | 38 | |---------------|-------------------------| |
| 39 | |`B5` | Timer 1 | | 39 | |`B5` | Timer 1 | |
| 40 | |`B6` | Timer 1 | | 40 | |`B6` | Timer 1 | |
| 41 | |`B7` | Timer 1 | | 41 | |`B7` | Timer 1 | |
| 42 | |`C6` | Timer 3 | | 42 | |`C6` | Timer 3 | |
| 43 | | other | Software PWM | | 43 | |`D4` | Timer 1 (ATmega32A only)| |
| 44 | | other | Software PWM | | ||
| 44 | 45 | ||
| 45 | The [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: | 46 | The [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: |
| 46 | 47 | ||
diff --git a/quantum/quantum.c b/quantum/quantum.c index 23263b700..36b7942d5 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c | |||
| @@ -1027,35 +1027,49 @@ void matrix_scan_quantum() { | |||
| 1027 | # define TCCRxB TCCR1B | 1027 | # define TCCRxB TCCR1B |
| 1028 | # define COMxx1 COM1C1 | 1028 | # define COMxx1 COM1C1 |
| 1029 | # define OCRxx OCR1C | 1029 | # define OCRxx OCR1C |
| 1030 | # define TIMERx_OVF_vect TIMER1_OVF_vect | ||
| 1031 | # define TOIEx TOIE1 | ||
| 1030 | # define ICRx ICR1 | 1032 | # define ICRx ICR1 |
| 1033 | # define TIMSKx TIMSK1 | ||
| 1031 | #elif BACKLIGHT_PIN == B6 | 1034 | #elif BACKLIGHT_PIN == B6 |
| 1032 | # define HARDWARE_PWM | 1035 | # define HARDWARE_PWM |
| 1033 | # define TCCRxA TCCR1A | 1036 | # define TCCRxA TCCR1A |
| 1034 | # define TCCRxB TCCR1B | 1037 | # define TCCRxB TCCR1B |
| 1035 | # define COMxx1 COM1B1 | 1038 | # define COMxx1 COM1B1 |
| 1036 | # define OCRxx OCR1B | 1039 | # define OCRxx OCR1B |
| 1040 | # define TIMERx_OVF_vect TIMER1_OVF_vect | ||
| 1041 | # define TOIEx TOIE1 | ||
| 1037 | # define ICRx ICR1 | 1042 | # define ICRx ICR1 |
| 1043 | # define TIMSKx TIMSK1 | ||
| 1038 | #elif BACKLIGHT_PIN == B5 | 1044 | #elif BACKLIGHT_PIN == B5 |
| 1039 | # define HARDWARE_PWM | 1045 | # define HARDWARE_PWM |
| 1040 | # define TCCRxA TCCR1A | 1046 | # define TCCRxA TCCR1A |
| 1041 | # define TCCRxB TCCR1B | 1047 | # define TCCRxB TCCR1B |
| 1042 | # define COMxx1 COM1A1 | 1048 | # define COMxx1 COM1A1 |
| 1043 | # define OCRxx OCR1A | 1049 | # define OCRxx OCR1A |
| 1050 | # define TIMERx_OVF_vect TIMER1_OVF_vect | ||
| 1051 | # define TOIEx TOIE1 | ||
| 1044 | # define ICRx ICR1 | 1052 | # define ICRx ICR1 |
| 1053 | # define TIMSKx TIMSK1 | ||
| 1045 | #elif BACKLIGHT_PIN == C6 | 1054 | #elif BACKLIGHT_PIN == C6 |
| 1046 | # define HARDWARE_PWM | 1055 | # define HARDWARE_PWM |
| 1047 | # define TCCRxA TCCR3A | 1056 | # define TCCRxA TCCR3A |
| 1048 | # define TCCRxB TCCR3B | 1057 | # define TCCRxB TCCR3B |
| 1049 | # define COMxx1 COM1A1 | 1058 | # define COMxx1 COM3A1 |
| 1050 | # define OCRxx OCR3A | 1059 | # define OCRxx OCR3A |
| 1060 | # define TIMERx_OVF_vect TIMER3_OVF_vect | ||
| 1061 | # define TOIEx TOIE3 | ||
| 1051 | # define ICRx ICR3 | 1062 | # define ICRx ICR3 |
| 1063 | # define TIMSKx TIMSK3 | ||
| 1052 | #elif defined(__AVR_ATmega32A__) && BACKLIGHT_PIN == D4 | 1064 | #elif defined(__AVR_ATmega32A__) && BACKLIGHT_PIN == D4 |
| 1053 | # define TCCRxA TCCR1A | 1065 | # define TCCRxA TCCR1A |
| 1054 | # define TCCRxB TCCR1B | 1066 | # define TCCRxB TCCR1B |
| 1055 | # define COMxx1 COM1B1 | 1067 | # define COMxx1 COM1B1 |
| 1056 | # define OCRxx OCR1B | 1068 | # define OCRxx OCR1B |
| 1069 | # define TIMERx_OVF_vect TIMER1_OVF_vect | ||
| 1070 | # define TOIEx TOIE1 | ||
| 1057 | # define ICRx ICR1 | 1071 | # define ICRx ICR1 |
| 1058 | # define TIMSK1 TIMSK | 1072 | # define TIMSKx TIMSK1 |
| 1059 | #else | 1073 | #else |
| 1060 | # if !defined(BACKLIGHT_CUSTOM_DRIVER) | 1074 | # if !defined(BACKLIGHT_CUSTOM_DRIVER) |
| 1061 | # if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO) | 1075 | # if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO) |
| @@ -1066,15 +1080,15 @@ void matrix_scan_quantum() { | |||
| 1066 | # define TCCRxA TCCR1A | 1080 | # define TCCRxA TCCR1A |
| 1067 | # define TCCRxB TCCR1B | 1081 | # define TCCRxB TCCR1B |
| 1068 | # define OCRxx OCR1A | 1082 | # define OCRxx OCR1A |
| 1069 | # define OCRxAH OCR1AH | ||
| 1070 | # define OCRxAL OCR1AL | ||
| 1071 | # define TIMERx_COMPA_vect TIMER1_COMPA_vect | 1083 | # define TIMERx_COMPA_vect TIMER1_COMPA_vect |
| 1072 | # define TIMERx_OVF_vect TIMER1_OVF_vect | 1084 | # define TIMERx_OVF_vect TIMER1_OVF_vect |
| 1073 | # define OCIExA OCIE1A | 1085 | # define OCIExA OCIE1A |
| 1074 | # define TOIEx TOIE1 | 1086 | # define TOIEx TOIE1 |
| 1075 | # define ICRx ICR1 | 1087 | # define ICRx ICR1 |
| 1076 | # ifndef TIMSK | 1088 | # if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register |
| 1077 | # define TIMSK TIMSK1 | 1089 | # define TIMSKx TIMSK |
| 1090 | # else | ||
| 1091 | # define TIMSKx TIMSK1 | ||
| 1078 | # endif | 1092 | # endif |
| 1079 | # elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO) | 1093 | # elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO) |
| 1080 | #pragma message "Using hardware timer 3 with software PWM" | 1094 | #pragma message "Using hardware timer 3 with software PWM" |
| @@ -1084,16 +1098,12 @@ void matrix_scan_quantum() { | |||
| 1084 | # define TCCRxA TCCR3A | 1098 | # define TCCRxA TCCR3A |
| 1085 | # define TCCRxB TCCR3B | 1099 | # define TCCRxB TCCR3B |
| 1086 | # define OCRxx OCR3A | 1100 | # define OCRxx OCR3A |
| 1087 | # define OCRxAH OCR3AH | ||
| 1088 | # define OCRxAL OCR3AL | ||
| 1089 | # define TIMERx_COMPA_vect TIMER3_COMPA_vect | 1101 | # define TIMERx_COMPA_vect TIMER3_COMPA_vect |
| 1090 | # define TIMERx_OVF_vect TIMER3_OVF_vect | 1102 | # define TIMERx_OVF_vect TIMER3_OVF_vect |
| 1091 | # define OCIExA OCIE3A | 1103 | # define OCIExA OCIE3A |
| 1092 | # define TOIEx TOIE3 | 1104 | # define TOIEx TOIE3 |
| 1093 | # define ICRx ICR1 | 1105 | # define ICRx ICR1 |
| 1094 | # ifndef TIMSK | 1106 | # define TIMSKx TIMSK3 |
| 1095 | # define TIMSK TIMSK3 | ||
| 1096 | # endif | ||
| 1097 | # else | 1107 | # else |
| 1098 | #pragma message "Audio in use - using pure software PWM" | 1108 | #pragma message "Audio in use - using pure software PWM" |
| 1099 | #define NO_HARDWARE_PWM | 1109 | #define NO_HARDWARE_PWM |
| @@ -1274,8 +1284,8 @@ void backlight_set(uint8_t level) { | |||
| 1274 | if (level == 0) { | 1284 | if (level == 0) { |
| 1275 | #ifdef BACKLIGHT_PWM_TIMER | 1285 | #ifdef BACKLIGHT_PWM_TIMER |
| 1276 | if (OCRxx) { | 1286 | if (OCRxx) { |
| 1277 | TIMSK &= ~(_BV(OCIExA)); | 1287 | TIMSKx &= ~(_BV(OCIExA)); |
| 1278 | TIMSK &= ~(_BV(TOIEx)); | 1288 | TIMSKx &= ~(_BV(TOIEx)); |
| 1279 | FOR_EACH_LED( | 1289 | FOR_EACH_LED( |
| 1280 | backlight_off(backlight_pin); | 1290 | backlight_off(backlight_pin); |
| 1281 | ) | 1291 | ) |
| @@ -1287,8 +1297,8 @@ void backlight_set(uint8_t level) { | |||
| 1287 | } else { | 1297 | } else { |
| 1288 | #ifdef BACKLIGHT_PWM_TIMER | 1298 | #ifdef BACKLIGHT_PWM_TIMER |
| 1289 | if (!OCRxx) { | 1299 | if (!OCRxx) { |
| 1290 | TIMSK |= _BV(OCIExA); | 1300 | TIMSKx |= _BV(OCIExA); |
| 1291 | TIMSK |= _BV(TOIEx); | 1301 | TIMSKx |= _BV(TOIEx); |
| 1292 | } | 1302 | } |
| 1293 | #else | 1303 | #else |
| 1294 | // Turn on PWM control of backlight pin | 1304 | // Turn on PWM control of backlight pin |
| @@ -1325,11 +1335,11 @@ bool is_breathing(void) { | |||
| 1325 | #else | 1335 | #else |
| 1326 | 1336 | ||
| 1327 | bool is_breathing(void) { | 1337 | bool is_breathing(void) { |
| 1328 | return !!(TIMSK1 & _BV(TOIE1)); | 1338 | return !!(TIMSKx & _BV(TOIEx)); |
| 1329 | } | 1339 | } |
| 1330 | 1340 | ||
| 1331 | #define breathing_interrupt_enable() do {TIMSK1 |= _BV(TOIE1);} while (0) | 1341 | #define breathing_interrupt_enable() do {TIMSKx |= _BV(TOIEx);} while (0) |
| 1332 | #define breathing_interrupt_disable() do {TIMSK1 &= ~_BV(TOIE1);} while (0) | 1342 | #define breathing_interrupt_disable() do {TIMSKx &= ~_BV(TOIEx);} while (0) |
| 1333 | #endif | 1343 | #endif |
| 1334 | 1344 | ||
| 1335 | #define breathing_min() do {breathing_counter = 0;} while (0) | 1345 | #define breathing_min() do {breathing_counter = 0;} while (0) |
| @@ -1411,7 +1421,7 @@ void breathing_task(void) | |||
| 1411 | /* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run | 1421 | /* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run |
| 1412 | * about 244 times per second. | 1422 | * about 244 times per second. |
| 1413 | */ | 1423 | */ |
| 1414 | ISR(TIMER1_OVF_vect) | 1424 | ISR(TIMERx_OVF_vect) |
| 1415 | #endif | 1425 | #endif |
| 1416 | { | 1426 | { |
| 1417 | uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS; | 1427 | uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS; |
