3 #include "AudioConfig.h"
6 #include "AudioTools/CoreAudio/AudioBasic/Collections.h"
8 #include "AudioTools/CoreAudio/AudioLogger.h"
9 #include "AudioTools/CoreAudio/AudioOutput.h"
10 #include "AudioTools/CoreAudio/AudioTypes.h"
12 #define READ_ERROR_MSG "Could not read full data"
18 typedef bool (*PWMCallbackType)(uint8_t channels, int16_t *data);
23 class PWMDriverRP2040;
41 uint16_t buffer_size = PWM_BUFFER_SIZE;
42 uint8_t buffers = PWM_BUFFER_COUNT;
45 uint32_t pwm_frequency = PWM_AUDIO_FREQUENCY;
47 uint8_t resolution = 8;
52 uint16_t start_pin = PIN_PWM_START;
55 template <
typename T,
int N>
56 void setPins(T (&a)[N]) {
59 for (
int i = 0; i < N; ++i) {
66 void setPins(
Pins &pins) {
68 for (
int i = 0; i < pins.size(); i++) {
69 pins_data.push_back(pins[i]);
75 if (pins_data.size() == 0) {
78 pins_data[j] = start_pin + j;
90 LOGI(
"buffer_size: %u", buffer_size);
91 LOGI(
"buffer_count: %u", buffers);
92 LOGI(
"pwm_frequency: %u", (
unsigned)pwm_frequency);
93 LOGI(
"resolution: %d", resolution);
110 PWMConfig &audioInfo() {
return audio_config; }
126 if (audio_config.
channels > maxChannels()) {
127 LOGE(
"Only max %d channels are supported!", maxChannels());
131 if (buffer ==
nullptr) {
132 LOGI(
"->Allocating new buffer %d * %d bytes", audio_config.buffers,
133 audio_config.buffer_size);
137 audio_config.buffers);
141 if (!isTimerStarted() || !cfg.
equals(actual_info)) {
142 audio_config.logConfig();
150 underflow_per_second = 0;
152 frames_per_second = 0;
154 LOGI(
"->Buffer available: %d", buffer->
available());
156 LOGI(
"->is_timer_started: %s ", isTimerStarted() ?
"true" :
"false");
160 virtual int availableForWrite() {
161 return is_blocking_write
162 ? audio_config.buffer_size
168 virtual size_t write(
const uint8_t *data,
size_t len) {
172 size = (size / frame_size) * frame_size;
173 LOGD(
"adjusted size: %d", (
int)size);
176 size = decimate.convert((uint8_t *)data, size);
177 LOGD(
"decimated size: %d", (
int)size);
181 LOGD(
"Waiting for buffer to be available");
184 size = min((
size_t)availableForWrite(), size);
187 size_t result = buffer->
writeArray(data, size);
188 if (result != size) {
189 LOGW(
"Could not write all data: %u -> %d", (
unsigned int)size, result);
192 if (!is_timer_started) startTimer();
197 uint32_t underflowsPerSecond() {
return underflow_per_second; }
199 uint32_t framesPerSecond() {
return frames_per_second; }
201 inline void updateStatistics() {
203 if (
millis() >= time_1_sec) {
204 time_1_sec =
millis() + 1000;
205 frames_per_second = frame_count;
206 underflow_per_second = underflow_count;
212 bool isTimerStarted() {
return is_timer_started; }
214 virtual void setupPWM() = 0;
215 virtual void setupTimer() = 0;
216 virtual void startTimer() = 0;
217 virtual int maxChannels() = 0;
218 virtual int maxOutputValue() = 0;
219 virtual void end() {};
221 virtual void pwmWrite(
int channel,
int value) = 0;
231 uint32_t underflow_count = 0;
232 uint32_t underflow_per_second = 0;
233 uint32_t frame_count = 0;
234 uint32_t frames_per_second = 0;
235 uint32_t frame_size = 0;
237 bool is_timer_started =
false;
238 bool is_blocking_write =
true;
241 void deleteBuffer() {
243 if (buffer !=
nullptr) {
251 if (isTimerStarted() && buffer !=
nullptr) {
255 for (
int j = 0; j < audio_config.
channels; j++) {
271 int16_t value = buffer->
read();
273 LOGE(READ_ERROR_MSG);
282 if (buffer->
readArray((uint8_t *)&value, 2) != 2) {
283 LOGE(READ_ERROR_MSG);
291 if (buffer->
readArray((uint8_t *)&value, 3) != 3) {
292 LOGE(READ_ERROR_MSG);
300 if (buffer->
readArray((uint8_t *)&value, 4) != 4) {
301 LOGE(READ_ERROR_MSG);
317 return audio_config.
sample_rate >= ANALOG_MAX_SAMPLE_RATE;