6 #include "../M5Unified.hpp"
8 #if __has_include (<esp_idf_version.h>)
9 #include <esp_idf_version.h>
10 #if ESP_IDF_VERSION_MAJOR >= 4
11 #define NON_BREAK ;[[fallthrough]];
19 #if __has_include(<sdkconfig.h>)
20 #include <sdkconfig.h>
24 #define __STDC_FORMAT_MACROS
29 #if defined ( ESP_PLATFORM )
30 #if defined (ESP_IDF_VERSION_VAL)
31 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
32 #define COMM_FORMAT_I2S (I2S_COMM_FORMAT_STAND_I2S)
33 #define COMM_FORMAT_MSB (I2S_COMM_FORMAT_STAND_MSB)
35 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 3)
36 #define SAMPLE_RATE_TYPE uint32_t
38 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
39 #define MIC_CLASS_ADC_WIDTH_BITS ADC_WIDTH_BIT_12
40 #define MIC_CLASS_ADC_ATTEN_DB ADC_ATTEN_DB_11
44 #ifndef COMM_FORMAT_I2S
45 #define COMM_FORMAT_I2S (I2S_COMM_FORMAT_I2S)
46 #define COMM_FORMAT_MSB (I2S_COMM_FORMAT_I2S_MSB)
49 #ifndef SAMPLE_RATE_TYPE
50 #define SAMPLE_RATE_TYPE int
53 #ifndef MIC_CLASS_ADC_WIDTH_BITS
54 #define MIC_CLASS_ADC_WIDTH_BITS ADC_WIDTH_12Bit
55 #define MIC_CLASS_ADC_ATTEN_DB ADC_ATTEN_11db
77 if (
_cfg.
use_adc) { sample_rate >>= 4; use_pdm =
false;}
79 i2s_config_t i2s_config;
80 memset(&i2s_config, 0,
sizeof(i2s_config_t));
81 i2s_config.mode = use_pdm
83 ? (i2s_mode_t)( I2S_MODE_MASTER | I2S_MODE_RX | (0x1 << 6) )
84 : (i2s_mode_t)( I2S_MODE_MASTER | I2S_MODE_RX );
85 i2s_config.sample_rate = sample_rate;
86 i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
87 i2s_config.channel_format =
_cfg.
stereo ? I2S_CHANNEL_FMT_RIGHT_LEFT : I2S_CHANNEL_FMT_ONLY_RIGHT;
88 i2s_config.communication_format = (i2s_comm_format_t)(
COMM_FORMAT_I2S );
92 i2s_pin_config_t pin_config;
93 memset(&pin_config, ~0u,
sizeof(i2s_pin_config_t));
94 #if defined (ESP_IDF_VERSION_VAL)
95 #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 1)
104 if (ESP_OK != (err = i2s_driver_install(
_cfg.
i2s_port, &i2s_config, 0,
nullptr)))
107 err = i2s_driver_install(
_cfg.
i2s_port, &i2s_config, 0,
nullptr);
109 if (err != ESP_OK) {
return err; }
111 #if !defined (CONFIG_IDF_TARGET) || defined (CONFIG_IDF_TARGET_ESP32)
115 static constexpr
const uint8_t adc_table[] =
122 255, 255, 255, 255, 255, 255, 255,
127 255, 255, 255, 255, 255, 255, 255, 255, 255,
142 if (adc_ch == 255) {
return ESP_FAIL; }
145 adc_set_data_width(unit, MIC_CLASS_ADC_WIDTH_BITS);
146 err = i2s_set_adc_mode(unit, (adc1_channel_t)adc_ch);
147 if (unit == ADC_UNIT_1)
149 adc1_config_channel_atten((adc1_channel_t)adc_ch, MIC_CLASS_ADC_ATTEN_DB);
153 adc2_config_channel_atten((adc2_channel_t)adc_ch, MIC_CLASS_ADC_ATTEN_DB);
157 I2S0.conf2.lcd_en =
true;
158 I2S0.conf.rx_right_first = 0;
159 I2S0.conf.rx_msb_shift = 0;
160 I2S0.conf.rx_mono = 0;
161 I2S0.conf.rx_short_sync = 0;
162 I2S0.fifo_conf.rx_fifo_mod =
true;
163 I2S0.conf_chan.rx_chan_mod =
true;
177 auto self = (Mic_Class*)args;
178 i2s_start(self->_cfg.i2s_port);
180 int oversampling =
self->_cfg.over_sampling;
181 if ( oversampling < 1) { oversampling = 1; }
182 else if (oversampling > 8) { oversampling = 8; }
184 int32_t gain =
self->_cfg.magnification;
185 const float f_gain = (float)gain / oversampling;
187 size_t src_idx = ~0u;
189 int32_t sum_value[4] = { 0,0 };
191 const bool in_stereo =
self->_cfg.stereo;
192 int32_t os_remain = oversampling;
193 const size_t dma_buf_len =
self->_cfg.dma_buf_len;
194 int16_t* src_buf = (int16_t*)alloca(dma_buf_len *
sizeof(int16_t));
196 i2s_read(self->_cfg.i2s_port, src_buf, dma_buf_len, &src_len, portTICK_PERIOD_MS);
197 i2s_read(self->_cfg.i2s_port, src_buf, dma_buf_len, &src_len, portTICK_PERIOD_MS);
199 while (self->_task_running)
201 bool rec_flip =
self->_rec_flip;
202 recording_info_t* current_rec = &(
self->_rec_info[!rec_flip]);
203 recording_info_t* next_rec = &(
self->_rec_info[ rec_flip]);
205 size_t dst_remain = current_rec->length;
208 rec_flip = !rec_flip;
209 self->_rec_flip = rec_flip;
210 xSemaphoreGive(self->_task_semaphore);
211 std::swap(current_rec, next_rec);
212 dst_remain = current_rec->length;
215 self->_is_recording =
false;
216 ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
224 self->_is_recording =
true;
228 if (src_idx >= src_len)
230 i2s_read(self->_cfg.i2s_port, src_buf, dma_buf_len, &src_len, 100 / portTICK_PERIOD_MS);
235 if (self->_cfg.use_adc)
239 #if defined (CONFIG_IDF_TARGET_ESP32)
240 sum_value[1 - (src_idx & 1)] += (src_buf[src_idx] & 0x0FFF) - 2048;
242 sum_value[src_idx & 1] += (src_buf[src_idx] & 0x0FFF) - 2048;
245 }
while (--os_remain && (src_idx < src_len));
251 #if defined (CONFIG_IDF_TARGET_ESP32)
252 sum_value[1 - (src_idx & 1)] += src_buf[src_idx];
254 sum_value[src_idx & 1] += src_buf[src_idx];
257 }
while (--os_remain && (src_idx < src_len));
259 if (os_remain) {
continue; }
260 os_remain = oversampling;
262 auto sv0 = sum_value[0];
263 auto sv1 = sum_value[1];
264 auto value_tmp = sv0 + sv1;
265 sum_value[0] += offset;
266 sum_value[1] += offset;
268 offset = (32 + offset * 62 - value_tmp) >> 6;
270 int32_t noise_filter =
self->_cfg.noise_filter_level;
273 for (
int i = 0; i < 2; ++i)
275 int32_t v = (sum_value[i] * (256 - noise_filter) +
prev_value[i] * noise_filter + 128) >> 8;
277 sum_value[i] = v * f_gain;
282 for (
int i = 0; i < 2; ++i)
284 sum_value[i] *= f_gain;
290 if (in_stereo != current_rec->is_stereo)
294 sum_value[0] = (sum_value[0] + sum_value[1] + 1) >> 1;
299 auto tmp = sum_value[1];
302 sum_value[1] = sum_value[0];
306 for (
int i = 0; i < output_num; ++i)
308 auto value = sum_value[i];
309 if (current_rec->is_16bit)
311 if (
value < INT16_MIN+16) {
value = INT16_MIN+16; }
312 else if (
value > INT16_MAX-16) {
value = INT16_MAX-16; }
313 auto dst = (int16_t*)(current_rec->data);
315 current_rec->data = dst;
322 auto dst = (uint8_t*)(current_rec->data);
324 current_rec->data = dst;
329 dst_remain -= output_num;
330 if ((int32_t)dst_remain <= 0)
332 current_rec->length = 0;
337 self->_is_recording =
false;
338 i2s_stop(self->_cfg.i2s_port);
340 self->_task_handle =
nullptr;
341 vTaskDelete(
nullptr);
368 #if portNUM_PROCESSORS > 1
397 bool Mic_Class::_rec_raw(
void* recdata,
size_t array_len,
bool flg_16bit, uint32_t sample_rate,
bool flg_stereo)
399 recording_info_t info;
401 info.length = array_len;
402 info.is_16bit = flg_16bit;
403 info.is_stereo = flg_stereo;
407 if (!
begin()) {
return false; }
408 if (array_len == 0) {
return true; }
esp_err_t _setup_i2s(void)
size_t isRecording(void) const
volatile bool _task_running
recording_info_t _rec_info[2]
static void mic_task(void *args)
uint32_t _rec_sample_rate
volatile SemaphoreHandle_t _task_semaphore
bool(* _cb_set_enabled)(void *args, bool enabled)
void * _cb_set_enabled_args
uint32_t _calc_rec_rate(void) const
TaskHandle_t _task_handle
bool _rec_raw(void *recdata, size_t array_len, bool flg_16bit, uint32_t sample_rate, bool stereo)
uint8_t task_priority
background task priority
i2s_port_t i2s_port
I2S port.
int pin_data_in
i2s_data_in (for mic)
uint8_t over_sampling
Sampling times of obtain the average value.
size_t dma_buf_count
for I2S dma_buf_count
uint32_t sample_rate
input sampling rate (Hz)
bool use_adc
use analog input mic ( need only pin_data_in )
size_t dma_buf_len
for I2S dma_buf_len
bool stereo
use stereo output
uint8_t task_pinned_core
background task pinned core