#include "platform.h"
#include "hal_headfile.h"
#include "board.h"
#include "debug.h"
#include "heap_5.h"
#include "audio.h"


audio_src_handle_typedef  src1;
DMA_HandleTypeDef         src1_rx_dma;
DMA_HandleTypeDef         src1_tx_dma;

#define SRC1_FRAM_POINTS           256
__ALIGNED(4) volatile uint8_t *src1_rx_dma_ptr;
__ALIGNED(4) volatile uint8_t *src1_tx_dma_ptr;
__ALIGNED(4) volatile audio_buff_deal_def  src1_data_mag[2];


/**
 * This function will initialize SRC1
 *
 * @param :none
 * @return:none.
 */
void src1_init(void)
{
    uint32_t  *cbuff_addr;
    src1.init.dev_sel = RX_MEM_TX_ASI0;/*接收mem数据，经过SRC后硬件连接到DAC*/
    src1.init.input_sampe_rate = 15600;
    src1.init.output_sampe_rate = aec_param.iis_smplerate;
    src1.init.input_fmt = LOW_16BIT;
    src1.init.output_fmt = LOW_16BIT;
    src1.init.track = SRC_STEREO;
    src1.dma_rx_handle = &src1_rx_dma;
    src1.dma_tx_handle = &src1_tx_dma;
    src1.Instance = SRC1;

    if ((src1.init.dev_sel == RX_MEM_TX_DAC) || (src1.init.dev_sel == RX_MEM_TX_ASI0) || (src1.init.dev_sel == RX_MEM_TX_ASI1))
    {
        src1_rx_dma_ptr = NULL;
        src1_rx_dma_ptr = (uint8_t *)pvPortMalloc(SRC1_FRAM_POINTS * 2 * 2 * 2); //2字节*2个通道*2个缓冲区

        if (src1_rx_dma_ptr == NULL)
        {
            debug("src1_rx_dma_ptr error\r\n");

            while (1);
        }

        src1_rx_dma_init(src1.dma_rx_handle);
        src1_data_mag[0].addr = (uint8_t *)pvPortMalloc(SRC1_FRAM_POINTS * 2 * 2);
        src1_data_mag[0].status = BUFF_FREE;
        src1_data_mag[1].addr = (uint8_t *)pvPortMalloc(SRC1_FRAM_POINTS * 2 * 2);
        src1_data_mag[1].status = BUFF_FREE;

        if ((src1_data_mag[0].addr == NULL) || (src1_data_mag[0].addr == NULL))
        {
            debug("src1_rx_dma_ptr error\r\n");

            while (1);
        }
    }

    if ((src1.init.dev_sel == RX_ADC_TX_MEM) || (src1.init.dev_sel == RX_ASI0_TX_MEM) || (src1.init.dev_sel == RX_ASI1_TX_MEM))
    {
        src1_tx_dma_ptr = NULL;
        src1_tx_dma_ptr = (uint8_t *)pvPortMalloc(SRC1_FRAM_POINTS * 2 * 2 * 2);

        if (src1_tx_dma_ptr == NULL)
        {
            debug("src1 src1_tx_dma_ptr error\r\n");

            while (1);
        }

        src1_tx_dma_init(src1.dma_tx_handle);
    }

    cbuff_addr = (uint32_t *)pvPortMalloc(2048 * 4);

    if (cbuff_addr == NULL)
    {
        debug("src1 cbuff malloc error\r\n");

        while (1);
    }

    src1.cfg_buff = cbuff_addr;
    hal_src_init(&src1);
    vPortFree(cbuff_addr);
}

/**
 * This function is used to initialize the src receiving DMA
 *
 * @param dma_handle:  DMA handle
 * @return: none.
 */
void src1_rx_dma_init(DMA_HandleTypeDef *dma_handle)
{
    /*目标地址*/
    dma_handle->init.dst_data_loc = DMA_Data_Location_Select_Low;
    dma_handle->init.dst_data_width = DMA_Data_Width_16Bit;
    dma_handle->init.dst_inc = DMA_Address_Type_Fix;
    /*源地址*/
    dma_handle->init.src_data_loc = DMA_Data_Location_Select_Low;
    dma_handle->init.src_data_width = DMA_Data_Width_16Bit;
    dma_handle->init.src_inc = DMA_Address_Type_Inc;
    /*DMA*/
    dma_handle->init.memory_burst = DMA_Burst_Length_Burst2;
    dma_handle->init.channel = CH2;
    dma_handle->init.priority = 2;
    dma_handle->init.mode = DMA_Mode_Circular;
    hal_dma_init(dma_handle);
    hal_dma_register_callback(dma_handle, HAL_DMA_XFER_CPLT_CB_ID, src1_rx_full_cplt);    /*注册完成中断服务函数*/
    hal_dma_register_callback(dma_handle, HAL_DMA_XFER_HALFCPLT_CB_ID, src1_rx_half_cplt); /*注册半完成中断服务函数*/
    hal_dma_start_it(dma_handle, (uint32_t)src1_rx_dma_ptr, (uint32_t)(&(src1.Instance->WBUF)), SRC1_FRAM_POINTS * 2 * 2 * 2, NULL); /*dma开始传输*/
}

/**
 * This function is used to initialize the src sending DMA
 *
 * @param dma_handle:  DMA handle
 * @return: none.
 */
void src1_tx_dma_init(DMA_HandleTypeDef *dma_handle)
{
    /*目标地址*/
    dma_handle->init.dst_data_loc = DMA_Data_Location_Select_Low;
    dma_handle->init.dst_data_width = DMA_Data_Width_16Bit;
    dma_handle->init.dst_inc = DMA_Address_Type_Inc;
    /*源地址*/
    dma_handle->init.src_data_loc = DMA_Data_Location_Select_Low;
    dma_handle->init.src_data_width = DMA_Data_Width_16Bit;
    dma_handle->init.src_inc = DMA_Address_Type_Fix;
    /*DMA*/
    dma_handle->init.memory_burst = DMA_Burst_Length_Burst2;
    dma_handle->init.channel = CH1;
    dma_handle->init.priority = 1;
    dma_handle->init.mode = DMA_Mode_Circular;
    hal_dma_init(dma_handle);
    hal_dma_register_callback(dma_handle, HAL_DMA_XFER_CPLT_CB_ID, src1_tx_full_cplt);    /*注册完成中断服务函数*/
    hal_dma_register_callback(dma_handle, HAL_DMA_XFER_HALFCPLT_CB_ID, src1_tx_half_cplt); /*注册半完成中断服务函数*/
    hal_dma_start_it(dma_handle, (uint32_t)(&(src1.Instance->RBUF)), (uint32_t)src1_tx_dma_ptr, SRC1_FRAM_POINTS * 2 * 2 * 2, NULL);
}

/**
 * SRC1 input full completes the DMA interrupt function
 *
 * @param dma_handle:  DMA handle
 * @return: none.
 */
//#define SRC1_DEBUG
void src1_rx_full_cplt(DMA_HandleTypeDef dma, void *param)
{
#ifndef  SRC1_DEBUG

    if (src1_data_mag[1].status == BUFF_BUSY)
    {
        brom_memcpy(((uint8_t *)src1_rx_dma_ptr) + (SRC1_FRAM_POINTS << 2), (uint8_t *)(src1_data_mag[1].addr), SRC1_FRAM_POINTS << 2);
        src1_data_mag[1].status = BUFF_FREE;
    }
    else
    {
        brom_memset(((uint8_t *)src1_rx_dma_ptr) + (SRC1_FRAM_POINTS << 2), 0, SRC1_FRAM_POINTS << 2);
    }

#else
    brom_memcpy(((uint8_t *)src1_rx_dma_ptr) + (SRC1_FRAM_POINTS << 2), (uint8_t *)(sin_tab), SRC1_FRAM_POINTS << 2);
#endif
}
/**
 * SRC1 input half completes the DMA interrupt function
 *
 * @param dma_handle:  DMA handle
 * @return: none.
 */
void src1_rx_half_cplt(DMA_HandleTypeDef dma, void *param)
{
#ifndef  SRC1_DEBUG

    if (src1_data_mag[0].status == BUFF_BUSY)
    {
        brom_memcpy((uint8_t *)src1_rx_dma_ptr, (uint8_t *)(src1_data_mag[0].addr), SRC1_FRAM_POINTS << 2);
        src1_data_mag[0].status = BUFF_FREE;
    }
    else
    {
        brom_memset((uint8_t *)src1_rx_dma_ptr, 0, SRC1_FRAM_POINTS << 2);
    }

#else
    brom_memcpy(((uint8_t *)src1_rx_dma_ptr), (uint8_t *)(sin_tab), SRC1_FRAM_POINTS << 2);
#endif
}
/**
 * SRC1 output full completes the DMA interrupt function
 *
 * @param dma_handle:  DMA handle
 * @return: none.
 */
void src1_tx_full_cplt(DMA_HandleTypeDef dma, void *param)
{
    //push_primitive_audio_from_adc((int16_t *)((uint8_t *)src1_tx_dma_ptr + SRC1_FRAM_POINTS * 2 * 2), SRC1_FRAM_POINTS); //point num
}
/**
 * SRC1 output half completes the DMA interrupt function
 *
 * @param dma_handle:  DMA handle
 * @return: none.
 */
void src1_tx_half_cplt(DMA_HandleTypeDef dma, void *param)
{
    //push_primitive_audio_from_adc((int16_t *)((uint8_t *)src1_tx_dma_ptr + 0), SRC1_FRAM_POINTS); //point num
}

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

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

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

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


void src_ch1_dynamic_ratio(uint8_t cmd)
{
    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;

//show_uart_wave(wbuf_wlevel,0,0,0,0);
//debug("wbuf_wlevel:%d\r\n",DEV_SRC->CHN[1].STA_f.WBUF_WLVL);
//debug("DEV_SRC->CHN[1].LSR:%d\r\n",DEV_SRC->CHN[1].LSR);
//debug("DEV_SRC->CHN[1].LSR:%d\r\n",DEV_SRC->CHN[1].LSR);
    if (!cmd)
    {
        return;
    }

    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;
        }
    }
}
