From baba1e78c7b8435f9a44de57ae295e505f459e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Sat, 15 Apr 2023 18:34:22 +0000 Subject: [PATCH] use uint16_t when writing to Timer/Counter4 Using uint16_t instead of uint32_t reduces code size and probably is quicker to execute OCR4C register is 2 bytes on ATmega2560 It's 1 byte on ATmega32u4 and ATmega16u4 Change in memory: Flash: -80 bytes SRAM: 0 bytes --- Firmware/tone04.c | 49 ++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/Firmware/tone04.c b/Firmware/tone04.c index f9a427c32..d9423f383 100644 --- a/Firmware/tone04.c +++ b/Firmware/tone04.c @@ -14,24 +14,24 @@ void timer4_init(void) { CRITICAL_SECTION_START; - + SET_OUTPUT(BEEPER); WRITE(BEEPER, LOW); - + SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN); - + // Set timer mode 9 (PWM,Phase and Frequency Correct) // Prescaler is CLK/1024 // Output compare is disabled on all timer pins // Input capture is disabled // All interrupts are disabled - TCCR4A = (1 << WGM40); - TCCR4B = (1 << WGM43) | (1 << CS42) | (1 << CS40); - OCR4A = 255; - OCR4B = 255; - OCR4C = 255; + TCCR4A = _BV(WGM40); + TCCR4B = _BV(WGM43) | _BV(CS42) | _BV(CS40); + OCR4A = 255U; + OCR4B = 255U; + OCR4C = 255U; TIMSK4 = 0; - + CRITICAL_SECTION_END; } @@ -41,7 +41,7 @@ void timer4_set_fan0(uint8_t duty) if (duty == 0 || duty == 255) { // We use digital logic if the duty cycle is 0% or 100% - TCCR4A &= ~(1 << COM4C1); + TCCR4A &= ~_BV(COM4C1); OCR4C = 0; WRITE(EXTRUDER_0_AUTO_FAN_PIN, duty); } @@ -52,8 +52,8 @@ void timer4_set_fan0(uint8_t duty) // Better be safe than sorry. CRITICAL_SECTION_START; // Enable the PWM output on the fan pin. - TCCR4A |= (1 << COM4C1); - OCR4C = (((uint32_t)duty) * ((uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255))) / ((uint32_t)255); + TCCR4A |= _BV(COM4C1); + OCR4C = (((uint16_t)duty) * ((uint16_t)((TIMSK4 & _BV(OCIE4A)) ? OCR4A : 255U))) / 255U; 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 uint8_t prescalarbits = 0b001; - uint32_t ocr = F_CPU / frequency / 2 - 1; - - if (ocr > 0xffff) - { - ocr = F_CPU / frequency / 2 / 64 - 1; + uint32_t pwm_freq = F_CPU / (2 * frequency); + + if (pwm_freq > UINT16_MAX) { + pwm_freq /= 64; // Increase prescaler to 64 prescalarbits = 0b011; } - + + uint16_t ocr = pwm_freq - 1; + CRITICAL_SECTION_START; // Set calcualted prescaler TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; #ifdef EXTRUDER_0_AUTO_FAN_PIN // 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 // Set calcualted ocr OCR4A = ocr; // Enable Output compare A interrupt and timer overflow interrupt - TIMSK4 |= (1 << OCIE4A) | (1 << TOIE4); + TIMSK4 |= _BV(OCIE4A) | _BV(TOIE4); CRITICAL_SECTION_END; } @@ -101,14 +102,14 @@ void noTone4(_UNUSED uint8_t _pin) { CRITICAL_SECTION_START; // 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 // 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 - OCR4A = 255; + OCR4A = 255U; // Disable Output compare A interrupt and timer overflow interrupt - TIMSK4 &= ~((1 << OCIE4A) | (1 << TOIE4)); + TIMSK4 &= ~(_BV(OCIE4A) | _BV(TOIE4)); CRITICAL_SECTION_END; // Turn beeper off if it was on when noTone was called WRITE(BEEPER, 0);