309 lines
7.6 KiB
C
Executable File
309 lines
7.6 KiB
C
Executable File
// Copyright 2020-2021 Beken
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <os/mem.h>
|
|
#include <os/os.h>
|
|
#include <os/str.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "driver/es8311.h"
|
|
#include "driver/es8311_types.h"
|
|
#include <driver/i2s.h>
|
|
#include <driver/i2s_types.h>
|
|
#include "ff.h"
|
|
#include "diskio.h"
|
|
#include "cli.h"
|
|
|
|
|
|
static beken_thread_t es8311_master_thread_hdl = NULL;
|
|
static beken_queue_t es8311_master_msg_que = NULL;
|
|
static RingBufferContext *ch1_rx_rb;
|
|
static uint8_t *es8311_rx_temp = NULL;
|
|
static FIL es8311_file_mic;
|
|
static RingBufferContext mic_data_rb;
|
|
static uint8_t *mic_data_buffer = NULL;
|
|
static i2s_config_t i2s_config = DEFAULT_I2S_CONFIG( );
|
|
static es8311_codec_config_t es8311_cfg = DEFAULT_ES8311_SETUP_CONFIG();
|
|
static bool es8311_mic_save_flag = true;
|
|
static uint8_t *file_temp_buff = NULL;
|
|
|
|
#define DMIC_FRAME_SIZE 320
|
|
#define DMIC_FRAME_NUM 20
|
|
#define DMIC_BUFF_HALF_SIZE 3200
|
|
|
|
|
|
#define MONO_MIC_DATA 1
|
|
|
|
|
|
typedef enum {
|
|
ES8311_MIC = 0,
|
|
ES8311_EXIT,
|
|
} es8311_op_t;
|
|
|
|
typedef struct {
|
|
es8311_op_t op;
|
|
} es8311_msg_t;
|
|
|
|
static void cli_es8311_help(void)
|
|
{
|
|
os_printf("es8311_codec_test {start|stop 16K xxx.pcm} \r\n");
|
|
}
|
|
|
|
|
|
static bk_err_t es8311_send_msg(es8311_op_t op)
|
|
{
|
|
bk_err_t ret;
|
|
es8311_msg_t msg;
|
|
|
|
msg.op = op;
|
|
|
|
if (es8311_master_msg_que) {
|
|
ret = rtos_push_to_queue(&es8311_master_msg_que, &msg, BEKEN_NO_WAIT);
|
|
if (kNoErr != ret) {
|
|
os_printf("es8311_send_int_msg fail \r\n");
|
|
return kOverrunErr;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
return kNoResourcesErr;
|
|
}
|
|
|
|
static int es8311_ch1_rx_data_handle_cb(uint32_t size)
|
|
{
|
|
uint32 uiTemp = 0;
|
|
|
|
//os_printf("%s, size: %d \n", __func__, size);
|
|
uiTemp = ring_buffer_read(ch1_rx_rb, es8311_rx_temp, size);
|
|
|
|
if (ring_buffer_get_free_size(&mic_data_rb) >= uiTemp) {
|
|
ring_buffer_write(&mic_data_rb, es8311_rx_temp, uiTemp);
|
|
}
|
|
|
|
if (ring_buffer_get_fill_size(&mic_data_rb) >= DMIC_BUFF_HALF_SIZE && es8311_mic_save_flag) {
|
|
es8311_send_msg(ES8311_MIC);
|
|
es8311_mic_save_flag = false;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static void es8311_master_main(void)
|
|
{
|
|
bk_err_t ret = BK_OK;
|
|
uint32 uiTemp = 0;
|
|
FRESULT fr;
|
|
uint32_t write_size = 0;
|
|
GLOBAL_INT_DECLARATION();
|
|
|
|
file_temp_buff = os_malloc(DMIC_BUFF_HALF_SIZE);
|
|
|
|
#if MONO_MIC_DATA
|
|
int16_t *mic_mono_data = NULL;
|
|
mic_mono_data = os_malloc(DMIC_BUFF_HALF_SIZE/4);
|
|
#endif
|
|
|
|
while(1) {
|
|
es8311_msg_t msg;
|
|
ret = rtos_pop_from_queue(&es8311_master_msg_que, &msg, BEKEN_WAIT_FOREVER);
|
|
if (kNoErr == ret) {
|
|
switch (msg.op) {
|
|
case ES8311_MIC:
|
|
GLOBAL_INT_DISABLE();
|
|
write_size = ring_buffer_read(&mic_data_rb, file_temp_buff, DMIC_BUFF_HALF_SIZE);
|
|
GLOBAL_INT_RESTORE();
|
|
es8311_mic_save_flag = true;
|
|
#if MONO_MIC_DATA
|
|
int16_t *ptr = (int16_t *)file_temp_buff;
|
|
for (uint32_t i = 0; i < write_size/8; i++) {
|
|
mic_mono_data[i] = ptr[i*4 + 1];
|
|
}
|
|
fr = f_write(&es8311_file_mic, (void *)mic_mono_data, write_size/4, &uiTemp);
|
|
#else
|
|
fr = f_write(&es8311_file_mic, (void *)file_temp_buff, write_size, &uiTemp);
|
|
#endif
|
|
if (fr != FR_OK) {
|
|
os_printf("write es8311 mic data fail.\r\n");
|
|
}
|
|
break;
|
|
|
|
case ES8311_EXIT:
|
|
goto es8311_exit;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
es8311_exit:
|
|
os_printf("goto es8311_exit \n");
|
|
os_free(file_temp_buff);
|
|
file_temp_buff = NULL;
|
|
#if MONO_MIC_DATA
|
|
os_free(mic_mono_data);
|
|
mic_mono_data = NULL;
|
|
#endif
|
|
|
|
/* delete msg queue */
|
|
ret = rtos_deinit_queue(&es8311_master_msg_que);
|
|
if (ret != kNoErr) {
|
|
os_printf("delete message queue fail \r\n");
|
|
}
|
|
es8311_master_msg_que = NULL;
|
|
os_printf("delete message queue complete \r\n");
|
|
|
|
/* delete task */
|
|
es8311_master_thread_hdl = NULL;
|
|
rtos_delete_thread(NULL);
|
|
}
|
|
|
|
void cli_es8311_codec_test_cmd(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
|
|
{
|
|
bk_err_t ret = BK_OK;
|
|
char mic_file_name[50];
|
|
FRESULT fr;
|
|
GLOBAL_INT_DECLARATION();
|
|
|
|
if (argc < 4) {
|
|
cli_es8311_help();
|
|
return;
|
|
}
|
|
|
|
if (os_strcmp(argv[1], "start") == 0) {
|
|
sprintf(mic_file_name, "1:/%s", argv[3]);
|
|
fr = f_open(&es8311_file_mic, mic_file_name, FA_CREATE_ALWAYS | FA_WRITE);
|
|
if (fr != FR_OK) {
|
|
os_printf("open %s fail.\r\n", mic_file_name);
|
|
return;
|
|
}
|
|
|
|
es8311_rx_temp = os_malloc(DMIC_FRAME_SIZE);
|
|
os_memset(es8311_rx_temp, 0x00, DMIC_FRAME_SIZE);
|
|
|
|
//init i2s driver
|
|
bk_i2s_driver_init();
|
|
|
|
//init i2s configure
|
|
i2s_config.role = I2S_ROLE_SLAVE;
|
|
i2s_config.samp_rate = I2S_SAMP_RATE_16000;
|
|
i2s_config.data_length = 32;
|
|
bk_i2s_init(I2S_GPIO_GROUP_1, &i2s_config);
|
|
os_printf("init i2s driver and config successful \r\n");
|
|
|
|
ret = bk_i2s_chl_init(I2S_CHANNEL_1, I2S_TXRX_TYPE_RX, 640, es8311_ch1_rx_data_handle_cb, &ch1_rx_rb);
|
|
if (ret != BK_OK) {
|
|
os_printf("bk_i2s_chl_init fail \n");
|
|
return;
|
|
}
|
|
|
|
mic_data_buffer = os_malloc(DMIC_FRAME_SIZE * DMIC_FRAME_NUM);
|
|
if (mic_data_buffer == NULL) {
|
|
os_printf("malloc mic_data_buffer fail \n");
|
|
return;
|
|
}
|
|
ring_buffer_init(&mic_data_rb, mic_data_buffer, DMIC_FRAME_SIZE * DMIC_FRAME_NUM, DMA_ID_MAX, RB_DMA_TYPE_NULL);
|
|
|
|
|
|
ret = rtos_init_queue(&es8311_master_msg_que,
|
|
"es8311_int_que",
|
|
sizeof(es8311_msg_t),
|
|
80);
|
|
if (ret != kNoErr) {
|
|
os_printf("ceate es8311 message queue fail \r\n");
|
|
return;
|
|
}
|
|
os_printf("ceate es8311 message queue complete \r\n");
|
|
|
|
|
|
/* create task to asr */
|
|
ret = rtos_create_thread(&es8311_master_thread_hdl,
|
|
3,
|
|
"es8311",
|
|
(beken_thread_function_t)es8311_master_main,
|
|
4096*2,
|
|
NULL);
|
|
if (ret != kNoErr) {
|
|
os_printf("create audio transfer driver task fail \r\n");
|
|
rtos_deinit_queue(&es8311_master_msg_que);
|
|
es8311_master_msg_que= NULL;
|
|
es8311_master_thread_hdl = NULL;
|
|
}
|
|
os_printf("create es8311 codec task complete \r\n");
|
|
|
|
GLOBAL_INT_DISABLE();
|
|
es8311_codec_init();
|
|
es8311_codec_start(&es8311_cfg);
|
|
es8311_read_all();
|
|
GLOBAL_INT_RESTORE();
|
|
|
|
bk_i2s_start();
|
|
|
|
os_printf("es8311 test start \r\n");
|
|
} else if (os_strcmp(argv[1], "stop") == 0) {
|
|
es8311_send_msg(ES8311_EXIT);
|
|
|
|
bk_i2s_stop();
|
|
bk_i2s_chl_deinit(I2S_CHANNEL_1, I2S_TXRX_TYPE_RX);
|
|
bk_i2s_deinit();
|
|
bk_i2s_driver_deinit();
|
|
|
|
es8311_stop();
|
|
es8311_codec_deinit();
|
|
|
|
rtos_delay_milliseconds(100);
|
|
|
|
fr = f_close(&es8311_file_mic);
|
|
if (fr != FR_OK) {
|
|
os_printf("close mic file %s fail!\r\n", mic_file_name);
|
|
return;
|
|
}
|
|
|
|
os_free(es8311_rx_temp);
|
|
es8311_rx_temp = NULL;
|
|
|
|
os_free(mic_data_buffer);
|
|
mic_data_buffer = NULL;
|
|
|
|
os_printf("es8311 test stop \r\n");
|
|
} else if (os_strcmp(argv[1], "read") == 0) {
|
|
/* read all es8311 register */
|
|
es8311_read_all();
|
|
|
|
os_printf("i2s master test stop successful \r\n");
|
|
} else if (os_strcmp(argv[1], "adc_init") == 0) {
|
|
/* init es8311 codec */
|
|
es8311_codec_init();
|
|
es8311_codec_start(&es8311_cfg);
|
|
es8311_read_all();
|
|
|
|
os_printf("es8311 test init \r\n");
|
|
} else {
|
|
cli_es8311_help();
|
|
return;
|
|
}
|
|
}
|
|
|
|
#define ES8311_CMD_CNT (sizeof(s_es8311_commands) / sizeof(struct cli_command))
|
|
static const struct cli_command s_es8311_commands[] = {
|
|
{"es8311_codec_test", "es8311_codec_test {start|stop 16K xxx.pcm}", cli_es8311_codec_test_cmd},
|
|
};
|
|
|
|
int cli_es8311_init(void)
|
|
{
|
|
return cli_register_commands(s_es8311_commands, ES8311_CMD_CNT);
|
|
}
|
|
|