#include #include #include #include #include #include #include "eos.h" #include "net.h" #include "cell.h" #define PCM_GPIO_BCK 1 #define PCM_GPIO_WS 41 #define PCM_GPIO_DIN 2 #define PCM_GPIO_DOUT 42 #define PCM_RX_WM 256 /* receive watermark, must be less than NET_SIZE_MTU */ static i2s_chan_handle_t tx_chan; static i2s_chan_handle_t rx_chan; static const char *TAG = "EOS CELL PCM"; static void pcm_rcvr_task(void *pvParameters) { unsigned char *buffer; size_t size_r; esp_err_t ret; int done = 0; int rv; while (!done) { buffer = eos_net_alloc(); buffer[0] = EOS_CELL_MTYPE_VOICE | EOS_CELL_MTYPE_VOICE_PCM; ret = i2s_channel_read(rx_chan, buffer + 1, PCM_RX_WM, &size_r, 1000); switch (ret) { case ESP_OK: { assert(size_r == PCM_RX_WM); break; } case ESP_ERR_INVALID_STATE: { done = 1; break; } default: { done = 1; ESP_LOGE(TAG, "CHAN READ ERR:%d", ret); break; } } if (ret == ESP_OK) { rv = eos_net_send(EOS_NET_MTYPE_CELL, buffer, size_r + 1); if (rv) ESP_LOGE(TAG, "NET SEND ERR:%d", rv); } else { eos_net_free(buffer); } } vTaskDelete(NULL); } void eos_cell_pcm_start(void) { BaseType_t rv; esp_err_t ret; ret = i2s_channel_enable(tx_chan); if (ret) { ESP_LOGE(TAG, "TX CHAN ENABLE ERR:%d", ret); return; } ret = i2s_channel_enable(rx_chan); if (ret) { ESP_LOGE(TAG, "RX CHAN ENABLE ERR:%d", ret); return; } rv = xTaskCreate(&pcm_rcvr_task, "pcm_rcvr", EOS_TASK_SSIZE_PCM, NULL, EOS_TASK_PRIORITY_PCM, NULL); assert(rv == pdPASS); } void eos_cell_pcm_stop(void) { esp_err_t ret; ret = i2s_channel_disable(tx_chan); if (ret) ESP_LOGE(TAG, "TX CHAN DISABLE ERR:%d", ret); ret = i2s_channel_disable(rx_chan); if (ret) ESP_LOGE(TAG, "RX CHAN DISABLE ERR:%d", ret); } void eos_cell_pcm_push(unsigned char *data, size_t size) { esp_err_t ret; size_t size_w; ret = i2s_channel_write(tx_chan, data, size, &size_w, 1000); if (ret == ESP_OK) { assert(size_w == size); } else { ESP_LOGE(TAG, "CHAN WRITE ERR:%d", ret); } } void eos_cell_pcm_init(void) { i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_SLAVE); i2s_tdm_config_t tdm_cfg = { .clk_cfg = I2S_TDM_CLK_DEFAULT_CONFIG(8000), .slot_cfg = I2S_TDM_PCM_SHORT_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO, I2S_TDM_SLOT0), .gpio_cfg = { .mclk = I2S_GPIO_UNUSED, .bclk = PCM_GPIO_BCK, .ws = PCM_GPIO_WS, .din = PCM_GPIO_DIN, .dout = PCM_GPIO_DOUT, .invert_flags = { .mclk_inv = false, .bclk_inv = false, .ws_inv = false, }, }, }; esp_err_t ret; tdm_cfg.slot_cfg.total_slot = 16; ret = i2s_new_channel(&chan_cfg, &tx_chan, &rx_chan); assert(ret == ESP_OK); ret = i2s_channel_init_tdm_mode(tx_chan, &tdm_cfg); assert(ret == ESP_OK); ret = i2s_channel_init_tdm_mode(rx_chan, &tdm_cfg); assert(ret == ESP_OK); ESP_LOGI(TAG, "INIT"); }