|
| 1 | +#include "py/obj.h" |
| 2 | +#include "py/runtime.h" |
| 3 | +#include "py/mphal.h" |
| 4 | +#include "esp_heap_caps.h" |
| 5 | +#include "esp_codec_dev.h" |
| 6 | +#include "adc_mic.h" // Include for audio_codec_adc_cfg_t, audio_codec_new_adc_data, etc. |
| 7 | + |
| 8 | +static mp_obj_t adc_mic_read(void) { |
| 9 | + // Configure for mono ADC on GPIO1 (ADC1_CHANNEL_0) at 16kHz |
| 10 | + audio_codec_adc_cfg_t cfg = DEFAULT_AUDIO_CODEC_ADC_MONO_CFG(ADC_CHANNEL_0, 16000); |
| 11 | + const audio_codec_data_if_t *adc_if = audio_codec_new_adc_data(&cfg); |
| 12 | + if (adc_if == NULL) { |
| 13 | + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to initialize ADC data interface")); |
| 14 | + } |
| 15 | + |
| 16 | + // Create codec device for input |
| 17 | + esp_codec_dev_cfg_t codec_dev_cfg = { |
| 18 | + .dev_type = ESP_CODEC_DEV_TYPE_IN, |
| 19 | + .data_if = adc_if, |
| 20 | + }; |
| 21 | + esp_codec_dev_handle_t dev = esp_codec_dev_new(&codec_dev_cfg); |
| 22 | + if (dev == NULL) { |
| 23 | + audio_codec_delete_adc_data(adc_if); |
| 24 | + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to create codec device")); |
| 25 | + } |
| 26 | + |
| 27 | + // Set sample info: 16kHz, mono, 16-bit |
| 28 | + esp_codec_dev_sample_info_t fs = { |
| 29 | + .sample_rate = 16000, |
| 30 | + .channel = 1, |
| 31 | + .bits_per_sample = 16, |
| 32 | + }; |
| 33 | + if (esp_codec_dev_open(dev, &fs) != ESP_OK) { |
| 34 | + esp_codec_dev_del(dev); |
| 35 | + audio_codec_delete_adc_data(adc_if); |
| 36 | + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to open codec device")); |
| 37 | + } |
| 38 | + |
| 39 | + // Allocate buffer for 16000 samples (16-bit, so 32000 bytes) |
| 40 | + const size_t buf_size = 16000 * sizeof(uint16_t); |
| 41 | + uint8_t *audio_buffer = (uint8_t *)heap_caps_malloc(buf_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); |
| 42 | + if (audio_buffer == NULL) { |
| 43 | + esp_codec_dev_close(dev); |
| 44 | + esp_codec_dev_del(dev); |
| 45 | + audio_codec_delete_adc_data(adc_if); |
| 46 | + mp_raise_OSError(MP_ENOMEM); |
| 47 | + } |
| 48 | + |
| 49 | + // Read the data (blocking until buffer is filled) |
| 50 | + int ret = esp_codec_dev_read(dev, audio_buffer, buf_size); |
| 51 | + if (ret < 0) { |
| 52 | + heap_caps_free(audio_buffer); |
| 53 | + esp_codec_dev_close(dev); |
| 54 | + esp_codec_dev_del(dev); |
| 55 | + audio_codec_delete_adc_data(adc_if); |
| 56 | + mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("Failed to read audio data: %d"), ret); |
| 57 | + } |
| 58 | + |
| 59 | + // Create MicroPython bytes object from the buffer |
| 60 | + mp_obj_t buf_obj = mp_obj_new_bytes(audio_buffer, ret); |
| 61 | + |
| 62 | + // Cleanup |
| 63 | + heap_caps_free(audio_buffer); |
| 64 | + esp_codec_dev_close(dev); |
| 65 | + esp_codec_dev_del(dev); |
| 66 | + audio_codec_delete_adc_data(adc_if); |
| 67 | + |
| 68 | + return buf_obj; |
| 69 | +} |
| 70 | +MP_DEFINE_CONST_FUN_OBJ_0(adc_mic_read_obj, adc_mic_read); |
| 71 | + |
| 72 | +static const mp_rom_map_elem_t adc_mic_module_globals_table[] = { |
| 73 | + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_adc_mic) }, |
| 74 | + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&adc_mic_read_obj) }, |
| 75 | +}; |
| 76 | +static MP_DEFINE_CONST_DICT(adc_mic_module_globals, adc_mic_module_globals_table); |
| 77 | + |
| 78 | +const mp_obj_module_t adc_mic_user_cmodule = { |
| 79 | + .base = { &mp_type_module }, |
| 80 | + .globals = (mp_obj_dict_t *)&adc_mic_module_globals, |
| 81 | +}; |
| 82 | + |
| 83 | +MP_REGISTER_MODULE(MP_QSTR_adc_mic, adc_mic_user_cmodule); |
0 commit comments