#include <AddCP.h>

void AddCP(int ConfigBaseAddr,int Nport,int Nsymbol,int CPLength0,int CPLength1,int InputAddr0,int InputAddr1,int OutputAddr0,int OutputAddr1,int CalAddr){
	if (Nsymbol*Nport==1)
	{Nsymbol=2;}
	//cycle
    const unsigned int addr_move_base = ConfigBaseAddr;
	volatile unsigned int *addr_move = (volatile unsigned int *)addr_move_base;
	int KI0=((Nsymbol*Nport+1)>>1)-1;
    addr_move[0] = KI0;
	addr_move[1] = 0x100;//4096

	int CPcycle1=CPLength0>>4;//352/16
	int CPcycle2=CPLength1>>4;//288/16
	addr_move[2] = CPcycle1>>1;
	addr_move[3] = CPcycle2>>1;

	if (Nport==1)
		addr_move[4] = CPcycle2>>1;

	else
		addr_move[4] = CPcycle1>>1;

    //BIU
    const unsigned int addr_biu_base1 = ConfigBaseAddr+0x40;
	volatile unsigned int *addr_biu1 = (volatile unsigned int *)addr_biu_base1;
    //BIU0.T0
    addr_biu1[0] = InputAddr0;
    addr_biu1[1] = InputAddr0;
    addr_biu1[2] = InputAddr0;
	addr_biu1[3] = InputAddr0;

    //BIU1.T0
    addr_biu1[0+16] = InputAddr1;
    addr_biu1[1+16] = InputAddr1;
    addr_biu1[2+16] = InputAddr1;
	addr_biu1[3+16] = InputAddr1;

    //BIU2.T1 symbol1
	int output_data_addr_cp1=OutputAddr0+CPLength0*4;
    addr_biu1[0+16*2] = output_data_addr_cp1;
    addr_biu1[1+16*2] = output_data_addr_cp1;
    addr_biu1[2+16*2] = output_data_addr_cp1;
    addr_biu1[3+16*2] = output_data_addr_cp1;
	//BIU2.T2 symbol2-4  dm0
	int output_data_addr_cp2=OutputAddr0+0x4000+CPLength0*4+CPLength1*4;
    addr_biu1[0+16*3] = output_data_addr_cp2;
    addr_biu1[1+16*3] = output_data_addr_cp2;
    addr_biu1[2+16*3] = output_data_addr_cp2;
    addr_biu1[3+16*3] = output_data_addr_cp2;

    addr_biu1[5+16*3] = 0x4000+CPLength1*4;

	if (Nport==1){
		output_data_addr_cp1=OutputAddr1+CPLength1*4;
		output_data_addr_cp2=OutputAddr1+0x4000+CPLength1*2*4;
	}
	else
	{
		output_data_addr_cp1=OutputAddr1+CPLength0*4;
		output_data_addr_cp2=OutputAddr1+0x4000+CPLength0*4+CPLength1*4;
	}
	//BIU3.T1 symbol1  dm1
    addr_biu1[0+16*4] = output_data_addr_cp1;
    addr_biu1[1+16*4] = output_data_addr_cp1;
    addr_biu1[2+16*4] = output_data_addr_cp1;
    addr_biu1[3+16*4] = output_data_addr_cp1;
	//BIU3.T2 symbol2-7  dm1
    addr_biu1[0+16*5] = output_data_addr_cp2;
    addr_biu1[1+16*5] = output_data_addr_cp2;
    addr_biu1[2+16*5] = output_data_addr_cp2;
    addr_biu1[3+16*5] = output_data_addr_cp2;

    addr_biu1[5+16*5] = 0x4000+CPLength1*4;


	//add cp
    //BIU0.T1 cp1
	int take_addr_cp1=OutputAddr0+0x4000;
    addr_biu1[0+16*6] = take_addr_cp1;
    addr_biu1[1+16*6] = take_addr_cp1;
    addr_biu1[2+16*6] = take_addr_cp1;
    addr_biu1[3+16*6] = take_addr_cp1;

    //BIU0.T2 cp2-4 dm0
	int take_addr_cp2=OutputAddr0+0x8000+(CPLength0<<2);
    addr_biu1[0+16*7] = take_addr_cp2;
    addr_biu1[1+16*7] = take_addr_cp2;
    addr_biu1[2+16*7] = take_addr_cp2;
    addr_biu1[3+16*7] = take_addr_cp2;
    addr_biu1[5+16*7] = 0x4000+CPLength1*4;
    addr_biu1[8+16*7] = CPcycle2+(CPcycle2<<16);

	if (Nport==1){
		take_addr_cp1=OutputAddr1+0x4000;
		take_addr_cp2=OutputAddr1+0x8000+(CPLength1<<2);
	}
	else
	{
		take_addr_cp1=OutputAddr1+0x4000;
		take_addr_cp2=OutputAddr1+0x8000+(CPLength0<<2);
	}
    //BIU1.T1 cp1 dm1
    addr_biu1[0+16*8] = take_addr_cp1;
    addr_biu1[1+16*8] = take_addr_cp1;
    addr_biu1[2+16*8] = take_addr_cp1;
    addr_biu1[3+16*8] = take_addr_cp1;
    //BIU1.T2 cp5-7 dm1
    addr_biu1[0+16*9] = take_addr_cp2;
    addr_biu1[1+16*9] = take_addr_cp2;
    addr_biu1[2+16*9] = take_addr_cp2;
    addr_biu1[3+16*9] = take_addr_cp2;
    addr_biu1[5+16*9] = 0x4000+CPLength1*4;
    addr_biu1[8+16*9] = CPcycle2+(CPcycle2<<16);

    //output cp
    //BIU2.T1  cp1
	int output_addr_cp1=OutputAddr0;
    addr_biu1[0+16*10] = output_addr_cp1;
    addr_biu1[1+16*10] = output_addr_cp1;
    addr_biu1[2+16*10] = output_addr_cp1;
    addr_biu1[3+16*10] = output_addr_cp1;
    //BIU2.T2  cp2-7
	int output_addr_cp2=OutputAddr0+0x4000+CPLength0*4;
    addr_biu1[0+16*11] = output_addr_cp2;
    addr_biu1[1+16*11] = output_addr_cp2;
    addr_biu1[2+16*11] = output_addr_cp2;
    addr_biu1[3+16*11] = output_addr_cp2;
    addr_biu1[5+16*11] = 0x4000+CPLength1*4;
    addr_biu1[8+16*11] = CPcycle2+(CPcycle2<<16);

	if (Nport==1){
		output_addr_cp1=OutputAddr1;
		output_addr_cp2=OutputAddr1+0x4000+CPLength1*4;
	}
	else
	{
		output_addr_cp1=OutputAddr1;
		output_addr_cp2=OutputAddr1+0x4000+CPLength0*4;
	}

    //BIU3.T1
    addr_biu1[0+16*12] = output_addr_cp1;
    addr_biu1[1+16*12] = output_addr_cp1;
    addr_biu1[2+16*12] = output_addr_cp1;
    addr_biu1[3+16*12] = output_addr_cp1;
    //BIU3.T2
    addr_biu1[0+16*13] = output_addr_cp2;
    addr_biu1[1+16*13] = output_addr_cp2;
    addr_biu1[2+16*13] = output_addr_cp2;
    addr_biu1[3+16*13] = output_addr_cp2;
    addr_biu1[5+16*11] = 0x4000+CPLength1*4;
    addr_biu1[8+16*11] = CPcycle2+(CPcycle2<<16);

	//input phasefactor
	addr_biu1[0+16*14] = CalAddr;
	addr_biu1[1+16*14] = CalAddr;
	addr_biu1[2+16*14] = CalAddr;
	addr_biu1[3+16*14] = CalAddr;
	if (Nport==1){
		addr_biu1[4+16*14] = 0x40;
	}
	else
	{
		addr_biu1[4+16*14] = 0;
	}

}
