summaryrefslogtreecommitdiff
path: root/code/esp32/components/eos/cell_pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'code/esp32/components/eos/cell_pcm.c')
-rw-r--r--code/esp32/components/eos/cell_pcm.c222
1 files changed, 161 insertions, 61 deletions
diff --git a/code/esp32/components/eos/cell_pcm.c b/code/esp32/components/eos/cell_pcm.c
index 961a322..426cd5f 100644
--- a/code/esp32/components/eos/cell_pcm.c
+++ b/code/esp32/components/eos/cell_pcm.c
@@ -10,29 +10,46 @@
#include "eos.h"
#include "net.h"
+#include "msgq.h"
#include "cell.h"
-static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1};
+#define PCM_MIC_WM 128
+#define PCM_HOLD_CNT_TX 2
+#define PCM_HOLD_CNT_RX 2
+#define PCM_SIZE_BUFQ 4
+#define PCM_SIZE_BUF (PCM_MIC_WM * 4)
+
+#define PCM_GPIO_BCK 33
+#define PCM_GPIO_WS 4
+#define PCM_GPIO_DIN 34
+#define PCM_GPIO_DOUT 2
+
+#define PCM_ETYPE_WRITE 1
-#define BUF_SIZE 2048
+static EOSBufQ pcm_buf_q;
+static unsigned char *pcm_bufq_array[PCM_SIZE_BUFQ];
-#define PCM_GPIO_BCK 33
-#define PCM_GPIO_WS 4
-#define PCM_GPIO_DIN 34
-#define PCM_GPIO_DOUT 2
+static EOSMsgQ pcm_evt_q;
+static EOSMsgItem pcm_evtq_array[PCM_SIZE_BUFQ];
+
+static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1};
static QueueHandle_t i2s_queue;
+static SemaphoreHandle_t mutex;
static const char *TAG = "EOS PCM";
static void i2s_event_task(void *pvParameters) {
- size_t size_out;
i2s_event_t event;
- // Reserve a buffer and process incoming data
- uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
-
- int first = 1;
- uint8_t *data_first = NULL;
+ unsigned char *buf;
+ unsigned char _type;
+ size_t bytes_w;
+ ssize_t bytes_r;
+ uint16_t bytes_e;
+ ssize_t hold_bytes_r = 0;
+ unsigned char *hold_buf = NULL;
+ static char hold_cnt_tx = 0;
+ static char hold_cnt_rx = 0;
while (1) {
// Waiting for I2S event.
@@ -40,65 +57,64 @@ static void i2s_event_task(void *pvParameters) {
switch (event.type) {
case I2S_EVENT_RX_DONE:
// Event of I2S receiving data
- // printf("*** I2S DATA RECEIVED: %d\n ***", event.size);
- i2s_read(I2S_NUM_0, (void *)data, BUF_SIZE, &size_out, 1000 / portTICK_RATE_MS);
- if (first) {
- if (data_first) {
- first = 0;
- i2s_write(I2S_NUM_0, (const void *)data_first, BUF_SIZE, &size_out, 1000 / portTICK_RATE_MS);
- free(data_first);
- data_first = NULL;
- } else {
- data_first = (uint8_t *) malloc(BUF_SIZE);
- memcpy(data_first, data, BUF_SIZE);
+ if (!hold_cnt_rx) {
+ buf = eos_net_alloc();
+ buf[0] = EOS_CELL_MTYPE_AUDIO;
+ bytes_r = eos_pcm_read(buf + 1, PCM_MIC_WM);
+ eos_net_send(EOS_NET_MTYPE_CELL, buf, bytes_r + 1, 0);
+ } else {
+ hold_cnt_rx--;
+ if (hold_buf == NULL) {
+ hold_buf = eos_net_alloc();
+ hold_buf[0] = EOS_CELL_MTYPE_AUDIO;
}
+ hold_bytes_r += eos_pcm_read(hold_buf + 1 + hold_bytes_r, PCM_MIC_WM);
+ if (hold_cnt_rx == 0) eos_net_send(EOS_NET_MTYPE_CELL, hold_buf, hold_bytes_r + 1, 0);
+ }
+
+ if (!hold_cnt_tx) {
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ eos_msgq_pop(&pcm_evt_q, &_type, &buf, &bytes_e, NULL);
+ xSemaphoreGive(mutex);
+ if (buf) {
+ i2s_write(I2S_NUM_0, (const void *)buf, bytes_e, &bytes_w, portMAX_DELAY);
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ eos_bufq_push(&pcm_buf_q, buf);
+ xSemaphoreGive(mutex);
+ }
+ } else {
+ hold_cnt_tx--;
}
- i2s_write(I2S_NUM_0, (const void *)data, BUF_SIZE, &size_out, 1000 / portTICK_RATE_MS);
break;
case I2S_EVENT_DMA_ERROR:
ESP_LOGE(TAG, "*** I2S DMA ERROR ***");
break;
+ case I2S_EVENT_MAX:
+ hold_cnt_tx = PCM_HOLD_CNT_TX;
+ hold_cnt_rx = PCM_HOLD_CNT_RX;
+ hold_bytes_r = 0;
+ hold_buf = NULL;
+ break;
default:
break;
}
}
}
- free(data);
vTaskDelete(NULL);
}
-/*
-static void i2s_write_task(void *pvParameters) {
- uint8_t *data = (uint8_t *) malloc(BUF_SIZE);
- memset(data, 0x0, BUF_SIZE);
-
+void eos_pcm_init(void) {
int i;
- for (i=0; i<BUF_SIZE; i+=16) {
- data[i+3] = 0xaa;
- data[i+2] = 0xff;
- }
- while(1) {
- size_t size_out;
- // i2s_read(I2S_NUM_0, (void *)data, BUF_SIZE, &size_out, 1000 / portTICK_RATE_MS);
- // printf("!! I2S DATA IN: %d\n", size_out);
- i2s_write(I2S_NUM_0, (const void *)data, BUF_SIZE, &size_out, 1000 / portTICK_RATE_MS);
- printf("I2S DATA OUT: %d\n", size_out);
- }
- free(data);
- vTaskDelete(NULL);
-}
-*/
-void eos_pcm_init(void) {
i2s_config_t i2s_config = {
.mode = I2S_MODE_SLAVE | I2S_MODE_TX | I2S_MODE_RX,
.sample_rate = 32000,
.bits_per_sample = 32,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
- .communication_format = I2S_COMM_FORMAT_PCM | I2S_COMM_FORMAT_PCM_LONG,
+ .communication_format = I2S_COMM_FORMAT_I2S,
.dma_buf_count = 4,
- .dma_buf_len = 512,
+ .dma_buf_len = PCM_MIC_WM,
.use_apll = true,
.fixed_mclk = 2048000 * 8,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1
@@ -115,31 +131,115 @@ void eos_pcm_init(void) {
i2s_set_pin(I2S_NUM_0, &pin_config);
gpio_matrix_in(pin_config.ws_io_num, I2S0I_WS_IN_IDX, 1);
gpio_matrix_in(pin_config.bck_io_num, I2S0I_BCK_IN_IDX, 1);
- I2S[I2S_NUM_0]->conf.tx_mono = 1;
+ ESP_LOGI(TAG, "TX FIFO:%d TX CHAN:%d RX FIFO:%d RX CHAN:%d", I2S[I2S_NUM_0]->fifo_conf.tx_fifo_mod, I2S[I2S_NUM_0]->conf_chan.tx_chan_mod, I2S[I2S_NUM_0]->fifo_conf.rx_fifo_mod, I2S[I2S_NUM_0]->conf_chan.rx_chan_mod);
+
+ I2S[I2S_NUM_0]->fifo_conf.tx_fifo_mod = 2;
+ I2S[I2S_NUM_0]->conf_chan.tx_chan_mod = 0;
+
+ I2S[I2S_NUM_0]->fifo_conf.rx_fifo_mod = 3;
+ I2S[I2S_NUM_0]->conf_chan.rx_chan_mod = 1;
+ // I2S[I2S_NUM_0]->conf.tx_mono = 1;
I2S[I2S_NUM_0]->conf.rx_mono = 1;
+ // I2S[I2S_NUM_0]->timing.tx_dsync_sw = 1
+ // I2S[I2S_NUM_0]->timing.rx_dsync_sw = 1
+ // I2S[I2S_NUM_0]->conf.sig_loopback = 0;
+
+ // I2S[I2S_NUM_0]->timing.tx_bck_in_inv = 1;
+
+ eos_msgq_init(&pcm_evt_q, pcm_evtq_array, PCM_SIZE_BUFQ);
+ eos_bufq_init(&pcm_buf_q, pcm_bufq_array, PCM_SIZE_BUFQ);
+ for (i=0; i<PCM_SIZE_BUFQ; i++) {
+ eos_bufq_push(&pcm_buf_q, malloc(PCM_SIZE_BUF));
+ }
+
+ mutex = xSemaphoreCreateBinary();
+ xSemaphoreGive(mutex);
// Create a task to handle i2s event from ISR
xTaskCreate(i2s_event_task, "i2s_event", EOS_TASK_SSIZE_I2S, NULL, EOS_TASK_PRIORITY_I2S, NULL);
- // xTaskCreate(i2s_write_task, "i2s_write_task", EOS_TASK_SSIZE_I2S, NULL, EOS_TASK_PRIORITY_I2S, NULL);
ESP_LOGI(TAG, "INIT");
- i2s_start(I2S_NUM_0);
}
-ssize_t eos_pcm_write(void *data, size_t size) {
- size_t size_out;
+ssize_t eos_pcm_read(unsigned char *data, size_t size) {
+ static unsigned char buf[PCM_SIZE_BUF];
+ size_t bytes_r;
+ int i;
+
+ if (size > PCM_MIC_WM) return EOS_ERR;
- esp_err_t ret = i2s_write(I2S_NUM_0, (const void *)data, size, &size_out, portMAX_DELAY);
+ esp_err_t ret = i2s_read(I2S_NUM_0, (void *)buf, size * 4, &bytes_r, portMAX_DELAY);
if (ret != ESP_OK) return EOS_ERR;
- return size_out;
+
+ for (i=0; i<size/2; i++) {
+ data[i * 2] = buf[i * 8 + 3];
+ data[i * 2 + 1] = buf[i * 8 + 2];
+ }
+
+ return bytes_r / 4;
+}
+
+ssize_t eos_pcm_expand(unsigned char *buf, unsigned char *data, size_t size) {
+ int i;
+
+ if (size > PCM_MIC_WM) return EOS_ERR;
+
+ memset(buf, 0, PCM_SIZE_BUF);
+ for (i=0; i<size/2; i++) {
+ /*
+ unsigned char _d;
+ if (i % 2 == 0) {
+ _d = 0xAA;
+ } else {
+ _d = 0xF0;
+ }
+ _d = 0xF0;
+ buf[i * 8 + 3] = _d;
+ buf[i * 8 + 2] = _d;
+ */
+ buf[i * 8 + 3] = data[i * 2];
+ buf[i * 8 + 2] = data[i * 2 + 1];
+ }
+
+ return size * 4;
+}
+
+int eos_pcm_push(unsigned char *data, size_t size) {
+ unsigned char *buf = NULL;
+ ssize_t esize;
+ int rv;
+
+ if (size > PCM_MIC_WM) return EOS_ERR;
+
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ buf = eos_bufq_pop(&pcm_buf_q);
+ xSemaphoreGive(mutex);
+ if (buf == NULL) return EOS_ERR_EMPTY;
+
+ esize = eos_pcm_expand(buf, data, size);
+ if (esize < 0) {
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ eos_bufq_push(&pcm_buf_q, buf);
+ xSemaphoreGive(mutex);
+ return esize;
+ }
+
+ xSemaphoreTake(mutex, portMAX_DELAY);
+ rv = eos_msgq_push(&pcm_evt_q, PCM_ETYPE_WRITE, buf, esize, 0);
+ if (rv) eos_bufq_push(&pcm_buf_q, buf);
+ xSemaphoreGive(mutex);
+
+ return rv;
}
-/*
-void eos_pcm_call(void) {
- const char *s = "ATD0631942317;\r";
+void eos_pcm_start(void) {
+ i2s_event_t evt;
+ evt.type = I2S_EVENT_MAX; /* my type */
+ xQueueSend(i2s_queue, (void *)&evt, portMAX_DELAY);
i2s_zero_dma_buffer(I2S_NUM_0);
- eos_modem_write((void *)s, strlen(s));
- vTaskDelay(1000 / portTICK_RATE_MS);
i2s_start(I2S_NUM_0);
}
-*/
+
+void eos_pcm_stop(void) {
+ i2s_stop(I2S_NUM_0);
+}