arduino-audio-tools
PWMAudioESP32.h
1 
2 #pragma once
3 #ifdef ESP32
4 #include "AudioTools/CoreAudio/AudioPWM/PWMAudioBase.h"
5 
6 namespace audio_tools {
7 
8 // forward declaration
9 class PWMDriverESP32;
14 using PWMDriver = PWMDriverESP32;
15 
21 struct PinInfoESP32 {
22  int pwm_channel;
23  int gpio;
24 };
25 
26 typedef PinInfoESP32 PinInfo;
27 
36 class PWMDriverESP32 : public DriverPWMBase {
37  public:
38  // friend void pwm_callback(void*ptr);
39 
40  PWMDriverESP32() { TRACED(); }
41 
42  // Ends the output
43  virtual void end() {
44  TRACED();
45  timer.end();
46  is_timer_started = false;
47  for (int j = 0; j < audio_config.channels; j++) {
48 #if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 0, 0)
49  ledcDetach(pins[j].gpio);
50 #else
51  ledcDetachPin(pins[j].gpio);
52 #endif
53  }
54  deleteBuffer();
55  }
56 
59  virtual void startTimer() {
60  if (!timer) {
61  TRACEI();
62  audio_config = audioInfo();
63  timer.begin(pwm_callback, audio_config.sample_rate, HZ);
64  is_timer_started = true;
65  }
66  }
67 
69  virtual void setupPWM() {
70  // frequency is driven by selected resolution
71  audio_config.pwm_frequency = frequency(audio_config.resolution) * 1000;
72 
73  pins.resize(audio_config.channels);
74  for (int j = 0; j < audio_config.channels; j++) {
75  pins[j].gpio = audio_config.pins()[j];
76 #if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 0, 0)
77  if (!ledcAttach(pins[j].gpio, audio_config.pwm_frequency,
78  audio_config.resolution)) {
79  LOGE("ledcAttach: %d", pins[j].gpio);
80  }
81 #else
82  int pwmChannel = j;
83  pins[j].pwm_channel = pwmChannel;
84  ledcSetup(pins[j].pwm_channel, audio_config.pwm_frequency,
85  audio_config.resolution);
86  ledcAttachPin(pins[j].gpio, pins[j].pwm_channel);
87 #endif
88  LOGI("setupPWM: pin=%d, channel=%d, frequency=%u, resolution=%d",
89  pins[j].gpio, pins[j].pwm_channel, (unsigned)audio_config.pwm_frequency,
90  audio_config.resolution);
91  }
92  logPins();
93  }
94 
95  void logPins() {
96  for (int j = 0; j < pins.size(); j++) {
97  LOGI("pin%d: %d", j, pins[j].gpio);
98  }
99  }
100 
102  virtual void setupTimer() {
103  timer.setCallbackParameter(this);
104  timer.setIsSave(false);
105  }
106 
109  virtual void pwmWrite(int channel, int value) {
110 #if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(5, 0, 0)
111  ledcWrite(pins[channel].gpio, value);
112 #else
113  ledcWrite(pins[channel].pwm_channel, value);
114 #endif
115  }
116 
117  protected:
118  Vector<PinInfo> pins;
119  TimerAlarmRepeating timer;
120 
122  int maxUnsignedValue(int resolution) { return pow(2, resolution); }
123 
124  virtual int maxChannels() { return 16; };
125 
127  virtual int maxOutputValue() {
128  return maxUnsignedValue(audio_config.resolution);
129  }
130 
132  float frequency(int resolution) {
133 // On ESP32S2 and S3, the frequncy seems off by a factor of 2
134 #if defined(ESP32S2) || defined(ESP32S3)
135  switch (resolution) {
136  case 7:
137  return 312.5;
138  case 8:
139  return 156.25;
140  case 9:
141  return 78.125;
142  case 10:
143  return 39.0625;
144  case 11:
145  return 19.53125;
146  }
147  return 312.5;
148 #else
149  switch (resolution) {
150  case 8:
151  return 312.5;
152  case 9:
153  return 156.25;
154  case 10:
155  return 78.125;
156  case 11:
157  return 39.0625;
158  }
159  return 312.5;
160 #endif
161  }
162 
164  static void pwm_callback(void *ptr) {
165  PWMDriverESP32 *accessAudioPWM = (PWMDriverESP32 *)ptr;
166  if (accessAudioPWM != nullptr) {
167  accessAudioPWM->playNextFrame();
168  }
169  }
170 };
171 
172 } // namespace audio_tools
173 
174 #endif
Base Class for all PWM drivers.
Definition: PWMAudioBase.h:105
void playNextFrame()
writes the next frame to the output pins
Definition: PWMAudioBase.h:250
Audio output to PWM pins for the ESP32. The ESP32 supports up to 16 channels.
Definition: PWMAudioESP32.h:36
float frequency(int resolution)
determiens the PWM frequency based on the requested resolution
Definition: PWMAudioESP32.h:132
virtual void setupPWM()
Setup LED PWM.
Definition: PWMAudioESP32.h:69
virtual int maxOutputValue()
provides the max value for the configured resulution
Definition: PWMAudioESP32.h:127
virtual void startTimer()
Definition: PWMAudioESP32.h:59
int maxUnsignedValue(int resolution)
provides the max value for the indicated resulution
Definition: PWMAudioESP32.h:122
virtual void pwmWrite(int channel, int value)
Definition: PWMAudioESP32.h:109
static void pwm_callback(void *ptr)
timer callback: write the next frame to the pins
Definition: PWMAudioESP32.h:164
virtual void setupTimer()
Setup ESP32 timer with callback.
Definition: PWMAudioESP32.h:102
Common Interface definition for TimerAlarmRepeating.
Definition: AudioTimer.h:25
Vector implementation which provides the most important methods as defined by std::vector....
Definition: Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:823
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition: AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition: AudioTypes.h:57
Information for a PIN.
Definition: PWMAudioESP32.h:21