|
|
|
@ -22,11 +22,10 @@
|
|
|
|
|
#ifdef __AVR__
|
|
|
|
|
|
|
|
|
|
#include "../../inc/MarlinConfigPre.h"
|
|
|
|
|
#include "HAL.h"
|
|
|
|
|
|
|
|
|
|
#if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM
|
|
|
|
|
|
|
|
|
|
#include "HAL.h"
|
|
|
|
|
|
|
|
|
|
struct Timer {
|
|
|
|
|
volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer
|
|
|
|
|
volatile uint16_t* OCRnQ[3]; // max 3 OCR registers per timer
|
|
|
|
@ -153,7 +152,7 @@ Timer get_pwm_timer(const pin_t pin) {
|
|
|
|
|
|
|
|
|
|
void set_pwm_frequency(const pin_t pin, int f_desired) {
|
|
|
|
|
Timer timer = get_pwm_timer(pin);
|
|
|
|
|
if (timer.n == 0) return; // Don't proceed if protected timer or not recognised
|
|
|
|
|
if (timer.n == 0) return; // Don't proceed if protected timer or not recognized
|
|
|
|
|
uint16_t size;
|
|
|
|
|
if (timer.n == 2) size = 255; else size = 65535;
|
|
|
|
|
|
|
|
|
@ -243,7 +242,11 @@ void set_pwm_frequency(const pin_t pin, int f_desired) {
|
|
|
|
|
_SET_ICRn(timer.ICRn, res); // Set ICRn value (TOP) = res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // NEEDS_HARDWARE_PWM
|
|
|
|
|
|
|
|
|
|
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
|
|
|
|
|
#if NEEDS_HARDWARE_PWM
|
|
|
|
|
|
|
|
|
|
// If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
|
|
|
|
|
// Note that digitalWrite also disables pwm output for us (sets COM bit to 0)
|
|
|
|
|
if (v == 0)
|
|
|
|
@ -252,7 +255,7 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255
|
|
|
|
|
digitalWrite(pin, !invert);
|
|
|
|
|
else {
|
|
|
|
|
Timer timer = get_pwm_timer(pin);
|
|
|
|
|
if (timer.n == 0) return; // Don't proceed if protected timer or not recognised
|
|
|
|
|
if (timer.n == 0) return; // Don't proceed if protected timer or not recognized
|
|
|
|
|
// Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted)
|
|
|
|
|
_SET_COMnQ(timer.TCCRnQ, (timer.q
|
|
|
|
|
#ifdef TCCR2
|
|
|
|
@ -261,22 +264,17 @@ void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255
|
|
|
|
|
), COM_CLEAR_SET + invert
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
uint16_t top;
|
|
|
|
|
if (timer.n == 2) { // if TIMER2
|
|
|
|
|
top = (
|
|
|
|
|
#if ENABLED(USE_OCR2A_AS_TOP)
|
|
|
|
|
*timer.OCRnQ[0] // top = OCR2A
|
|
|
|
|
#else
|
|
|
|
|
255 // top = 0xFF (max)
|
|
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
uint16_t top = (timer.n == 2) ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn;
|
|
|
|
|
_SET_OCRnQ(timer.OCRnQ, timer.q, (v * top + v_size / 2) / v_size); // Scale 8/16-bit v to top value
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
top = *timer.ICRn; // top = ICRn
|
|
|
|
|
|
|
|
|
|
_SET_OCRnQ(timer.OCRnQ, timer.q, v * float(top) / float(v_size)); // Scale 8/16-bit v to top value
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
analogWrite(pin, v);
|
|
|
|
|
UNUSED(v_size);
|
|
|
|
|
UNUSED(invert);
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // NEEDS_HARDWARE_PWM
|
|
|
|
|
#endif // __AVR__
|
|
|
|
|