710 lines
19 KiB
C
710 lines
19 KiB
C
#include "xc_drv_codec.h"
|
|
#include "xc_drv_dma.h"
|
|
#include "string.h"
|
|
#include "ringbuffer.h"
|
|
#if XC_CHECK(XC_CODEC_ENABLED)
|
|
#define CONFIG_ENABLE_DMA
|
|
#define AON_RF_AONREG ((volatile unsigned *)0x40002430)
|
|
|
|
#define RF_ANA02 ((volatile unsigned *)(0X4002F000+ 0x008))
|
|
#define RF_ANA03 ((volatile unsigned *)(0X4002F000+ 0x00C))
|
|
#define RF_ANA08 ((volatile unsigned *)(0X4002F000+ 0x020))
|
|
#define RF_ANA15 ((volatile unsigned *)(0X4002F000+ 0x03C))
|
|
#define RF_ANA21 ((volatile unsigned *)(0X4002F000+ 0x054))
|
|
#define RF_ANA26 ((volatile unsigned *)(0X4002F000+ 0x068))
|
|
#define RF_ANA27 ((volatile unsigned *)(0X4002F000+ 0x06C))
|
|
#define RF_ANA28 ((volatile unsigned *)(0X4002F000+ 0x070))
|
|
#define RF_ANA29 ((volatile unsigned *)(0X4002F000+ 0x074))
|
|
|
|
#define DMAS_BASE 0x50001000
|
|
|
|
|
|
#define DMAS_CHx_SAR(a) ((volatile unsigned *)(DMAS_BASE + 0x40 + ((a) * 0x20)))
|
|
#define DMAS_CHx_DAR(a) ((volatile unsigned *)(DMAS_BASE + 0x44 + ((a) * 0x20)))
|
|
#define DMAS_CHx_CTL0(a) ((volatile unsigned *)(DMAS_BASE + 0x48 + ((a) * 0x20)))
|
|
#define DMAS_CHx_CTL1(a) ((volatile unsigned *)(DMAS_BASE + 0x4C + ((a) * 0x20)))
|
|
#define DMAS_CHx_CA(a) ((volatile unsigned *)(DMAS_BASE + 0x50 + ((a) * 0x20)))
|
|
|
|
#define DMAS_INT_EN0 ((volatile unsigned *)(DMAS_BASE + 0x10))
|
|
|
|
codec_finish_callback_t finish_callback;
|
|
|
|
void xc_codec_dac_digital_enable(void)
|
|
{
|
|
cdc_ana_reg2__endac__setf(ENABLE);
|
|
}
|
|
|
|
void xc_codec_dac_digital_disable(void)
|
|
{
|
|
cdc_ana_reg2__endac__setf(DISABLE);
|
|
}
|
|
|
|
void xc_codec_dac_analog_enable(void)
|
|
{
|
|
cdc_ana_reg0__pdbias__setf(0);
|
|
// PDL=0, PDPAL=0
|
|
cdc_ana_reg3__pdl__setf(PDL_RST);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
cdc_ana_reg3__pdpal__setf(PDPAL_RST);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
}
|
|
|
|
void xc_codec_dac_analog_disable(void)
|
|
{
|
|
cdc_ana_reg3__pdl__setf(1);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
cdc_ana_reg3__pdpal__setf(1);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
|
|
cdc_ana_reg0__pdvbias__setf(1);
|
|
cdc_ana_reg0__pdbias__setf(1);
|
|
cdc_ana_reg0__pdmic__setf(1);
|
|
cdc_ana_reg0__pdsto__setf(1);
|
|
cdc_ana_reg0__pdpgal__setf(1);
|
|
cdc_ana_reg0__pdpgar__setf(1);
|
|
cdc_ana_reg0__pdsdml__setf(1);
|
|
cdc_ana_reg0__pdsdmr__setf(1);
|
|
}
|
|
|
|
void xc_codec_dac_disable(void)
|
|
{
|
|
xc_codec_dac_analog_disable();
|
|
xc_codec_dac_digital_disable();
|
|
}
|
|
|
|
void xc_codec_dac_enable(void)
|
|
{
|
|
xc_codec_dac_analog_enable();
|
|
xc_codec_dac_digital_enable();
|
|
}
|
|
|
|
// 0x1F:max volume, -2dB step (0x00:+6dB)
|
|
void xc_codec_dac_analog_gain_set(uint8_t leftgain, uint8_t rightgain)
|
|
{
|
|
cdc_ana_reg1__dacavl__setf(leftgain);
|
|
for(int i=0;i<10;i++){__NOP();};
|
|
cdc_ana_reg1__dacavr__setf(rightgain);
|
|
for(int i=0;i<10;i++){__NOP();};
|
|
}
|
|
|
|
// 0x80:max volume, 1/128 step
|
|
void xc_codec_dac_digital_gain_set(uint8_t leftgain, uint8_t rightgain)
|
|
{
|
|
cdc_ana_reg2__dacvoll__setf(leftgain);
|
|
cdc_ana_reg2__dacvolr__setf(rightgain);
|
|
}
|
|
|
|
void codec_irq_enable(uint32_t irq)
|
|
{
|
|
uint32_t val = cdc_int_en_get();
|
|
val |= irq;
|
|
cdc_int_en_set(val);
|
|
}
|
|
|
|
void codec_irq_disable(uint32_t irq)
|
|
{
|
|
uint32_t val = cdc_int_en_get();
|
|
val &= ~irq;
|
|
cdc_int_en_set(val);
|
|
}
|
|
|
|
void xc_codec_dma_enable(uint32_t sta)
|
|
{
|
|
uint32_t val = cdc_dma_config_get();
|
|
val |= sta;
|
|
cdc_dma_config_set(val);
|
|
}
|
|
|
|
void xc_codec_dma_disable(uint32_t sta)
|
|
{
|
|
uint32_t val = cdc_dma_config_get();
|
|
val &= ~sta;
|
|
cdc_dma_config_set(val);
|
|
}
|
|
|
|
void xc_codec_dac_blk_finish_cb_register(codec_finish_callback callback)
|
|
{
|
|
finish_callback.codec_dac_trans_finish_callback = callback;
|
|
}
|
|
|
|
void xc_codec_adc_blk_finish_cb_register(codec_finish_callback callback)
|
|
{
|
|
finish_callback.codec_adc_receive_finish_callback = callback;
|
|
}
|
|
|
|
void xc_codec_select_none_integer_clk_div(uint32_t div)
|
|
{
|
|
uint32_t val;
|
|
|
|
__read_hw_reg32(CDC_ANA_REG6,val);
|
|
|
|
if (div)
|
|
val |= (0x40 << 16);
|
|
__write_hw_reg32(CDC_ANA_REG6,val);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
}
|
|
|
|
static void xc_codec_set_dac_dn(uint32_t dn_val)
|
|
{
|
|
uint32_t val;
|
|
|
|
__read_hw_reg32(CDC_ANA_REG7,val);
|
|
val &= 0xFFFF00FF;
|
|
val |= ((dn_val & 0xFF) << 8);
|
|
__write_hw_reg32(CDC_ANA_REG7, val);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
|
|
if (dn_val & 0xFF00) {
|
|
__read_hw_reg32(CDC_ANA_REG6,val);
|
|
val |= (4 << 16);
|
|
__write_hw_reg32(CDC_ANA_REG6,val);
|
|
}
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
}
|
|
|
|
static void xc_codec_set_dac_dm(uint32_t dn_val)
|
|
{
|
|
uint32_t val;
|
|
|
|
__read_hw_reg32(CDC_ANA_REG7,val);
|
|
val &= 0xFF00FFFF;
|
|
val |= ((dn_val & 0xFF) << 16);
|
|
__write_hw_reg32(CDC_ANA_REG7, val);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
|
|
if (dn_val & 0xFF00) {
|
|
__read_hw_reg32(CDC_ANA_REG6,val);
|
|
val |= (8 << 16);
|
|
__write_hw_reg32(CDC_ANA_REG6,val);
|
|
}
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
}
|
|
|
|
static void xc_codec_set_adc_dn(uint32_t dn_val)
|
|
{
|
|
uint32_t val;
|
|
|
|
__read_hw_reg32(CDC_ANA_REG6,val);
|
|
val &= 0x00FFFFFF;
|
|
val |= ((dn_val & 0xFF) << 24);
|
|
__write_hw_reg32(CDC_ANA_REG6, val);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
|
|
if (dn_val & 0xFF00) {
|
|
__read_hw_reg32(CDC_ANA_REG6,val);
|
|
val |= (1 << 16);
|
|
__write_hw_reg32(CDC_ANA_REG6,val);
|
|
}
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
}
|
|
|
|
static void xc_codec_set_adc_dm(uint32_t dm_val)
|
|
{
|
|
uint32_t val;
|
|
|
|
__read_hw_reg32(CDC_ANA_REG7,val);
|
|
val &= 0xFFFFFF00;
|
|
val |= dm_val & 0xFF;
|
|
__write_hw_reg32(CDC_ANA_REG7, val);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
|
|
if (dm_val & 0xFF00) {
|
|
__read_hw_reg32(CDC_ANA_REG6,val);
|
|
val |= (2 << 16);
|
|
__write_hw_reg32(CDC_ANA_REG6,val);
|
|
}
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
}
|
|
|
|
static int xc_codec_mclk_12m_set_lrck(Codec_SampleRate_e lr_clk, uint8_t type)
|
|
{
|
|
uint32_t dn_val,dm_val;
|
|
|
|
if (lr_clk >= LRCK_96KHZ)
|
|
{
|
|
return -1;
|
|
}
|
|
switch (lr_clk)
|
|
{
|
|
case LRCK_48KHZ:
|
|
dm_val = 61;
|
|
dn_val = 64;
|
|
break;
|
|
case LRCK_32KHZ:
|
|
dm_val = 247;
|
|
dn_val = 128;
|
|
break;
|
|
case LRCK_24KHZ:
|
|
dm_val = 93;
|
|
dn_val = 32;
|
|
break;
|
|
case LRCK_16KHZ:
|
|
dm_val = 311;
|
|
dn_val = 64;
|
|
break;
|
|
case LRCK_12KHZ:
|
|
dm_val = 109;
|
|
dn_val = 16;
|
|
break;
|
|
case LRCK_8KHZ:
|
|
dm_val = 343;
|
|
dn_val = 32;
|
|
break;
|
|
case LRCK_44_1KHZ:
|
|
dm_val = 9;
|
|
dn_val = 8;
|
|
break;
|
|
case LRCK_22_05KHZ:
|
|
dm_val = 13;
|
|
dn_val = 4;
|
|
break;
|
|
case LRCK_11_025KHZ:
|
|
dm_val = 15;
|
|
dn_val = 2;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
if (type == 1)
|
|
{
|
|
xc_codec_set_dac_dn(dn_val);
|
|
xc_codec_set_dac_dm(dm_val);
|
|
}
|
|
else
|
|
{
|
|
xc_codec_set_adc_dn(dn_val);
|
|
xc_codec_set_adc_dm(dm_val);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int xc_codec_mclk_13m_set_lrck(Codec_SampleRate_e lr_clk, uint8_t type)
|
|
{
|
|
uint32_t dn_val, dm_val;
|
|
if (lr_clk > LRCK_96KHZ)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
switch (lr_clk)
|
|
{
|
|
case LRCK_96KHZ:
|
|
dm_val = 256;
|
|
dn_val = 15;
|
|
break;
|
|
case LRCK_48KHZ:
|
|
dm_val = 128;
|
|
dn_val = 143;
|
|
break;
|
|
case LRCK_32KHZ:
|
|
dm_val = 64;
|
|
dn_val = 139;
|
|
break;
|
|
case LRCK_24KHZ:
|
|
dm_val = 64;
|
|
dn_val = 207;
|
|
break;
|
|
case LRCK_16KHZ:
|
|
dm_val = 32;
|
|
dn_val = 171;
|
|
break;
|
|
case LRCK_12KHZ:
|
|
dm_val = 32;
|
|
dn_val = 239;
|
|
break;
|
|
case LRCK_8KHZ:
|
|
dm_val = 16;
|
|
dn_val = 187;
|
|
break;
|
|
case LRCK_44_1KHZ:
|
|
dm_val = 128;
|
|
dn_val = 167;
|
|
break;
|
|
case LRCK_22_05KHZ:
|
|
dm_val = 64;
|
|
dn_val = 231;
|
|
break;
|
|
case LRCK_11_025KHZ:
|
|
dm_val = 32;
|
|
dn_val = 263;
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
if (type == 1)
|
|
{
|
|
xc_codec_set_dac_dn(dn_val);
|
|
xc_codec_set_dac_dm(dm_val);
|
|
}
|
|
else
|
|
{
|
|
xc_codec_set_adc_dn(dn_val);
|
|
xc_codec_set_adc_dm(dm_val);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void xc_codec_set_pga_gain(Mic_PGA_Gain_e gain)
|
|
{
|
|
uint32_t val;
|
|
|
|
__read_hw_reg32(CDC_ANA_REG0,val);
|
|
val &= 0xFFEFFFFF;
|
|
val |= gain << 20;
|
|
__write_hw_reg32(CDC_ANA_REG0, val);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
}
|
|
|
|
void xc_codec_set_adc_gain(ADC_Analog_Vol_e r_gain)
|
|
{
|
|
uint32_t val;
|
|
|
|
__read_hw_reg32(CDC_ANA_REG0,val);
|
|
val &= 0xFFFF00FF;
|
|
val |= r_gain << 8;
|
|
__write_hw_reg32(CDC_ANA_REG0, val);
|
|
for(int i=0;i<5000;i++){__NOP();};
|
|
}
|
|
|
|
static int codec_clk_enable(Codec_clk_e clk)
|
|
{
|
|
uint8_t cdcclk, cdcmul = 1, cdcdiv = 1;
|
|
CLOCK_HFCLK_In_Typedef hf_clk = xc_clock_hfclk_in_get();
|
|
|
|
cpr_ctlapbclken_grctl__bt_pclk_en__setf(ENABLE);/* bt_pclk */
|
|
cprao_aon_coreldo_en__bb_corerfldo_en__setf(ENABLE); /* open rf digital */
|
|
|
|
cpr_rf_reg1__cdc_rstn_reg__setf(RSTN_VALID); /* reset audio adc */
|
|
cpr_rf_reg1__cdc_rstn_reg__setf(RSTN_INVALID);
|
|
|
|
//audio ADC mclk primary frequency division set 2[FPGA no active]
|
|
if (clk == CODEC_MCLK_12M)
|
|
{
|
|
if (hf_clk == CLOCK_HFCLK_IN_16M) {
|
|
cdcclk = 4;
|
|
}
|
|
else if (hf_clk == CLOCK_HFCLK_IN_24M) {
|
|
#if (CONFIG_HFCLK_IS_OSC24M_PLL_24M)
|
|
cdcclk = 4;
|
|
#else
|
|
cdcclk = 4;
|
|
#endif
|
|
}
|
|
else if (hf_clk == CLOCK_HFCLK_IN_32M) {
|
|
cdcclk = 2;
|
|
}
|
|
else if (hf_clk == CLOCK_HFCLK_IN_48M) {
|
|
cdcclk = 4;
|
|
}
|
|
else if (hf_clk == CLOCK_HFCLK_IN_64M) {
|
|
cdcclk = 1;
|
|
}
|
|
else if (hf_clk == CLOCK_HFCLK_IN_96M) {
|
|
cdcclk = 2;
|
|
}
|
|
else {
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
cpr_rf_reg1__cdc_mclk_gr__setf(cdcclk);
|
|
cpr_rf_reg2_pack(cdcmul, cdcdiv); /* cdc mclk_mul mclk_div set */
|
|
cpr_rf_reg1__cdc_mclk_gr_upd__setf(ENABLE);
|
|
|
|
cpr_rf_reg1__cdc_hclk_en__setf(ENABLE);
|
|
for(int i=0;i<10;i++){__NOP();};
|
|
cdc_ana_reg6__sel_noni__setf(1); /* Select None-integer clock divider */
|
|
return 0;
|
|
}
|
|
|
|
void codec_clk_disable(uint8_t clk)
|
|
{
|
|
cpr_rf_reg1__cdc_hclk_en__setf(DISABLE);
|
|
cprao_aon_coreldo_en__bb_corerfldo_en__setf(DISABLE);
|
|
cpr_ctlapbclken_grctl__bt_pclk_en__setf(DISABLE);
|
|
}
|
|
|
|
static void codec_adc_analog_enable(void)
|
|
{
|
|
cdc_ana_reg0__pdvbias__setf(1); __NOP();__NOP();
|
|
cdc_ana_reg0__pdbias__setf(0); __NOP();__NOP();
|
|
cdc_ana_reg0__pdmic__setf(0); __NOP();__NOP();
|
|
cdc_ana_reg0__pdsto__setf(0); __NOP();__NOP();
|
|
cdc_ana_reg0__pdpgal__setf(1); __NOP();__NOP();
|
|
cdc_ana_reg0__pdpgar__setf(0); __NOP();__NOP();
|
|
cdc_ana_reg0__pdsdml__setf(1); __NOP();__NOP();
|
|
cdc_ana_reg0__pdsdmr__setf(0); __NOP();__NOP();
|
|
}
|
|
|
|
static void codec_adc_dma_init(uint32_t daraddr, uint32_t transfsize)
|
|
{
|
|
DMA_Chx_Cfg_t ch_cfg = {
|
|
.sar = (uint32_t)0x50004020,
|
|
.dar = daraddr,
|
|
.ctl_src_msize = DMA_MSIZE_1,
|
|
.ctl_dst_msize = DMA_MSIZE_1,
|
|
.ctl_sinc = DMA_ADDR_NOCHANGE,
|
|
.ctl_dinc = DMA_ADDR_INCREMENT,
|
|
.ctl_src_tr_width = DMA_TRANS_WIDTH_32,
|
|
.ctl_dst_tr_width = DMA_TRANS_WIDTH_32,
|
|
.ctl_block_ts = transfsize,
|
|
.ctl_tt_fc = DMA_PRF2MEM_DMA,
|
|
.cfg_hs_sel_src = DMA_HS_HARDWARE,
|
|
.cfg_hs_sel_dst = DMA_HS_HARDWARE,
|
|
.cfg_fifo_mode = DMA_FIFO_MODE_SINGLE,
|
|
.cfg_src_per = CDC_DMA_RX_HS_IF13,
|
|
};
|
|
cdc_dma_config__dma_rx_en__setf(1);
|
|
|
|
xc_dma_init();
|
|
xc_dma_set_channel_config(CODEC_ADC_DMA_CHANNEL, &ch_cfg);
|
|
xc_dma_set_listener(CODEC_ADC_DMA_CHANNEL, NULL);
|
|
}
|
|
|
|
void xc_codec_adc_init(codec_adc_config_t *cfg)
|
|
{
|
|
codec_clk_enable(cfg->codec_clk);
|
|
xc_codec_mclk_12m_set_lrck(cfg->sampleRate, 0);
|
|
|
|
cdc_ana_reg0__adinsell__setf(2);
|
|
__NOP();__NOP();
|
|
cdc_ana_reg0__adinselr__setf(2);
|
|
__NOP();__NOP();
|
|
cdc_ana_reg0__adcvoll__setf(cfg->analog_vol_l);
|
|
cdc_ana_reg0__adcvolr__setf(cfg->analog_vol_r);
|
|
__NOP();__NOP();
|
|
cdc_ana_reg0__vbctrl_l__setf(1);
|
|
__NOP();__NOP();
|
|
cdc_ana_reg0__micsel__setf(MIC1);
|
|
__NOP();__NOP();
|
|
cdc_ana_reg0__micgain__setf(cfg->mic_pga_gain);
|
|
__NOP();__NOP();
|
|
cdc_ana_reg0__stogain__setf(cfg->sto_pga_gain); //Sidetone PGA Gain Control
|
|
__NOP();__NOP();
|
|
cdc_ana_reg1__enhpf__setf(0);
|
|
__NOP();__NOP();
|
|
cdc_ana_reg1__hpfbypass__setf(1);
|
|
__NOP();__NOP();
|
|
cdc_ana_reg4__acdc_vol__setf(cfg->digital_vol);
|
|
__NOP();__NOP();
|
|
codec_adc_analog_enable();
|
|
|
|
cdc_dma_config__dma_rxlvl__setf(CODEC_ADC_FIFO_LEN);
|
|
|
|
cdc_fifo_status__rxfifo_flush__setf(1);
|
|
for(int i=0;i<20;i++){__NOP();};
|
|
cdc_fifo_status__rxfifo_flush__setf(0);
|
|
__NOP();__NOP();
|
|
cdc_ana_reg1__hpfbypass__setf(1);
|
|
|
|
#ifdef USE_DMA
|
|
codec_adc_dma_init((uint32_t)cfg->voice_buffer,cfg->transf_size);
|
|
#endif
|
|
}
|
|
|
|
void xc_codec_adc_start(void* cb)
|
|
{
|
|
#ifndef USE_DMA
|
|
xc_codec_adc_blk_finish_cb_register((codec_finish_callback)cb);
|
|
codec_irq_enable(RXFIFO_UNDERFLOW_EN | RXFIFO_OVERFLOW_EN | RXFIFO_DATA_READY_EN);
|
|
NVIC_EnableIRQ(CDC_IRQn);
|
|
#else
|
|
NVIC_EnableIRQ(DMA_IRQn);
|
|
xc_dma_enable();
|
|
uint8_t ret = xc_dma_start_transfer(CODEC_ADC_DMA_CHANNEL, (DMA_Callback)cb);
|
|
if (ret != 0)
|
|
{
|
|
DEBUG("\nERROR: Failed to begin the interrupt transfer\n");
|
|
}
|
|
#endif
|
|
// flush RX FIFO
|
|
cdc_fifo_status__rxfifo_flush__setf(1);
|
|
for(int i=0;i<20;i++){__NOP();};
|
|
cdc_fifo_status__rxfifo_flush__setf(0);
|
|
__NOP();__NOP();
|
|
cdc_ana_reg1__hpfbypass__setf(1);
|
|
//Enable ADC
|
|
if (cdc_ana_reg1__enadc__getf() == DISABLE)
|
|
{
|
|
cdc_ana_reg1__enadc__setf(ENABLE);
|
|
}
|
|
}
|
|
|
|
void xc_codec_adc_stop(void)
|
|
{
|
|
// flush RX FIFO
|
|
cdc_fifo_status__rxfifo_flush__setf(1);
|
|
for(int i=0;i<20;i++){__NOP();};
|
|
cdc_fifo_status__rxfifo_flush__setf(0);
|
|
#ifndef USE_DMA
|
|
NVIC_DisableIRQ(CDC_IRQn);
|
|
#else
|
|
NVIC_DisableIRQ(DMA_IRQn);
|
|
// xc_dma_disable();
|
|
#endif
|
|
xc_codec_dac_disable();
|
|
}
|
|
|
|
static void codec_dac_dma_init(uint32_t saraddr, uint32_t transfsize)
|
|
{
|
|
DMA_Chx_Cfg_t ch_cfg = {
|
|
.sar = saraddr,
|
|
.dar = (uint32_t)0x50004038,
|
|
.ctl_src_msize = DMA_MSIZE_8,
|
|
.ctl_dst_msize = DMA_MSIZE_8,
|
|
.ctl_sinc = DMA_ADDR_INCREMENT,
|
|
.ctl_dinc = DMA_ADDR_NOCHANGE,
|
|
.ctl_src_tr_width = DMA_TRANS_WIDTH_32,
|
|
.ctl_dst_tr_width = DMA_TRANS_WIDTH_32,
|
|
.ctl_block_ts = transfsize,
|
|
.ctl_tt_fc = DMA_MEM2PRF_DMA,
|
|
.cfg_hs_sel_src = DMA_HS_HARDWARE,
|
|
.cfg_hs_sel_dst = DMA_HS_HARDWARE,
|
|
.cfg_fifo_mode = DMA_FIFO_MODE_SINGLE,
|
|
.cfg_dst_per = CDC_DMA_TX_HS_IF6,
|
|
};
|
|
cdc_dma_config__dma_tx_en__setf(1);
|
|
|
|
xc_dma_init();
|
|
xc_dma_set_channel_config(CODEC_DAC_DMA_CHANNEL, &ch_cfg);
|
|
xc_dma_set_listener(CODEC_DAC_DMA_CHANNEL, NULL);
|
|
}
|
|
|
|
void xc_codec_dac_init(codec_dac_config_t *cfg)
|
|
{
|
|
if (cpr_rf_reg1__cdc_hclk_en__getf() == DISABLE)
|
|
{
|
|
codec_clk_enable(cfg->codec_clk);
|
|
}
|
|
cdc_ana_reg2__dacmono__setf(cfg->mono_mode);
|
|
__NOP();
|
|
xc_codec_mclk_12m_set_lrck(cfg->sampleRate, 1);
|
|
if (cfg->sampleRate >= LRCK_44_1KHZ)
|
|
{
|
|
cdc_ana_reg6__filt_sel__setf((uint8_t)(cfg->sampleRate - LRCK_44_1KHZ));
|
|
}
|
|
else
|
|
{
|
|
cdc_ana_reg6__filt_sel__setf((uint8_t)RATE_OTHERS);
|
|
}
|
|
|
|
// reg14 bit 0:from i2s,1: from ahb bus
|
|
cdc_ana_reg5__dac_data_sel__setf(1);
|
|
if (cfg->digital_vol_l > 0x80)
|
|
{
|
|
cfg->digital_vol_l = 0x80;
|
|
}
|
|
if (cfg->digital_vol_r > 0x80)
|
|
{
|
|
cfg->digital_vol_r = 0x80;
|
|
}
|
|
if (cfg->analog_vol_l > DAC_ANALOG_VOL_MUTE)
|
|
{
|
|
cfg->analog_vol_l = DAC_ANALOG_VOL_MUTE;
|
|
}
|
|
// dac digital volume set
|
|
xc_codec_dac_digital_gain_set(cfg->digital_vol_l, cfg->digital_vol_r);
|
|
// dac analog volume set
|
|
xc_codec_dac_analog_gain_set(cfg->analog_vol_l, cfg->analog_vol_r);
|
|
// cdc_ana_reg2__ictrl__setf(1);
|
|
|
|
cdc_dma_config__dma_txlvl__setf(CODEC_DAC_FIFO_LEN);
|
|
#ifdef USE_DMA
|
|
codec_dac_dma_init((uint32_t)cfg->voice_buffer,cfg->transf_size);
|
|
#endif
|
|
}
|
|
|
|
void xc_codec_dac_start(void* cb)
|
|
{
|
|
#ifndef USE_DMA
|
|
xc_codec_dac_blk_finish_cb_register((codec_finish_callback)cb);
|
|
codec_irq_enable(TXFIFO_UNDERFLOW_EN | TXFIFO_OVERFLOW_EN | TXFIFO_DATA_READY_EN);
|
|
NVIC_EnableIRQ(CDC_IRQn);
|
|
#else
|
|
NVIC_EnableIRQ(DMA_IRQn);
|
|
xc_dma_enable();
|
|
uint8_t ret = xc_dma_start_transfer(CODEC_DAC_DMA_CHANNEL, (DMA_Callback)cb);
|
|
if (ret != 0)
|
|
{
|
|
DEBUG("\nERROR: Failed to begin the interrupt transfer\n");
|
|
}
|
|
#endif
|
|
// flush TX FIFO
|
|
cdc_fifo_status__txfifo_flush__setf(1);
|
|
for(int i=0;i<20;i++){__NOP();};
|
|
cdc_fifo_status__txfifo_flush__setf(0);
|
|
//Enable DAC
|
|
xc_codec_dac_enable();
|
|
if (cdc_ana_reg1__enadc__getf() == DISABLE)
|
|
{
|
|
cdc_ana_reg1__enadc__setf(ENABLE);
|
|
}
|
|
}
|
|
|
|
void xc_codec_dac_stop(void)
|
|
{
|
|
// flush TX FIFO
|
|
cdc_fifo_status__txfifo_flush__setf(1);
|
|
for(int i=0;i<20;i++){__NOP();};
|
|
cdc_fifo_status__txfifo_flush__setf(0);
|
|
#ifndef USE_DMA
|
|
NVIC_DisableIRQ(CDC_IRQn);
|
|
#else
|
|
NVIC_DisableIRQ(DMA_IRQn);
|
|
// xc_dma_disable();
|
|
#endif
|
|
xc_codec_dac_disable();
|
|
}
|
|
|
|
void CDC_Handler()
|
|
{
|
|
uint32_t val = cdc_int_get();
|
|
if (val & TXFIFO_UNDERFLOW_EN)
|
|
{
|
|
if (finish_callback.codec_dac_trans_finish_callback != NULL)
|
|
{
|
|
finish_callback.codec_dac_trans_finish_callback(TXFIFO_UNDERFLOW_EN);
|
|
}
|
|
}
|
|
if (val & TXFIFO_OVERFLOW_EN)
|
|
{
|
|
if (finish_callback.codec_dac_trans_finish_callback != NULL)
|
|
{
|
|
finish_callback.codec_dac_trans_finish_callback(TXFIFO_OVERFLOW_EN);
|
|
}
|
|
}
|
|
if (val & TXFIFO_DATA_READY_EN)
|
|
{
|
|
if (finish_callback.codec_dac_trans_finish_callback != NULL)
|
|
{
|
|
finish_callback.codec_dac_trans_finish_callback(TXFIFO_DATA_READY_EN);
|
|
}
|
|
}
|
|
if (val & RXFIFO_UNDERFLOW_EN)
|
|
{
|
|
if (finish_callback.codec_adc_receive_finish_callback != NULL)
|
|
{
|
|
finish_callback.codec_adc_receive_finish_callback(RXFIFO_UNDERFLOW_EN);
|
|
}
|
|
}
|
|
if (val & RXFIFO_OVERFLOW_EN)
|
|
{
|
|
if (finish_callback.codec_adc_receive_finish_callback != NULL)
|
|
{
|
|
finish_callback.codec_adc_receive_finish_callback(RXFIFO_OVERFLOW_EN);
|
|
}
|
|
}
|
|
if (val & RXFIFO_DATA_READY_EN)
|
|
{
|
|
if (finish_callback.codec_adc_receive_finish_callback != NULL)
|
|
{
|
|
finish_callback.codec_adc_receive_finish_callback(RXFIFO_DATA_READY_EN);
|
|
}
|
|
}
|
|
cdc_int_set(val);
|
|
}
|
|
#endif // XC_CHECK(XC_CODEC_ENABLED)
|