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:
		
							parent
							
								
									c6850bad74
								
							
						
					
					
						commit
						6bdcbfb25a
					
				
					 3 changed files with 38 additions and 27 deletions
				
			
		| 
						 | 
					@ -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`
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,11 +35,12 @@ 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                 |
 | 
				
			||||||
 | 
					|`D4`           | Timer 1 (ATmega32A only)|
 | 
				
			||||||
| other         | Software PWM            |
 | 
					| 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:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue