1
0
Fork 0

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
This commit is contained in:
fauxpark 2019-06-18 12:37:17 +10:00 committed by Drashna Jaelre
parent c6850bad74
commit 6bdcbfb25a
3 changed files with 38 additions and 27 deletions

View file

@ -76,7 +76,7 @@ This is a C header file that is one of the first things included, and will persi
* `#define B7_AUDIO` * `#define B7_AUDIO`
* 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) * 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)
* `#define BACKLIGHT_PIN B7` * `#define BACKLIGHT_PIN B7`
* pin of the backlight - B5, B6, B7 use PWM, others use softPWM * pin of the backlight - `B5`, `B6`, `B7` and `C6` (and `D4` on ATmega32A) use hardware PWM, others use software implementation
* `#define BACKLIGHT_LEVELS 3` * `#define BACKLIGHT_LEVELS 3`
* number of levels your backlight will have (maximum 15 excluding off) * number of levels your backlight will have (maximum 15 excluding off)
* `#define BACKLIGHT_BREATHING` * `#define BACKLIGHT_BREATHING`

View file

@ -34,13 +34,14 @@ Hardware PWM is only supported on certain pins of the MCU, so if the backlightin
Hardware PWM is supported according to the following table: Hardware PWM is supported according to the following table:
| Backlight Pin | Hardware timer | | Backlight Pin | Hardware timer |
|---------------|----------------| |---------------|-------------------------|
|`B5` | Timer 1 | |`B5` | Timer 1 |
|`B6` | Timer 1 | |`B6` | Timer 1 |
|`B7` | Timer 1 | |`B7` | Timer 1 |
|`C6` | Timer 3 | |`C6` | Timer 3 |
| other | Software PWM | |`D4` | Timer 1 (ATmega32A only)|
| other | Software PWM |
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: 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:

View file

@ -1027,35 +1027,49 @@ void matrix_scan_quantum() {
# define TCCRxB TCCR1B # define TCCRxB TCCR1B
# define COMxx1 COM1C1 # define COMxx1 COM1C1
# define OCRxx OCR1C # define OCRxx OCR1C
# define TIMERx_OVF_vect TIMER1_OVF_vect
# define TOIEx TOIE1
# define ICRx ICR1 # define ICRx ICR1
# define TIMSKx TIMSK1
#elif BACKLIGHT_PIN == B6 #elif BACKLIGHT_PIN == B6
# define HARDWARE_PWM # define HARDWARE_PWM
# define TCCRxA TCCR1A # define TCCRxA TCCR1A
# define TCCRxB TCCR1B # define TCCRxB TCCR1B
# define COMxx1 COM1B1 # define COMxx1 COM1B1
# define OCRxx OCR1B # define OCRxx OCR1B
# define TIMERx_OVF_vect TIMER1_OVF_vect
# define TOIEx TOIE1
# define ICRx ICR1 # define ICRx ICR1
# define TIMSKx TIMSK1
#elif BACKLIGHT_PIN == B5 #elif BACKLIGHT_PIN == B5
# define HARDWARE_PWM # define HARDWARE_PWM
# define TCCRxA TCCR1A # define TCCRxA TCCR1A
# define TCCRxB TCCR1B # define TCCRxB TCCR1B
# define COMxx1 COM1A1 # define COMxx1 COM1A1
# define OCRxx OCR1A # define OCRxx OCR1A
# define TIMERx_OVF_vect TIMER1_OVF_vect
# define TOIEx TOIE1
# define ICRx ICR1 # define ICRx ICR1
# define TIMSKx TIMSK1
#elif BACKLIGHT_PIN == C6 #elif BACKLIGHT_PIN == C6
# define HARDWARE_PWM # define HARDWARE_PWM
# define TCCRxA TCCR3A # define TCCRxA TCCR3A
# define TCCRxB TCCR3B # define TCCRxB TCCR3B
# define COMxx1 COM1A1 # define COMxx1 COM3A1
# define OCRxx OCR3A # define OCRxx OCR3A
# define TIMERx_OVF_vect TIMER3_OVF_vect
# define TOIEx TOIE3
# define ICRx ICR3 # define ICRx ICR3
# define TIMSKx TIMSK3
#elif defined(__AVR_ATmega32A__) && BACKLIGHT_PIN == D4 #elif defined(__AVR_ATmega32A__) && BACKLIGHT_PIN == D4
# define TCCRxA TCCR1A # define TCCRxA TCCR1A
# define TCCRxB TCCR1B # define TCCRxB TCCR1B
# define COMxx1 COM1B1 # define COMxx1 COM1B1
# define OCRxx OCR1B # define OCRxx OCR1B
# define TIMERx_OVF_vect TIMER1_OVF_vect
# define TOIEx TOIE1
# define ICRx ICR1 # define ICRx ICR1
# define TIMSK1 TIMSK # define TIMSKx TIMSK1
#else #else
# if !defined(BACKLIGHT_CUSTOM_DRIVER) # if !defined(BACKLIGHT_CUSTOM_DRIVER)
# if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO) # if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO)
@ -1066,15 +1080,15 @@ void matrix_scan_quantum() {
# define TCCRxA TCCR1A # define TCCRxA TCCR1A
# define TCCRxB TCCR1B # define TCCRxB TCCR1B
# define OCRxx OCR1A # define OCRxx OCR1A
# define OCRxAH OCR1AH
# define OCRxAL OCR1AL
# define TIMERx_COMPA_vect TIMER1_COMPA_vect # define TIMERx_COMPA_vect TIMER1_COMPA_vect
# define TIMERx_OVF_vect TIMER1_OVF_vect # define TIMERx_OVF_vect TIMER1_OVF_vect
# define OCIExA OCIE1A # define OCIExA OCIE1A
# define TOIEx TOIE1 # define TOIEx TOIE1
# define ICRx ICR1 # define ICRx ICR1
# ifndef TIMSK # if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register
# define TIMSK TIMSK1 # define TIMSKx TIMSK
# else
# define TIMSKx TIMSK1
# endif # endif
# elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO) # elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO)
#pragma message "Using hardware timer 3 with software PWM" #pragma message "Using hardware timer 3 with software PWM"
@ -1084,16 +1098,12 @@ void matrix_scan_quantum() {
# define TCCRxA TCCR3A # define TCCRxA TCCR3A
# define TCCRxB TCCR3B # define TCCRxB TCCR3B
# define OCRxx OCR3A # define OCRxx OCR3A
# define OCRxAH OCR3AH
# define OCRxAL OCR3AL
# define TIMERx_COMPA_vect TIMER3_COMPA_vect # define TIMERx_COMPA_vect TIMER3_COMPA_vect
# define TIMERx_OVF_vect TIMER3_OVF_vect # define TIMERx_OVF_vect TIMER3_OVF_vect
# define OCIExA OCIE3A # define OCIExA OCIE3A
# define TOIEx TOIE3 # define TOIEx TOIE3
# define ICRx ICR1 # define ICRx ICR1
# ifndef TIMSK # define TIMSKx TIMSK3
# define TIMSK TIMSK3
# endif
# else # else
#pragma message "Audio in use - using pure software PWM" #pragma message "Audio in use - using pure software PWM"
#define NO_HARDWARE_PWM #define NO_HARDWARE_PWM
@ -1274,8 +1284,8 @@ void backlight_set(uint8_t level) {
if (level == 0) { if (level == 0) {
#ifdef BACKLIGHT_PWM_TIMER #ifdef BACKLIGHT_PWM_TIMER
if (OCRxx) { if (OCRxx) {
TIMSK &= ~(_BV(OCIExA)); TIMSKx &= ~(_BV(OCIExA));
TIMSK &= ~(_BV(TOIEx)); TIMSKx &= ~(_BV(TOIEx));
FOR_EACH_LED( FOR_EACH_LED(
backlight_off(backlight_pin); backlight_off(backlight_pin);
) )
@ -1287,8 +1297,8 @@ void backlight_set(uint8_t level) {
} else { } else {
#ifdef BACKLIGHT_PWM_TIMER #ifdef BACKLIGHT_PWM_TIMER
if (!OCRxx) { if (!OCRxx) {
TIMSK |= _BV(OCIExA); TIMSKx |= _BV(OCIExA);
TIMSK |= _BV(TOIEx); TIMSKx |= _BV(TOIEx);
} }
#else #else
// Turn on PWM control of backlight pin // Turn on PWM control of backlight pin
@ -1325,11 +1335,11 @@ bool is_breathing(void) {
#else #else
bool is_breathing(void) { bool is_breathing(void) {
return !!(TIMSK1 & _BV(TOIE1)); return !!(TIMSKx & _BV(TOIEx));
} }
#define breathing_interrupt_enable() do {TIMSK1 |= _BV(TOIE1);} while (0) #define breathing_interrupt_enable() do {TIMSKx |= _BV(TOIEx);} while (0)
#define breathing_interrupt_disable() do {TIMSK1 &= ~_BV(TOIE1);} while (0) #define breathing_interrupt_disable() do {TIMSKx &= ~_BV(TOIEx);} while (0)
#endif #endif
#define breathing_min() do {breathing_counter = 0;} while (0) #define breathing_min() do {breathing_counter = 0;} while (0)
@ -1411,7 +1421,7 @@ void breathing_task(void)
/* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run /* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run
* about 244 times per second. * about 244 times per second.
*/ */
ISR(TIMER1_OVF_vect) ISR(TIMERx_OVF_vect)
#endif #endif
{ {
uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS; uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS;