Skip to content

Commit

Permalink
include bug fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Bytecm committed Mar 14, 2023
1 parent ebeb3bd commit 6855790
Showing 1 changed file with 30 additions and 6 deletions.
36 changes: 30 additions & 6 deletions Marlin/src/HAL/AVR/fast_pwm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@

#include "../../inc/MarlinConfig.h"

//#define DEBUG_AVR_FAST_PWM
#define DEBUG_OUT ENABLED(DEBUG_AVR_FAST_PWM)
#include "../../core/debug_out.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
Expand Down Expand Up @@ -108,36 +112,47 @@ const Timer get_pwm_timer(const pin_t pin) {
}

void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
DEBUG_ECHOLNPGM("set_pwm_frequency:: pin:",pin," frequency: ",f_desired);
const Timer timer = get_pwm_timer(pin);
if (timer.isProtected || !timer.isPWM) return; // Don't proceed if protected timer or not recognized

const bool is_timer2 = timer.n == 2;
const uint16_t maxtop = is_timer2 ? 0xFF : 0xFFFF;

DEBUG_ECHOLNPGM("maxtop: ",maxtop);
uint16_t res = 0xFF; // resolution (TOP value)
uint8_t j = CS_NONE; // prescaler index
uint8_t wgm = WGM_PWM_PC_8; // waveform generation mode

// Calculating the prescaler and resolution to use to achieve closest frequency
if (f_desired != 0) {
constexpr uint16_t prescaler[] = { 1, 8, (32), 64, (128), 256, 1024 }; // (*) are Timer 2 only
uint16_t f = (F_CPU) / (2 * 1024 * maxtop) + 1; // Start with the lowest non-zero frequency achievable (1 or 31)
uint16_t f = (F_CPU) / ((uint32_t)maxtop<<11) + 1; // Start with the lowest non-zero frequency achievable (for 16MHz, 1 or 31)

DEBUG_ECHOLNPGM("F: ",f);
DEBUG_ECHOLNPGM("Startloop::");
LOOP_L_N(i, COUNT(prescaler)) { // Loop through all prescaler values
const uint16_t p = prescaler[i];
DEBUG_ECHOLNPGM("prescaler: ",p);
uint16_t res_fast_temp, res_pc_temp;
if (is_timer2) {
DEBUG_ECHOLNPGM("Is Timer2::");
#if ENABLED(USE_OCR2A_AS_TOP) // No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP
const uint16_t rft = (F_CPU) / (p * f_desired);
res_fast_temp = rft - 1;
DEBUG_ECHOLNPGM("res_fast_temp: ",res_fast_temp);
res_pc_temp = rft / 2;
DEBUG_ECHOLNPGM("res_pc_temp: ",res_pc_temp);
#else
res_fast_temp = res_pc_temp = maxtop;
DEBUG_ECHOLNPGM("res_fast_temp: ",maxtop);
DEBUG_ECHOLNPGM("res_pc_temp: ",maxtop);
#endif
}
else {
DEBUG_ECHOLNPGM("Not Timer2::");
if (p == 32 || p == 128) continue; // Skip TIMER2 specific prescalers when not TIMER2
const uint16_t rft = (F_CPU) / (p * f_desired);
DEBUG_ECHOLNPGM("F_CPU: ",STRINGIFY(F_CPU)," prescaler: ",p," f_desired: ",f_desired);
res_fast_temp = rft - 1;
res_pc_temp = rft / 2;
}
Expand All @@ -146,22 +161,31 @@ void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
LIMIT(res_pc_temp, 1U, maxtop);

// Calculate frequencies of test prescaler and resolution values
const uint16_t f_fast_temp = (F_CPU) / (p * (1 + res_fast_temp)),
f_pc_temp = (F_CPU) / (2 * p * res_pc_temp);
const int f_diff = _MAX(f, f_desired) - _MIN(f, f_desired),
const uint16_t f_fast_temp = (F_CPU) / ((uint32_t)p * (1 + res_fast_temp)),
f_pc_temp = (F_CPU) / (((uint32_t)p * res_pc_temp)<<1),
f_diff = _MAX(f, f_desired) - _MIN(f, f_desired),
f_fast_diff = _MAX(f_fast_temp, f_desired) - _MIN(f_fast_temp, f_desired),
f_pc_diff = _MAX(f_pc_temp, f_desired) - _MIN(f_pc_temp, f_desired);
DEBUG_ECHOLNPGM("f_fast_temp: ",f_fast_temp);
DEBUG_ECHOLNPGM("f_pc_temp: ",f_pc_temp);
DEBUG_ECHOLNPGM("f_diff: ",f_diff);
DEBUG_ECHOLNPGM("f_fast_diff: ",f_fast_diff);
DEBUG_ECHOLNPGM("f_pc_diff: ",f_pc_diff);

if (f_fast_diff < f_diff && f_fast_diff <= f_pc_diff) { // FAST values are closest to desired f
DEBUG_ECHOLNPGM("Using FAST::");
// Set the Wave Generation Mode to FAST PWM
wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_FAST_PWM_OCR2A, WGM2_FAST_PWM)) : uint8_t(WGM_FAST_PWM_ICRn);
// Remember this combination
f = f_fast_temp; res = res_fast_temp; j = i + 1;
DEBUG_ECHOLNPGM("updated f: ",f);
}
else if (f_pc_diff < f_diff) { // PHASE CORRECT values are closes to desired f
DEBUG_ECHOLNPGM("Using PHASE::");
// Set the Wave Generation Mode to PWM PHASE CORRECT
wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_PWM_PC_OCR2A, WGM2_PWM_PC)) : uint8_t(WGM_PWM_PC_ICRn);
f = f_pc_temp; res = res_pc_temp; j = i + 1;
DEBUG_ECHOLNPGM("updated f: ",f);
}
}
}
Expand Down Expand Up @@ -219,4 +243,4 @@ void MarlinHAL::init_pwm_timers() {
set_pwm_frequency(pwm_pin[i], 1000);
}

#endif // __AVR__
#endif // __AVR__

0 comments on commit 6855790

Please sign in to comment.