/******************************************************************
 * @file  receiver_Proc.s.c
 * @brief:    [file description] 
 * @author: HUOHUO
 * @Date 2024年4月20日
 * COPYRIGHT NOTICE: ITTC
 * Change_date         Owner         Change_content
 * 2024年4月20日        HUOHUO       create file

*****************************************************************/
#include "receiver_sync_first_func.h"
#define ADDR_ALIGN(addr, val)   ((((uint32_t)(addr) + (2<<(val)) - 1)>>(val))<<(val)) 

void dm_check(uint32_t mark)
{
    uint32_t idx;
    uint32_t flag = 0;
    for( idx = 0 ;idx < 8; idx++)
    {
        if(0xa5a55a5a != *last_mem_dm[idx])
        {
            flag |= (1<<idx);
            LOG_ERROR_S("lk 0x%08x\n", last_mem_dm[idx]);
        }
    }

    if(0 != flag)
    {
    LOG_ERROR_S("dm leadking detect!!%d 0x%08x\n", mark, flag);
    __ucps2_synch(0);
    __ucps2_synch(0);
    __ucps2_synch(0);
    __ucps2_synch(0);
    __ucps2_synch(0);
    __ucps2_dbgbreak();
    }
}

void Receiver_Sync_First_Memory_Alloc( )
{
    uint32_t dm0_space;
    uint32_t dm1_space;
    uint32_t dm2_space;
    uint32_t dm3_space;

     //0 空间回收
    dmalloc_trim(0, APE_DM0);
    dmalloc_trim(0, APE_DM1);
    dmalloc_trim(0, APE_DM2);
    dmalloc_trim(0, APE_DM3);   

    //1. DM0空间申请
    dm0_space = getFreeSpace(APE_DM0);
    // LOG_ERROR_S("dm0 space:%d\n",dm0_space);
    receiver_sync_first_malloc_dm0_ptr = dmalloc_unit(dm0_space - 1024, APE_DM0); //尽量申请空间
    if (NULLPTR == receiver_sync_first_malloc_dm0_ptr)
    {
        LOG_ERROR_S("rec sync DM0 fail\n");
        return;
    }

    //2. DM0空间分配
    //DM0第一段，微码相关空间
    receiver_sync_first_config_dm0_ptr = (uint32_t*)receiver_sync_first_malloc_dm0_ptr;
        
    ape_csu_dma_1D_G2L_ch2ch3_transfer((uint64_t)g_receiver_sync_first_table_param.receiver_sync_first_config0_ddr_ptr,
                                 (uint64_t)DM_TO_CSU_ADDR(receiver_sync_first_config_dm0_ptr),
                                 g_receiver_sync_first_table_param.receiver_sync_first_config0_length,
                                 DMA_TAG_G2L,
                                 0);    

    //DM0第二段，堆空间
    receiver_sync_first_temp_dm0_ptr = (int32_t *)ADDR_ALIGN(receiver_sync_first_config_dm0_ptr + \
        (g_receiver_sync_first_table_param.receiver_sync_first_config0_length>>2), 12); //起始地址4kbyte对齐
    
    //3. DM3空间申请
    dm3_space = getFreeSpace(APE_DM3);
    receiver_sync_first_malloc_dm3_ptr = dmalloc_unit(dm3_space - 1024, APE_DM3);//尽量申请
    //若空间申请失败，则释放已申请的空间，再退出任务
    if (NULLPTR == receiver_sync_first_malloc_dm3_ptr)
    {
        LOG_ERROR_S("rec sync DM3 fail\n");
        dfree_unit(receiver_sync_first_malloc_dm0_ptr, APE_DM0);
        return;
    }
    //DM3第一段，堆空间
    receiver_sync_first_temp_dm3_ptr = (int32_t *)ADDR_ALIGN(receiver_sync_first_malloc_dm3_ptr, 12); //起始地址4k对齐


    //4. DM1空间申请
    dm1_space = getFreeSpace(APE_DM1);
    receiver_sync_first_malloc_dm1_ptr = dmalloc_unit(dm1_space - 1024, APE_DM1);//尽量申请
    //若空间申请失败，则释放已申请的空间，再退出任务
    if (NULLPTR == receiver_sync_first_malloc_dm1_ptr)
    {
        LOG_ERROR_S("rec sync DM1 fail\n");
        dfree_unit(receiver_sync_first_malloc_dm3_ptr, APE_DM3);
        dfree_unit(receiver_sync_first_malloc_dm0_ptr, APE_DM0);
        return;
    }
    //DM1第一段,堆空间
    receiver_sync_first_temp_dm1_ptr = (int32_t *)ADDR_ALIGN(receiver_sync_first_malloc_dm1_ptr + \
        (g_receiver_sync_first_table_param.receiver_sync_first_config1_length>>2), 12); //起始地址4k对齐

    //5. DM2空间申请
    dm2_space = getFreeSpace(APE_DM2);
    receiver_sync_first_malloc_dm2_ptr = dmalloc_unit(dm2_space - 1024, APE_DM2);//尽量申请
    //若空间申请失败，释放已申请的空间，再退出任务
    if (NULLPTR == receiver_sync_first_malloc_dm2_ptr)
    {
        LOG_ERROR_S("rec sync DM2 fail\n");
        dfree_unit(receiver_sync_first_malloc_dm3_ptr, APE_DM3);
        dfree_unit(receiver_sync_first_malloc_dm0_ptr, APE_DM0);
        dfree_unit(receiver_sync_first_malloc_dm1_ptr, APE_DM1);
        return;
    }
    //DM2第一段,堆空间
    receiver_sync_first_temp_dm2_ptr = (int32_t *)ADDR_ALIGN(receiver_sync_first_malloc_dm2_ptr + \
        (g_receiver_sync_first_table_param.receiver_sync_first_config2_length>>2), 12); //起始地址4byte对齐

    ape_csu_task_lookup(DMA_TAG_G2L, 1);
    

    //debug
    last_mem_dm[0] = receiver_sync_first_malloc_dm0_ptr + ((dm0_space - 1024)>>2) -1;
    last_mem_dm[1] = receiver_sync_first_malloc_dm0_ptr + ((dm0_space - 1024)>>2) -2;
    last_mem_dm[2] = receiver_sync_first_malloc_dm1_ptr + ((dm1_space - 1024)>>2) -1;
    last_mem_dm[3] = receiver_sync_first_malloc_dm1_ptr + ((dm1_space - 1024)>>2) -2;
    last_mem_dm[4] = receiver_sync_first_malloc_dm2_ptr + ((dm2_space - 1024)>>2) -1;
    last_mem_dm[5] = receiver_sync_first_malloc_dm2_ptr + ((dm2_space - 1024)>>2) -2;
    last_mem_dm[6] = receiver_sync_first_malloc_dm3_ptr + ((dm3_space - 1024)>>2) -1;
    last_mem_dm[7] = receiver_sync_first_malloc_dm3_ptr + ((dm3_space - 1024)>>2) -2;

    *last_mem_dm[0] = 0xa5a55a5a;
    *last_mem_dm[1] = 0xa5a55a5a;
    *last_mem_dm[2] = 0xa5a55a5a;
    *last_mem_dm[3] = 0xa5a55a5a;
    *last_mem_dm[4] = 0xa5a55a5a;
    *last_mem_dm[5] = 0xa5a55a5a;
    *last_mem_dm[6] = 0xa5a55a5a;
    *last_mem_dm[7] = 0xa5a55a5a;

    

}



void Receiver_Sync_First_Memory_Free( )
{
    //8. 内存释放
    dfree_unit(receiver_sync_first_malloc_dm2_ptr, APE_DM2);
    dfree_unit(receiver_sync_first_malloc_dm1_ptr, APE_DM1);
    dfree_unit(receiver_sync_first_malloc_dm3_ptr, APE_DM3);
    dfree_unit(receiver_sync_first_malloc_dm0_ptr, APE_DM0);
}




//耗时长，用于第一次同步
void Receiver_First_Sync_Proc(receiver_sync2first_sync_t* msg_ptr, uint32_t msg_len)
{

    g_time_start[0] = TIME_NS();
    RUN_CNT(TRACE_RECEIVER_SYNC_FIRST_ADDR, 0);

    const uint32_t loop_num = 1;
    uint32_t ret;
    uint16_t sfn = LOAD_EX_S(&msg_ptr->sfn);
    uint16_t slot = LOAD_EX_S(&msg_ptr->slot);
    uint32_t section_idx;
    const uint32_t sample_per_tti = 61440;//每个500us采样点数
    const uint32_t addition_sample = 1024;//额外样点
    uint32_t total_nsample = sample_per_tti + addition_sample;
    uint32_t sample_per_csu = (total_nsample >> 1);//分两次处理
    int32_t  *cfg_addr;// 配置地址指针
    uint32_t maxPosition = 0;
    uint32_t maxsum;
    volatile uint16_t dbg_time0, dbg_time1;

    //Proc的DM空间申请
    Receiver_Sync_First_Memory_Alloc();
    TRACE(TRACE_RECEIVER_SYNC_FIRST_ADDR, 3, 1); 
    //寻找帧同步头，更新同步信息结构体

    //搬移500us+数据供定时同步,奇数slot处理偶buffer数据，反之
    dbg_time0 = Time_offset(0); 
    uint32_t src_addr0;
    uint32_t src_addr1;
#ifndef RECV_DBG_DATA_TEST
    if( 1 == (slot & 0x01) )
    {
        src_addr0 = (uint32_t)JESD_NRFDD_RX_SLOT_EVEN_DATA_ADDR;
        src_addr1 = (uint32_t)JESD_NRFDD_RX_SLOT_ODD_DATA_ADDR;
    }
    else
    {
        src_addr0 = (uint32_t)JESD_NRFDD_RX_SLOT_ODD_DATA_ADDR; 
        src_addr1 = (uint32_t)JESD_NRFDD_RX_SLOT_EVEN_DATA_ADDR;       
    }
#else
    src_addr0 = (uint32_t)JESD_NRFDD_RX_SLOT_EVEN_DATA_ADDR;
    src_addr1 = (uint32_t)JESD_NRFDD_RX_SLOT_ODD_DATA_ADDR;   
#endif

    ape_csu_dma_1D_G2L_ch0ch1_transfer((uint64_t)(src_addr0),
                                        (uint64_t)JESD_NRFDD_RX_SLOT_SRC0_DATA_ADDR,//第一次固定搬移到dm0
                                        (61440)<<2,
                                        DMA_TAG_G2G,
                                        0);    
    ape_csu_dma_1D_G2L_ch2ch3_transfer((uint64_t)(src_addr1),
                                        (uint64_t)JESD_NRFDD_RX_SLOT_SRC1_DATA_ADDR,//第一次固定搬移到dm0
                                        (2048)<<2,
                                        DMA_TAG_G2G,
                                        1);    

    TRACE(TRACE_RECEIVER_SYNC_FIRST_ADDR, 3, 2); 
    src_addr0 = (uint32_t)JESD_NRFDD_RX_SLOT_SRC0_DATA_ADDR; 
    src_addr1 = (uint32_t)JESD_NRFDD_RX_SLOT_SRC1_DATA_ADDR;                                         


    //搬移数据
    ape_csu_dma_1D_G2L_ch0ch1_transfer((uint64_t)(src_addr0),
                                        (uint64_t)DM_TO_CSU_ADDR(receiver_sync_first_temp_dm0_ptr),//第一次固定搬移到dm0
                                        (sample_per_csu + 1024)<<2,
                                        DMA_TAG_G2L,
                                        0);       

    

    cfg_addr = (int32_t *)receiver_sync_first_config_dm0_ptr + g_receiver_sync_first_table_param.ConfigByteCopy_CFG1_Offset;


    //Debug:
    //  LOG_ERROR_S("0x%08x 0x%08x 0x%08x %d\n", cfg_addr, receiver_sync_first_temp_dm0_ptr + 1024, receiver_sync_first_temp_dm1_ptr, (total_nsample - 1024)<<2);
        // ape_csu_dma_1D_L2G_ch0ch1_transfer((uint64_t)DM_TO_CSU_ADDR(cfg_addr),
        //                                 (uint64_t)0x88a00000,
        //                                 48<<2,
        //                                 DMA_TAG_L2G,
        //                                 1); 

    ByteCopy((int)cfg_addr, 
            MPU_ADDR(receiver_sync_first_temp_dm0_ptr + 1024),//数据之间相差1024
            MPU_ADDR(receiver_sync_first_temp_dm1_ptr),
            ((sample_per_csu)<<2));

    WAIT_MPU_STOP;
    ape_csu_task_lookup(DMA_TAG_G2L, 1);
    TRACE(TRACE_RECEIVER_SYNC_FIRST_ADDR, 3, 3); 
    SVRReg[0] = MPU_ADDR(cfg_addr);
    ByteCopyAsm(SVRReg);
   
    //Debug:
    //  LOG_ERROR_S("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", cfg_addr, receiver_sync_first_temp_dm0_ptr, receiver_sync_first_temp_dm1_ptr, receiver_sync_first_temp_dm2_ptr,
    //     receiver_sync_first_temp_dm3_ptr);


    // dm_check(0); 

    cfg_addr = (int32_t *)receiver_sync_first_config_dm0_ptr + g_receiver_sync_first_table_param.ConfigSlidingCorrelation_CFG2_Offset;

    // LOG_ERROR_S("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", cfg_addr, receiver_sync_first_temp_dm0_ptr, receiver_sync_first_temp_dm1_ptr, receiver_sync_first_temp_dm2_ptr,
    //     receiver_sync_first_temp_dm3_ptr);
    // ape_csu_dma_1D_L2G_ch0ch1_transfer((uint64_t)DM_TO_CSU_ADDR(cfg_addr),
    //                                 (uint64_t)0x88b00000,
    //                                 512,
    //                                 DMA_TAG_L2G,
    //                                 1);     

    SlidingCorrelation((int)cfg_addr, 
                        MPU_ADDR(receiver_sync_first_temp_dm0_ptr), 
                        MPU_ADDR(receiver_sync_first_temp_dm1_ptr), 
                        MPU_ADDR(receiver_sync_first_temp_dm2_ptr),
                        MPU_ADDR(receiver_sync_first_temp_dm3_ptr));

    WAIT_MPU_STOP;
    TRACE(TRACE_RECEIVER_SYNC_FIRST_ADDR, 3, 4); 
    SVRReg[0] = MPU_ADDR(cfg_addr);
    SlidingCorrelationAsm(SVRReg);

    
    WAIT_MPU_STOP;
    TRACE(TRACE_RECEIVER_SYNC_FIRST_ADDR, 3, 5); 
    //dm_check(1);
    maxPosition = receiver_sync_first_temp_dm3_ptr[0];
    maxsum = receiver_sync_first_temp_dm3_ptr[1];
    LOG_ERROR_S("1 maxPosition:%d maxsum:%d\n",maxPosition, maxsum);

    ape_csu_dma_1D_G2L_ch0ch1_transfer((uint64_t)(src_addr0 + (sample_per_csu<<2)),
                                        (uint64_t)DM_TO_CSU_ADDR(receiver_sync_first_temp_dm0_ptr),//
                                        (61440 - sample_per_csu)<<2,
                                        DMA_TAG_G2L,
                                        0);    
    ape_csu_dma_1D_G2L_ch2ch3_transfer((uint64_t)(src_addr1),
                                        (uint64_t)DM_TO_CSU_ADDR(receiver_sync_first_temp_dm0_ptr + (61440 - sample_per_csu)),//
                                        (2048)<<2,
                                        DMA_TAG_G2L,
                                        0);  
    
                                   

    cfg_addr = (int32_t *)receiver_sync_first_config_dm0_ptr + g_receiver_sync_first_table_param.ConfigByteCopy_CFG1_Offset;

      
    ByteCopy((int)cfg_addr, 
            MPU_ADDR(receiver_sync_first_temp_dm0_ptr + 1024),//数据之间相差1024
            MPU_ADDR(receiver_sync_first_temp_dm1_ptr),
            ((sample_per_csu)<<2));


    WAIT_MPU_STOP;
    ape_csu_task_lookup(DMA_TAG_G2L, 1);
    
    SVRReg[0] = MPU_ADDR(cfg_addr);
    ByteCopyAsm(SVRReg);

    cfg_addr = (int32_t *)receiver_sync_first_config_dm0_ptr + g_receiver_sync_first_table_param.ConfigSlidingCorrelationSecond_CFG3_Offset;
        //Debug:
    

    // LOG_ERROR_S("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", cfg_addr, receiver_sync_first_temp_dm0_ptr, receiver_sync_first_temp_dm1_ptr, receiver_sync_first_temp_dm2_ptr,
    //     receiver_sync_first_temp_dm3_ptr);

        // ape_csu_dma_1D_L2G_ch0ch1_transfer((uint64_t)DM_TO_CSU_ADDR(cfg_addr),
        //                                 (uint64_t)0x88a00000,
        //                                 512,
        //                                 DMA_TAG_L2G,
        //                                 1);     

    SlidingCorrelationSecond((int)cfg_addr, 
                            MPU_ADDR(receiver_sync_first_temp_dm0_ptr), 
                            MPU_ADDR(receiver_sync_first_temp_dm1_ptr), 
                            MPU_ADDR(receiver_sync_first_temp_dm2_ptr),
                            MPU_ADDR(receiver_sync_first_temp_dm3_ptr));
    WAIT_MPU_STOP;

    TRACE(TRACE_RECEIVER_SYNC_FIRST_ADDR, 3, 6); 
    //dm_check(2);
    SVRReg[0] = MPU_ADDR(cfg_addr);
    SlidingCorrelationSecondAsm(SVRReg);
    WAIT_MPU_STOP;

    TRACE(TRACE_RECEIVER_SYNC_FIRST_ADDR, 3, 7); 
    LOG_ERROR_S("2 maxPosition:%d maxsum:%d\n",receiver_sync_first_temp_dm3_ptr[0], receiver_sync_first_temp_dm3_ptr[1]);
    if(maxsum < receiver_sync_first_temp_dm3_ptr[1])
    {
        maxPosition = receiver_sync_first_temp_dm3_ptr[0];
        maxsum = receiver_sync_first_temp_dm3_ptr[1];
    }
    LOG_ERROR_S("3 maxPosition:%d maxsum:%d\n",maxPosition, maxsum);
    //dm_check(3);
    //TODO:后续需要添加门限判断条件
    uint32_t threshold = 1;
    if(threshold)
    {
        STORE_EX_W(&g_receiver_sync_status_SM_ptr->frame_head_offset , maxPosition % 61440);
        LOG_INFO_S("rec sync first offset: %d %d\n", maxPosition, maxsum );
        ret = SYNC_OK;
    } 

    //执行完成，更新状态机
    if(SYNC_OK == ret)
    {
         STORE_EX_W(&g_receiver_sync_status_SM_ptr->sync_status , SYNC_TRACKING);
         __ucps2_synch(0);
    }
    else
    {
        STORE_EX_W(&g_receiver_sync_status_SM_ptr->sync_status , SYNC_IDLE);
        STORE_EX_W(&g_receiver_sync_status_SM_ptr->cylic_buffer_proc_data_offset , -1);
        STORE_EX_W(&g_receiver_sync_status_SM_ptr->cylic_buffer_data_len, 0);
        __ucps2_synch(0);
    }
    Receiver_Sync_First_Memory_Free();


    // LOG_ERROR_S("dgb break\n");
    // __ucps2_synch(0);
    // __ucps2_synch(0);
    // __ucps2_synch(0);
    // __ucps2_synch(0);
    // __ucps2_synch(0);
    // __ucps2_dbgbreak();
    TRACE(TRACE_RECEIVER_SYNC_FIRST_ADDR, 3, 8); 


    RUN_CNT(TRACE_RECEIVER_SYNC_FIRST_ADDR, 1);
    TRACE_MAX(TRACE_RECEIVER_SYNC_FIRST_ADDR, 2, Time_offset(0));
    return;
}
