arduino-audio-tools
Loading...
Searching...
No Matches
PWMComplementaryDriverESP32.h
Go to the documentation of this file.
1
2#pragma once
3#ifdef ESP32
5#include "driver/mcpwm.h"
6
7namespace audio_tools {
8
20 int gpio_high; // high-side pin (PWMxA)
21 int gpio_low; // low-side pin (PWMxB)
24};
25
83 public:
84 // friend void pwm_callback(void*ptr);
85
87
88 // Ends the output
89 virtual void end() {
90 TRACED();
91 timer.end();
92 is_timer_started = false;
93 for (int j = 0; j < pins.size(); j++) {
94 mcpwm_stop(pins[j].unit, pins[j].timer);
95 }
97 }
98
109
111 virtual void setupPWM() {
112 // frequency is driven by selected resolution
113 if (audio_config.pwm_frequency == 0) {
115 }
117 LOGE("Only %d complementary channels supported", maxChannels());
119 }
120 bool has_pairs = audio_config.pins().size() >= (size_t)(audio_config.channels * 2);
121 if (!has_pairs) {
122 LOGW("Expected %d pins for %d complementary channels, got %d - assuming consecutive pin+1 as low-side", audio_config.channels*2, audio_config.channels, audio_config.pins().size());
123 }
124 pins.resize(audio_config.channels);
125 for (int j = 0; j < audio_config.channels; j++) {
126 pins[j].unit = (mcpwm_unit_t)(j / 3);
127 pins[j].timer = (mcpwm_timer_t)(j % 3);
128 if (pins[j].unit > MCPWM_UNIT_1) { LOGE("Too many channels for MCPWM: %d", j); break; }
129 if (has_pairs) {
130 pins[j].gpio_high = audio_config.pins()[j*2];
131 pins[j].gpio_low = audio_config.pins()[j*2 + 1];
132 } else {
133 pins[j].gpio_high = audio_config.pins()[j];
134 pins[j].gpio_low = pins[j].gpio_high + 1;
135 }
138 esp_err_t err = mcpwm_gpio_init(pins[j].unit, sigA, pins[j].gpio_high);
139 if (err != ESP_OK) LOGE("mcpwm_gpio_init high error=%d", (int)err);
140 err = mcpwm_gpio_init(pins[j].unit, sigB, pins[j].gpio_low);
141 if (err != ESP_OK) LOGE("mcpwm_gpio_init low error=%d", (int)err);
142 mcpwm_config_t cfg; cfg.frequency = audio_config.pwm_frequency; cfg.cmpr_a = 0; cfg.cmpr_b = 0; cfg.counter_mode = MCPWM_UP_COUNTER; cfg.duty_mode = MCPWM_DUTY_MODE_0;
143 err = mcpwm_init(pins[j].unit, pins[j].timer, &cfg);
144 if (err != ESP_OK) LOGE("mcpwm_init error=%d", (int)err);
145 if (audio_config.dead_time_us > 0) {
146 uint32_t dead_ticks = audio_config.dead_time_us * 80u; // 80MHz APB
149 if (dead_ticks > 0) {
151 if (err != ESP_OK) LOGE("deadtime_enable error=%d", (int)err);
152 }
153 }
154 LOGI("Complementary PWM ch=%d unit=%d timer=%d high=%d low=%d freq=%u dead_us=%u", j,(int)pins[j].unit,(int)pins[j].timer,pins[j].gpio_high,pins[j].gpio_low,(unsigned)audio_config.pwm_frequency,(unsigned)audio_config.dead_time_us);
155 }
156 }
157
158
160 virtual void setupTimer() {
162 timer.setIsSave(false);
163
165 timer.end();
166 startTimer();
167 }
168 }
169
172 virtual void pwmWrite(int channel, int value) {
173 if (channel < 0 || channel >= pins.size()) return;
174 int duty = (int)((int64_t)value * 100 / maxOutputValue());
175 if (duty < 0) duty = 0; else if (duty > 100) duty = 100;
176 mcpwm_set_duty(pins[channel].unit, pins[channel].timer, MCPWM_OPR_A, duty);
178 if (audio_config.dead_time_us == 0) {
179 // software complementary: invert
180 mcpwm_set_duty(pins[channel].unit, pins[channel].timer, MCPWM_OPR_B, 100 - duty);
182 }
183 }
184
185 protected:
189
191 int maxUnsignedValue(int resolution) { return pow(2, resolution); }
192
193 virtual int maxChannels() { return 6; };
194
196 virtual int maxOutputValue() {
198 }
199
201 float frequency(int resolution) {
202// On ESP32S2 and S3, the frequncy seems off by a factor of 2
203#if defined(ESP32S2) || defined(ESP32S3)
204 switch (resolution) {
205 case 7:
206 return 312.5;
207 case 8:
208 return 156.25;
209 case 9:
210 return 78.125;
211 case 10:
212 return 39.0625;
213 case 11:
214 return 19.53125;
215 }
216 return 312.5;
217#else
218 switch (resolution) {
219 case 8:
220 return 312.5;
221 case 9:
222 return 156.25;
223 case 10:
224 return 78.125;
225 case 11:
226 return 39.0625;
227 }
228 return 312.5;
229#endif
230 }
231
233 static void pwm_callback(void *ptr) {
235 if (drv != nullptr) {
236 drv->playNextFrame();
237 }
238 }
239};
240
241} // namespace audio_tools
242
243#endif
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGE(...)
Definition AudioLoggerIDF.h:30
Base Class for all PWM drivers.
Definition PWMDriverBase.h:114
virtual int effectiveOutputSampleRate()
Provides the effective sample rate.
Definition PWMDriverBase.h:246
void playNextFrame()
writes the next frame to the output pins
Definition PWMDriverBase.h:274
bool is_timer_started
Definition PWMDriverBase.h:260
PWMConfig audio_config
Definition PWMDriverBase.h:251
void deleteBuffer()
Definition PWMDriverBase.h:265
Audio output to PWM pins for the ESP32. The ESP32 supports up to 16 channels.
Definition PWMComplementaryDriverESP32.h:82
Vector< PinInfoESP32Compl > pins
Definition PWMComplementaryDriverESP32.h:186
PWMComplementaryDriverESP32()
Definition PWMComplementaryDriverESP32.h:86
float frequency(int resolution)
determiens the PWM frequency based on the requested resolution
Definition PWMComplementaryDriverESP32.h:201
virtual int maxChannels()
Definition PWMComplementaryDriverESP32.h:193
TimerAlarmRepeating timer
Definition PWMComplementaryDriverESP32.h:187
virtual void setupPWM()
Setup complementary MCPWM.
Definition PWMComplementaryDriverESP32.h:111
virtual int maxOutputValue()
provides the max value for the configured resulution
Definition PWMComplementaryDriverESP32.h:196
virtual void startTimer()
Definition PWMComplementaryDriverESP32.h:101
int maxUnsignedValue(int resolution)
provides the max value for the indicated resulution
Definition PWMComplementaryDriverESP32.h:191
virtual void pwmWrite(int channel, int value)
Definition PWMComplementaryDriverESP32.h:172
static void pwm_callback(void *ptr)
timer callback: write the next frame to the pins
Definition PWMComplementaryDriverESP32.h:233
virtual void setupTimer()
Setup ESP32 timer with callback.
Definition PWMComplementaryDriverESP32.h:160
virtual void end()
Definition PWMComplementaryDriverESP32.h:89
uint32_t actual_timer_frequency
Definition PWMComplementaryDriverESP32.h:188
Common Interface definition for TimerAlarmRepeating.
Definition AudioTimer.h:29
void setIsSave(bool is_save)
Definition AudioTimer.h:66
void setCallbackParameter(void *obj)
Definition AudioTimer.h:56
bool begin(repeating_timer_callback_t callback_f, uint32_t time, TimeUnit unit=MS)
Definition AudioTimer.h:43
bool end()
Definition AudioTimer.h:51
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
@ HZ
Definition AudioTypes.h:48
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:512
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
uint8_t resolution
Only used by ESP32: must be between 8 and 11 -> drives pwm frequency // 20,000Hz (not used by ESP32)
Definition PWMDriverBase.h:48
uint32_t pwm_frequency
additinal info which might not be used by all processors
Definition PWMDriverBase.h:46
uint16_t dead_time_us
Dead time in microseconds for symmetric PWM (ESP32 only)
Definition PWMDriverBase.h:53
Mapping information for one complementary PWM audio channel.
Definition PWMComplementaryDriverESP32.h:19
mcpwm_unit_t unit
Definition PWMComplementaryDriverESP32.h:22
int gpio_low
Definition PWMComplementaryDriverESP32.h:21
int gpio_high
Definition PWMComplementaryDriverESP32.h:20
mcpwm_timer_t timer
Definition PWMComplementaryDriverESP32.h:23