@@ -17,53 +17,30 @@ void defaultPWMAudioOutputCallback();
17
17
// Stream classes
18
18
class PWMAudioStreamESP32 ;
19
19
class PWMAudioStreamPico ;
20
+ class PWMAudioStreamMBED ;
20
21
21
22
/* *
22
23
* PWMConfigAVR
23
24
* @author Phil Schatzmann
24
25
* @copyright GPLv3
25
26
*/
26
27
struct PWMConfig {
28
+ friend class PWMAudioStreamESP32 ;
29
+ friend class PWMAudioStreamPico ;
30
+ friend class PWMAudioStreamMBED ;
31
+
32
+ // basic information
27
33
uint16_t sample_rate = 10000 ; // sample rate in Hz
28
34
uint8_t channels = 2 ;
29
35
uint8_t bits_per_sample = 16 ;
30
36
uint16_t buffer_size = PWM_BUFFER_SIZE;
31
37
uint8_t buffers = PWM_BUFFERS;
32
38
33
- void logConfig (){
34
- LOGI (" sample_rate: %d" , sample_rate);
35
- LOGI (" channels: %d" , channels);
36
- LOGI (" bits_per_sample: %d" , bits_per_sample);
37
- LOGI (" buffer_size: %d" , buffer_size);
38
- }
39
-
40
- #ifdef ESP32
41
- /* *
42
- * @brief Configuration for PWM output
43
- * RES | BITS | MAX_FREQ (kHz)
44
- * ----|------|-------
45
- * 8 | 256 | 312.5
46
- * 9 | 512 | 156.25
47
- * 10 | 1024 | 78.125
48
- * 11 | 2048 | 39.0625
49
- *
50
- * The default resolution is 8. The value must be between 8 and 11 and also drives the PWM frequency.
51
- */
52
- int resolution = 8 ; // must be between 8 and 11 -> drives pwm frequency
53
- int start_pin = 4 ;
54
- uint8_t timer_id = 0 ; // must be between 0 and 3
55
- #endif
56
-
57
- #ifdef ARDUINO_ARCH_RP2040
58
- int pwm_freq = 60000 ; // audable range is from 20 to 20,000Hz
59
- int start_pin = 2 ; // channel 0 will be on gpio 2, channel 1 on 3 etc
60
- #endif
61
-
62
- // for architectures which support many flexible pins we support setPins
63
- #if defined(ESP32) || defined(ARDUINO_ARCH_RP2040)
64
- friend class PWMAudioStreamESP32 ;
65
- friend class PWMAudioStreamPico ;
66
-
39
+ // additinal info
40
+ uint16_t start_pin = PWM_START_PIN;
41
+ uint32_t pwm_frequency = PWM_FREQUENCY; // audable range is from 20 to 20,000Hz (not used by ESP32)
42
+ uint8_t resolution = 8 ; // Only used by ESP32: must be between 8 and 11 -> drives pwm frequency
43
+ uint8_t timer_id = 0 ; // Only used by ESP32 must be between 0 and 3
67
44
68
45
// define all pins by passing an array and updates the channels by the number of pins
69
46
template <size_t N>
@@ -78,12 +55,21 @@ struct PWMConfig {
78
55
start_pin = -1 ; // mark start pin as invalid
79
56
}
80
57
58
+ void logConfig (){
59
+ LOGI (" sample_rate: %d" , sample_rate);
60
+ LOGI (" channels: %d" , channels);
61
+ LOGI (" bits_per_sample: %d" , bits_per_sample);
62
+ LOGI (" buffer_size: %d" , buffer_size);
63
+ LOGI (" start_pin: %d" , start_pin);
64
+ LOGI (" pwm_frequency: %d" , pwm_frequency);
65
+ // LOGI("resolution: %d", resolution);
66
+ // LOGI("timer_id: %d", timer_id);
67
+ }
68
+
81
69
protected:
82
70
int *pins = nullptr ;
83
71
84
72
85
- #endif
86
-
87
73
} default_config;
88
74
89
75
@@ -93,6 +79,11 @@ struct PWMConfig {
93
79
*/
94
80
class PWMAudioStreamBase : public Stream {
95
81
public:
82
+ ~PWMAudioStreamBase (){
83
+ if (is_timer_started){
84
+ end ();
85
+ }
86
+ }
96
87
97
88
PWMConfig defaultConfig () {
98
89
return default_config;
@@ -134,6 +125,8 @@ class PWMAudioStreamBase : public Stream {
134
125
if (buffer==nullptr ) {
135
126
LOGI (" Allocating new buffer %d * %d bytes" ,config.buffers , config.buffer_size );
136
127
buffer = new NBuffer<uint8_t >(config.buffer_size , config.buffers );
128
+ } else {
129
+ buffer->reset ();
137
130
}
138
131
// check allocation
139
132
if (buffer==nullptr ){
@@ -146,7 +139,45 @@ class PWMAudioStreamBase : public Stream {
146
139
setupTimer ();
147
140
148
141
return true ;
149
- }
142
+ }
143
+
144
+ // restart with prior definitions
145
+ bool begin (){
146
+ LOGD (__FUNCTION__);
147
+ // allocate buffer if necessary
148
+ if (user_callback==nullptr ) {
149
+ if (buffer==nullptr ) {
150
+ LOGI (" ->Allocating new buffer %d * %d bytes" ,audio_config.buffers , audio_config.buffer_size );
151
+ buffer = new NBuffer<uint8_t >(audio_config.buffer_size , audio_config.buffers );
152
+ } else {
153
+ buffer->reset ();
154
+ }
155
+ }
156
+ // initialize if necessary
157
+ if (!is_timer_started){
158
+ logConfig ();
159
+ setupPWM ();
160
+ setupTimer ();
161
+ }
162
+
163
+ // reset class variables
164
+ is_timer_started = true ;
165
+ underflow_count = 0 ;
166
+ underflow_per_second = 0 ;
167
+ frame_count = 0 ;
168
+ frames_per_second = 0 ;
169
+
170
+ LOGI (" ->Buffer available: %d" , buffer->available ());
171
+ LOGI (" ->Buffer available for write: %d" , buffer->availableToWrite ());
172
+ LOGI (" ->is_timer_started: %s " , is_timer_started ? " true" : " false" );
173
+ }
174
+
175
+ virtual void end (){
176
+ LOGD (__FUNCTION__);
177
+ is_timer_started = false ;
178
+ }
179
+
180
+
150
181
// not supported
151
182
virtual int available () {
152
183
LOGE (" not supported" );
@@ -190,15 +221,10 @@ class PWMAudioStreamBase : public Stream {
190
221
191
222
// blocking write for an array: we expect a singed value and convert it into a unsigned
192
223
virtual size_t write (const uint8_t *wrt_buffer, size_t size){
193
- LOGD (" write: %lu bytes" , size)
194
- bool log_flag = true ;
195
- while (availableForWrite ()<size){
196
- if (log_flag) LOGI (" Buffer is full - waiting..." );
197
- log_flag = false ;
198
- delay (10 );
199
- }
200
- size_t result = buffer->writeArray (wrt_buffer, size);
201
- if (result!=size){
224
+ size_t available = min ((size_t )availableForWrite (),size);
225
+ LOGD (" write: %lu bytes -> %lu" , size, available);
226
+ size_t result = buffer->writeArray (wrt_buffer, available);
227
+ if (result!=available){
202
228
LOGW (" Could not write all data: %d -> %d" , size, result);
203
229
}
204
230
// activate the timer now - if not already done
@@ -229,10 +255,6 @@ class PWMAudioStreamBase : public Stream {
229
255
uint64_t time_1_sec;
230
256
bool is_timer_started = false ;
231
257
232
- virtual void logConfig () {
233
- audio_config.logConfig ();
234
- }
235
-
236
258
virtual void setupPWM () = 0;
237
259
virtual void setupTimer () = 0;
238
260
virtual int maxChannels () = 0;
@@ -258,6 +280,9 @@ class PWMAudioStreamBase : public Stream {
258
280
}
259
281
}
260
282
283
+ void logConfig () {
284
+ audio_config.logConfig ();
285
+ }
261
286
262
287
void playNextFrameCallback (){
263
288
// LOGD(__FUNCTION__);
0 commit comments