#include "platform.h"
#include "hal_headfile.h"
#include "debug.h"
#include "audio.h"
#include "config.h"


void dac_data_half_cplt(DMA_HandleTypeDef dma, void *param);
void dac_data_full_cplt(DMA_HandleTypeDef dma, void *param);

audio_dac_handle_typedef      audio_dac;
DMA_HandleTypeDef             dac_dma;

#define DAC_FRAM_SIZE         256
volatile __ALIGNED(4) static uint16_t dac_dma_buff[DAC_FRAM_SIZE * 2 * 2]; //双通道、pingpong总buf，每次dma中断搬运AUDIO_CALLBACK_LEN*2个点，单个声道即AUDIO_CALLBACK_LEN个点
volatile audio_buff_deal_def  audio_dac_buff[2];
/**
 * audio dac init
 *
 * @param: none:
 *
 * @return: none.
 */
void audio_dac_init(void)
{
    static uint8_t  init_flag = 0;
    volatile __ALIGNED(4) static uint16_t dac_buff[2][DAC_FRAM_SIZE * 2];
    audio_dac_buff[0].addr = (uint8_t *)dac_buff[0];
    audio_dac_buff[0].status = BUFF_FREE;
    audio_dac_buff[1].addr = (uint8_t *)dac_buff[1];
    audio_dac_buff[1].status = BUFF_FREE;
    audio_dac.init.track = DAC_STEREO;
    audio_dac.init.sample_rate = DAC_SAMPLE_RATE_16K;
    audio_dac.init.outfrom = HEADPHONE;
#ifndef    DAC_USE_SRC0
    audio_dac.init.src_sel = AHB;
    audio_dac.init.data_format = width_16bit_useful_16bit;
#else
    audio_dac.init.src_sel = SRC;
    audio_dac.init.data_format = width_32bit_useful_low_16bit;
#endif
    audio_dac.init.mix_source = MIX_SOURCE_DAC_DETACHED;
    audio_dac.init.vol = aec_param.hp_volume;
    audio_dac.init.eq_type = EQ_NORMAL_TYPE;
    audio_dac.init.inverse = aec_param.dac_output_inverse;
    audio_dac.dma_handle = &dac_dma;
    hal_audio_dac_init(&audio_dac);
    audio_dac_EQ_init();
    audio_dac_drc_init();

    if (init_flag == 0)
    {
        init_flag = 1;
        dac_dma_cfg();
    }

    audio_dac_cmd(&audio_dac, ENABLE);
}
/**
 * this function will init EQ
 *
 * @param: none:
 *
 * @return: none.
 */
void audio_dac_EQ_init(void)
{
    if ((eq_param.eq_param_enable != 0) && (eq_param.eq_param_enable != 0))
    {
        if (eq_param.eq_type < 0x07) //预设场景
        {
            audio_dac_set_eq_type(&audio_dac, eq_param.eq_type);
        }
        else if (eq_param.eq_type == 0x07) //自定义场景
        {
            audio_dac_set_eq_param(&audio_dac, (uint32_t *)eq_param.data);
        }
    }
}

/**
 * this function will init DRC
 *
 * @param: none:
 *
 * @return: none.
 */
void audio_dac_drc_init(void)
{
    if (drc_param.drc_param_enable != 0)
    {
        audio_dac_drc_config(&audio_dac, &drc_param.drc_config);
        debug("audio_drc_enable\e\n");
    }
    else
    {
      debug("audio_drc_disable\e\n");
    }
}

/**
 * this function will suspend dac.
 *
 * @param: none:
 *
 * @return: none.
 */
void audio_dac_suspend(void)
{
    cmu_set_clk_en(DAC_CLOCK_ENABLE, DISABLE);
    rmu_set_rst_en(DAC_RST_ENABLE, DISABLE);
}

/**
 * audio dac dma channel init
 *
 * @param: none:
 *
 * @return: none.
 */
void dac_dma_cfg(void)
{
    audio_dac.dma_handle->init.dst_data_loc = DMA_Data_Location_Select_Low;
    audio_dac.dma_handle->init.dst_data_width = DMA_Data_Width_16Bit;
    audio_dac.dma_handle->init.dst_inc = DMA_Address_Type_Fix;
    /*源地址*/
    audio_dac.dma_handle->init.src_data_loc = DMA_Data_Location_Select_Low;
    audio_dac.dma_handle->init.src_data_width = DMA_Data_Width_16Bit;
    audio_dac.dma_handle->init.src_inc = DMA_Address_Type_Inc;
    /*DMA*/
    audio_dac.dma_handle->init.memory_burst = DMA_Burst_Length_Burst2;
    audio_dac.dma_handle->init.channel = CH6;
    audio_dac.dma_handle->init.priority = 6;
    audio_dac.dma_handle->init.mode = DMA_Mode_Circular;
    hal_dma_init(audio_dac.dma_handle);
    hal_dma_register_callback(audio_dac.dma_handle, HAL_DMA_XFER_CPLT_CB_ID, dac_data_full_cplt);    /*注册完成中断服务函数*/
    hal_dma_register_callback(audio_dac.dma_handle, HAL_DMA_XFER_HALFCPLT_CB_ID, dac_data_half_cplt); /*注册半完成中断服务函数*/
    hal_dma_start_it(audio_dac.dma_handle, (uint32_t)dac_dma_buff, (uint32_t)&DEV_DAC->TBUF, DAC_FRAM_SIZE * 2 * 2 * 2, NULL); /*dma开始传输*/
}

/**
 * Callback function after DMA transfer
 *
 * @param _hdma:  dac dma handle
 *
 * @return: none.
 */
void dac_data_full_cplt(DMA_HandleTypeDef dma, void *param)
{
    if (audio_dac_buff[1].status == BUFF_BUSY)
    {
        brom_memcpy(((uint8_t *)dac_dma_buff) + (DAC_FRAM_SIZE << 2), (uint8_t *)(audio_dac_buff[1].addr), DAC_FRAM_SIZE << 2);
        audio_dac_buff[1].status = BUFF_FREE;
    }
    else
    {
        brom_memset(((uint8_t *)dac_dma_buff) + (DAC_FRAM_SIZE << 2), 0, DAC_FRAM_SIZE << 2);
    }
}
/**
 * Callback function halfway through DMA transfer
 *
 * @param _hdma:  dac dma handle
 *
 * @return: none.
 */
void dac_data_half_cplt(DMA_HandleTypeDef dma, void *param)
{
    if (audio_dac_buff[0].status == BUFF_BUSY)
    {
        brom_memcpy((uint8_t *)dac_dma_buff, (uint8_t *)(audio_dac_buff[0].addr), DAC_FRAM_SIZE << 2);
        audio_dac_buff[0].status = BUFF_FREE;
    }
    else
    {
        brom_memset((uint8_t *)dac_dma_buff, 0, DAC_FRAM_SIZE << 2);
    }
}

/**
 * This function is used to write audio data to DAC
 *
 * @param buf:     addr of audio data
 * @param points:  point number of audio data
 * @return: none.
 */
int32_t dac_write_data(uint8_t *buf, uint16_t points)
{
    static uint8_t i = 0;

    if (points != (DAC_FRAM_SIZE)) //每次给256个点
    {
        return -1;
    }

    if (audio_dac_buff[i].status == BUFF_FREE)
    {
        brom_memcpy((uint8_t *)(audio_dac_buff[i].addr), (uint8_t *)buf, DAC_FRAM_SIZE << 2);
        audio_dac_buff[i].status = BUFF_BUSY;
    }
    else
    {
        return -2;
    }

    i = (i + 1) % 2;
    return -0;
}

void codec_dac_set_volume(uint32_t volume)
{
    audio_dac_set_volume(&audio_dac, volume);
}

void codec_dac_set_eq_type(eq_param_class_type eqtype)
{
    audio_dac_set_eq_type(&audio_dac, eqtype);
}
