在安装完OpenAirInterface之后(安装过程可查看本博客文章OpenAirInterface安装说明),可以运行LTE PHY仿真
支持的信道类型
PBCH(物理广播信道):pbchsim
DCI/PDCCH(下行控制信道):pdcchsim
DLSCH/PDSCH(下行共享信道):dlsim
ULSCH/PUSCH(上行共享信道):ulsim
PUCCH(上行控制信道):pucchsim
PRACH(随机接入信道):prachsim
MCH/PMCH(物理多播信道):mbmssim
PHY模拟的目录在 cmake_targets/lte-simulators/build
这个地方有更多的test case:$OPENAIR1_DIR/PHY/CODING/TESTBENCH
首先研究一下openair1文件夹里面的东西,这里面是物理层的代码,看一下README.txt文件。
README.txt文件:
PHY大目录
每一个目录包含猪少一个defs.h(结构体和函数的声明),vars.h(变量的声明)和extern.h(外部变量)
1 . CODING Turbo和卷积码,编码和解码操作,速率匹配,crc生成部分代码
1.1 TESTBENCH 独立的测试单元(信道编解码的)
2. INIT 在vars.h中定义的变量,在这里面初始化(分配内存)
3. LTE_ESTIMATION 定时、频偏、信道估计
4. LTE_REFSIG LTE参考信号生成(36211)
5. LTE_TRANSPORT 上层循环(每个信道的)
6. MODULATION 调制解调操作(FFT/SC-FDMA)
7. TOOLS FFT/IFFT,向量运算,矩阵乘法等等
7.1 FFTTEST 专门测试FFT的
8. defs.h
9. extern.h
10. impl_defs.h
11. impl_defs_lte.h
12. impl_defs_top.h
13. spec_defs.h
14. spec_defs_top.h
15. types.h
16. vars.h
SCHED大目录(调度不同的物理层函数)
SIMULATION大目录(PHY仿真函数)
目前的进展
目前来看,如果在PHY大目录里改变东西,还得到最开始的地方用./build_oai –lte-simulators来编译,尝试跟一下编辑过程?这样有些麻烦。
2018.03.15更新
好久没有更新OAI的东西,今日从openair1\SIMULATION/LTE_PHY目录下的dlsim.c开始分析,一定要把他攻克。由于我在阅读代码时候加了一些注释,改变了代码结构,所以我的代码的行数和OAI的行数会有一些微小的差别,大家可以对照自己的代码来看。
dlsim.c是LTE下行的物理层仿真主函数,在编译了./build_oai –lte-simulators之后,就可以通过单独sudo make dlsim来编译dlsim这个可执行文件,从而使自己的修改可以实现。记得在运行时要加sudo,因为dlsim流程中包含创建文件的操作,需要sudo权限。
本文会针对dlsim中涉及到的函数进行分析,分析过程中采用5MHz带宽,FDD格式,暂时不考虑TDD的东西。
1268行
主函数为int main(int argc, char **argv)
这里列出了一些参数最初的初始化
// 参数最初的初始化
//
uint8_t extended_prefix_flag=0,transmission_mode=1,n_tx_port=1,n_tx_phy=1,n_rx=2;//第一项是普通CP还是拓展CP,第二项是7种传输模式(36.213 7.1.1)
double SNR,snr0=-2.0,snr1,rate = 0; //信噪比
double snr_step=1,input_snr_step=1, snr_int=30;
unsigned char mcs1=0,mcs2=0,mcs_i=0,dual_stream_UE = 0,awgn_flag=0,round; //调制编码方式
SCM_t channel_model=AWGN;//信道模型
uint8_t N_RB_DL=25,osf=1; //下行RB数量,代表带宽,可选1.4,3,5,10,15,20,osf为过采样倍数
frame_t frame_type = FDD;//帧结构,是FDD还是TDD
uint16_t tdd_config=3;//帧结构,是FDD还是TDD
1770-1793行
if (common_flag == 0) { //DLSCH_RB_ALLOC DLSCH资源分配,36.212 5.3.3.1.2 DCI格式1中给出了资源分配,下面是计算比特数(根据资源块和p的对应关系)
//6个RB使用6个比特,25个RB使用13个比特,50个RB使用17个比特,100个RB使用25个比特
//因为6个RB时候1个比特代表1个RB,25个RB时有12个RBG包含2个RB,1个RBG包含1个RB,所以是13个比特,50个RB时有16个RBG包含3个RB,1个RBG包含2个RB,所以是17个比特,100个RB时有25个RBG包含4个RB。
//RBG和RB、P的关系在36.213 7.1.6.1
switch (N_RB_DL) {
case 6:
if (rballocset==0) DLSCH_RB_ALLOC = 0x3f;//63 0x3f是6个比特
num_pdcch_symbols = 3;
break;
case 25:
if (rballocset==0) DLSCH_RB_ALLOC = 0x1fff;//8191 5MHz是13个比特,0x1fff是13个比特
break;
case 50:
if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffff;//131071 0x1ffff是17个比特
break;
case 100:
if (rballocset==0) DLSCH_RB_ALLOC = 0x1ffffff;//33554431 0x1ffffff是25个比特
break;
}
NB_RB=conv_nprb(0,DLSCH_RB_ALLOC,N_RB_DL); //NB_RB = NB_RB_DL
}
else
NB_RB = 4;
1814行
lte_param_init(n_tx_port, //发送端口
n_tx_phy,//发送天线
n_rx,//接收数目
transmission_mode,//传输模式TM
extended_prefix_flag,//CP指示
frame_type,//FDD
Nid_cell,//0
tdd_config,//3,如果是FDD不考虑这个
N_RB_DL,//25
threequarter_fs,//0
osf,//过采样倍数
perfect_ce);//0
这个函数在openair1\PHY\INIT\lte_param_init.c中,这个函数是初始化函数,里面包含了7个函数,尝试分析一下。
void lte_param_init(unsigned char N_tx_port_eNB,
unsigned char N_tx_phy,
unsigned char N_rx,
unsigned char transmission_mode,
uint8_t extended_prefix_flag,
frame_t frame_type,
uint16_t Nid_cell,
uint8_t tdd_config,
uint8_t N_RB_DL,
uint8_t threequarter_fs,
uint8_t osf,
uint32_t perfect_ce)
{
LTE_DL_FRAME_PARMS *frame_parms;
int i;
printf("Startn lte_param_init\n");
eNB = malloc(sizeof(PHY_VARS_eNB));
UE = malloc(sizeof(PHY_VARS_UE));
memset((void*)eNB,0,sizeof(PHY_VARS_eNB));
memset((void*)UE,0,sizeof(PHY_VARS_UE));
//PHY_config = malloc(sizeof(PHY_CONFIG));
mac_xface = malloc(sizeof(MAC_xface));
srand(0);
randominit(0);
set_taus_seed(0);
frame_parms = &(eNB->frame_parms);
frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz
frame_parms->N_RB_UL = N_RB_DL;
frame_parms->threequarter_fs = threequarter_fs;
frame_parms->Ncp = extended_prefix_flag;
frame_parms->Ncp_UL = extended_prefix_flag;
frame_parms->Nid_cell = Nid_cell;
frame_parms->nushift = Nid_cell%6;
frame_parms->nb_antennas_tx = N_tx_phy;
frame_parms->nb_antennas_rx = N_rx;
frame_parms->nb_antenna_ports_eNB = N_tx_port_eNB;
frame_parms->phich_config_common.phich_resource = oneSixth; //36.331
frame_parms->phich_config_common.phich_duration = normal;
frame_parms->tdd_config = tdd_config;
frame_parms->frame_type = frame_type;
// frame_parms->Csrs = 2;
// frame_parms->Bsrs = 0;
// frame_parms->kTC = 0;44
// frame_parms->n_RRC = 0;
frame_parms->mode1_flag = (transmission_mode == 1 || transmission_mode ==7)? 1 : 0;//1代表SISO,单天线收发
init_frame_parms(frame_parms,osf);//1 初始化帧参数
//copy_lte_parms_to_phy_framing(frame_parms, &(PHY_config->PHY_framing));
// phy_init_top(frame_parms); //allocation
UE->is_secondary_ue = 0;
UE->frame_parms = *frame_parms;
eNB->frame_parms = *frame_parms;
eNB->transmission_mode[0] = transmission_mode;
UE->transmission_mode[0] = transmission_mode;
phy_init_lte_top(frame_parms);//2
dump_frame_parms(frame_parms);//3
UE->measurements.n_adj_cells=0;
UE->measurements.adj_cell_id[0] = Nid_cell+1;
UE->measurements.adj_cell_id[1] = Nid_cell+2;
for (i=0; i<3; i++)
lte_gold(frame_parms,UE->lte_gold_table[i],Nid_cell+i);
phy_init_lte_ue(UE,1,0);//4
phy_init_lte_eNB(eNB,0,0);//5
generate_pcfich_reg_mapping(&UE->frame_parms);//6
generate_phich_reg_mapping(&UE->frame_parms);//7
// DL power control init
//if (transmission_mode == 1) {
if (transmission_mode == 1 || transmission_mode ==7) {
eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB
((eNB->frame_parms).pdsch_config_common).p_b = 0;
UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB
((UE->frame_parms).pdsch_config_common).p_b = 0;
} else { // rho_a = rhob
eNB->pdsch_config_dedicated->p_a = dBm3; // 4 = 0dB
((eNB->frame_parms).pdsch_config_common).p_b = 1;
UE->pdsch_config_dedicated->p_a = dBm3; // 4 = 0dB
((UE->frame_parms).pdsch_config_common).p_b = 1;
}
UE->perfect_ce = perfect_ce;
printf("Done lte_param_init\n");
}
1
int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf)
//该函数在openair1\PHT\INIT\lte_parms.c中,这里只分析frame_parms->N_RB_DL为25的case,其他case类似
int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf)
{
uint8_t log2_osf;
LOG_I(PHY,"Initializing frame parms for N_RB_DL %d, Ncp %d, osf %d\n",frame_parms->N_RB_DL,frame_parms->Ncp,osf);
if (frame_parms->Ncp==EXTENDED) {//拓展CP,注意这里对应的是20MHz的参数,采样率为30.72MHz
frame_parms->nb_prefix_samples0=512;
frame_parms->nb_prefix_samples = 512;
frame_parms->symbols_per_tti = 12;
} else {正常CP,注意这里对应的是20MHz的参数
frame_parms->nb_prefix_samples0 = 160;
frame_parms->nb_prefix_samples = 144;
frame_parms->symbols_per_tti = 14;
}
switch(osf) {//过采样倍数,下面转换为log2为底的对数值
case 1:
log2_osf = 0;
break;
case 2:
log2_osf = 1;
break;
case 4:
log2_osf = 2;
break;
case 8:
log2_osf = 3;
break;
case 16:
log2_osf = 4;
break;
default:
printf("Illegal oversampling %d\n",osf);
return(-1);
}
switch (frame_parms->N_RB_DL) {
case 100:
if (osf>1) {
printf("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL);
return(-1);
}
if (frame_parms->threequarter_fs) {
frame_parms->ofdm_symbol_size = 1536;
frame_parms->samples_per_tti = 23040;
frame_parms->first_carrier_offset = 1536-600;
frame_parms->nb_prefix_samples=(frame_parms->nb_prefix_samples*3)>>2;
frame_parms->nb_prefix_samples0=(frame_parms->nb_prefix_samples0*3)>>2;
}
else {
frame_parms->ofdm_symbol_size = 2048;
frame_parms->samples_per_tti = 30720;
frame_parms->first_carrier_offset = 2048-600;
}
frame_parms->N_RBGS = 4;
frame_parms->N_RBG = 25;
break;
case 75:
if (osf>1) {
printf("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL);
return(-1);
}
frame_parms->ofdm_symbol_size = 1536;
frame_parms->samples_per_tti = 23040;
frame_parms->first_carrier_offset = 1536-450;
frame_parms->nb_prefix_samples=(frame_parms->nb_prefix_samples*3)>>2;
frame_parms->nb_prefix_samples0=(frame_parms->nb_prefix_samples0*3)>>2;
frame_parms->N_RBGS = 4;
frame_parms->N_RBG = 25;
break;
case 50:
if (osf>1) {
printf("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL);
return(-1);
}
frame_parms->ofdm_symbol_size = 1024*osf;
frame_parms->samples_per_tti = 15360*osf;
frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 300;
frame_parms->nb_prefix_samples>>=(1-log2_osf);
frame_parms->nb_prefix_samples0>>=(1-log2_osf);
frame_parms->N_RBGS = 3;
frame_parms->N_RBG = 17;
break;
case 25:
if (osf>2) {
printf("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL);
return(-1);
}
frame_parms->ofdm_symbol_size = 512*osf; //因为有300个子载波,所以至少做512点FFT
frame_parms->samples_per_tti = 7680*osf;//采样频率为7680MHz
frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 150; //和数据位置有关,362,中间的部分是有用子载波,旁边是空闲子载波
frame_parms->nb_prefix_samples>>=(2-log2_osf); //注意是>>=,就是除以4
frame_parms->nb_prefix_samples0>>=(2-log2_osf); //注意是>>=,就是除以4,因为前面的160是20MHz的,这里是5MHz
frame_parms->N_RBGS = 2; //p96
frame_parms->N_RBG = 13; //p96,有一个RBG的size是1
break;
case 15:
frame_parms->ofdm_symbol_size = 256*osf;
frame_parms->samples_per_tti = 3840*osf;
frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 90;
frame_parms->nb_prefix_samples>>=(3-log2_osf);
frame_parms->nb_prefix_samples0>>=(3-log2_osf);
frame_parms->N_RBGS = 2;
frame_parms->N_RBG = 8;
break;
case 6:
frame_parms->ofdm_symbol_size = 128*osf;
frame_parms->samples_per_tti = 1920*osf;
frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 36;
frame_parms->nb_prefix_samples>>=(4-log2_osf);
frame_parms->nb_prefix_samples0>>=(4-log2_osf);
frame_parms->N_RBGS = 1;
frame_parms->N_RBG = 6;
break;
default:
printf("init_frame_parms: Error: Number of resource blocks (N_RB_DL %d) undefined, frame_parms = %p \n",frame_parms->N_RB_DL, frame_parms);
return(-1);
break;
}
printf("lte_parms.c: Setting N_RB_DL to %d, ofdm_symbol_size %d\n",frame_parms->N_RB_DL, frame_parms->ofdm_symbol_size);
if (frame_parms->frame_type == TDD) set_S_config(frame_parms);
// frame_parms->tdd_config=3;
return(0);
}
2
void phy_init_lte_top(LTE_DL_FRAME_PARMS *frame_parms)
//该函数在openair1\PHT\INIT\lte_init.c中,这个函数是生成crc,维特比,16QAM等等的表格,后面应该查表会用到
4
int phy_init_lte_eNB(PHY_VARS_eNB *eNB, unsigned char is_secondary_eNB, unsigned char abstraction_flag)
//该函数在openair1\PHT\INIT\lte_init.c中,eNB的初始化
5
void generate_pcfich_reg_mapping(LTE_DL_FRAME_PARMS *frame_parms)
//该函数在openair1\PHT\LTE_TRANSPORT\pcfich.c中