#include "platform.h"
#include "hal_dma.h"
#include "hal_def.h"
#include "hal_audio.h"
#include "hal_audio_src.h"
#include "hal_src_cfg_data.h"

void cbuf_dma_init(audio_src_handle_typedef *hsrc)
{
    DMA_HandleTypeDef    src_dma;
    /*目标地址*/
    src_dma.init.dst_data_loc = DMA_Data_Location_Select_Low;
    src_dma.init.dst_data_width = DMA_Data_Width_32Bit;
    src_dma.init.dst_inc = DMA_Address_Type_Fix;
    /*源地址*/
    src_dma.init.src_data_loc = DMA_Data_Location_Select_Low;
    src_dma.init.src_data_width = DMA_Data_Width_32Bit;
    src_dma.init.src_inc = DMA_Address_Type_Inc;
    /*DMA*/
    src_dma.init.memory_burst = DMA_Burst_Length_Burst1;
    src_dma.init.priority = 5;
    src_dma.init.mode = DMA_Mode_Single;
    hal_dma_init(&src_dma);
    hal_dma_start(&src_dma, (uint32_t)hsrc->cfg_buff, (uint32_t) & (hsrc->Instance->CBUF), 2048 * 4, NULL); /*dma开始传输*/

    while (HAL_DMA_STATE_READY != hal_dma_get_state(&src_dma))
    {
        ;
    }

    hal_dma_ch_free(&src_dma, NULL);
}

uint32_t  sample_rate;

HAL_StatusTypeDef hal_src_init(audio_src_handle_typedef *hsrc)
{
    uint32_t  sample_rate_temp;
    uint32_t  cfg_temp;
    src_filter_cfg_typedef  cfg_data;

    if (hsrc == NULL)
    {
        return HAL_ERROR;
    }

    if (hsrc->init.input_sampe_rate <= hsrc->init.output_sampe_rate)
    {
        /*低转高*/
        cfg_data.cbuf_addr = (uint32_t *)coe22k;
        cfg_data.shift.sel0 = DEV_SRC_CHNn_CFG_SHIFT_SEL0_19;
        cfg_data.shift.sel1 = DEV_SRC_CHNn_CFG_SHIFT_SEL1_19;
        cfg_data.shift.sel2 = DEV_SRC_CHNn_CFG_SHIFT_SEL2_19;
        cfg_data.shift.sel3 = DEV_SRC_CHNn_CFG_SHIFT_SEL3_23;
    }
    else
    {
        /*高转低*/
        cfg_data.cbuf_addr = (uint32_t *)coe8k;
        cfg_data.shift.sel0 = DEV_SRC_CHNn_CFG_SHIFT_SEL0_20;
        cfg_data.shift.sel1 = DEV_SRC_CHNn_CFG_SHIFT_SEL1_20;
        cfg_data.shift.sel2 = DEV_SRC_CHNn_CFG_SHIFT_SEL2_21;
        cfg_data.shift.sel3 = DEV_SRC_CHNn_CFG_SHIFT_SEL3_24;
    }

    hsrc->Instance->CFG &= ~(DEV_SRC_CHNn_CFG_Enable_ENABLE | DEV_SRC_CHNn_CFG_CBUF_EN_ENABLE);
    sample_rate_temp = (uint32_t)((float)(hsrc->init.input_sampe_rate) / hsrc->init.output_sampe_rate * 1024 * 1024);
    hsrc->Instance->LSR = sample_rate_temp;
    hsrc->Instance->USR = sample_rate_temp;
    hsrc->Instance->LTH = 0x100;
    hsrc->Instance->UTH = 0x700;
    cfg_temp = (LVL_512 << 12) |
               (hsrc->init.dev_sel) |
               (hsrc->init.input_fmt << 24) |
               (hsrc->init.output_fmt << 26) |
               (cfg_data.shift.sel0) |
               (cfg_data.shift.sel1) |
               (cfg_data.shift.sel2) |
               (cfg_data.shift.sel3) |
               (SOFT_SRC << 1) |
               (hsrc->init.track << 3) |
               DEV_SRC_CHNn_CFG_CBUF_EN_ENABLE |
               DEV_SRC_CHNn_CFG_Enable_ENABLE;
    hsrc->Instance->CFG = cfg_temp;

    for (int i = 0; i < 2048; i ++)
    {
        hsrc->cfg_buff[i] = cfg_data.cbuf_addr[i] << 8;
    }

    cbuf_dma_init(hsrc);
    hsrc->Instance->CFG &= ~ DEV_SRC_CHNn_CFG_CBUF_EN_ENABLE;
    //hsrc->Instance->PD = 0x3f;
    //hsrc->Instance->IE = (DEV_SRC_CHNn_IE_WBUF_AE + DEV_SRC_CHNn_IE_WBUF_AF);
    //hsrc->Instance->IE = 0x3e;
    //HAL_INTERRUPT_ENABLE(IRQ_SOURCE_SRC);
    return HAL_OK;
}

void src0_set_rate(uint32_t input_sampe_rate,uint32_t output_sampe_rate)
{
	uint32_t  sample_rate_temp;
    sample_rate_temp = (uint32_t)((float)(input_sampe_rate) / output_sampe_rate * 1024 * 1024);

    DEV_SRC->CHN[0].LSR = sample_rate_temp;
    DEV_SRC->CHN[0].USR = sample_rate_temp;
}


void src1_set_rate(uint32_t input_sampe_rate,uint32_t output_sampe_rate)
{
	uint32_t  sample_rate_temp;
    sample_rate_temp = (uint32_t)((float)(input_sampe_rate) / output_sampe_rate * 1024 * 1024);

    DEV_SRC->CHN[1].LSR = sample_rate_temp;
    DEV_SRC->CHN[1].USR = sample_rate_temp;
}



HAL_StatusTypeDef src_cmd(audio_src_handle_typedef *hsrc, Options_EnableEnum cmd)
{
    if (hsrc == NULL)
    {
        return HAL_ERROR;
    }

    hsrc->Instance->CFG_f.Enable = cmd;
    return HAL_OK;
}

HAL_StatusTypeDef src_deinit(audio_src_handle_typedef *hsrc)
{
    DEV_RMU->RSTEN0 &= ~DEV_RMU_RSTEN0_SRC;
    DEV_RMU->RSTEN0 |=  DEV_RMU_RSTEN0_SRC;
    DEV_CMU->CLKEN0 |=  DEV_CMU_CLKEN0_SRC;
    return HAL_OK;
}

void src_irq_handler(void)
{
    if (DEV_SRC->CHN[0].PD & DEV_SRC_CHNn_PD_WBUF_AE)
    {
        DEV_SRC->CHN[0].PD |= DEV_SRC_CHNn_PD_WBUF_AE;
    }

    if (DEV_SRC->CHN[0].PD & DEV_SRC_CHNn_PD_WBUF_AF)
    {
        DEV_SRC->CHN[0].PD |= DEV_SRC_CHNn_PD_WBUF_AF;
    }

    if (DEV_SRC->CHN[0].PD & DEV_SRC_CHNn_PD_RX_FIFO_UF)
    {
        DEV_SRC->CHN[0].PD |= DEV_SRC_CHNn_PD_RX_FIFO_UF;
    }

    if (DEV_SRC->CHN[0].PD & DEV_SRC_CHNn_PD_TX_FIFO_OF)
    {
        DEV_SRC->CHN[0].PD |= DEV_SRC_CHNn_PD_TX_FIFO_OF;
    }

    if (DEV_SRC->CHN[0].PD & DEV_SRC_CHNn_PD_RX_FIFO_HFUL)
    {
        DEV_SRC->CHN[0].PD |= DEV_SRC_CHNn_PD_RX_FIFO_HFUL;
    }

    if (DEV_SRC->CHN[0].PD & DEV_SRC_CHNn_PD_TX_FIFO_HEMP)
    {
        DEV_SRC->CHN[0].PD |= DEV_SRC_CHNn_PD_TX_FIFO_HEMP;
    }
}


void sample_src0_rate_updata(void)
{
    static uint16_t wbuf_wlevel_bak, time_cnt, set_up_step, set_down_step;
    uint16_t wbuf_wlevel;
    wbuf_wlevel = DEV_SRC->CHN[0].STA_f.WBUF_WLVL;

    if (wbuf_wlevel < 200) //有危险多调点
    {
        DEV_SRC->CHN[0].LSR += 0x200;
    }
    else if (wbuf_wlevel > 2048 - 200) //有危险多调点
    {
        DEV_SRC->CHN[0].LSR -= 0x100;
    }

    if (time_cnt == 0)
    {
        wbuf_wlevel_bak = wbuf_wlevel;
    }

    time_cnt ++;

    if (time_cnt >= 1)
    {
        if ((wbuf_wlevel > 800) && (wbuf_wlevel < wbuf_wlevel_bak)) //大于800，但是趋势是向下走,加速向下
        {
            time_cnt = 0;
            DEV_SRC->CHN[0].LSR -= 0x60;
        }
        else if ((wbuf_wlevel > 500) && (wbuf_wlevel > wbuf_wlevel_bak)) //大于1024，但是趋势是向上走
        {
            if (set_down_step < 0x300)
            {
                set_down_step += 10;
            }

            DEV_SRC->CHN[0].LSR -= set_down_step;
            time_cnt = 0;
            set_up_step = 0;
        }
        else if ((wbuf_wlevel < 500) && (wbuf_wlevel < wbuf_wlevel_bak)) //小于1024，但是趋势是向下走
        {
            if (set_up_step < 0x300)
            {
                set_up_step += 10;
            }

            DEV_SRC->CHN[0].LSR += set_up_step;
            time_cnt = 0;
            set_down_step = 0;
        }
        else if ((wbuf_wlevel < 300) && (wbuf_wlevel > wbuf_wlevel_bak)) //小于1024，但是趋势是向上走，
        {
            DEV_SRC->CHN[0].LSR += 0x60;
            time_cnt = 0;
        }
    }
}


void sample_src1_rate_updata(void)
{
    static uint16_t wbuf_wlevel_bak, time_cnt, set_up_step, set_down_step;
    uint16_t wbuf_wlevel;
    wbuf_wlevel = DEV_SRC->CHN[1].STA_f.WBUF_WLVL;

    if (wbuf_wlevel < 200) //有危险多调点
    {
        DEV_SRC->CHN[1].LSR += 0x200;
    }
    else if (wbuf_wlevel > 2048 - 200) //有危险多调点
    {
        DEV_SRC->CHN[1].LSR -= 0x100;
    }

    if (time_cnt == 0)
    {
        wbuf_wlevel_bak = wbuf_wlevel;
    }

    time_cnt ++;

    if (time_cnt >= 1)
    {
        if ((wbuf_wlevel > 800) && (wbuf_wlevel < wbuf_wlevel_bak)) //大于800，但是趋势是向下走,加速向下
        {
            time_cnt = 0;
            DEV_SRC->CHN[1].LSR -= 0x60;
        }
        else if ((wbuf_wlevel > 500) && (wbuf_wlevel > wbuf_wlevel_bak)) //大于1024，但是趋势是向上走
        {
            if (set_down_step < 0x300)
            {
                set_down_step += 10;
            }

            DEV_SRC->CHN[1].LSR -= set_down_step;
            time_cnt = 0;
            set_up_step = 0;
        }
        else if ((wbuf_wlevel < 500) && (wbuf_wlevel < wbuf_wlevel_bak)) //小于1024，但是趋势是向下走
        {
            if (set_up_step < 0x300)
            {
                set_up_step += 10;
            }

            DEV_SRC->CHN[1].LSR += set_up_step;
            time_cnt = 0;
            set_down_step = 0;
        }
        else if ((wbuf_wlevel < 300) && (wbuf_wlevel > wbuf_wlevel_bak)) //小于1024，但是趋势是向上走，
        {
            DEV_SRC->CHN[1].LSR += 0x60;
            time_cnt = 0;
        }
    }
}

uint32_t src_wbuff_printf(void)
{
    return DEV_SRC->CHN[0].STA;
}
