Слияние кода завершено, страница обновится автоматически
#include "luat_base.h"
#include "luat_i2s.h"
#include "wm_include.h"
#include "wm_i2s.h"
#include "wm_gpio_afsel.h"
#include "c_common.h"
#define LUAT_LOG_TAG "i2s"
#include "luat_log.h"
#define AUDIO_BUF_SIZE (1024 * 10)
#define PERIOD_PLAY 64
static uint8_t i2s_tx_buffer[PERIOD_PLAY];
static luat_i2s_conf_t i2s_conf = {0}; // 记录i2s配置信息
static wm_dma_handler_type dma_tx;
static Buffer_Struct dma_tx_buf;
#define CODEC_RUNING (1 << 0)
// volatile uint8_t run_status = 0;
static int I2s_tx_send(){
uint16_t send_bytes;
if (PERIOD_PLAY>dma_tx_buf.Pos){
send_bytes = dma_tx_buf.Pos;
}else{
send_bytes = PERIOD_PLAY;
}
memcpy(i2s_tx_buffer, dma_tx_buf.Data, send_bytes);
OS_BufferRemove(&dma_tx_buf, send_bytes);
if(send_bytes == 0)
return -1;
DMA_SRCADDR_REG(dma_tx.channel) = (uint32_t )i2s_tx_buffer;
DMA_CTRL_REG(dma_tx.channel) &= ~0xFFFF00;
DMA_CTRL_REG(dma_tx.channel) |= (send_bytes<<8);
DMA_CHNLCTRL_REG(dma_tx.channel) = DMA_CHNL_CTRL_CHNL_ON;
wm_i2s_tx_dma_enable(1);
wm_i2s_tx_enable(1);
wm_i2s_enable(1);
return 0;
}
static void I2s_dma_tx_irq(void *p){
int ret_len = dma_tx_buf.Pos;
if(ret_len >= 4 ){
I2s_tx_send();
}else{
i2s_conf.state = LUAT_I2S_STATE_STOP;
}
}
static int I2s_tx_dma_init(void){
if (dma_tx_buf.Data){
return 0;
}
OS_InitBuffer(&dma_tx_buf, AUDIO_BUF_SIZE);
memset(&dma_tx, 0, sizeof(wm_dma_handler_type));
if(dma_tx.channel){
tls_dma_free(dma_tx.channel);
}
dma_tx.channel = tls_dma_request(WM_I2S_TX_DMA_CHANNEL, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_I2S_TX) | TLS_DMA_FLAGS_HARD_MODE);
if(dma_tx.channel == 0){
return -1;
}
if (tls_dma_stop(dma_tx.channel)){
return -1;
}
tls_dma_irq_register(dma_tx.channel, I2s_dma_tx_irq, &dma_tx, TLS_DMA_IRQ_TRANSFER_DONE);
DMA_INTMASK_REG &= ~(0x02<<(dma_tx.channel*2));
DMA_DESTADDR_REG(dma_tx.channel) = HR_I2S_TX;
DMA_CTRL_REG(dma_tx.channel) = DMA_CTRL_SRC_ADDR_INC | DMA_CTRL_DATA_SIZE_WORD | DMA_CTRL_BURST_SIZE1;
DMA_MODE_REG(dma_tx.channel) = DMA_MODE_SEL_I2S_TX | DMA_MODE_HARD_MODE;
DMA_CTRL_REG(dma_tx.channel) &= ~0xFFFF00;
return 0;
}
static int tls_i2s_io_init(void){
wm_i2s_ck_config(WM_IO_PB_08);
wm_i2s_ws_config(WM_IO_PB_09);
wm_i2s_di_config(WM_IO_PB_10);
wm_i2s_do_config(WM_IO_PB_11);
wm_i2s_extclk_config(WM_IO_PA_07);
LLOGD("ck--PB08, ws--PB09, di--PB10, do--PB11, mclk--PA07");
return WM_SUCCESS;
}
luat_i2s_conf_t *luat_i2s_get_config(uint8_t id){
if (id != 0) return NULL;
return &i2s_conf;
}
int luat_i2s_setup(const luat_i2s_conf_t *conf) {
if (I2s_tx_dma_init()){
return -1;
}
memcpy(&i2s_conf, conf, sizeof(luat_i2s_conf_t));
tls_i2s_io_init();
// 然后转本地i2s配置
I2S_InitDef opts = { I2S_MODE_MASTER, I2S_CTRL_STEREO, I2S_RIGHT_CHANNEL, I2S_Standard, I2S_DataFormat_16, 8000, 5000000 };
opts.I2S_Mode_MS = conf->mode;
opts.I2S_Mode_SS = conf->channel_format==LUAT_I2S_CHANNEL_STEREO?I2S_CTRL_STEREO:I2S_CTRL_MONO;
opts.I2S_Mode_LR = conf->channel_format==0?I2S_LEFT_CHANNEL:I2S_RIGHT_CHANNEL;
opts.I2S_Trans_STD = (conf->standard*0x1000000);
opts.I2S_DataFormat = (conf->data_bits/8 - 1)*0x10;
opts.I2S_AudioFreq = conf->sample_rate;
// uint16_t fs = conf->data_bits * (conf->channel_format==LUAT_I2S_CHANNEL_STEREO?2:1) * conf->channel_bits/16;
// printf("------------fs:%d\n", fs);
opts.I2S_MclkFreq = 2*256*conf->sample_rate;
wm_i2s_port_init(&opts);
// wm_i2s_register_callback(NULL);
i2s_conf.state = LUAT_I2S_STATE_STOP;
return 0;
}
int luat_i2s_modify(uint8_t id,uint8_t channel_format,uint8_t data_bits,uint32_t sample_rate){
if (id != 0) return -1;
i2s_conf.channel_format = channel_format;
i2s_conf.data_bits = data_bits;
i2s_conf.sample_rate = sample_rate;
wm_i2s_mono_select(channel_format==LUAT_I2S_CHANNEL_STEREO?I2S_CTRL_STEREO:I2S_CTRL_MONO);
wm_i2s_left_channel_sel(channel_format==0?I2S_LEFT_CHANNEL:I2S_RIGHT_CHANNEL);
wm_i2s_set_word_len((data_bits/8 - 1)*0x10);
wm_i2s_set_freq(sample_rate, 2*256*sample_rate);
return 0;
}
int luat_i2s_send(uint8_t id, uint8_t* buff, size_t len) {
int ret;
if (buff == NULL) {
return -1;
}
if (len == 0) {
return 0;
}
OS_BufferWrite(&dma_tx_buf, buff, len);
if (i2s_conf.state == LUAT_I2S_STATE_STOP) {
i2s_conf.state = LUAT_I2S_STATE_RUNING;
ret = I2s_tx_send();
if(ret == -1){
LLOGE("fifo empty for send\n");
i2s_conf.state = LUAT_I2S_STATE_STOP;
return 0;
}
}
return len;
}
int luat_i2s_recv(uint8_t id, uint8_t* buff, size_t len) {
wm_i2s_rx_int((int16_t *)buff, len / 2);
return len;
}
int luat_i2s_pause(uint8_t id) {
wm_i2s_tx_enable(0);
i2s_conf.state = LUAT_I2S_STATE_STOP;
return 0;
}
int luat_i2s_resume(uint8_t id) {
wm_i2s_tx_enable(1);
return 0;
}
int luat_i2s_close(uint8_t id) {
wm_i2s_tx_enable(0);
i2s_conf.state = LUAT_I2S_STATE_STOP;
if(dma_tx.channel){
tls_dma_free(dma_tx.channel);
}
if (dma_tx_buf.Data){
OS_DeInitBuffer(&dma_tx_buf);
}
return 0;
}
int luat_i2s_tx_stat(uint8_t id, size_t *buffsize, size_t* remain) {
*buffsize = AUDIO_BUF_SIZE;
*remain = dma_tx_buf.Pos;
return 0;
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )