Merge pull request #4149 from gudnimg/tone-opt

use `uint16_t` instead of `uint32_t` when writing to OCR4C register
This commit is contained in:
3d-gussner 2023-11-29 08:26:54 +01:00 committed by GitHub
commit 3216ef863a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 25 additions and 24 deletions

View File

@ -14,24 +14,24 @@
void timer4_init(void) void timer4_init(void)
{ {
CRITICAL_SECTION_START; CRITICAL_SECTION_START;
SET_OUTPUT(BEEPER); SET_OUTPUT(BEEPER);
WRITE(BEEPER, LOW); WRITE(BEEPER, LOW);
SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN); SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
// Set timer mode 9 (PWM,Phase and Frequency Correct) // Set timer mode 9 (PWM,Phase and Frequency Correct)
// Prescaler is CLK/1024 // Prescaler is CLK/1024
// Output compare is disabled on all timer pins // Output compare is disabled on all timer pins
// Input capture is disabled // Input capture is disabled
// All interrupts are disabled // All interrupts are disabled
TCCR4A = (1 << WGM40); TCCR4A = _BV(WGM40);
TCCR4B = (1 << WGM43) | (1 << CS42) | (1 << CS40); TCCR4B = _BV(WGM43) | _BV(CS42) | _BV(CS40);
OCR4A = 255; OCR4A = 255U;
OCR4B = 255; OCR4B = 255U;
OCR4C = 255; OCR4C = 255U;
TIMSK4 = 0; TIMSK4 = 0;
CRITICAL_SECTION_END; CRITICAL_SECTION_END;
} }
@ -41,7 +41,7 @@ void timer4_set_fan0(uint8_t duty)
if (duty == 0 || duty == 255) if (duty == 0 || duty == 255)
{ {
// We use digital logic if the duty cycle is 0% or 100% // We use digital logic if the duty cycle is 0% or 100%
TCCR4A &= ~(1 << COM4C1); TCCR4A &= ~_BV(COM4C1);
OCR4C = 0; OCR4C = 0;
WRITE(EXTRUDER_0_AUTO_FAN_PIN, duty); WRITE(EXTRUDER_0_AUTO_FAN_PIN, duty);
} }
@ -52,8 +52,8 @@ void timer4_set_fan0(uint8_t duty)
// Better be safe than sorry. // Better be safe than sorry.
CRITICAL_SECTION_START; CRITICAL_SECTION_START;
// Enable the PWM output on the fan pin. // Enable the PWM output on the fan pin.
TCCR4A |= (1 << COM4C1); TCCR4A |= _BV(COM4C1);
OCR4C = (((uint32_t)duty) * ((uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255))) / ((uint32_t)255); OCR4C = (((uint16_t)duty) * ((uint16_t)((TIMSK4 & _BV(OCIE4A)) ? OCR4A : 255U))) / 255U;
CRITICAL_SECTION_END; CRITICAL_SECTION_END;
} }
} }
@ -75,25 +75,26 @@ void tone4(_UNUSED uint8_t _pin, uint16_t frequency)
{ {
//this ocr and prescalarbits calculation is taken from the Arduino core and simplified for one type of timer only //this ocr and prescalarbits calculation is taken from the Arduino core and simplified for one type of timer only
uint8_t prescalarbits = 0b001; uint8_t prescalarbits = 0b001;
uint32_t ocr = F_CPU / frequency / 2 - 1; uint32_t pwm_freq = F_CPU / (2 * frequency);
if (ocr > 0xffff) if (pwm_freq > UINT16_MAX) {
{ pwm_freq /= 64; // Increase prescaler to 64
ocr = F_CPU / frequency / 2 / 64 - 1;
prescalarbits = 0b011; prescalarbits = 0b011;
} }
uint16_t ocr = pwm_freq - 1;
CRITICAL_SECTION_START; CRITICAL_SECTION_START;
// Set calcualted prescaler // Set calcualted prescaler
TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
#ifdef EXTRUDER_0_AUTO_FAN_PIN #ifdef EXTRUDER_0_AUTO_FAN_PIN
// Scale the fan PWM duty cycle so that it remains constant, but at the tone frequency // Scale the fan PWM duty cycle so that it remains constant, but at the tone frequency
OCR4C = (((uint32_t)OCR4C) * ocr) / (uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255); OCR4C = (OCR4C * ocr) / (uint16_t)((TIMSK4 & _BV(OCIE4A)) ? OCR4A : 255U);
#endif //EXTRUDER_0_AUTO_FAN_PIN #endif //EXTRUDER_0_AUTO_FAN_PIN
// Set calcualted ocr // Set calcualted ocr
OCR4A = ocr; OCR4A = ocr;
// Enable Output compare A interrupt and timer overflow interrupt // Enable Output compare A interrupt and timer overflow interrupt
TIMSK4 |= (1 << OCIE4A) | (1 << TOIE4); TIMSK4 |= _BV(OCIE4A) | _BV(TOIE4);
CRITICAL_SECTION_END; CRITICAL_SECTION_END;
} }
@ -101,14 +102,14 @@ void noTone4(_UNUSED uint8_t _pin)
{ {
CRITICAL_SECTION_START; CRITICAL_SECTION_START;
// Revert prescaler to CLK/1024 // Revert prescaler to CLK/1024
TCCR4B = (TCCR4B & 0b11111000) | (1 << CS42) | (1 << CS40); TCCR4B = (TCCR4B & 0b11111000) | _BV(CS42) | _BV(CS40);
#ifdef EXTRUDER_0_AUTO_FAN_PIN #ifdef EXTRUDER_0_AUTO_FAN_PIN
// Scale the fan OCR back to the original value. // Scale the fan OCR back to the original value.
OCR4C = (((uint32_t)OCR4C) * (uint32_t)255) / (uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255); OCR4C = (OCR4C * 255U) / (uint16_t)((TIMSK4 & _BV(OCIE4A)) ? OCR4A : 255U);
#endif //EXTRUDER_0_AUTO_FAN_PIN #endif //EXTRUDER_0_AUTO_FAN_PIN
OCR4A = 255; OCR4A = 255U;
// Disable Output compare A interrupt and timer overflow interrupt // Disable Output compare A interrupt and timer overflow interrupt
TIMSK4 &= ~((1 << OCIE4A) | (1 << TOIE4)); TIMSK4 &= ~(_BV(OCIE4A) | _BV(TOIE4));
CRITICAL_SECTION_END; CRITICAL_SECTION_END;
// Turn beeper off if it was on when noTone was called // Turn beeper off if it was on when noTone was called
WRITE(BEEPER, 0); WRITE(BEEPER, 0);