iqplayer_lib.c总结

主题:IQ文件头、IQ文件内容、播放涉及的操作
时间:2021年1月6日
作者:ybb
参考:iqplayer_lib.c

D:\OAI\openairinterface5g-develop-20209018\openairinterface5g-develop\targets\ARCH\iqplayer\iqplayer_lib.c总结
概述:IQ文件头、IQ文件内容、播放涉及的操作

初始化收发设备

device_init

int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
  device->openair0_cfg = openair0_cfg;//应用设定的射频前端参数
  device->trx_start_func = trx_iqplayer_start;//启动
  device->trx_get_stats_func = NULL;//获取收发函数状态
  device->trx_reset_stats_func = NULL;//重设收发函数状态
  device->trx_end_func   = trx_iqplayer_end;//收发终止函数
  device->trx_stop_func  = NULL;//收发停止函数
  device->trx_set_freq_func = NULL;//收发函数频率设定
  device->trx_set_gains_func   = NULL;//收发函数增益设置
  // Replay subframes from from file从文件回放子帧
  //  openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;校准表
  //  bw_gain_adjust=1;带宽增益调整
  device->trx_write_func = trx_iqplayer_write;//收发写函数
  device->trx_read_func  = trx_iqplayer_read;//收发度函数
  iqplayer_loadfile(device, openair0_cfg);
  LOG_UI(HW,"iqplayer device initialized, replay %s  for %i iterations",openair0_cfg->recplay_conf->u_sf_filename,openair0_cfg->recplay_conf->u_sf_loops);//replay的文件和循环次数
  return 0;
}

openair0_device

/*!\brief structure holds the parameters to configure USRP devices用于配置USRP设备的参数*/
typedef struct openair0_device_t openair0_device;

//#define USRP_GAIN_OFFSET (56.0)  定义USRP增益偏置
// 86 calibrated for USRP B210 @ 2.6 GHz to get equivalent RS EPRE in OAI to SMBV100 output
//86用于校准USRP B210 2.6G 得到等效的RS EPRE
typedef enum {
  max_gain=0,med_gain,byp_gain
} rx_gain_t;

typedef enum {
  duplex_mode_TDD=1,duplex_mode_FDD=0//0代表FDD 1代表TDD
} duplex_mode_t;

openair0_device_t


/*!\brief structure holds the parameters to configure USRP devices 配置USRP设备的参数*/
struct openair0_device_t {
  /*!tx write thread*/
  openair0_thread_t write_thread;

  /*!brief Module ID of this device */
  int Mod_id;

  /*!brief Component Carrier ID of this device */
  int CC_id;

  /*!brief Type of this device */
  dev_type_t type;

  /*!brief Transport protocol type that the device supports (in case I/Q samples need to be transported) 设备支持的传输协议类型,IQ采样需要指定传输类型传输IQ样本*/
  transport_type_t transp_type;

  /*!brief Type of the device's host (RAU/RRU) */
  host_type_t host_type;

  /* !brief RF frontend parameters set by application */
  openair0_config_t *openair0_cfg;//射频前端参数集
  
  /* !brief ETH params set by application */
  eth_params_t *eth_params;
  //! record player data, definition in record_player.h//record player的数据和定义
  recplay_state_t *recplay_state;
  /* !brief Indicates if device already initialized 指示设备是否初始化了*/
  int is_init;


  /*!brief Can be used by driver to hold internal structure能够由驱动使用的内部结构*/
  void *priv;

  /* Functions API, which are called by the application FAPI RRU负责物理层low RAU负责物理层high*/

  /*! \brief Called to start the transceiver. Return 0 if OK, < 0 if error启动收发机
      @param device pointer to the device structure specific to the RF hardware target设备指向设备架构
  */
  int (*trx_start_func)(openair0_device *device);

 /*! \brief Called to configure the device配置设备
      @param device pointer to the device structure specific to the RF hardware target  指向设备结构的射频硬件目标
  */


  int (*trx_config_func)(openair0_device* device, openair0_config_t *openair0_cfg);

  /*! \brief Called to send a request message between RAU-RRU on control port
      @param device pointer to the device structure specific to the RF hardware target
      @param msg pointer to the message structure passed between RAU-RRU
      @param msg_len length of the message
  */
  int (*trx_ctlsend_func)(openair0_device *device, void *msg, ssize_t msg_len);

  /*! \brief Called to receive a reply  message between RAU-RRU on control port
      @param device pointer to the device structure specific to the RF hardware target
      @param msg pointer to the message structure passed between RAU-RRU
      @param msg_len length of the message
  */
  int (*trx_ctlrecv_func)(openair0_device *device, void *msg, ssize_t msg_len);

  /*! \brief Called to send samples to the RF target
      @param device pointer to the device structure specific to the RF hardware target
      @param timestamp The timestamp at whicch the first sample MUST be sent
      @param buff Buffer which holds the samples
      @param nsamps number of samples to be sent
      @param antenna_id index of the antenna if the device has multiple anteannas
      @param flags flags must be set to TRUE if timestamp parameter needs to be applied
  */
  int (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id, int flags);

  /*! \brief Receive samples from hardware.
   * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for
   * the first channel. *ptimestamp is the time at which the first sample
   * was received.
   * \param device the hardware to use
   * \param[out] ptimestamp the time at which the first sample was received.
   * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps.
   * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte.
   * \param antenna_id Index of antenna for which to receive samples
   * \returns the number of sample read
   */
  int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int antenna_id);

  /*! \brief print the device statistics
   * \param device the hardware to use
   * \returns  0 on success
   */
  int (*trx_get_stats_func)(openair0_device *device);

  /*! \brief Reset device statistics
   * \param device the hardware to use
   * \returns 0 in success
   */
  int (*trx_reset_stats_func)(openair0_device *device);

  /*! \brief Terminate operation of the transceiver -- free all associated resources
   * \param device the hardware to use
   */
  void (*trx_end_func)(openair0_device *device);

  /*! \brief Stop operation of the transceiver
   */
  int (*trx_stop_func)(openair0_device *device);

  /* Functions API related to UE*/

  /*! \brief Set RX feaquencies
   * \param device the hardware to use
   * \param openair0_cfg RF frontend parameters set by application
   * \param exmimo_dump_config  dump EXMIMO configuration
   * \returns 0 in success
   */
  int (*trx_set_freq_func)(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config);

  /*! \brief Set gains
   * \param device the hardware to use
   * \param openair0_cfg RF frontend parameters set by application
   * \returns 0 in success
   */
  int (*trx_set_gains_func)(openair0_device *device, openair0_config_t *openair0_cfg);

  /*! \brief RRU Configuration callback
   * \param idx RU index
   * \param arg pointer to capabilities or configuration
   */
  void (*configure_rru)(int idx, void *arg);

  /*! \brief RRU Configuration callback
   * \param idx RU index
   * \param arg pointer to capabilities or configuration
   */
  int (*trx_write_init)(openair0_device *device);
  /* \brief Get internal parameter
   * \param id parameter to get
   * \return a pointer to the parameter
   */
  void *(*get_internal_parameter)(char *id);
};

openair0_config_t

/*! \brief RF frontend parameters set by application应用设定的射频前端参数 */
typedef struct {
  //! Module ID for this configuration用于此配置的模块ID
  int Mod_id;
  //! device log level设备log级
  int log_level;
  //! duplexing mode双工模式,0代表FDD,1代表TDD
  duplex_mode_t duplex_mode;
  //! number of downlink resource blocks下行资源块数量
  int num_rb_dl;
  //! number of samples per frame每帧的采样数量(与设置的采样速率有关)
  unsigned int  samples_per_frame;
  //! the sample rate for both transmit and receive.发射接收的采样速率
  double sample_rate;
  //! flag to indicate that the device is doing mmapped DMA transfers设备是否做mmap的标志
  int mmapped_dma;
  //! offset in samples between TX and RX paths发射和接收路径采样的偏置
  int tx_sample_advance;
  //! samples per packet on the fronthaul interface在前程链路接口每个包的采样数量
  int samples_per_packet;
  //! number of RX channels (=RX antennas)接收天线数量
  int rx_num_channels;
  //! number of TX channels (=TX antennas)发射天线数量
  int tx_num_channels;
  //! \brief RX base addresses for mmapped_dma接收基地址
  int32_t *rxbase[4];
  //! \brief TX base addresses for mmapped_dma发射基地址
  int32_t *txbase[4];
  //! \brief Center frequency in Hz for RX.用于接收的中心频率(设置好中心频率)
  //! index: [0..rx_num_channels[
  double rx_freq[4];
  //! \brief Center frequency in Hz for TX.用于发射的中心频率(设置好中心频率)
  //! index: [0..rx_num_channels[ !!! see lte-ue.c:427 FIXME iterates over rx_num_channels
  double tx_freq[4];
  //! \brief memory
  //! \brief Pointer to Calibration table for RX gains指向接收增益校准表的指针
  rx_gain_calib_table_t *rx_gain_calib_table;
  //! mode for rxgain (ExpressMIMO2)
  rx_gain_t rxg_mode[4];
  //! \brief Gain for RX in dB.接收增益
  //! index: [0..rx_num_channels]
  double rx_gain[4];
  //! \brief Gain offset (for calibration) in dB用于校准的接收增益偏置
  //! index: [0..rx_num_channels]
  double rx_gain_offset[4];
  //! gain for TX in dB发射增益
  double tx_gain[4];
  //! RX bandwidth in Hz接收带宽
  double rx_bw;
  //! TX bandwidth in Hz传输带宽
  double tx_bw;
  //! clock source时钟源
  clock_source_t clock_source;
  //! timing_source时间源
  clock_source_t time_source;
  //! Manual SDR IP address手动指定SDR的IP地址
  //#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
  char *sdr_addrs;
  //! Auto calibration flag自动校准标志
  int autocal[4];
  //! rf devices work with x bits iqs when oai have its own iq format当OAI有自己的IQ格式时,射频设备和xbit IQ工作
  //! the two following parameters are used to convert iqs
  int iq_txshift;//IQ传输偏移
  int iq_rxrescale;//IQ接收大小再定义
  //! Configuration file for LMS7002M
  char *configFilename;
  //! remote IP/MAC addr for Ethernet interface
  char *remote_addr;
  //! remote port number for Ethernet interface
  unsigned int remote_port;
  //! local IP/MAC addr for Ethernet interface (eNB/BBU, UE)
  char *my_addr;
  //! local port number for Ethernet interface (eNB/BBU, UE)
  unsigned int my_port;
  //! record player configuration, definition in record_player.h
  uint32_t       recplay_mode;//recplay模式
  recplay_conf_t *recplay_conf;//recplay配置
  //! number of samples per tti每个TTI的采样数量(1个TTI对应一个时隙,因为子载波间隔是可变的所以时隙的长度是可变的,但是时钟定义为14个OFDM符号的长度,一个OFDM_symbol_sized对应是FFT size么?)
  unsigned int  samples_per_tti;
  //! the sample rate for receive.接收端采样速率
  double rx_sample_rate;
  //! the sample rate for transmit.发射端采样率,采样率是对应的帧?还是子帧
  double tx_sample_rate;
  //! check for threequarter sampling rate检查3/4采样率
  int8_t threequarter_fs;
} openair0_config_t;

下面的注释没有懂,需要针对不同USRP设备设置不同的接收增益么?

  // Replay subframes from from file从文件回放子帧
  //  openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;校准表
  //  bw_gain_adjust=1;带宽增益调整

replay的文件名和循环次数:

LOG_UI(HW,"iqplayer device initialized, replay %s  for %i iterations",openair0_cfg->recplay_conf->u_sf_filename,openair0_cfg->recplay_conf->u_sf_loops);//replay的文件和循环次数

全局变量 静态全局变量 局部变量 静态局部变量 (加了static之后再本文件内都可以使用)

第一步:识别IQ文件头:

指定回放设备类型和带宽
eg:
FRCI_QData100M.bin
usrp_samples.dat

第二步:加载IQ文件
mmap?
用mmap从xxx加载子帧 文件名为u_sf_filename大小为st_size
iqrec_t结构体包含 头部、时间戳、rfu1、rfu2、
unsigned char samples[BELL_LABS_IQ_BYTES_PER_SF]

typedef struct {
  int64_t       header;//头部
  int64_t       ts;//时间戳
  int64_t       rfu1;
  int64_t       rfu2; // pad for 256 bits alignement required by AVX2
  unsigned char samples[BELL_LABS_IQ_BYTES_PER_SF]; // iq's for one subframe贝尔实验室每个子帧的IQ采样,4个字节,2字节对应int16,2字节i与2字节q
} iqrec_t;//iq 记录器类型
#define    OAIIQFILE_ID "OIQF"//oai IQ文件ID
typedef struct {
  uint64_t      devtype;//设备类型 B2XX
  uint64_t      tx_sample_advance;//发射采样提前
  double        bw;//带宽 5M
  char          oaiid[4];//oai ID用4字节存储
} iqfile_header_t;//iq文件头类型

typedef struct {
  int64_t       header;//头部
  int64_t       ts;//时间戳
  int64_t       rfu1;
  int64_t       rfu2; // pad for 256 bits alignement required by AVX2
  unsigned char samples[BELL_LABS_IQ_BYTES_PER_SF]; // iq's for one subframe贝尔实验室每个子帧的IQ采样,4个字节,2字节对应int16,2字节i与2字节q
} iqrec_t;//iq 记录器类型
#define DEF_NB_SF           120000               // default nb of sf or ms to capture (2 minutes at 5MHz)
#define DEF_SF_FILE         "/tmp/iqfile"        // default subframes file name
#define DEF_SF_DELAY_READ   700                  // default read delay  碌s (860=real)
#define DEF_SF_DELAY_WRITE  15                   // default write delay 碌s (15=real)
#define DEF_SF_NB_LOOP      5                    // default nb loops

加载每ms的采样数量:

parse_iqfile_header(device, (iqfile_header_t *)mptr);
        s->ms_sample = (iqrec_t *)((char *)mptr + sizeof(iqfile_header_t));//每ms的采样
        s->nb_samples = ((sb.st_size-sizeof(iqfile_header_t)) / sizeof(iqrec_t));//不算IQ文件头部的有效采样
        int aligned = (((unsigned long)s->ms_sample & 31) == 0)? 1:0;//是否进行了32位对齐
LOG_I(HW,"Loaded %u subframes.\n",s->nb_samples );//加载采样数量的子帧

需要与mmap地址保持32位对齐,如果映射设备则退出。
第三步:IQ文件定义
跳过头部处理数据

第四步:启动OAI IQ player
第五步:终止OAI IQ player

第六步:replay模式下写入IQ时,写IQ,引入一个时延
第七步:从IQ文件接收样本,读IQ

One sample is 2 byte I + 2 byte Q => 4 byte
这段代码是用来加载一个名为 Octree_python_lib.so 的动态链接库,并定义了一些函数接口和函数参数的类型。下面是对每个定义的函数接口和参数类型的解释: - c_double_p: 定义了一个指向 double 类型的指针。 - c_uint16_p: 定义了一个指向 uint16 类型的指针。 - lib = cdll.LoadLibrary(os.path.dirname(os.path.abspath(__file__))+'/Octree_python_lib.so'): 加载 Octree_python_lib.so 动态链接库,并将其赋值给 lib 变量。 - lib.new_vector: 函数接口,返回类型为 c_void_p,无参数。 - lib.delete_vector: 函数接口,返回类型为 None,参数为 c_void_p。 - lib.vector_size: 函数接口,返回类型为 c_int,参数为 c_void_p。 - lib.vector_get: 函数接口,返回类型为 c_void_p,参数为 c_void_p 和 c_int。 - lib.vector_push_back: 函数接口,返回类型为 None,参数为 c_void_p 和 c_int。 - lib.genOctreeInterface: 函数接口,返回类型为 c_void_p,参数为 c_void_p、c_double_p 和 c_int。 - lib.Nodes_get: 函数接口,返回类型为指向 Node 类型的指针 (POINTER(Node)),参数为 c_void_p 和 c_int。 - lib.Nodes_size: 函数接口,返回类型为 c_int,参数为 c_void_p。 - lib.int_size: 函数接口,返回类型为 c_int,参数为 c_void_p。 - lib.int_get: 函数接口,返回类型为 c_int,参数为 c_void_p 和 c_int。 这些函数接口的具体功能需要根据实际的动态链接库 Octree_python_lib.so 来确定。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值