#include "transform_para_func.h"

volatile uint32_t g_thita1_val;
volatile uint32_t g_thita2_val;
volatile uint32_t g_thita34_val;

double thita2imag[4][4] = {{0.382683432365090,	0.923879532511287,	-0.382683432365090,	-0.923879532511287},
                           {0.500000000000000,	0.866025403784439,	-0.500000000000000,	-0.866025403784439},
                           {0.707106781186548,	0.707106781186548,	-0.707106781186548,	-0.707106781186548},
                           {0.866025403784439,	0.500000000000000,	-0.866025403784439,	-0.500000000000000}};

double thita2real[4][4] = {{0.923879532511287,	-0.382683432365090,	-0.923879532511287,	0.382683432365090},
                           {0.866025403784439,	-0.500000000000000,	-0.866025403784439,	0.500000000000000},
                           {0.707106781186548,	-0.707106781186548,	-0.707106781186548,	0.707106781186547},
                           {0.500000000000000,	-0.866025403784439,	-0.500000000000000,	0.866025403784438}};                           



//查bit具体值使用的表
uint32_t g_thita1_addr;
uint32_t g_thita2_addr;
uint32_t g_thita3_addr;
uint32_t g_thita4_addr;
//查解算表2偏移量使用的表
uint32_t g_no1_addr;
uint32_t g_no2_addr;
uint32_t g_no3_addr;
//查解算得到的序号值使用的表
uint32_t g_nxtstate9_addr;
uint32_t g_nxtstate11_addr;
uint32_t g_nxtstate13_addr;
uint32_t g_thita_len;//not use

int transform_para_init(uint32_t thita1_init, uint32_t thita2_init, uint32_t thita34_init)
{   
    //配置初始值
    transform_set_para(thita1_init, thita2_init, thita34_init);
 
    //载入查表文件到ddr，获取数据首地址存为全局变量
    uint32_t ret = -1;
    ret = osp_get_cfgfile("thita1.dat",
        (uint32_t *)&(g_thita1_addr),
        (int32_t *)&(g_thita_len));
    if(0 != ret)
    {
        //LOG_ERROR_S("thita1.dat load fail!\n");
    }
    ret = osp_get_cfgfile("thita2.dat",
        (uint32_t *)&(g_thita2_addr),
        (int32_t *)&(g_thita_len));
    if(0 != ret)
    {
        //LOG_ERROR_S("thita2.dat load fail!\n");
    }
    ret = osp_get_cfgfile("thita3.dat",
        (uint32_t *)&(g_thita3_addr),
        (int32_t *)&(g_thita_len));
    if(0 != ret)
    {
        //LOG_ERROR_S("thita3.dat load fail!\n");
    }
    ret = osp_get_cfgfile("thita4.dat",
        (uint32_t *)&(g_thita4_addr),
        (int32_t *)&(g_thita_len));
    if(0 != ret)
    {
        //LOG_ERROR_S("thita4.dat load fail!\n");
    }
    ret = osp_get_cfgfile("no1.dat",
        (uint32_t *)&(g_no1_addr),
        (int32_t *)&(g_thita_len));
    if(0 != ret)
    {
        //LOG_ERROR_S("no1.dat load fail!\n");
    }
    ret = osp_get_cfgfile("no2.dat",
        (uint32_t *)&(g_no2_addr),
        (int32_t *)&(g_thita_len));
    if(0 != ret)
    {
        //LOG_ERROR_S("no2.dat load fail!\n");
    }
    ret = osp_get_cfgfile("no3.dat",
        (uint32_t *)&(g_no3_addr),
        (int32_t *)&(g_thita_len));
    if(0 != ret)
    {
        //LOG_ERROR_S("no3.dat load fail!\n");
    }
    ret = osp_get_cfgfile("nextstate9.dat",
        (uint32_t *)&(g_nxtstate9_addr),
        (int32_t *)&(g_thita_len));
    if(0 != ret)
    {
        //LOG_ERROR_S("nextstate9.dat load fail!\n");
    }
    ret = osp_get_cfgfile("nextstate11.dat",
        (uint32_t *)&(g_nxtstate11_addr),
        (int32_t *)&(g_thita_len));
    if(0 != ret)
    {
        //LOG_ERROR_S("nextstate11.dat load fail!\n");
    }
    ret = osp_get_cfgfile("nextstate13.dat",
        (uint32_t *)&(g_nxtstate13_addr),
        (int32_t *)&(g_thita_len));
    if(0 != ret)
    {
        //LOG_ERROR_S("nextstate13.dat load fail!\n");
    }
    //LOG_INFO_S("trasnform para dat init & load finish!\n");
    return 0;
}


//设置存储寄存器变量
int transform_set_para(uint32_t thita1_init, uint32_t thita2_init, uint32_t thita34_init)
{
    g_thita1_val = thita1_init;
    g_thita2_val = thita2_init;
    g_thita34_val = thita34_init;
    return 0;
}

//递推n次
int transform_para_update(uint32_t n)
{
    g_thita1_val = (g_thita1_val +n) %(THITA1_LEN);
    g_thita2_val = (g_thita2_val +n) %(THITA2_LEN);
    g_thita34_val = (g_thita34_val +n) %(THITA34_LEN);
    return 0;
}

//根据pcie返回的结果计算当前状态
int transform_decode_para(uint32_t thita1_para, uint32_t thita2_para, uint32_t thita34_para)
{
    int32_t ret = -1;
    //根据pcie提供的值查no1/2/3系列表，得到next偏移量, 分别取9，11，13bit作为查表值,左移两位后再分别右移7/5/19位
    volatile uint32_t temp1 = LOAD_EX_W(g_no1_addr + ((thita1_para & 0xff80)>>5));
    volatile uint32_t temp2 = LOAD_EX_W(g_no2_addr + ((thita2_para & 0xffe0)>>3));
    volatile uint32_t temp3 = LOAD_EX_W(g_no3_addr + ((thita34_para & 0xfff80000)>>17));

    //根据next9/11/13系列表，结合偏移量查询计算的时间点下的参数
    temp1 = LOAD_EX_W(g_nxtstate9_addr + (temp1<<2));
    temp2 = LOAD_EX_W(g_nxtstate11_addr + (temp2<<2));
    temp3 = LOAD_EX_W(g_nxtstate13_addr + (temp3<<2));

    //算好后更新参数
    transform_set_para(temp1, temp2, temp3);  

    return 0;
}


int transform_decode_para_check(uint32_t thita1_para, uint32_t thita2_para, uint32_t thita34_para)
{
    //取出用来对比的部分
    
    uint32_t temp1 = (uint32_t)0xff & thita1_para;
    uint32_t temp2 = (uint32_t)0xff & thita2_para;
    uint32_t temp3 = (uint32_t)0xffff & thita34_para;
    uint32_t cnt = 0;
    uint32_t cmp_temp1 = 0;
    uint32_t cmp_temp2 = 0;
    uint32_t cmp_temp3 = 0;


    //初次递推
    transform_para_update(4);
    while(cnt < 4)
    {

        cmp_temp1 = (cmp_temp1 <<2) | transform_get_thita1_2bit();
        cmp_temp2 = (cmp_temp2 <<2) | transform_get_thita2_2bit();
        cmp_temp3 = (cmp_temp3 <<4) | (transform_get_thita3_2bit() | (transform_get_thita4_2bit() << 2));

        transform_para_update(1);
        cnt++;
    }

    uint32_t cmp_res = ( (temp1 == cmp_temp1) && (temp2 == cmp_temp2) && (temp3 == cmp_temp3) );

    LOG_INFO_S("transform check:%d %d %d %d\n", cmp_res, (temp1 == cmp_temp1) , (temp2 == cmp_temp2), (temp3 == cmp_temp3) );

    return (cmp_res == 1) ? 0 : -1;
}


//根据时序偏差更新寄存器参数
int transform_update_cur_para(uint32_t cur_sfn, uint32_t cur_slot,  uint32_t ref_sfn, uint32_t ref_slot)
{
    uint32_t interval_slot_num;
    //假设两者的间隔不超过1024个sfn，周期1024*20slot
    if((cur_sfn == ref_sfn) && (cur_slot < ref_slot))
    {
        interval_slot_num = NR_SFN_NUM*NR_SFN_SLOT_NUM + cur_slot - ref_slot;
    }
    else if(cur_sfn < ref_sfn)
    {
        interval_slot_num = (ref_sfn + NR_SFN_NUM - cur_sfn)*NR_SFN_SLOT_NUM +  cur_slot - ref_slot;
    }
    else
    {
        interval_slot_num = (cur_sfn - ref_sfn)*NR_SFN_SLOT_NUM + cur_slot - ref_slot;
    }

    //递推
    transform_para_update(interval_slot_num);

    return 0;
}