diff --git a/Marlin/src/HAL/HAL_ESP32/HAL.cpp b/Marlin/src/HAL/HAL_ESP32/HAL.cpp
index f37a3a4ef83df6bd7e4aa42d01f8dcf089fa7e5e..37bba692603abc7dc5ff42af0b90c2c629149db7 100644
--- a/Marlin/src/HAL/HAL_ESP32/HAL.cpp
+++ b/Marlin/src/HAL/HAL_ESP32/HAL.cpp
@@ -23,6 +23,7 @@
#ifdef ARDUINO_ARCH_ESP32
#include "HAL.h"
+#include "HAL_timers_ESP32.h"
#include <rom/rtc.h>
#include <driver/adc.h>
#include <esp_adc_cal.h>
@@ -67,6 +68,9 @@ uint16_t HAL_adc_result;
// ------------------------
esp_adc_cal_characteristics_t characteristics;
+volatile int numPWMUsed = 0,
+ pwmPins[MAX_PWM_PINS],
+ pwmValues[MAX_PWM_PINS];
// ------------------------
// Public functions
@@ -168,25 +172,64 @@ void HAL_adc_init() {
void HAL_adc_start_conversion(uint8_t adc_pin) {
uint32_t mv;
esp_adc_cal_get_voltage((adc_channel_t)get_channel(adc_pin), &characteristics, &mv);
-
- HAL_adc_result = mv*1023.0/3300.0;
+ HAL_adc_result = mv * 1023.0 / 3300.0;
}
void analogWrite(pin_t pin, int value) {
+ // Use ledc hardware for internal pins
+ if (pin < 34) {
+ static int cnt_channel = 1, pin_to_channel[40] = { 0 };
+ if (pin_to_channel[pin] == 0) {
+ ledcAttachPin(pin, cnt_channel);
+ ledcSetup(cnt_channel, 490, 8);
+ ledcWrite(cnt_channel, value);
+ pin_to_channel[pin] = cnt_channel++;
+ }
+ ledcWrite(pin_to_channel[pin], value);
+ return;
+ }
+
+ int idx = -1;
- if (!PWM_PIN(pin)) return;
+ // Search Pin
+ for (int i = 0; i < numPWMUsed; ++i)
+ if (pwmPins[i] == pin) { idx = i; break; }
- static int cnt_channel = 1,
- pin_to_channel[40] = {};
- if (pin_to_channel[pin] == 0) {
- ledcAttachPin(pin, cnt_channel);
- ledcSetup(cnt_channel, 490, 8);
- ledcWrite(cnt_channel, value);
+ // not found ?
+ if (idx < 0) {
+ // No slots remaining
+ if (numPWMUsed >= MAX_PWM_PINS) return;
- pin_to_channel[pin] = cnt_channel++;
+ // Take new slot for pin
+ idx = numPWMUsed;
+ pwmPins[idx] = pin;
+ // Start timer on first use
+ if (idx == 0) HAL_timer_start(PWM_TIMER_NUM, PWM_TIMER_FREQUENCY);
+
+ ++numPWMUsed;
}
- ledcWrite(pin_to_channel[pin], value);
+ // Use 7bit internal value - add 1 to have 100% high at 255
+ pwmValues[idx] = (value + 1) / 2;
+}
+
+// Handle PWM timer interrupt
+HAL_PWM_TIMER_ISR() {
+ HAL_timer_isr_prologue(PWM_TIMER_NUM);
+
+ static uint8_t count = 0;
+
+ for (int i = 0; i < numPWMUsed; ++i) {
+ if (count == 0) // Start of interval
+ WRITE(pwmPins[i], pwmValues[i] ? HIGH : LOW);
+ else if (pwmValues[i] == count) // End of duration
+ WRITE(pwmPins[i], LOW);
+ }
+
+ // 128 for 7 Bit resolution
+ count = (count + 1) & 0x7F;
+
+ HAL_timer_isr_epilogue(PWM_TIMER_NUM);
}
#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.cpp b/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.cpp
index 27bd42bdf886ad8953ded85b2e4514e86fcb38be..fc90af4b8fd5bc8e145c7df1d032bcef2111029b 100644
--- a/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.cpp
+++ b/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.cpp
@@ -47,7 +47,7 @@ static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};
const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
{ TIMER_GROUP_0, TIMER_0, STEPPER_TIMER_PRESCALE, stepTC_Handler }, // 0 - Stepper
{ TIMER_GROUP_0, TIMER_1, TEMP_TIMER_PRESCALE, tempTC_Handler }, // 1 - Temperature
- { TIMER_GROUP_1, TIMER_0, 1, nullptr }, // 2
+ { TIMER_GROUP_1, TIMER_0, PWM_TIMER_PRESCALE, pwmTC_Handler }, // 2 - PWM
{ TIMER_GROUP_1, TIMER_1, 1, nullptr }, // 3
};
@@ -55,28 +55,28 @@ const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
// Public functions
// ------------------------
-void IRAM_ATTR timer_group0_isr(void *para) {
- const int timer_idx = (int)para;
+void IRAM_ATTR timer_isr(void *para) {
+ const tTimerConfig& timer = TimerConfig[(int)para];
// Retrieve the interrupt status and the counter value
// from the timer that reported the interrupt
- uint32_t intr_status = TIMERG0.int_st_timers.val;
- TIMERG0.hw_timer[timer_idx].update = 1;
+ uint32_t intr_status = TG[timer.group]->int_st_timers.val;
+ TG[timer.group]->hw_timer[timer.idx].update = 1;
// Clear the interrupt
- if (intr_status & BIT(timer_idx)) {
- switch (timer_idx) {
- case TIMER_0: TIMERG0.int_clr_timers.t0 = 1; break;
- case TIMER_1: TIMERG0.int_clr_timers.t1 = 1; break;
+ if (intr_status & BIT(timer.idx)) {
+ switch (timer.idx) {
+ case TIMER_0: TG[timer.group]->int_clr_timers.t0 = 1; break;
+ case TIMER_1: TG[timer.group]->int_clr_timers.t1 = 1; break;
+ case TIMER_MAX: break;
}
}
- const tTimerConfig timer = TimerConfig[timer_idx];
timer.fn();
// After the alarm has been triggered
// Enable it again so it gets triggered the next time
- TIMERG0.hw_timer[timer_idx].config.alarm_en = TIMER_ALARM_EN;
+ TG[timer.group]->hw_timer[timer.idx].config.alarm_en = TIMER_ALARM_EN;
}
/**
@@ -106,8 +106,7 @@ void HAL_timer_start(const uint8_t timer_num, uint32_t frequency) {
timer_enable_intr(timer.group, timer.idx);
- // TODO need to deal with timer_group1_isr
- timer_isr_register(timer.group, timer.idx, timer_group0_isr, (void*)timer.idx, 0, nullptr);
+ timer_isr_register(timer.group, timer.idx, timer_isr, (void*)timer_num, 0, nullptr);
timer_start(timer.group, timer.idx);
}
diff --git a/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.h b/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.h
index d3da0aef80013e957d8cda02dcab66b358e07e1e..0806fd2c776e085a7b1ae8abb6832477b4223e68 100644
--- a/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.h
+++ b/Marlin/src/HAL/HAL_ESP32/HAL_timers_ESP32.h
@@ -40,6 +40,7 @@ typedef uint64_t hal_timer_t;
#define STEP_TIMER_NUM 0 // index of timer to use for stepper
#define TEMP_TIMER_NUM 1 // index of timer to use for temperature
+#define PWM_TIMER_NUM 2 // index of timer to use for PWM outputs
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define HAL_TIMER_RATE APB_CLK_FREQ // frequency of timer peripherals
@@ -59,6 +60,14 @@ typedef uint64_t hal_timer_t;
#define TEMP_TIMER_PRESCALE 1000 // prescaler for setting Temp timer, 72Khz
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
+#define PWM_TIMER_PRESCALE 10
+#if ENABLED(FAST_PWM_FAN)
+ #define PWM_TIMER_FREQUENCY FAST_PWM_FAN_FREQUENCY
+#else
+ #define PWM_TIMER_FREQUENCY (50*128) // 50Hz and 7bit resolution
+#endif
+#define MAX_PWM_PINS 32 // Number of PWM pin-slots
+
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
@@ -72,10 +81,11 @@ typedef uint64_t hal_timer_t;
#define HAL_TEMP_TIMER_ISR() extern "C" void tempTC_Handler(void)
#define HAL_STEP_TIMER_ISR() extern "C" void stepTC_Handler(void)
+#define HAL_PWM_TIMER_ISR() extern "C" void pwmTC_Handler(void)
extern "C" void tempTC_Handler(void);
extern "C" void stepTC_Handler(void);
-
+extern "C" void pwmTC_Handler(void);
// ------------------------
// Types
diff --git a/Marlin/src/HAL/HAL_ESP32/fastio_ESP32.h b/Marlin/src/HAL/HAL_ESP32/fastio_ESP32.h
index 364777409587b6d1fa34a84381a42d1b1fcf26a5..1641116b9023df6365f7aeb29d569c94b2f96b86 100644
--- a/Marlin/src/HAL/HAL_ESP32/fastio_ESP32.h
+++ b/Marlin/src/HAL/HAL_ESP32/fastio_ESP32.h
@@ -66,7 +66,7 @@
#define extDigitalWrite(IO,V) digitalWrite(IO,V)
// PWM outputs
-#define PWM_PIN(P) (P < 34) // NOTE Pins >= 34 are input only on ESP32, so they can't be used for output.
+#define PWM_PIN(P) (P < 34 || P > 127) // NOTE Pins >= 34 are input only on ESP32, so they can't be used for output.
// Toggle pin value
#define TOGGLE(IO) WRITE(IO, !READ(IO))
diff --git a/Marlin/src/HAL/HAL_ESP32/i2s.cpp b/Marlin/src/HAL/HAL_ESP32/i2s.cpp
index 557714f870f8cbe23ca84fc17597143f89c41b1f..1f7c508cf1c48d108635adb61840758f8ccd0ba9 100644
--- a/Marlin/src/HAL/HAL_ESP32/i2s.cpp
+++ b/Marlin/src/HAL/HAL_ESP32/i2s.cpp
@@ -56,7 +56,7 @@ static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1};
static i2s_dma_t dma;
// output value
-uint32_t i2s_port_data;
+uint32_t i2s_port_data = 0;
#define I2S_ENTER_CRITICAL() portENTER_CRITICAL(&i2s_spinlock[i2s_num])
#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num])
@@ -140,13 +140,13 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) {
}
void stepperTask(void* parameter) {
- uint32_t i, remaining = 0;
+ uint32_t remaining = 0;
while (1) {
xQueueReceive(dma.queue, &dma.current, portMAX_DELAY);
dma.rw_pos = 0;
- for (i = 0; i < DMA_SAMPLE_COUNT; i++) {
+ while (dma.rw_pos < DMA_SAMPLE_COUNT) {
// Fill with the port data post pulse_phase until the next step
if (remaining) {
i2s_push_sample();
@@ -254,7 +254,13 @@ int i2s_init() {
I2S0.fifo_conf.dscr_en = 0;
- I2S0.conf_chan.tx_chan_mod = 0;
+ I2S0.conf_chan.tx_chan_mod = (
+ #if ENABLED(I2S_STEPPER_SPLIT_STREAM)
+ 4
+ #else
+ 0
+ #endif
+ );
I2S0.fifo_conf.tx_fifo_mod = 0;
I2S0.conf.tx_mono = 0;
@@ -314,10 +320,19 @@ int i2s_init() {
}
void i2s_write(uint8_t pin, uint8_t val) {
+ #if ENABLED(I2S_STEPPER_SPLIT_STREAM)
+ if (pin >= 16) {
+ SET_BIT_TO(I2S0.conf_single_data, pin, val);
+ return;
+ }
+ #endif
SET_BIT_TO(i2s_port_data, pin, val);
}
uint8_t i2s_state(uint8_t pin) {
+ #if ENABLED(I2S_STEPPER_SPLIT_STREAM)
+ if (pin >= 16) return TEST(I2S0.conf_single_data, pin);
+ #endif
return TEST(i2s_port_data, pin);
}