#include "phal_sw_api.h" #include "utils.h" #include "uectrl.h" #include "itf_types.h" #include "ctrl_interfaces_types.h" #include "reference_modes.h" #define UPLINK_DPDCH_NUMFORMATS 7 int Nph[MAX_TRCH][MAX_TF]; int Zfix[MAX_TRCH]; int Z[MAX_TRCH][MAX_TFC]; int N[MAX_TRCH][MAX_TFC]; int deltaN[MAX_TRCH]; int Nmax[MAX_TRCH]; Downlink_PhCh_t PH; TrCh_t TR[MAX_TRCH]; TL3Control_t L3Control; struct ratem_params_t ratem_params; extern struct binsource_h ctrlsource; extern struct crc_h ctrlcrc; extern struct codec_h ctrlcdc; extern struct convcodec_h ctrlconv; extern struct ratem_h ctrlrm; extern struct timemux_h ctrltimemux; extern struct chmux_h ctrlmux; extern struct phchinterl_h ctrlphch; extern struct interleaver_h ctrlint; int longest_tti; struct uplink_dpdch_t up_dpdch_table[7]={\ 15,15,256,150,10,10,\ 30,30,128,300,20,20,\ 60,60,64,600,40,40,\ 120,120,32,1200,80,80,\ 240,240,16,2400,160,160,\ 480,480,8,4800,320,320,\ 960,960,4,9600,640,640,\ }; struct uplink_dpcch_t up_dpcch_table[7]={\ 6,2,2,0,\ 8,2,0,0,\ 5,2,2,1,\ 7,2,0,1,\ 6,2,0,2,\ 5,1,2,2,\ }; struct downlink_dpch_t dn_dpch_table[17]={\ 15,7.5,512,10,0,4,2,0,4,\ 15,7.5,512,10,0,2,2,2,4,\ 30,15,256,20,2,14,2,0,2,\ 30,15,256,20,2,12,2,2,2,\ 30,15,256,20,2,12,2,0,4,\ 30,15,256,20,2,10,2,2,4,\ 30,15,256,20,2,8,2,0,8,\ 30,15,256,20,2,6,2,2,8,\ 60,30,128,40,6,28,2,0,4,\ 60,30,128,40,6,26,2,2,4,\ 60,30,128,40,6,24,2,0,8,\ 60,30,128,40,6,22,2,2,8,\ 120,60,64,80,12,48,4,8,8,\ 240,120,32,160,28,112,4,8,8,\ 480,240,16,320,56,232,8,8,16,\ 960,480,8,640,120,488,8,8,16,\ 1920,960,4,1280,248,1000,8,8,16,\ }; void Define_Params(TrCh_t *TR, TL3Control_t *Control, struct ue_ref_modes *mode); int slotnum; int tfc; int send; int setParams(struct uectrl_h *uectrl, int s) { struct ue_ref_modes *mode=NULL; int ch; int reference_mode = uectrl->reference_mode; if (reference_mode<0) { return 1; } if (reference_mode > NUM_REFERENCE_MODES-1) { Log("UECTRL: Invalid reference mode!"); return 0; } Log("UECTRL: Setting reference mode %d\n",reference_mode); mode = &ref_modes[reference_mode]; longest_tti=mode->tti0>mode->tti1?mode->tti0:mode->tti1; slotnum = mode->slot_format; tfc = 6; /** only TFC 6 is supported with reference mode */ send=s; PH.slot_format_number=slotnum; PH.Ndata=(dn_dpch_table[slotnum].bitsxslot); PH.fixed=1; Define_Params(TR,&L3Control,mode); Compute_Block_Size(TR,&L3Control); TR[0].TF[L3Control.TFS[tfc].F[0]].N_out_rm = mode->long_tti_rm0; TR[1].TF[L3Control.TFS[tfc].F[1]].N_out_rm = mode->long_tti_rm1; for (ch=0;chNumTFC=MAX_TFC; Control->NumTrCH=MAX_TRCH; Control->uplink_maxphch=2; Control->uplink_minsf=4; TR[0].Code_Rate=mode->code_rate0; TR[0].Code_Type=mode->code_type0; TR[0].Long_CRC=mode->crc0; TR[0].NumTF=5; TR[0].RM=256; TR[0].TF[0].Long_TransportBlock=mode->longtb0; TR[0].TF[0].Num_TransportBlocks=0; TR[0].TF[1].Long_TransportBlock=mode->longtb0; TR[0].TF[1].Num_TransportBlocks=1; TR[0].TF[2].Long_TransportBlock=mode->longtb0; TR[0].TF[2].Num_TransportBlocks=2; TR[0].TF[3].Long_TransportBlock=mode->longtb0; TR[0].TF[3].Num_TransportBlocks=4; TR[0].TF[4].Long_TransportBlock=mode->longtb0; TR[0].TF[4].Num_TransportBlocks=8; TR[0].TTI=mode->tti0; TR[1].Code_Type=mode->code_type1; TR[1].Long_CRC=mode->crc1; TR[1].NumTF=2; TR[1].RM=256; TR[1].Code_Rate=mode->code_rate1; TR[1].TF[0].Long_TransportBlock=mode->longtb1; TR[1].TF[0].Num_TransportBlocks=0; TR[1].TF[1].Long_TransportBlock=mode->longtb1; TR[1].TF[1].Num_TransportBlocks=1; TR[1].TTI=mode->tti1; Control->TFS[0].F[0]=0; Control->TFS[0].F[1]=0; Control->TFS[1].F[0]=1; Control->TFS[1].F[1]=0; Control->TFS[2].F[0]=2; Control->TFS[2].F[1]=0; Control->TFS[3].F[0]=3; Control->TFS[3].F[1]=0; Control->TFS[4].F[0]=4; Control->TFS[4].F[1]=0; Control->TFS[5].F[0]=0; Control->TFS[5].F[1]=1; Control->TFS[6].F[0]=1; Control->TFS[6].F[1]=1; Control->TFS[7].F[0]=2; Control->TFS[7].F[1]=1; Control->TFS[8].F[0]=3; Control->TFS[8].F[1]=1; Control->TFS[9].F[0]=4; Control->TFS[9].F[1]=1; } void Compute_RM_downlink_fixed(TrCh_t *TR, Downlink_PhCh_t *PH, struct ratem_params_t *control,TL3Control_t *L3Control) { float sum,sum2; int i,j,k; for (i=0;iNumTrCH;i++) { Nmax[i]=-1; for (j=0;jNmax[i]) { Nmax[i]=TR[i].TF[j].N_tti; Log("Nmax[%d]=%d\n",i,Nmax[i]); } } } Zfix[0]=0; for (i=0;iNumTrCH;i++) { sum=0; sum2=0; for (k=0;k<=i;k++) sum+=TR[k].RM*Nmax[k]/TR[i].TTI; for (k=0;kNumTrCH;k++) sum2+=TR[k].RM*Nmax[k]/TR[i].TTI; if (sum2==0) Zfix[i+1]=0; else Zfix[i+1]=(int) sum*PH->Ndata/sum2; deltaN[i]=TR[i].TTI*(Zfix[i+1]-Zfix[i])-Nmax[i]; } /* rest of transport formats have same maximum deltaN */ for (i=0;iNumTrCH;i++) { for (j=0;jdeltaNtti[i][j]=deltaN[i]; } } } void Compute_RM_downlink_flexible(TrCh_t *TR, Downlink_PhCh_t *PH, struct ratem_params_t *control,TL3Control_t *L3Control) { int i,j,k; int maxtfc,maxrate,rate; int num,den; int D,n; int sum,sum2; /* search max rate tfc */ maxrate=0; for (i=0;iNumTFC;i++) { rate=0; for (j=0;jNumTrCH;j++) rate+=TR[j].TF[L3Control->TFS[i].F[j]].N_tti; if (rate>maxrate) { maxrate=rate; maxtfc=i; } } den=0; for (k=0;kNumTrCH;k++) den+=TR[k].RM*TR[k].TF[L3Control->TFS[maxtfc].F[k]].N_tti/TR[k].TTI; for (i=0;iNumTrCH;i++) { for (j=0;jNdata-1)/den)+1)); /* up rounding */ } } for (i=0;iNumTrCH;i++) { for (j=0;jdeltaNtti[i][j]=TR[i].TTI*Nph[i][j]-TR[i].TF[j].N_tti; TR[i].TF[j].N_out_rm=TR[i].TF[j].N_tti+control->deltaNtti[i][j]; } else { TR[i].TF[j].N_out_rm=0; } } } /* check not to exceed bit rate */ for (j=0;jNumTFC;j++) { D=0; for (i=0;iNumTrCH;i++) D+=TR[i].TF[L3Control->TFS[j].F[i]].N_out_rm/TR[i].TTI; if(D>PH->Ndata) { /* calculate as it was uplink */ for (k=0;kNumTFC;k++) { for (i=0;iNumTrCH;i++) N[i][k]=TR[i].TF[L3Control->TFS[k].F[i]].N_tti/TR[i].TTI; } for (i=0;iNumTrCH;i++) { for (n=0;nNumTFC;n++) { sum=0; sum2=0; for (k=0;k<=i;k++) sum+=TR[k].RM*N[k][n]; for (k=0;kNumTrCH;k++) sum2+=TR[k].RM*N[k][n]; if (sum2==0) Z[i][n]=0; else Z[i][n]=(int) sum*PH->Ndata/sum2; control->deltaN[n][i]=Z[i][n]-N[i][n]; if (i>0) control->deltaN[n][i]-=Z[i-1][n]; } } for (k=0;kNumTrCH;k++) { if (control->deltaNtti[k][L3Control->TFS[j].F[k]]>TR[k].TTI*control->deltaN[j][k]) { control->deltaNtti[k][L3Control->TFS[j].F[k]]=TR[k].TTI*control->deltaN[j][k]; TR[k].TF[L3Control->TFS[j].F[k]].N_out_rm=TR[k].TF[L3Control->TFS[j].F[k]].N_tti+control->deltaNtti[k][L3Control->TFS[j].F[k]]; } } } } } void Compute_RM_uplink(TrCh_t *TR, Uplink_PhCh_t *PH, struct ratem_params_t *control,TL3Control_t *L3Control,struct uplink_dpdch_t *up_dpdch_table) { float sum,sum2; int i,j,k,n; int maxTF; int reqNdata[MAX_TFC]; maxTF=0; for (i=0;iNumTrCH;i++) { if (TR[i].NumTF>maxTF) maxTF=TR[i].NumTF; } for (k=0;kNumTFC;k++) { reqNdata[k]=0; for (i=0;iNumTrCH;i++) { N[i][k]=TR[i].TF[L3Control->TFS[k].F[i]].N_tti/TR[i].TTI; reqNdata[k]+=N[i][k]; } } /* select Ndata for phch and number of phch for each tfc */ for (k=0;kNumTFC;k++) { for (n=1;n<=L3Control->uplink_maxphch;n++) { for (i=0;iL3Control->uplink_minsf;i++) { if (n*up_dpdch_table[i].bitsxframe>=reqNdata[k]) break; } } PH->Ndata[k]=n*up_dpdch_table[i].bitsxframe; PH->num_dpdch=n; PH->dpdch_slotformat=i; } for (i=0;iNumTrCH;i++) { for (j=0;jNumTFC;j++) { sum=0; sum2=0; for (k=0;k<=i;k++) sum+=TR[k].RM*N[k][j]; for (k=0;kNumTrCH;k++) sum2+=TR[k].RM*N[k][j]; if (sum2==0) Z[i][j]=0; else Z[i][j]=(int) sum*PH->Ndata[j]/sum2; control->deltaN[i][j]=Z[i][j]-N[i][j]; if (i>0) control->deltaN[i][j]-=Z[i-1][j]; } } } int Compute_CodeBlock(int tf, TrCh_t *TR) { int long_total_transblocks,max_long_codeblock; long_total_transblocks=TR->TF[tf].Long_TransportBlock_CRC*TR->TF[tf].Num_TransportBlocks; switch(TR->Code_Type) { case CODE_NO: TR->TF[tf].Long_CodeBlock=TR->TF[tf].Long_TransportBlock_CRC; TR->TF[tf].Num_CodeBlocks=TR->TF[tf].Num_TransportBlocks; TR->TF[tf].Num_Bits_Fill=0; return 1; case CODE_TURBO: max_long_codeblock=LONG_CODEBLOCK_TURBO; break; case CODE_CONV: max_long_codeblock=LONG_CODEBLOCK_CONV; break; default: return 0; } if (TR->TF[tf].Num_TransportBlocks==0) { TR->TF[tf].Num_CodeBlocks=0; TR->TF[tf].Long_CodeBlock=0; TR->TF[tf].N_tti=0; TR->TF[tf].Num_Bits_Fill=0; } else { if (long_total_transblocks > max_long_codeblock && max_long_codeblock>0) { TR->TF[tf].Num_CodeBlocks=IntDiv(long_total_transblocks,max_long_codeblock); TR->TF[tf].Long_CodeBlock=IntDiv(long_total_transblocks,TR->TF[tf].Num_CodeBlocks); } else { if (long_total_transblocksCode_Type==CODE_TURBO) { TR->TF[tf].Long_CodeBlock=MIN_CODEBLOCK_TURBO; TR->TF[tf].Num_CodeBlocks=1; } else { TR->TF[tf].Num_CodeBlocks=1; TR->TF[tf].Long_CodeBlock=long_total_transblocks; } } TR->TF[tf].Num_Bits_Fill=(TR->TF[tf].Num_CodeBlocks) * (TR->TF[tf].Long_CodeBlock) - long_total_transblocks; switch(TR->Code_Type) { case CODE_CONV: TR->TF[tf].Long_out_CodeBlock=(TR->Code_Rate*(TR->TF[tf].Long_CodeBlock+8)); break; case CODE_TURBO: TR->TF[tf].Long_out_CodeBlock=(3*TR->TF[tf].Long_CodeBlock+12); break; default: TR->TF[tf].Long_out_CodeBlock=(TR->TF[tf].Long_CodeBlock); break; } TR->TF[tf].N_tti=TR->TF[tf].Long_out_CodeBlock*TR->TF[tf].Num_CodeBlocks; } return 1; } void Compute_Block_Size(TrCh_t *TR, TL3Control_t *Control) { int i,j; for (i=0;iNumTrCH;i++) { for (j=0;j