You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
if (dmType == 5) dmType = SR_DMTYPE; // MCU does not support PDM
2895
2908
if (dmType == 51) dmType = SR_DMTYPE; // MCU does not support legacy PDM
2896
-
#endif
2897
2909
#else
2898
2910
if (dmType == 5) useInputFilter = 1; // enable filter for PDM
2899
2911
if (dmType == 51) useInputFilter = 1; // switch on filter for legacy PDM
@@ -2951,9 +2963,9 @@ class AudioReactive : public Usermod {
2951
2963
oappend(SET_F("ux='AudioReactive';")); // ux = shortcut for Audioreactive - fingers crossed that "ux" isn't already used as JS var, html post parameter or css style
2952
2964
oappend(SET_F("uxp=ux+':digitalmic:pin[]';")); // uxp = shortcut for AudioReactive:digitalmic:pin[]
@@ -1144,6 +1142,172 @@ class I2SAdcSource : public I2SSource {
1144
1142
int8_t _audioPin;
1145
1143
int8_t _myADCchannel = 0x0F; // current ADC channel for analog input. 0x0F means "undefined"
1146
1144
};
1145
+
#elif defined(AR_DMA_ADC_SAMPLING)
1146
+
1147
+
/* ADC sampling with DMA
1148
+
This microphone is an ADC pin sampled via ADC1 in continuous mode
1149
+
This allows to sample in the background with high sample rates and minimal CPU load
1150
+
note: only ADC1 channels can be used (ADC2 is used for WiFi)
1151
+
ESP32 is not implemented as it supports I2S for ADC sampling (see above)
1152
+
*/
1153
+
1154
+
#include"driver/adc.h"
1155
+
#include"hal/adc_types.h"
1156
+
#defineADC_TIMEOUT30// Timout for one full frame of samples in ms (TODO: could use (FFT_MIN_CYCLE + 5) but need to move the ifdefs before the include in the cpp file)
1157
+
#defineADC_RESULT_BYTE SOC_ADC_DIGI_RESULT_BYTES //for C3 & S3 this is 4 bytes, S2 is 2 bytes, first 12bits is ADC result, see adc_digi_output_data_t
1158
+
#ifdef CONFIG_IDF_TARGET_ESP32C3
1159
+
#defineMAX_ADC1_CHANNEL4// C3 has 5 channels (0-4)
1160
+
#else
1161
+
#defineMAX_ADC1_CHANNEL9// ESP32, S2, S3 have 10 channels (0-9)
1162
+
#endif
1163
+
1164
+
classDMAadcSource : publicAudioSource {
1165
+
public:
1166
+
DMAadcSource(SRate_t sampleRate, int blockSize, float sampleScale = 1.0f) :
.max_store_buf_size = (unsigned)blockSize * ADC_RESULT_BYTE, // internal storage of DMA driver (in bytes, one sample is 4 bytes on C3&S3, 2bytes on S2 note: using 2x buffer size would reduce overflows but can add latency
1171
+
.conv_num_each_intr = (unsigned)blockSize * ADC_RESULT_BYTE, // number of bytes per interrupt (or per frame, one sample contains 12bit of sample data)
1172
+
.adc1_chan_mask = 0, // ADC1 channel mask (set to correct channel in initialize())
1173
+
.adc2_chan_mask = 0, // dont use adc2 (used for wifi)
1174
+
};
1175
+
1176
+
adcpattern = {
1177
+
.atten = ADC_ATTEN_DB_11, // approx. 0-2.5V input range
1178
+
.channel = 0, // channel mask (set to correct channel in initialize())
1179
+
.unit = 0, // use ADC1
1180
+
.bit_width = SOC_ADC_DIGI_MAX_BITWIDTH, // set to 12bit
1181
+
};
1182
+
1183
+
dig_cfg = {
1184
+
.conv_limit_en = 0, // disable limit (does not work right if enabled)
if ((err == ESP_OK || err == ESP_ERR_INVALID_STATE) && ret_num > 0) { // in invalid sate (internal buffer overrun), still read the last valid sample, then reset the ADC DMA afterwards (better than not having samples at all)
1239
+
totalbytes += ret_num; // after an error, DMA buffer can be misaligned, returning partial frames. Found no solution to re-align or flush the buffers, seems to be yet another IDF4 bug
1240
+
1241
+
if (totalbytes > framesize) { // got too many bytes to fit sample buffer
1242
+
ret_num -= totalbytes - framesize; // discard extra samples
1243
+
}
1244
+
for (int i = 0; i < ret_num; i += ADC_RESULT_BYTE) {
buffer[j++] = float((int(p->val & 0x0FFF))); // get the 12bit sample data and convert to float note: works on both format types
1247
+
// TODO: for integer math: when scaling up to 16bit: compared to I2S mic the scaling seems about the same when not shifting at all, so need to divide by 16 after FFT if scaling up to 16bit
1248
+
}
1249
+
} else { // no samples or other error: usually ESP_ERR_TIMEOUT (if DMA has stopped for some reason)
1250
+
reset_DMA_ADC();
1251
+
DEBUGSR_PRINTF("ADC ERROR!\n");
1252
+
return; // something went very wrong, just exit
1253
+
}
1254
+
} while (totalbytes < framesize); // read more samples if a partial frame was returned (data is still consistent in split frames)
1255
+
1256
+
// remove DC TODO: should really do this in int on C3 & S2... -> needs an update after PR #248 is merged
1257
+
int32_t sum = 0;
1258
+
for (int i = 0; i < num_samples; i++) sum += buffer[i];
1259
+
int32_t mean = sum / num_samples;
1260
+
for (int i = 0; i < num_samples; i++) buffer[i] -= mean; //uses static mean, as it should not change too much over time, deducted above
1261
+
1262
+
if (err == ESP_ERR_INVALID_STATE) { // error reading data, error means buffer overrun, need to fully reset the DMA ADC to make it work again
0 commit comments