在安装完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中