From 3dbe4ac59395048c98f6cd76bdaada7fac807f64 Mon Sep 17 00:00:00 2001 From: Victor Date: Fri, 30 Oct 2020 00:17:04 +0200 Subject: [PATCH] FAST_PWM for STM32F1 (#19952) --- Marlin/src/HAL/STM32F1/HAL.h | 17 ++++++ Marlin/src/HAL/STM32F1/fast_pwm.cpp | 68 ++++++++++++++++++++++ Marlin/src/HAL/STM32F1/inc/SanityCheck.h | 4 -- Marlin/src/lcd/menu/menu_spindle_laser.cpp | 6 +- 4 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 Marlin/src/HAL/STM32F1/fast_pwm.cpp diff --git a/Marlin/src/HAL/STM32F1/HAL.h b/Marlin/src/HAL/STM32F1/HAL.h index eaf6494dfa..b77539d7b6 100644 --- a/Marlin/src/HAL/STM32F1/HAL.h +++ b/Marlin/src/HAL/STM32F1/HAL.h @@ -244,3 +244,20 @@ void analogWrite(pin_t pin, int pwm_val8); // PWM only! mul by 257 in maple!? #define PLATFORM_M997_SUPPORT void flashFirmware(const int16_t); + +#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment + +/** + * set_pwm_frequency + * Set the frequency of the timer corresponding to the provided pin + * All Timer PWM pins run at the same frequency + */ +void set_pwm_frequency(const pin_t pin, int f_desired); + +/** + * set_pwm_duty + * Set the PWM duty cycle of the provided pin to the provided value + * Optionally allows inverting the duty cycle [default = false] + * Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255] + */ +void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false); diff --git a/Marlin/src/HAL/STM32F1/fast_pwm.cpp b/Marlin/src/HAL/STM32F1/fast_pwm.cpp new file mode 100644 index 0000000000..884d482af5 --- /dev/null +++ b/Marlin/src/HAL/STM32F1/fast_pwm.cpp @@ -0,0 +1,68 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifdef __STM32F1__ + +#include "../../inc/MarlinConfigPre.h" + +#if NEEDS_HARDWARE_PWM + +#include +#include "HAL.h" +#include "timers.h" + +void set_pwm_frequency(const pin_t pin, int f_desired) { + if (!PWM_PIN(pin)) return; // Don't proceed if no hardware timer + + timer_dev *timer = PIN_MAP[pin].timer_device; + uint8_t channel = PIN_MAP[pin].timer_channel; + + // Protect used timers + if (timer == get_timer_dev(TEMP_TIMER_NUM)) return; + if (timer == get_timer_dev(STEP_TIMER_NUM)) return; + #if PULSE_TIMER_NUM != STEP_TIMER_NUM + if (timer == get_timer_dev(PULSE_TIMER_NUM)) return; + #endif + + if (!(timer->regs.bas->SR & TIMER_CR1_CEN)) // Ensure the timer is enabled + timer_init(timer); + + timer_set_mode(timer, channel, TIMER_PWM); + uint16_t preload = 255; // Lock 255 PWM resolution for high frequencies + int32_t prescaler = (HAL_TIMER_RATE) / (preload + 1) / f_desired - 1; + if (prescaler > 65535) { // For low frequencies increase prescaler + prescaler = 65535; + preload = (HAL_TIMER_RATE) / (prescaler + 1) / f_desired - 1; + } + if (prescaler < 0) return; // Too high frequency + timer_set_reload(timer, preload); + timer_set_prescaler(timer, prescaler); +} + +void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { + timer_dev *timer = PIN_MAP[pin].timer_device; + uint16_t max_val = timer->regs.bas->ARR * v / v_size; + if (invert) max_val = v_size - max_val; + pwmWrite(pin, max_val); +} + +#endif // NEEDS_HARDWARE_PWM +#endif // __STM32F1__ diff --git a/Marlin/src/HAL/STM32F1/inc/SanityCheck.h b/Marlin/src/HAL/STM32F1/inc/SanityCheck.h index a0381ea8c8..937bef8803 100644 --- a/Marlin/src/HAL/STM32F1/inc/SanityCheck.h +++ b/Marlin/src/HAL/STM32F1/inc/SanityCheck.h @@ -25,10 +25,6 @@ * Test STM32F1-specific configuration values for errors at compile-time. */ -#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY - #error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on STM32F1." -#endif - #if !defined(HAVE_SW_SERIAL) && HAS_TMC_SW_SERIAL #warning "With TMC2208/9 consider using SoftwareSerialM with HAVE_SW_SERIAL and appropriate SS_TIMER." #error "Missing SoftwareSerial implementation." diff --git a/Marlin/src/lcd/menu/menu_spindle_laser.cpp b/Marlin/src/lcd/menu/menu_spindle_laser.cpp index 04b999eaf6..f1bf433c21 100644 --- a/Marlin/src/lcd/menu/menu_spindle_laser.cpp +++ b/Marlin/src/lcd/menu/menu_spindle_laser.cpp @@ -55,10 +55,8 @@ #endif } - #if ENABLED(MARLIN_DEV_MODE) - #if ENABLED(HAL_CAN_SET_PWM_FREQ) && defined(SPINDLE_LASER_FREQUENCY) - EDIT_ITEM_FAST(CUTTER_MENU_FREQUENCY_TYPE, MSG_CUTTER_FREQUENCY, &cutter.frequency, 2000, 50000, cutter.refresh_frequency); - #endif + #if BOTH(MARLIN_DEV_MODE, HAL_CAN_SET_PWM_FREQ) && defined(SPINDLE_LASER_FREQUENCY) + EDIT_ITEM_FAST(CUTTER_MENU_FREQUENCY_TYPE, MSG_CUTTER_FREQUENCY, &cutter.frequency, 2000, 50000, cutter.refresh_frequency); #endif END_MENU(); }