diff --git a/build/devices/esp32/targets/m5stack_cores3/manifest.json b/build/devices/esp32/targets/m5stack_cores3/manifest.json index 05106f8ad..fd9e73bf6 100644 --- a/build/devices/esp32/targets/m5stack_cores3/manifest.json +++ b/build/devices/esp32/targets/m5stack_cores3/manifest.json @@ -112,14 +112,18 @@ "dataout_pin": 13 } }, - "audioIn": { - "sampleRate": 11025, + "audioIn": { + "sampleRate": 16000, "bitsPerSample": 16, + "numChannels": 2, "i2s": { + "num": 1, + "slot": "I2S_STD_SLOT_BOTH", + "format_i2s": 1, "bck_pin": 34, "lr_pin": 33, - "datain": 14, - "pdm": 1 + "mck_pin": 0, + "datain": 14 } }, "camera": { diff --git a/build/devices/esp32/targets/m5stack_cores3/setup-target.js b/build/devices/esp32/targets/m5stack_cores3/setup-target.js index 4c4b67b89..9d7adcc15 100644 --- a/build/devices/esp32/targets/m5stack_cores3/setup-target.js +++ b/build/devices/esp32/targets/m5stack_cores3/setup-target.js @@ -67,6 +67,8 @@ export default function (done) { // power globalThis.power = new Power({sensor: { ...device.I2C.internal, io: device.io.SMBus }}); globalThis.amp = new AW88298({sensor: { ...device.I2C.internal, io: device.io.SMBus }}); + globalThis.mic = new ES7210({sensor: { ...device.I2C.internal, io: device.io.SMBus }}); + globalThis.mic.init(); // start-up sound if (config.startupSound) { @@ -153,6 +155,60 @@ class AW88298 { } } +/** + * ES7210 audio ADC (microphone) + */ +class ES7210 { + #io; + + constructor(options) { + this.#io = new options.sensor.io ({ + hz: 400_000, + address: 0x40, + ...options.sensor + }); + } + + init() { + const io = this.#io; + io.writeUint8(0x00, 0xFF); // RESET_CTL + const data = [ + [0x00, 0x41], // RESET_CTL + [0x01, 0x1f], // CLK_ON_OFF + [0x06, 0x00], // DIGITAL_PDN + [0x07, 0x20], // ADC_OSR + [0x08, 0x10], // MODE_CFG + [0x09, 0x30], // TCT0_CHPINI + [0x0A, 0x30], // TCT1_CHPINI + [0x20, 0x0a], // ADC34_HPF2 + [0x21, 0x2a], // ADC34_HPF1 + [0x22, 0x0a], // ADC12_HPF2 + [0x23, 0x2a], // ADC12_HPF1 + [0x02, 0xC1], + [0x04, 0x01], + [0x05, 0x00], + [0x11, 0x60], + [0x40, 0x42], // ANALOG_SYS + [0x41, 0x70], // MICBIAS12 + [0x42, 0x70], // MICBIAS34 + [0x43, 0x1B], // MIC1_GAIN + [0x44, 0x1B], // MIC2_GAIN + [0x45, 0x00], // MIC3_GAIN + [0x46, 0x00], // MIC4_GAIN + [0x47, 0x00], // MIC1_LP + [0x48, 0x00], // MIC2_LP + [0x49, 0x00], // MIC3_LP + [0x4A, 0x00], // MIC4_LP + [0x4B, 0x00], // MIC12_PDN + [0x4C, 0xFF], // MIC34_PDN + [0x01, 0x14], // CLK_ON_OFF + ]; + for (const [reg, value] of data) { + io.writeUint8(reg, value); + } + } +} + class Power { // extends AXP2101 { #axp2101; @@ -166,6 +222,7 @@ class Power { // extends AXP2101 { axp2101.writeByte(0x27, 0); axp2101.writeByte(0x69, 0x11); axp2101.writeByte(0x10, 0x30); + axp2101.writeByte(0x30, 0x0f); // ADC enabled (for voltage measurement) this.expander = new AW9523({ ...options }); this.expander.writeByte(0x02, 0b00000111); diff --git a/examples/io/audioin/capture-sync/main.js b/examples/io/audioin/capture-sync/main.js index b8c13e355..b1c9a9121 100644 --- a/examples/io/audioin/capture-sync/main.js +++ b/examples/io/audioin/capture-sync/main.js @@ -21,11 +21,14 @@ samples.total = 0; trace("recording\n") const input = new AudioIn({ + channels: 1, onReadable(size) { const buffer = new SharedArrayBuffer(size); input.read(buffer); - samples.push(new Uint8Array(buffer)); - samples.total += buffer.byteLength; + const data = new Uint8Array(buffer); + + samples.push(data); + samples.total += data.byteLength; if (samples.total >= input.sampleRate * (input.bitsPerSample / 8) * 5) { this.close(); diff --git a/examples/io/audioin/capture-sync/manifest.json b/examples/io/audioin/capture-sync/manifest.json index c5a2e8746..b264d3bfc 100644 --- a/examples/io/audioin/capture-sync/manifest.json +++ b/examples/io/audioin/capture-sync/manifest.json @@ -25,5 +25,33 @@ }, "modules": { "*": "./main" + }, + "platforms": { + "esp32/m5stack_cores3": { + "defines": { + "audioIn": { + "sampleRate": 24000, + "numChannels": 2, + "bitsPerSample": 16 + }, + "audioOut": { + "bitsPerSample": 16, + "numChannels": 1, + "sampleRate": 24000 + } + }, + "creation": { + "static": 0, + "chunk": { + "initial": 1000000, + "incremental": 0 + }, + "heap": { + "initial": 8192, + "incremental": 0 + }, + "stack": 1024 + } + } } } diff --git a/modules/io/audioin/esp32/audioin.c b/modules/io/audioin/esp32/audioin.c index e583c4398..9842a3025 100644 --- a/modules/io/audioin/esp32/audioin.c +++ b/modules/io/audioin/esp32/audioin.c @@ -41,6 +41,12 @@ #ifndef MODDEF_AUDIOIN_I2S_LR_PIN #define MODDEF_AUDIOIN_I2S_LR_PIN (33) #endif +#ifndef MODDEF_AUDIOIN_I2S_MCK_PIN + #define MODDEF_AUDIOIN_I2S_MCK_PIN (I2S_GPIO_UNUSED) +#endif +#ifndef MODDEF_AUDIOIN_I2S_FORMAT_I2S + #define MODDEF_AUDIOIN_I2S_FORMAT_I2S (0) +#endif #ifndef MODDEF_AUDIOIN_I2S_DATAIN #define MODDEF_AUDIOIN_I2S_DATAIN (27) #endif @@ -56,6 +62,9 @@ #ifndef MODDEF_AUDIOIN_I2S_SLOT #define MODDEF_AUDIOIN_I2S_SLOT (I2S_STD_SLOT_RIGHT) #endif +#ifndef MODDEF_AUDIOIN_NUMCHANNELS + #define MODDEF_AUDIOIN_NUMCHANNELS (1) +#endif #if MODDEF_AUDIOIN_I2S_ADC #if MODDEF_AUDIOIN_SAMPLERATE < SOC_ADC_SAMPLE_FREQ_THRES_LOW @@ -518,9 +527,15 @@ void audioInLoop(void *pvParameter) #else i2s_std_config_t rx_std_cfg = { .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(input->sampleRate), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), +#if MODDEF_AUDIOIN_I2S_FORMAT_I2S + .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, + (2 == MODDEF_AUDIOIN_NUMCHANNELS) ? I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO), +#else + .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, + (2 == MODDEF_AUDIOIN_NUMCHANNELS) ? I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO), +#endif .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, + .mclk = MODDEF_AUDIOIN_I2S_MCK_PIN, .bclk = MODDEF_AUDIOIN_I2S_BCK_PIN, .ws = MODDEF_AUDIOIN_I2S_LR_PIN, .dout = I2S_GPIO_UNUSED, @@ -532,7 +547,9 @@ void audioInLoop(void *pvParameter) } } }; - rx_std_cfg.slot_cfg.slot_mask = I2S_STD_SLOT_RIGHT; //@@ + rx_std_cfg.slot_cfg.slot_mask = (2 == MODDEF_AUDIOIN_NUMCHANNELS) + ? I2S_STD_SLOT_BOTH + : MODDEF_AUDIOIN_I2S_SLOT; //@@ err = i2s_channel_init_std_mode(input->handle, &rx_std_cfg); if (err) { @@ -737,4 +754,3 @@ void xs_audioin_get_sampleRate(xsMachine *the) AudioInput input = xsmcGetHostDataValidate(xsThis, (void *)&xsAudioInHooks); xsmcSetInteger(xsResult, input->sampleRate); } - diff --git a/modules/pins/audioin/esp32/audioin.c b/modules/pins/audioin/esp32/audioin.c index b94bbe8c3..c4274ecf8 100755 --- a/modules/pins/audioin/esp32/audioin.c +++ b/modules/pins/audioin/esp32/audioin.c @@ -56,11 +56,23 @@ #ifndef MODDEF_AUDIOIN_I2S_LR_PIN #define MODDEF_AUDIOIN_I2S_LR_PIN (33) #endif + #ifndef MODDEF_AUDIOIN_I2S_MCK_PIN + #define MODDEF_AUDIOIN_I2S_MCK_PIN (I2S_GPIO_UNUSED) + #endif + #ifndef MODDEF_AUDIOIN_I2S_FORMAT_I2S + #define MODDEF_AUDIOIN_I2S_FORMAT_I2S (0) + #endif #ifndef MODDEF_AUDIOIN_I2S_DATAIN #define MODDEF_AUDIOIN_I2S_DATAIN (27) #endif - #ifndef MODDEF_AUDIOIN_I2S_ADC - #define MODDEF_AUDIOIN_I2S_ADC (0) +#ifndef MODDEF_AUDIOIN_I2S_ADC + #define MODDEF_AUDIOIN_I2S_ADC (0) +#endif +#ifndef MODDEF_AUDIOIN_NUMCHANNELS + #define MODDEF_AUDIOIN_NUMCHANNELS (1) +#endif + #ifndef MODDEF_AUDIOIN_I2S_SLOT + #define MODDEF_AUDIOIN_I2S_SLOT (I2S_STD_SLOT_RIGHT) #endif #if MODDEF_AUDIOIN_I2S_ADC @@ -152,9 +164,15 @@ void xs_audioin(xsMachine *the) #else i2s_std_config_t rx_std_cfg = { .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(MODDEF_AUDIOIN_SAMPLERATE), - .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), +#if MODDEF_AUDIOIN_I2S_FORMAT_I2S + .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, + (2 == MODDEF_AUDIOIN_NUMCHANNELS) ? I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO), +#else + .slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, + (2 == MODDEF_AUDIOIN_NUMCHANNELS) ? I2S_SLOT_MODE_STEREO : I2S_SLOT_MODE_MONO), +#endif .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, + .mclk = MODDEF_AUDIOIN_I2S_MCK_PIN, .bclk = MODDEF_AUDIOIN_I2S_BCK_PIN, .ws = MODDEF_AUDIOIN_I2S_LR_PIN, .dout = I2S_GPIO_UNUSED, @@ -166,7 +184,9 @@ void xs_audioin(xsMachine *the) } } }; - rx_std_cfg.slot_cfg.slot_mask = I2S_STD_SLOT_RIGHT; //@@ + rx_std_cfg.slot_cfg.slot_mask = (2 == MODDEF_AUDIOIN_NUMCHANNELS) + ? I2S_STD_SLOT_BOTH + : MODDEF_AUDIOIN_I2S_SLOT; //@@ err = i2s_channel_init_std_mode(rx_handle, &rx_std_cfg); if (err) {