mirror of https://github.com/PentHertz/srsLTE.git
Initial NR PDSCH CSI-RS RE skip and other changes
This commit is contained in:
parent
5bc55ec48c
commit
5bdf2c93b3
|
@ -161,6 +161,63 @@ struct phy_cfg_nr_t {
|
|||
pdcch.search_space[2].nof_candidates[4] = 0;
|
||||
pdcch.search_space[2].type = srsran_search_space_type_ue;
|
||||
pdcch.search_space_present[2] = true;
|
||||
// pdsch-Config: setup (1)
|
||||
// setup
|
||||
// dmrs-DownlinkForPDSCH-MappingTypeA: setup (1)
|
||||
// setup
|
||||
// dmrs-AdditionalPosition: pos1 (1)
|
||||
// tci-StatesToAddModList: 1 item
|
||||
// Item 0
|
||||
// TCI-State
|
||||
// tci-StateId: 0
|
||||
// qcl-Type1
|
||||
// referenceSignal: ssb (1)
|
||||
// ssb: 0
|
||||
// qcl-Type: typeD (3)
|
||||
// resourceAllocation: resourceAllocationType1 (1)
|
||||
// rbg-Size: config1 (0)
|
||||
// prb-BundlingType: staticBundling (0)
|
||||
// staticBundling
|
||||
// bundleSize: wideband (1)
|
||||
// zp-CSI-RS-ResourceToAddModList: 1 item
|
||||
// Item 0
|
||||
// ZP-CSI-RS-Resource
|
||||
// zp-CSI-RS-ResourceId: 0
|
||||
// resourceMapping
|
||||
// frequencyDomainAllocation: row4 (2)
|
||||
// row4: 80 [bit length 3, 5 LSB pad bits, 100. ....
|
||||
// decimal value 4]
|
||||
// nrofPorts: p4 (2)
|
||||
// firstOFDMSymbolInTimeDomain: 8
|
||||
// cdm-Type: fd-CDM2 (1)
|
||||
// density: one (1)
|
||||
// one: NULL
|
||||
// freqBand
|
||||
// startingRB: 0
|
||||
// nrofRBs: 52
|
||||
// periodicityAndOffset: slots80 (9)
|
||||
// slots80: 1
|
||||
// p-ZP-CSI-RS-ResourceSet: setup (1)
|
||||
// setup
|
||||
// zp-CSI-RS-ResourceSetId: 0
|
||||
// zp-CSI-RS-ResourceIdList: 1 item
|
||||
// Item 0
|
||||
// ZP-CSI-RS-ResourceId: 0
|
||||
srsran_csi_rs_zp_resource_t zp_csi_rs_resource0 = {};
|
||||
zp_csi_rs_resource0.resource_mapping.row = srsran_csi_rs_resource_mapping_row_4;
|
||||
zp_csi_rs_resource0.resource_mapping.frequency_domain_alloc[0] = true;
|
||||
zp_csi_rs_resource0.resource_mapping.frequency_domain_alloc[1] = false;
|
||||
zp_csi_rs_resource0.resource_mapping.frequency_domain_alloc[2] = false;
|
||||
zp_csi_rs_resource0.resource_mapping.nof_ports = 4;
|
||||
zp_csi_rs_resource0.resource_mapping.first_symbol_idx = 8;
|
||||
zp_csi_rs_resource0.resource_mapping.cdm = srsran_csi_rs_cdm_fd_cdm2;
|
||||
zp_csi_rs_resource0.resource_mapping.density = srsran_csi_rs_resource_mapping_density_one;
|
||||
zp_csi_rs_resource0.resource_mapping.freq_band.start_rb = 0;
|
||||
zp_csi_rs_resource0.resource_mapping.freq_band.nof_rb = 52;
|
||||
zp_csi_rs_resource0.periodicity.period = 80;
|
||||
zp_csi_rs_resource0.periodicity.offset = 1;
|
||||
pdsch.p_zp_csi_rs_set.data[0] = zp_csi_rs_resource0;
|
||||
pdsch.p_zp_csi_rs_set.count = 1;
|
||||
|
||||
// pdsch-ConfigCommon: setup (1)
|
||||
// setup
|
||||
|
@ -648,6 +705,230 @@ struct phy_cfg_nr_t {
|
|||
harq_ack.dl_data_to_ul_ack[6] = 11;
|
||||
harq_ack.nof_dl_data_to_ul_ack = 7;
|
||||
|
||||
// nzp-CSI-RS-ResourceToAddModList: 5 items
|
||||
// Item 0
|
||||
// NZP-CSI-RS-Resource
|
||||
// nzp-CSI-RS-ResourceId: 0
|
||||
// resourceMapping
|
||||
// frequencyDomainAllocation: row2 (1)
|
||||
// row2: 8000 [bit length 12, 4 LSB pad bits, 1000 0000 0000 .... decimal value 2048]
|
||||
// nrofPorts: p1 (0)
|
||||
// firstOFDMSymbolInTimeDomain: 4
|
||||
// cdm-Type: noCDM (0)
|
||||
// density: one (1)
|
||||
// one: NULL
|
||||
// freqBand
|
||||
// startingRB: 0
|
||||
// nrofRBs: 52
|
||||
// powerControlOffset: 0dB
|
||||
// powerControlOffsetSS: db0 (1)
|
||||
// scramblingID: 0
|
||||
// periodicityAndOffset: slots80 (9)
|
||||
// slots80: 1
|
||||
// qcl-InfoPeriodicCSI-RS: 0
|
||||
srsran_csi_rs_nzp_resource_t nzp_resource_0 = {};
|
||||
nzp_resource_0.resource_mapping.row = srsran_csi_rs_resource_mapping_row_2;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[0] = true;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[1] = false;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[2] = false;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[3] = false;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[4] = false;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[5] = false;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[6] = false;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[7] = false;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[8] = false;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[9] = false;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[10] = false;
|
||||
nzp_resource_0.resource_mapping.frequency_domain_alloc[11] = false;
|
||||
nzp_resource_0.resource_mapping.nof_ports = 1;
|
||||
nzp_resource_0.resource_mapping.first_symbol_idx = 4;
|
||||
nzp_resource_0.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm;
|
||||
nzp_resource_0.resource_mapping.density = srsran_csi_rs_resource_mapping_density_one;
|
||||
nzp_resource_0.resource_mapping.freq_band.start_rb = 0;
|
||||
nzp_resource_0.resource_mapping.freq_band.nof_rb = 52;
|
||||
nzp_resource_0.power_control_offset = 0;
|
||||
nzp_resource_0.power_control_offset_ss = 0;
|
||||
nzp_resource_0.scrambling_id = 0;
|
||||
nzp_resource_0.periodicity.period = 80;
|
||||
nzp_resource_0.periodicity.offset = 1;
|
||||
|
||||
// Item 1
|
||||
// NZP-CSI-RS-Resource
|
||||
// nzp-CSI-RS-ResourceId: 1
|
||||
// resourceMapping
|
||||
// frequencyDomainAllocation: row1 (0)
|
||||
// row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal value 1]
|
||||
// nrofPorts: p1 (0)
|
||||
// firstOFDMSymbolInTimeDomain: 4
|
||||
// cdm-Type: noCDM (0)
|
||||
// density: three (2)
|
||||
// three: NULL
|
||||
// freqBand
|
||||
// startingRB: 0
|
||||
// nrofRBs: 52
|
||||
// powerControlOffset: 0dB
|
||||
// powerControlOffsetSS: db0 (1)
|
||||
// scramblingID: 0
|
||||
// periodicityAndOffset: slots40 (7)
|
||||
// slots40: 11
|
||||
// qcl-InfoPeriodicCSI-RS: 0
|
||||
srsran_csi_rs_nzp_resource_t nzp_resource_1 = {};
|
||||
nzp_resource_1.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1;
|
||||
nzp_resource_1.resource_mapping.frequency_domain_alloc[0] = false;
|
||||
nzp_resource_1.resource_mapping.frequency_domain_alloc[1] = false;
|
||||
nzp_resource_1.resource_mapping.frequency_domain_alloc[2] = false;
|
||||
nzp_resource_1.resource_mapping.frequency_domain_alloc[3] = true;
|
||||
nzp_resource_1.resource_mapping.nof_ports = 1;
|
||||
nzp_resource_1.resource_mapping.first_symbol_idx = 4;
|
||||
nzp_resource_1.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm;
|
||||
nzp_resource_1.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three;
|
||||
nzp_resource_1.resource_mapping.freq_band.start_rb = 0;
|
||||
nzp_resource_1.resource_mapping.freq_band.nof_rb = 52;
|
||||
nzp_resource_1.power_control_offset = 0;
|
||||
nzp_resource_1.power_control_offset_ss = 0;
|
||||
nzp_resource_1.scrambling_id = 0;
|
||||
nzp_resource_1.periodicity.period = 40;
|
||||
nzp_resource_1.periodicity.offset = 11;
|
||||
// Item 2
|
||||
// NZP-CSI-RS-Resource
|
||||
// nzp-CSI-RS-ResourceId: 2
|
||||
// resourceMapping
|
||||
// frequencyDomainAllocation: row1 (0)
|
||||
// row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal value 1]
|
||||
// nrofPorts: p1 (0)
|
||||
// firstOFDMSymbolInTimeDomain: 8
|
||||
// cdm-Type: noCDM (0)
|
||||
// density: three (2)
|
||||
// three: NULL
|
||||
// freqBand
|
||||
// startingRB: 0
|
||||
// nrofRBs: 52
|
||||
// powerControlOffset: 0dB
|
||||
// powerControlOffsetSS: db0 (1)
|
||||
// scramblingID: 0
|
||||
// periodicityAndOffset: slots40 (7)
|
||||
// slots40: 11
|
||||
// qcl-InfoPeriodicCSI-RS: 0
|
||||
srsran_csi_rs_nzp_resource_t nzp_resource_2 = {};
|
||||
nzp_resource_2.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1;
|
||||
nzp_resource_2.resource_mapping.frequency_domain_alloc[0] = false;
|
||||
nzp_resource_2.resource_mapping.frequency_domain_alloc[1] = false;
|
||||
nzp_resource_2.resource_mapping.frequency_domain_alloc[2] = false;
|
||||
nzp_resource_2.resource_mapping.frequency_domain_alloc[3] = true;
|
||||
nzp_resource_2.resource_mapping.nof_ports = 1;
|
||||
nzp_resource_2.resource_mapping.first_symbol_idx = 8;
|
||||
nzp_resource_2.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm;
|
||||
nzp_resource_2.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three;
|
||||
nzp_resource_2.resource_mapping.freq_band.start_rb = 0;
|
||||
nzp_resource_2.resource_mapping.freq_band.nof_rb = 52;
|
||||
nzp_resource_2.power_control_offset = 0;
|
||||
nzp_resource_2.power_control_offset_ss = 0;
|
||||
nzp_resource_2.scrambling_id = 0;
|
||||
nzp_resource_2.periodicity.period = 40;
|
||||
nzp_resource_2.periodicity.offset = 11;
|
||||
// Item 3
|
||||
// NZP-CSI-RS-Resource
|
||||
// nzp-CSI-RS-ResourceId: 3
|
||||
// resourceMapping
|
||||
// frequencyDomainAllocation: row1 (0)
|
||||
// row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal value 1]
|
||||
// nrofPorts: p1 (0)
|
||||
// firstOFDMSymbolInTimeDomain: 4
|
||||
// cdm-Type: noCDM (0)
|
||||
// density: three (2)
|
||||
// three: NULL
|
||||
// freqBand
|
||||
// startingRB: 0
|
||||
// nrofRBs: 52
|
||||
// powerControlOffset: 0dB
|
||||
// powerControlOffsetSS: db0 (1)
|
||||
// scramblingID: 0
|
||||
// periodicityAndOffset: slots40 (7)
|
||||
// slots40: 12
|
||||
// qcl-InfoPeriodicCSI-RS: 0
|
||||
srsran_csi_rs_nzp_resource_t nzp_resource_3 = {};
|
||||
nzp_resource_3.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1;
|
||||
nzp_resource_3.resource_mapping.frequency_domain_alloc[0] = false;
|
||||
nzp_resource_3.resource_mapping.frequency_domain_alloc[1] = false;
|
||||
nzp_resource_3.resource_mapping.frequency_domain_alloc[2] = false;
|
||||
nzp_resource_3.resource_mapping.frequency_domain_alloc[3] = true;
|
||||
nzp_resource_3.resource_mapping.nof_ports = 1;
|
||||
nzp_resource_3.resource_mapping.first_symbol_idx = 4;
|
||||
nzp_resource_3.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm;
|
||||
nzp_resource_3.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three;
|
||||
nzp_resource_3.resource_mapping.freq_band.start_rb = 0;
|
||||
nzp_resource_3.resource_mapping.freq_band.nof_rb = 52;
|
||||
nzp_resource_3.power_control_offset = 0;
|
||||
nzp_resource_3.power_control_offset_ss = 0;
|
||||
nzp_resource_3.scrambling_id = 0;
|
||||
nzp_resource_3.periodicity.period = 40;
|
||||
nzp_resource_3.periodicity.offset = 12;
|
||||
// Item 4
|
||||
// NZP-CSI-RS-Resource
|
||||
// nzp-CSI-RS-ResourceId: 4
|
||||
// resourceMapping
|
||||
// frequencyDomainAllocation: row1 (0)
|
||||
// row1: 10 [bit length 4, 4 LSB pad bits, 0001 .... decimal value 1]
|
||||
// nrofPorts: p1 (0)
|
||||
// firstOFDMSymbolInTimeDomain: 8
|
||||
// cdm-Type: noCDM (0)
|
||||
// density: three (2)
|
||||
// three: NULL
|
||||
// freqBand
|
||||
// startingRB: 0
|
||||
// nrofRBs: 52
|
||||
// powerControlOffset: 0dB
|
||||
// powerControlOffsetSS: db0 (1)
|
||||
// scramblingID: 0
|
||||
// periodicityAndOffset: slots40 (7)
|
||||
// slots40: 12
|
||||
// qcl-InfoPeriodicCSI-RS: 0
|
||||
srsran_csi_rs_nzp_resource_t nzp_resource_4 = {};
|
||||
nzp_resource_4.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1;
|
||||
nzp_resource_4.resource_mapping.frequency_domain_alloc[0] = false;
|
||||
nzp_resource_4.resource_mapping.frequency_domain_alloc[1] = false;
|
||||
nzp_resource_4.resource_mapping.frequency_domain_alloc[2] = false;
|
||||
nzp_resource_4.resource_mapping.frequency_domain_alloc[3] = true;
|
||||
nzp_resource_4.resource_mapping.nof_ports = 1;
|
||||
nzp_resource_4.resource_mapping.first_symbol_idx = 8;
|
||||
nzp_resource_4.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm;
|
||||
nzp_resource_4.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three;
|
||||
nzp_resource_4.resource_mapping.freq_band.start_rb = 0;
|
||||
nzp_resource_4.resource_mapping.freq_band.nof_rb = 52;
|
||||
nzp_resource_4.power_control_offset = 0;
|
||||
nzp_resource_4.power_control_offset_ss = 0;
|
||||
nzp_resource_4.scrambling_id = 0;
|
||||
nzp_resource_4.periodicity.period = 40;
|
||||
nzp_resource_4.periodicity.offset = 12;
|
||||
// zp-CSI-RS-ResourceSetToAddModList: 2 items
|
||||
// Item 0
|
||||
// NZP-CSI-RS-ResourceSet
|
||||
// nzp-CSI-ResourceSetId: 0
|
||||
// nzp-CSI-RS-Resources: 1 item
|
||||
// Item 0
|
||||
// NZP-CSI-RS-ResourceId: 0
|
||||
pdsch.nzp_csi_rs_sets[0].data[0] = nzp_resource_0;
|
||||
pdsch.nzp_csi_rs_sets[0].count = 1;
|
||||
pdsch.nzp_csi_rs_sets[0].trs_info = false;
|
||||
// Item 1
|
||||
// NZP-CSI-RS-ResourceSet
|
||||
// nzp-CSI-ResourceSetId: 1
|
||||
// nzp-CSI-RS-Resources: 4 items
|
||||
// Item 0
|
||||
// NZP-CSI-RS-ResourceId: 1
|
||||
// Item 1
|
||||
// NZP-CSI-RS-ResourceId: 2
|
||||
// Item 2
|
||||
// NZP-CSI-RS-ResourceId: 3
|
||||
// Item 3
|
||||
// NZP-CSI-RS-ResourceId: 4
|
||||
// trs-Info: true (0)
|
||||
pdsch.nzp_csi_rs_sets[1].data[0] = nzp_resource_1;
|
||||
pdsch.nzp_csi_rs_sets[1].data[1] = nzp_resource_2;
|
||||
pdsch.nzp_csi_rs_sets[1].data[2] = nzp_resource_3;
|
||||
pdsch.nzp_csi_rs_sets[1].data[3] = nzp_resource_4;
|
||||
pdsch.nzp_csi_rs_sets[1].count = 4;
|
||||
pdsch.nzp_csi_rs_sets[1].trs_info = true;
|
||||
// csi-ReportConfigToAddModList: 1 item
|
||||
// Item 0
|
||||
// CSI-ReportConfig
|
||||
|
|
|
@ -13,95 +13,35 @@
|
|||
#ifndef SRSRAN_CSI_RS_H_
|
||||
#define SRSRAN_CSI_RS_H_
|
||||
|
||||
#include "srsran/config.h"
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
#include "csi_rs_cfg.h"
|
||||
#include "srsran/phy/phch/phch_cfg_nr.h"
|
||||
#include <complex.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Number of frequency domain elements for Row 1
|
||||
*/
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW1 4
|
||||
|
||||
/**
|
||||
* @brief Number of frequency domain elements for Row 2
|
||||
*/
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW2 12
|
||||
|
||||
/**
|
||||
* @brief Number of frequency domain elements for Row 4
|
||||
*/
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW4 3
|
||||
|
||||
/**
|
||||
* @brief Number of frequency domain elements for other rows
|
||||
*/
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_OTHER 6
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_MAX 12
|
||||
|
||||
typedef enum SRSRAN_API {
|
||||
srsran_csi_rs_resource_mapping_row_1 = 0,
|
||||
srsran_csi_rs_resource_mapping_row_2,
|
||||
srsran_csi_rs_resource_mapping_row_4,
|
||||
srsran_csi_rs_resource_mapping_row_other,
|
||||
} srsran_csi_rs_resource_mapping_row_t;
|
||||
|
||||
typedef enum SRSRAN_API {
|
||||
srsran_csi_rs_resource_mapping_density_three = 0,
|
||||
srsran_csi_rs_resource_mapping_density_dot5_even,
|
||||
srsran_csi_rs_resource_mapping_density_dot5_odd,
|
||||
srsran_csi_rs_resource_mapping_density_one,
|
||||
srsran_csi_rs_resource_mapping_density_spare
|
||||
} srsran_csi_rs_density_t;
|
||||
|
||||
typedef enum SRSRAN_API {
|
||||
srsran_csi_rs_cdm_nocdm = 0,
|
||||
srsran_csi_rs_cdm_fd_cdm2,
|
||||
srsran_csi_rs_cdm_cdm4_fd2_td2,
|
||||
srsran_csi_rs_cdm_cdm8_fd2_td4
|
||||
} srsran_csi_rs_cdm_t;
|
||||
|
||||
/**
|
||||
* @brief Contains CSI-FrequencyOccupation flattened configuration
|
||||
* @brief Measurement structure
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
uint32_t start_rb; ///< PRB where this CSI resource starts in relation to common resource block #0 (CRB#0) on the
|
||||
///< common resource block grid. Only multiples of 4 are allowed (0, 4, ..., 274)
|
||||
|
||||
uint32_t nof_rb; ///< Number of PRBs across which this CSI resource spans. Only multiples of 4 are allowed. The
|
||||
///< smallest configurable number is the minimum of 24 and the width of the associated BWP. If the
|
||||
///< configured value is larger than the width of the corresponding BWP, the UE shall assume that the
|
||||
///< actual CSI-RS bandwidth is equal to the width of the BWP.
|
||||
} srsran_csi_rs_freq_occupation_t;
|
||||
|
||||
/**
|
||||
* @brief Contains CSI-ResourcePeriodicityAndOffset flattened configuration
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
uint32_t period; // 4,5,8,10,16,20,32,40,64,80,160,320,640
|
||||
uint32_t offset; // 0..period-1
|
||||
} srsran_csi_rs_period_and_offset_t;
|
||||
|
||||
/**
|
||||
* @brief Contains CSI-RS-ResourceMapping flattened configuration
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_csi_rs_resource_mapping_row_t row;
|
||||
bool frequency_domain_alloc[SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_MAX];
|
||||
uint32_t ports; // 1, 2, 4, 8, 12, 16, 24, 32
|
||||
uint32_t first_symbol_idx; // 0..13
|
||||
uint32_t first_symbol_idx2; // 2..12 (set to 0 for disabled)
|
||||
srsran_csi_rs_cdm_t cdm;
|
||||
srsran_csi_rs_density_t density;
|
||||
srsran_csi_rs_freq_occupation_t freq_band;
|
||||
} srsran_csi_rs_resource_mapping_t;
|
||||
|
||||
/**
|
||||
* @brief Contains NZP-CSI-RS-Resource flattened configuration
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_csi_rs_resource_mapping_t resource_mapping;
|
||||
|
||||
float power_control_offset; // -8..15 dB
|
||||
float power_control_offset_ss; // -3, 0, 3, 6 dB
|
||||
|
||||
uint32_t scrambling_id; // 0..1023
|
||||
|
||||
srsran_csi_rs_period_and_offset_t periodicity;
|
||||
|
||||
} srsran_csi_rs_nzp_resource_t;
|
||||
|
||||
SRSRAN_API int srsran_csi_rs_nzp_put(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_nzp_resource_t* resource,
|
||||
cf_t* grid);
|
||||
|
||||
typedef struct SRSRAN_API {
|
||||
float rsrp;
|
||||
float rsrp_dB;
|
||||
|
@ -113,6 +53,35 @@ typedef struct SRSRAN_API {
|
|||
uint32_t nof_re;
|
||||
} srsran_csi_rs_measure_t;
|
||||
|
||||
/**
|
||||
* @brief Calculates if the given periodicity implies a CSI-RS transmission in the given slot
|
||||
* @remark Described in TS 36.211 section 7.4.1.5.3 Mapping to physical resources
|
||||
* @param periodicity Periodicity configuration
|
||||
* @param slot_cfg Slot configuration
|
||||
* @return True if the periodicity configuration matches with the slot, false otherwise
|
||||
*/
|
||||
SRSRAN_API bool srsran_csi_rs_send(const srsran_csi_rs_period_and_offset_t* periodicity,
|
||||
const srsran_slot_cfg_t* slot_cfg);
|
||||
|
||||
/**
|
||||
* @brief Adds to a RE pattern list the RE used in a CSI-RS resource for all CDM grops. This is intended for generating
|
||||
* reserved RE pattern for PDSCH transmission.
|
||||
* @param carrier Provides carrier configuration
|
||||
* @param resource Provides a CSI-RS resource
|
||||
* @param nof_resources Provides the number of ZP-CSI-RS resources
|
||||
* @param l Symbol index in the slot
|
||||
* @param[out] rvd_mask Provides the reserved mask
|
||||
* @return SRSRAN_SUCCESS if the provided data is valid, and SRSRAN_ERROR code otherwise
|
||||
*/
|
||||
SRSRAN_API int srsran_csi_rs_append_resource_to_pattern(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_csi_rs_resource_mapping_t* resource,
|
||||
srsran_re_pattern_list_t* re_pattern_list);
|
||||
|
||||
SRSRAN_API int srsran_csi_rs_nzp_put(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_nzp_resource_t* resource,
|
||||
cf_t* grid);
|
||||
|
||||
SRSRAN_API int srsran_csi_rs_nzp_measure(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_nzp_resource_t* resource,
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_CSI_RS_CFG_H
|
||||
#define SRSRAN_CSI_RS_CFG_H
|
||||
|
||||
#include "srsran/config.h"
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
|
||||
/**
|
||||
* @brief Maximum number of ZP CSI-RS resources per set defined in
|
||||
* - TS 38.214 clause 5.1.4.2 PDSCH resource mapping with RE level granularity
|
||||
* - TS 38.331 constant maxNrofZP-CSI-RS-ResourcesPerSet
|
||||
*/
|
||||
#define SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_PER_SET 16
|
||||
|
||||
/**
|
||||
* @brief Maximum number of ZP CSI-RS Sets defined in TS 38.331 constant maxNrofZP-CSI-RS-ResourceSets
|
||||
*/
|
||||
#define SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_SETS 16
|
||||
|
||||
/**
|
||||
* @brief Maximum number of CSI-RS frequency domain allocation bits
|
||||
*/
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_MAX 12
|
||||
|
||||
typedef enum SRSRAN_API {
|
||||
srsran_csi_rs_resource_mapping_row_1 = 0,
|
||||
srsran_csi_rs_resource_mapping_row_2,
|
||||
srsran_csi_rs_resource_mapping_row_4,
|
||||
srsran_csi_rs_resource_mapping_row_other,
|
||||
} srsran_csi_rs_resource_mapping_row_t;
|
||||
|
||||
typedef enum SRSRAN_API {
|
||||
srsran_csi_rs_resource_mapping_density_three = 0,
|
||||
srsran_csi_rs_resource_mapping_density_dot5_even,
|
||||
srsran_csi_rs_resource_mapping_density_dot5_odd,
|
||||
srsran_csi_rs_resource_mapping_density_one,
|
||||
srsran_csi_rs_resource_mapping_density_spare
|
||||
} srsran_csi_rs_density_t;
|
||||
|
||||
typedef enum SRSRAN_API {
|
||||
srsran_csi_rs_cdm_nocdm = 0,
|
||||
srsran_csi_rs_cdm_fd_cdm2,
|
||||
srsran_csi_rs_cdm_cdm4_fd2_td2,
|
||||
srsran_csi_rs_cdm_cdm8_fd2_td4
|
||||
} srsran_csi_rs_cdm_t;
|
||||
|
||||
/**
|
||||
* @brief Contains CSI-FrequencyOccupation flattened configuration
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
uint32_t start_rb; ///< PRB where this CSI resource starts in relation to common resource block #0 (CRB#0) on the
|
||||
///< common resource block grid. Only multiples of 4 are allowed (0, 4, ..., 274)
|
||||
|
||||
uint32_t nof_rb; ///< Number of PRBs across which this CSI resource spans. Only multiples of 4 are allowed. The
|
||||
///< smallest configurable number is the minimum of 24 and the width of the associated BWP. If the
|
||||
///< configured value is larger than the width of the corresponding BWP, the UE shall assume that the
|
||||
///< actual CSI-RS bandwidth is equal to the width of the BWP.
|
||||
} srsran_csi_rs_freq_occupation_t;
|
||||
|
||||
/**
|
||||
* @brief Contains CSI-ResourcePeriodicityAndOffset flattened configuration
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
uint32_t period; // 4,5,8,10,16,20,32,40,64,80,160,320,640
|
||||
uint32_t offset; // 0..period-1
|
||||
} srsran_csi_rs_period_and_offset_t;
|
||||
|
||||
/**
|
||||
* @brief Contains CSI-RS-ResourceMapping flattened configuration
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_csi_rs_resource_mapping_row_t row;
|
||||
bool frequency_domain_alloc[SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_MAX];
|
||||
uint32_t nof_ports; // 1, 2, 4, 8, 12, 16, 24, 32
|
||||
uint32_t first_symbol_idx; // 0..13
|
||||
uint32_t first_symbol_idx2; // 2..12 (set to 0 for disabled)
|
||||
srsran_csi_rs_cdm_t cdm;
|
||||
srsran_csi_rs_density_t density;
|
||||
srsran_csi_rs_freq_occupation_t freq_band;
|
||||
} srsran_csi_rs_resource_mapping_t;
|
||||
|
||||
/**
|
||||
* @brief Contains TS 38.331 NZP-CSI-RS-Resource flattened configuration
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_csi_rs_resource_mapping_t resource_mapping; ///< CSI-RS time/frequency mapping
|
||||
float power_control_offset; ///< -8..15 dB
|
||||
float power_control_offset_ss; ///< -3, 0, 3, 6 dB
|
||||
uint32_t scrambling_id; ///< 0..1023
|
||||
srsran_csi_rs_period_and_offset_t periodicity; ///< Periodicity
|
||||
} srsran_csi_rs_nzp_resource_t;
|
||||
|
||||
/**
|
||||
* @brief Non-Zero-Power CSI resource set
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_csi_rs_nzp_resource_t data[SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_PER_SET]; ///< Resources
|
||||
uint32_t count; ///< Set to zero for not present
|
||||
bool trs_info; ///< Indicates that the antenna port for all NZP-CSI-RS resources in the CSI-RS resource set is same.
|
||||
} srsran_csi_rs_nzp_set_t;
|
||||
|
||||
/**
|
||||
* @brief Contains TS 38.331 ZP-CSI-RS-Resource flattened configuration
|
||||
*/
|
||||
typedef struct {
|
||||
srsran_csi_rs_resource_mapping_t resource_mapping; ///< CSI-RS time/frequency mapping
|
||||
srsran_csi_rs_period_and_offset_t periodicity;
|
||||
} srsran_csi_rs_zp_resource_t;
|
||||
|
||||
/**
|
||||
* @brief Zero-Power CSI resource set
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_csi_rs_zp_resource_t data[SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_PER_SET]; ///< Resources
|
||||
uint32_t count; ///< Number of resources in the set
|
||||
} srsran_csi_rs_zp_set_t;
|
||||
|
||||
#endif // SRSRAN_CSI_RS_CFG_H
|
|
@ -63,15 +63,14 @@ SRSRAN_API int srsran_dmrs_sch_get_symbols_idx(const srsran_dmrs_sch_cfg_t* dmrs
|
|||
uint32_t symbols_idx[SRSRAN_DMRS_SCH_MAX_SYMBOLS]);
|
||||
|
||||
/**
|
||||
* @brief Computes the sub-carrier indexes carrying DMRS
|
||||
*
|
||||
* @brief Computes the resource element pattern of resource elements reserved for DMRS
|
||||
* @param cfg PDSCH DMRS configuration provided by upper layers
|
||||
* @param max_count is the number of sub-carriers to generate
|
||||
* @param sc_idx is the destination pointer where the sub-carrier indexes are stored
|
||||
*
|
||||
* @return It returns the number of sub-carriers if inputs are valid, otherwise, it returns SRSRAN_ERROR code.
|
||||
* @param[out] pattern Provides the RE pattern to fill
|
||||
* @return SRSRAN_SUCCESS if computation is successful, SRSRAN_ERROR code otherwise
|
||||
*/
|
||||
SRSRAN_API int srsran_dmrs_sch_get_sc_idx(const srsran_dmrs_sch_cfg_t* cfg, uint32_t max_count, uint32_t* sc_idx);
|
||||
SRSRAN_API int srsran_dmrs_sch_rvd_re_pattern(const srsran_dmrs_sch_cfg_t* cfg,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
srsran_re_pattern_t* pattern);
|
||||
|
||||
/**
|
||||
* @brief Calculates the number of resource elements taken by a PDSCH-DMRS for a given PDSCH transmission
|
||||
|
@ -143,8 +142,8 @@ SRSRAN_API int srsran_dmrs_sch_put_sf(srsran_dmrs_sch_t* q,
|
|||
* @attention Current implementation supports only type1 PDSCH DMRS (1 pilot every 2 RE)
|
||||
*
|
||||
* @param q DMRS-PDSCH object
|
||||
* @param slot_cfg Slot configuration
|
||||
* @param pdsch_cfg PDSCH configuration provided by upper layers
|
||||
* @param slot Slot configuration
|
||||
* @param cfg PDSCH configuration provided by upper layers
|
||||
* @param grant PDSCH information provided by a DCI
|
||||
* @param sf_symbols Received resource grid
|
||||
* @param[out] ce Channel estimates
|
||||
|
@ -152,8 +151,8 @@ SRSRAN_API int srsran_dmrs_sch_put_sf(srsran_dmrs_sch_t* q,
|
|||
* @return it returns SRSRAN_ERROR code if an error occurs, otherwise it returns SRSRAN_SUCCESS
|
||||
*/
|
||||
SRSRAN_API int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_sch_cfg_nr_t* pdsch_cfg,
|
||||
const srsran_slot_cfg_t* slot,
|
||||
const srsran_sch_cfg_nr_t* cfg,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
const cf_t* sf_symbols,
|
||||
srsran_chest_dl_res_t* chest_res);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
* @brief Maximum number of CSI-RS resources defined in TS 38.331 maxNrofCSI-ResourceConfigurations
|
||||
*/
|
||||
#define SRSRAN_CSI_MAX_NOF_RESOURCES 112
|
||||
|
||||
/**
|
||||
* @brief CSI report types defined in TS 38.331 CSI-ReportConfig
|
||||
*/
|
||||
|
|
|
@ -55,6 +55,8 @@ typedef struct SRSRAN_API {
|
|||
srsran_evm_buffer_t* evm_buffer;
|
||||
bool meas_time_en;
|
||||
uint32_t meas_time_us;
|
||||
srsran_re_pattern_t dmrs_re_pattern;
|
||||
uint32_t nof_rvd_re;
|
||||
} srsran_pdsch_nr_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,9 +21,17 @@
|
|||
#ifndef SRSRAN_PHCH_CFG_NR_H
|
||||
#define SRSRAN_PHCH_CFG_NR_H
|
||||
|
||||
#include "srsran/phy/ch_estimation/csi_rs_cfg.h"
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
#include "srsran/phy/phch/sch_cfg_nr.h"
|
||||
#include "srsran/phy/phch/uci_cfg_nr.h"
|
||||
#include "srsran/phy/utils/re_pattern.h"
|
||||
|
||||
/**
|
||||
* @brief Specifies the maximum number of ZP-CSI-RS resources configured per slot. It is not implicitly specified in the
|
||||
* TS.
|
||||
*/
|
||||
#define SRSRAN_PHCH_CFG_MAX_NOF_ZP_CSI_RS_RES_PER_SLOT 16
|
||||
|
||||
/**
|
||||
* @brief PDSCH DMRS type
|
||||
|
@ -203,6 +211,12 @@ typedef struct SRSRAN_API {
|
|||
|
||||
srsran_sch_cfg_t sch_cfg; ///< Common shared channel parameters
|
||||
|
||||
/// PDSCH Periodic ZP-CSI-RS set
|
||||
srsran_csi_rs_zp_set_t p_zp_csi_rs_set;
|
||||
|
||||
/// PDSCH Periodic NZP-CSI-RS set, indexed by nzp-CSI-ResourceSetId
|
||||
srsran_csi_rs_nzp_set_t nzp_csi_rs_sets[SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_SETS];
|
||||
|
||||
/// PUSCH only
|
||||
srsran_beta_offsets_t beta_offsets; /// Semi-static only.
|
||||
float scaling; /// Indicates a scaling factor to limit the number of resource elements assigned to UCI on PUSCH.
|
||||
|
@ -213,12 +227,12 @@ typedef struct SRSRAN_API {
|
|||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
bool scrambling_id_present;
|
||||
uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023)
|
||||
uint32_t scambling_id; ///< Identifier used to initialize data scrambling (0-1023)
|
||||
|
||||
srsran_dmrs_sch_cfg_t dmrs;
|
||||
srsran_sch_grant_nr_t grant;
|
||||
|
||||
srsran_sch_cfg_t sch_cfg; ///< Common shared channel parameters
|
||||
srsran_dmrs_sch_cfg_t dmrs; ///< DMRS configuration for this transmission
|
||||
srsran_sch_grant_nr_t grant; ///< Actual SCH grant
|
||||
srsran_sch_cfg_t sch_cfg; ///< Common shared channel parameters
|
||||
srsran_re_pattern_list_t rvd_re; ///< Reserved resource elements, as pattern
|
||||
|
||||
/// PUSCH only parameters
|
||||
srsran_uci_cfg_nr_t uci; ///< Uplink Control Information configuration
|
||||
|
|
|
@ -90,12 +90,14 @@ SRSRAN_API int srsran_ra_nr_fill_tb(const srsran_sch_cfg_nr_t* pdsch_cfg,
|
|||
* Note: Only TypeA PDSCH mapping type is supported
|
||||
*
|
||||
* @param carrier Carrier information struct
|
||||
* @param slot Slot configuration
|
||||
* @param pdsch_cfg PDSCH configuration indicated by higher layers
|
||||
* @param dci_dl DCI downlink (format 1_0 or 1_1)
|
||||
* @param pdsch_grant Generated PDSCH grant
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
SRSRAN_API int srsran_ra_dl_dci_to_grant_nr(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot,
|
||||
const srsran_sch_hl_cfg_nr_t* pdsch_cfg,
|
||||
const srsran_dci_dl_nr_t* dci_dl,
|
||||
srsran_sch_cfg_nr_t* cfg,
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_RE_PATTERN_H
|
||||
#define SRSRAN_RE_PATTERN_H
|
||||
|
||||
#include "../common/phy_common_nr.h"
|
||||
|
||||
/**
|
||||
* @brief Maximum number of elements in a pattern list
|
||||
*/
|
||||
#define SRSRAN_RE_PATTERN_LIST_SIZE 4
|
||||
|
||||
/**
|
||||
* @brief Characterizes a pattern in frequency-time domain in an NR slot resource grid
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
uint32_t rb_begin; ///< RB where the pattern begins in frequency domain
|
||||
uint32_t rb_end; ///< RB where the pattern ends in frequency domain (excluded)
|
||||
uint32_t rb_stride; ///< RB index jump
|
||||
bool sc[SRSRAN_NRE]; ///< Frequency-domain pattern
|
||||
bool symbol[SRSRAN_NSYMB_PER_SLOT_NR]; ///< Indicates OFDM symbols where the pattern is present
|
||||
} srsran_re_pattern_t;
|
||||
|
||||
/**
|
||||
* @brief List of RE patterns
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
srsran_re_pattern_t data[SRSRAN_RE_PATTERN_LIST_SIZE]; ///< Actual patterns
|
||||
uint32_t count; ///< Number of RE patterns
|
||||
} srsran_re_pattern_list_t;
|
||||
|
||||
/**
|
||||
* @brief Calculates if a pattern matches a RE given a symbol l and a subcarrier k
|
||||
* @param list Provides a list of patterns
|
||||
* @param l OFDM symbol index
|
||||
* @param k Subcarrier index
|
||||
* @return True if pattern is valid and there is a match, false otherwise
|
||||
*/
|
||||
SRSRAN_API bool srsran_re_pattern_to_mask(const srsran_re_pattern_list_t* list, uint32_t l, uint32_t k);
|
||||
|
||||
/**
|
||||
* @brief Calculates the pattern mask for an entire symbol from a RE pattern list
|
||||
* @param list Provides a list of patterns
|
||||
* @param l OFDM symbol index
|
||||
* @param[out] mask Mask vector
|
||||
* @return SRSRAN_SUCCESS if the mask is computed successfully, SRSRAN_ERROR code otherwise
|
||||
*/
|
||||
SRSRAN_API int srsran_re_pattern_to_symbol_mask(const srsran_re_pattern_t* pattern, uint32_t l, bool* mask);
|
||||
|
||||
/**
|
||||
* @brief Calculates the pattern mask for an entire symbol from a RE pattern
|
||||
* @param list Provides a list of patterns
|
||||
* @param l OFDM symbol index
|
||||
* @param[out] mask Mask vector
|
||||
* @return SRSRAN_SUCCESS if the mask is computed successfully, SRSRAN_ERROR code otherwise
|
||||
*/
|
||||
SRSRAN_API int srsran_re_pattern_list_to_symbol_mask(const srsran_re_pattern_list_t* list, uint32_t l, bool* mask);
|
||||
|
||||
/**
|
||||
* @brief Merges a pattern into the pattern list, it either merges subcarrier or symbol mask or simply appends a new
|
||||
* pattern
|
||||
* @param patterns Provides a list of patterns
|
||||
* @param p Provides pattern to merge
|
||||
* @return SRSRAN_SUCCESS if merging is successful, SRSRAN_ERROR code otherwise
|
||||
*/
|
||||
SRSRAN_API int srsran_re_pattern_merge(srsran_re_pattern_list_t* list, const srsran_re_pattern_t* p);
|
||||
|
||||
/**
|
||||
* @brief Checks collision between a RE pattern list and a RE pattern
|
||||
* @param list Provides pattern list
|
||||
* @param p Provides a pattern
|
||||
* @return SRSLTE_SUCCESS if no collision is detected, SRSLTE_ERROR code otherwise
|
||||
*/
|
||||
SRSRAN_API int srsran_re_pattern_check_collision(const srsran_re_pattern_list_t* list, const srsran_re_pattern_t* p);
|
||||
|
||||
/**
|
||||
* @brief Initialises a given pattern list
|
||||
* @param patterns Provides a list of patterns
|
||||
*/
|
||||
SRSRAN_API void srsran_re_pattern_reset(srsran_re_pattern_list_t* list);
|
||||
|
||||
/**
|
||||
* @brief Writes a RE pattern information into a string
|
||||
* @param pattern Provides the pattern
|
||||
* @param str Provides string pointer
|
||||
* @param str_len Maximum string length
|
||||
* @return The number of characters writen into the string
|
||||
*/
|
||||
SRSRAN_API uint32_t srsran_re_pattern_info(const srsran_re_pattern_t* pattern, char* str, uint32_t str_len);
|
||||
|
||||
/**
|
||||
* @brief Writes a RE pattern list information into a string
|
||||
* @param pattern Provides the pattern list
|
||||
* @param str Provides string pointer
|
||||
* @param str_len Maximum string length
|
||||
* @return The number of characters writen into the string
|
||||
*/
|
||||
SRSRAN_API uint32_t srsran_re_pattern_list_info(const srsran_re_pattern_list_t* pattern, char* str, uint32_t str_len);
|
||||
|
||||
/**
|
||||
* @brief Counts the number of RE in a transmission characterised by initial and final symbol indexes and a PRB mask.
|
||||
* @param list RE pattern list
|
||||
* @param symbol_begin First transmission symbol
|
||||
* @param symbol_end Last (excluded) transmission symbol
|
||||
* @param prb_mask Frequency domain resource block mask
|
||||
* @return The number of RE occupied by the pattern list in the transmission
|
||||
*/
|
||||
SRSRAN_API uint32_t srsran_re_pattern_list_count(const srsran_re_pattern_list_t* list,
|
||||
uint32_t symbol_begin,
|
||||
uint32_t symbol_end,
|
||||
const bool prb_mask[SRSRAN_MAX_PRB_NR]);
|
||||
|
||||
#endif // SRSRAN_RE_PATTERN_H
|
|
@ -181,6 +181,7 @@ SRSRAN_API void srsran_vec_prod_sss(const int16_t* x, const int16_t* y, int16_t*
|
|||
// Negate sign (scrambling)
|
||||
SRSRAN_API void srsran_vec_neg_sss(const int16_t* x, const int16_t* y, int16_t* z, const uint32_t len);
|
||||
SRSRAN_API void srsran_vec_neg_bbb(const int8_t* x, const int8_t* y, int8_t* z, const uint32_t len);
|
||||
SRSRAN_API void srsran_vec_neg_bb(const int8_t* x, int8_t* z, const uint32_t len);
|
||||
|
||||
/* Dot-product */
|
||||
SRSRAN_API cf_t srsran_vec_dot_prod_cfc(const cf_t* x, const float* y, const uint32_t len);
|
||||
|
|
|
@ -12,23 +12,27 @@
|
|||
|
||||
#include "srsran/phy/ch_estimation/csi_rs.h"
|
||||
#include "srsran/phy/common/sequence.h"
|
||||
#include "srsran/phy/utils/debug.h"
|
||||
#include "srsran/phy/utils/vector.h"
|
||||
#include <complex.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW1 4
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW2 12
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW4 3
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_OTHER 6
|
||||
#define SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_MAX 12
|
||||
/**
|
||||
* @brief Maximum number of subcarriers occupied by a CSI-RS resource as defined in TS 38.211 Table 7.4.1.5.3-1
|
||||
*/
|
||||
#define CSI_RS_MAX_SUBC_PRB 4
|
||||
|
||||
#define CSI_RS_MAX_CDM_GROUP 16
|
||||
/**
|
||||
* @brief Maximum number of symbols occupied by a CSI-RS resource as defined in TS 38.211 Table 7.4.1.5.3-1
|
||||
*/
|
||||
#define CSI_RS_MAX_SYMBOLS_SLOT 4
|
||||
|
||||
static int csi_rs_location_f(const srsran_csi_rs_resource_mapping_t* resource, uint32_t i)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
uint32_t nof_freq_domain = 0;
|
||||
uint32_t mul = 1;
|
||||
switch (resource->row) {
|
||||
case srsran_csi_rs_resource_mapping_row_1:
|
||||
nof_freq_domain = SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW1;
|
||||
|
@ -38,28 +42,32 @@ static int csi_rs_location_f(const srsran_csi_rs_resource_mapping_t* resource, u
|
|||
break;
|
||||
case srsran_csi_rs_resource_mapping_row_4:
|
||||
nof_freq_domain = SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW4;
|
||||
mul = 4;
|
||||
break;
|
||||
case srsran_csi_rs_resource_mapping_row_other:
|
||||
nof_freq_domain = SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_OTHER;
|
||||
mul = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < nof_freq_domain; j++) {
|
||||
if (resource->frequency_domain_alloc[j]) {
|
||||
if (resource->frequency_domain_alloc[nof_freq_domain - 1 - j]) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == i) {
|
||||
return i;
|
||||
return j * mul;
|
||||
}
|
||||
}
|
||||
|
||||
ERROR("Unhandled configuration");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Table 7.4.1.5.3-1: CSI-RS locations within a slot
|
||||
static int csi_rs_location_get_k_list(const srsran_csi_rs_resource_mapping_t* resource,
|
||||
uint32_t k_list[CSI_RS_MAX_CDM_GROUP])
|
||||
uint32_t j,
|
||||
uint32_t k_list[CSI_RS_MAX_SUBC_PRB])
|
||||
{
|
||||
int k0 = csi_rs_location_f(resource, 1);
|
||||
// int k1 = csi_rs_location_f(resource, 2);
|
||||
|
@ -71,20 +79,49 @@ static int csi_rs_location_get_k_list(const srsran_csi_rs_resource_mapping_t* re
|
|||
}
|
||||
|
||||
// Row 1
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_1 && resource->ports == 1 &&
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_three && resource->cdm == srsran_csi_rs_cdm_nocdm) {
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_1 && resource->nof_ports == 1 &&
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_three && resource->cdm == srsran_csi_rs_cdm_nocdm &&
|
||||
j == 0) {
|
||||
k_list[0] = k0;
|
||||
k_list[1] = k0 + 4;
|
||||
k_list[2] = k0 + 8;
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Row 2
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 &&
|
||||
resource->cdm == srsran_csi_rs_cdm_nocdm) {
|
||||
if (resource->density == srsran_csi_rs_resource_mapping_density_one ||
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_even ||
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) {
|
||||
k_list[0] = k0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Row 4
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_4 && resource->nof_ports == 4 &&
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_one && resource->cdm == srsran_csi_rs_cdm_fd_cdm2) {
|
||||
if (j == 0) {
|
||||
k_list[0] = k0;
|
||||
k_list[1] = k0 + 1;
|
||||
return 2;
|
||||
}
|
||||
if (j == 1) {
|
||||
k_list[0] = k0 + 2;
|
||||
k_list[1] = k0 + 2 + 1;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
ERROR("Unhandled configuration");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Table 7.4.1.5.3-1: CSI-RS locations within a slot
|
||||
static int csi_rs_location_get_l_list(const srsran_csi_rs_resource_mapping_t* resource,
|
||||
uint32_t l_list[CSI_RS_MAX_CDM_GROUP])
|
||||
uint32_t j,
|
||||
uint32_t l_list[CSI_RS_MAX_SYMBOLS_SLOT])
|
||||
{
|
||||
uint32_t l0 = resource->first_symbol_idx;
|
||||
|
||||
|
@ -98,19 +135,44 @@ static int csi_rs_location_get_l_list(const srsran_csi_rs_resource_mapping_t* re
|
|||
// }
|
||||
|
||||
// Row 1
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_1 && resource->ports == 1 &&
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_1 && resource->nof_ports == 1 &&
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_three && resource->cdm == srsran_csi_rs_cdm_nocdm) {
|
||||
l_list[0] = l0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Row 2
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 &&
|
||||
resource->cdm == srsran_csi_rs_cdm_nocdm) {
|
||||
if (resource->density == srsran_csi_rs_resource_mapping_density_one ||
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_even ||
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) {
|
||||
l_list[0] = l0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Row 4
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_4 && resource->nof_ports == 4 &&
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_one && resource->cdm == srsran_csi_rs_cdm_fd_cdm2) {
|
||||
if (j == 0) {
|
||||
l_list[0] = l0;
|
||||
return 1;
|
||||
}
|
||||
if (j == 1) {
|
||||
l_list[0] = l0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
ERROR("Unhandled configuration");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t csi_rs_cinit(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_nzp_resource_t* resource,
|
||||
uint32_t l)
|
||||
static uint32_t csi_rs_cinit(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_nzp_resource_t* resource,
|
||||
uint32_t l)
|
||||
{
|
||||
uint32_t n = SRSRAN_SLOT_NR_MOD(carrier->numerology, slot_cfg->idx);
|
||||
uint32_t n_id = resource->scrambling_id;
|
||||
|
@ -118,7 +180,7 @@ uint32_t csi_rs_cinit(const srsran_carrier_nr_t* carrier,
|
|||
return ((SRSRAN_NSYMB_PER_SLOT_NR * n + l + 1UL) * (2UL * n_id) << 10UL) + n_id;
|
||||
}
|
||||
|
||||
bool srsran_csi_send(const srsran_csi_rs_period_and_offset_t* periodicity, const srsran_slot_cfg_t* slot_cfg)
|
||||
bool srsran_csi_rs_send(const srsran_csi_rs_period_and_offset_t* periodicity, const srsran_slot_cfg_t* slot_cfg)
|
||||
{
|
||||
if (periodicity == NULL || slot_cfg == NULL) {
|
||||
return false;
|
||||
|
@ -133,6 +195,43 @@ bool srsran_csi_send(const srsran_csi_rs_period_and_offset_t* periodicity, const
|
|||
return n == 0;
|
||||
}
|
||||
|
||||
static int csi_rs_nof_cdm_groups(const srsran_csi_rs_resource_mapping_t* resource)
|
||||
{
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_1 && resource->nof_ports == 1 &&
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_three && resource->cdm == srsran_csi_rs_cdm_nocdm) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Row 1
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 &&
|
||||
resource->cdm == srsran_csi_rs_cdm_nocdm) {
|
||||
if (resource->density == srsran_csi_rs_resource_mapping_density_one ||
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_even ||
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Row 2
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 &&
|
||||
resource->cdm == srsran_csi_rs_cdm_nocdm) {
|
||||
if (resource->density == srsran_csi_rs_resource_mapping_density_one ||
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_even ||
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Row 3
|
||||
if (resource->row == srsran_csi_rs_resource_mapping_row_4 && resource->nof_ports == 4 &&
|
||||
resource->density == srsran_csi_rs_resource_mapping_density_one && resource->cdm == srsran_csi_rs_cdm_fd_cdm2) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
ERROR("Unhandled configuration");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t csi_rs_count(srsran_csi_rs_density_t density, uint32_t nprb)
|
||||
{
|
||||
switch (density) {
|
||||
|
@ -150,7 +249,7 @@ uint32_t csi_rs_count(srsran_csi_rs_density_t density, uint32_t nprb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint32_t csi_rs_rb_begin(const srsran_carrier_nr_t* carrier, const srsran_csi_rs_resource_mapping_t* m)
|
||||
static uint32_t csi_rs_rb_begin(const srsran_carrier_nr_t* carrier, const srsran_csi_rs_resource_mapping_t* m)
|
||||
{
|
||||
uint32_t ret = SRSRAN_MAX(carrier->start, m->freq_band.start_rb);
|
||||
|
||||
|
@ -162,12 +261,12 @@ uint32_t csi_rs_rb_begin(const srsran_carrier_nr_t* carrier, const srsran_csi_rs
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint32_t csi_rs_rb_end(const srsran_carrier_nr_t* carrier, const srsran_csi_rs_resource_mapping_t* m)
|
||||
static uint32_t csi_rs_rb_end(const srsran_carrier_nr_t* carrier, const srsran_csi_rs_resource_mapping_t* m)
|
||||
{
|
||||
return SRSRAN_MIN(carrier->start + carrier->nof_prb, m->freq_band.start_rb + m->freq_band.nof_rb);
|
||||
}
|
||||
|
||||
uint32_t csi_rs_rb_stride(const srsran_csi_rs_resource_mapping_t* m)
|
||||
static uint32_t csi_rs_rb_stride(const srsran_csi_rs_resource_mapping_t* m)
|
||||
{
|
||||
uint32_t ret = 1;
|
||||
|
||||
|
@ -181,6 +280,65 @@ uint32_t csi_rs_rb_stride(const srsran_csi_rs_resource_mapping_t* m)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int srsran_csi_rs_append_resource_to_pattern(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_csi_rs_resource_mapping_t* resource,
|
||||
srsran_re_pattern_list_t* re_pattern_list)
|
||||
{
|
||||
// Check inputs
|
||||
if (resource == NULL || re_pattern_list == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Create temporal pattern
|
||||
srsran_re_pattern_t pattern = {};
|
||||
pattern.rb_begin = csi_rs_rb_begin(carrier, resource);
|
||||
pattern.rb_end = csi_rs_rb_end(carrier, resource);
|
||||
pattern.rb_stride = csi_rs_rb_stride(resource);
|
||||
|
||||
// Calculate number of CDM groups
|
||||
int nof_cdm_groups = csi_rs_nof_cdm_groups(resource);
|
||||
if (nof_cdm_groups < SRSRAN_SUCCESS) {
|
||||
ERROR("Error getting number of CDM groups");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Iterate over all CDM groups
|
||||
for (int j = 0; j < nof_cdm_groups; j++) {
|
||||
// Get SC indexes
|
||||
uint32_t k_list[CSI_RS_MAX_SUBC_PRB] = {};
|
||||
int nof_k = csi_rs_location_get_k_list(resource, j, k_list);
|
||||
if (nof_k < SRSRAN_SUCCESS) {
|
||||
ERROR("Error getting indexes for CSI-RS");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Fill subcarrier mask
|
||||
for (int k = 0; k < nof_k; k++) {
|
||||
pattern.sc[k_list[k]] = true;
|
||||
}
|
||||
|
||||
// Get OFDM symbol indexes
|
||||
uint32_t l_list[CSI_RS_MAX_SUBC_PRB] = {};
|
||||
int nof_l = csi_rs_location_get_l_list(resource, j, l_list);
|
||||
if (nof_l < SRSRAN_SUCCESS) {
|
||||
ERROR("Error getting indexes for CSI-RS");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Fill OFDM symbol mask
|
||||
for (int l = 0; l < nof_l; l++) {
|
||||
pattern.symbol[l_list[l]] = true;
|
||||
}
|
||||
|
||||
if (srsran_re_pattern_merge(re_pattern_list, &pattern) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error merging pattern");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_csi_rs_nzp_put(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_nzp_resource_t* resource,
|
||||
|
@ -190,14 +348,17 @@ int srsran_csi_rs_nzp_put(const srsran_carrier_nr_t* carrier,
|
|||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t k_list[CSI_RS_MAX_CDM_GROUP];
|
||||
int nof_k = csi_rs_location_get_k_list(&resource->resource_mapping, k_list);
|
||||
// Force CDM group to 0
|
||||
uint32_t j = 0;
|
||||
|
||||
uint32_t k_list[CSI_RS_MAX_SUBC_PRB];
|
||||
int nof_k = csi_rs_location_get_k_list(&resource->resource_mapping, j, k_list);
|
||||
if (nof_k <= 0) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t l_list[CSI_RS_MAX_CDM_GROUP];
|
||||
int nof_l = csi_rs_location_get_l_list(&resource->resource_mapping, l_list);
|
||||
uint32_t l_list[CSI_RS_MAX_SYMBOLS_SLOT];
|
||||
int nof_l = csi_rs_location_get_l_list(&resource->resource_mapping, j, l_list);
|
||||
if (nof_l <= 0) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
@ -261,14 +422,17 @@ int srsran_csi_rs_nzp_measure(const srsran_carrier_nr_t* carrier,
|
|||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t k_list[CSI_RS_MAX_CDM_GROUP];
|
||||
int nof_k = csi_rs_location_get_k_list(&resource->resource_mapping, k_list);
|
||||
// Force CDM group to 0
|
||||
uint32_t j = 0;
|
||||
|
||||
uint32_t k_list[CSI_RS_MAX_SUBC_PRB];
|
||||
int nof_k = csi_rs_location_get_k_list(&resource->resource_mapping, j, k_list);
|
||||
if (nof_k <= 0) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t l_list[CSI_RS_MAX_CDM_GROUP];
|
||||
int nof_l = csi_rs_location_get_l_list(&resource->resource_mapping, l_list);
|
||||
uint32_t l_list[CSI_RS_MAX_SYMBOLS_SLOT];
|
||||
int nof_l = csi_rs_location_get_l_list(&resource->resource_mapping, j, l_list);
|
||||
if (nof_l <= 0) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#define DMRS_PDCCH_INFO_TX(...) INFO("PDCCH DMRS Tx: " __VA_ARGS__)
|
||||
#define DMRS_PDCCH_INFO_RX(...) INFO("PDCCH DMRS Rx: " __VA_ARGS__)
|
||||
#define DMRS_PDCCH_DEBUG_RX(...) DEBUG("PDCCH DMRS Rx: " __VA_ARGS__)
|
||||
|
||||
/// @brief Enables interpolation at CCE frequency bandwidth to avoid interference with adjacent PDCCH DMRS
|
||||
#define DMRS_PDCCH_INTERPOLATE_GROUP 1
|
||||
|
@ -347,8 +348,6 @@ int srsran_dmrs_pdcch_estimate(srsran_dmrs_pdcch_estimator_t* q,
|
|||
// Calculate PRN sequence initial state
|
||||
uint32_t cinit = dmrs_pdcch_get_cinit(slot_idx, l, n_id);
|
||||
|
||||
DMRS_PDCCH_INFO_RX("n=%d; l=%d; cinit=%08x", slot_idx, l, cinit);
|
||||
|
||||
// Extract pilots least square estimates
|
||||
srsran_dmrs_pdcch_extract(q, cinit, &sf_symbols[l * q->carrier.nof_prb * SRSRAN_NRE], q->lse[l]);
|
||||
}
|
||||
|
@ -410,8 +409,8 @@ int srsran_dmrs_pdcch_get_measure(const srsran_dmrs_pdcch_estimator_t* q,
|
|||
float sync_err = 0.0f;
|
||||
cf_t corr[SRSRAN_CORESET_DURATION_MAX] = {};
|
||||
for (uint32_t l = 0; l < q->coreset.duration; l++) {
|
||||
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_INFO && !handler_registered) {
|
||||
DMRS_PDCCH_INFO_RX("Measuring PDCCH l=%d; lse=", l);
|
||||
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
|
||||
DMRS_PDCCH_DEBUG_RX("Measuring PDCCH l=%d; lse=", l);
|
||||
srsran_vec_fprint_c(stdout, &q->lse[l][pilot_idx], nof_pilots);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
#include "srsran/phy/ch_estimation/dmrs_sch.h"
|
||||
#include "srsran/phy/ch_estimation/csi_rs.h"
|
||||
#include "srsran/phy/common/sequence.h"
|
||||
#include <complex.h>
|
||||
#include <srsran/phy/utils/debug.h>
|
||||
|
@ -399,26 +400,56 @@ int srsran_dmrs_sch_get_symbols_idx(const srsran_dmrs_sch_cfg_t* dmrs_cfg,
|
|||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
int srsran_dmrs_sch_get_sc_idx(const srsran_dmrs_sch_cfg_t* cfg, uint32_t max_count, uint32_t* sc_idx)
|
||||
int srsran_dmrs_sch_rvd_re_pattern(const srsran_dmrs_sch_cfg_t* cfg,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
srsran_re_pattern_t* pattern)
|
||||
{
|
||||
int count = 0;
|
||||
uint32_t delta = 0;
|
||||
if (cfg == NULL || pattern == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Initialise pattern with zeros
|
||||
SRSRAN_MEM_ZERO(pattern, srsran_re_pattern_t, 1);
|
||||
|
||||
// Fill RB bounds
|
||||
pattern->rb_begin = 0;
|
||||
pattern->rb_end = SRSRAN_MAX_PRB_NR;
|
||||
pattern->rb_stride = 1;
|
||||
|
||||
// Fill subcarrier mask
|
||||
if (cfg->type == srsran_dmrs_sch_type_1) {
|
||||
for (uint32_t n = 0; count < max_count; n += 4) {
|
||||
for (uint32_t k_prime = 0; k_prime < 2 && count < max_count; k_prime++) {
|
||||
sc_idx[count++] = n + 2 * k_prime + delta;
|
||||
for (uint32_t n = 0; n < 3; n++) {
|
||||
for (uint32_t k_prime = 0; k_prime < 2; k_prime++) {
|
||||
for (uint32_t delta = 0; delta < grant->nof_dmrs_cdm_groups_without_data; delta++) {
|
||||
pattern->sc[(4 * n + 2 * k_prime + delta) % SRSRAN_NRE] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint32_t n = 0; count < max_count; n += 6) {
|
||||
for (uint32_t k_prime = 0; k_prime < 2 && count < max_count; k_prime++) {
|
||||
sc_idx[count++] = n + k_prime + delta;
|
||||
for (uint32_t n = 0; n < 2; n++) {
|
||||
for (uint32_t k_prime = 0; k_prime < 2; k_prime++) {
|
||||
for (uint32_t delta = 0; delta < grant->nof_dmrs_cdm_groups_without_data; delta++) {
|
||||
pattern->sc[(6 * n + k_prime + 2 * delta) % SRSRAN_NRE] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
// Calculate OFDM symbols
|
||||
uint32_t symbols[SRSRAN_DMRS_SCH_MAX_SYMBOLS];
|
||||
int nof_l = srsran_dmrs_sch_get_symbols_idx(cfg, grant, symbols);
|
||||
if (nof_l < SRSRAN_SUCCESS) {
|
||||
ERROR("Error calculating OFDM symbols");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Set OFDM symbol mask
|
||||
for (int i = 0; i < nof_l; i++) {
|
||||
uint32_t l = symbols[i];
|
||||
pattern->symbol[l % SRSRAN_NSYMB_PER_SLOT_NR] = true;
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_dmrs_sch_get_N_prb(const srsran_dmrs_sch_cfg_t* dmrs_cfg, const srsran_sch_grant_nr_t* grant)
|
||||
|
@ -666,26 +697,26 @@ static int srsran_dmrs_sch_get_symbol(srsran_dmrs_sch_t* q,
|
|||
}
|
||||
|
||||
int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_sch_cfg_nr_t* pdsch_cfg,
|
||||
const srsran_slot_cfg_t* slot,
|
||||
const srsran_sch_cfg_nr_t* cfg,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
const cf_t* sf_symbols,
|
||||
srsran_chest_dl_res_t* chest_res)
|
||||
{
|
||||
const uint32_t delta = 0;
|
||||
|
||||
if (q == NULL || slot_cfg == NULL || sf_symbols == NULL || chest_res == NULL) {
|
||||
if (q == NULL || slot == NULL || sf_symbols == NULL || chest_res == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
const srsran_dmrs_sch_cfg_t* dmrs_cfg = &pdsch_cfg->dmrs;
|
||||
const srsran_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs;
|
||||
|
||||
cf_t* ce = q->temp;
|
||||
uint32_t symbol_sz = q->carrier.nof_prb * SRSRAN_NRE; // Symbol size in resource elements
|
||||
|
||||
// Get symbols indexes
|
||||
uint32_t symbols[SRSRAN_DMRS_SCH_MAX_SYMBOLS] = {};
|
||||
int nof_symbols = srsran_dmrs_sch_get_symbols_idx(&pdsch_cfg->dmrs, grant, symbols);
|
||||
int nof_symbols = srsran_dmrs_sch_get_symbols_idx(&cfg->dmrs, grant, symbols);
|
||||
if (nof_symbols <= SRSRAN_SUCCESS) {
|
||||
ERROR("Error getting symbol indexes");
|
||||
return SRSRAN_ERROR;
|
||||
|
@ -697,11 +728,11 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
|
|||
for (uint32_t i = 0; i < nof_symbols; i++) {
|
||||
uint32_t l = symbols[i]; // Symbol index inside the slot
|
||||
|
||||
uint32_t cinit = srsran_dmrs_sch_seed(
|
||||
&q->carrier, pdsch_cfg, grant, SRSRAN_SLOT_NR_MOD(q->carrier.numerology, slot_cfg->idx), l);
|
||||
uint32_t cinit =
|
||||
srsran_dmrs_sch_seed(&q->carrier, cfg, grant, SRSRAN_SLOT_NR_MOD(q->carrier.numerology, slot->idx), l);
|
||||
|
||||
nof_pilots_x_symbol = srsran_dmrs_sch_get_symbol(
|
||||
q, pdsch_cfg, grant, cinit, delta, &sf_symbols[symbol_sz * l], &q->pilot_estimates[nof_pilots_x_symbol * i]);
|
||||
q, cfg, grant, cinit, delta, &sf_symbols[symbol_sz * l], &q->pilot_estimates[nof_pilots_x_symbol * i]);
|
||||
|
||||
if (nof_pilots_x_symbol == 0) {
|
||||
ERROR("Error, no pilots extracted (i=%d, l=%d)", i, l);
|
||||
|
@ -784,6 +815,26 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
|
|||
symbol_idx++;
|
||||
}
|
||||
|
||||
// Initialise reserved mask
|
||||
bool rvd_mask_wb[SRSRAN_NRE * SRSRAN_MAX_PRB_NR] = {};
|
||||
|
||||
// Compute reserved RE
|
||||
if (srsran_re_pattern_list_to_symbol_mask(&cfg->rvd_re, l, rvd_mask_wb) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error generating reserved RE mask");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Narrow reserved subcarriers to the ones used in the transmission
|
||||
bool rvd_mask[SRSRAN_NRE * SRSRAN_MAX_PRB_NR] = {};
|
||||
for (uint32_t i = 0, k = 0; i < q->carrier.nof_prb; i++) {
|
||||
if (grant->prb_idx[i]) {
|
||||
for (uint32_t j = 0; j < SRSRAN_NRE; j++) {
|
||||
rvd_mask[k++] = rvd_mask_wb[i * SRSRAN_NRE + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if it s DMRS symbol
|
||||
if (symbols[symbol_idx] == l) {
|
||||
switch (dmrs_cfg->type) {
|
||||
case srsran_dmrs_sch_type_1:
|
||||
|
@ -792,8 +843,9 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
|
|||
continue;
|
||||
}
|
||||
for (uint32_t i = 1; i < nof_re_x_symbol; i += 2) {
|
||||
chest_res->ce[0][0][count] = ce[i];
|
||||
count++;
|
||||
if (!rvd_mask[i]) {
|
||||
chest_res->ce[0][0][count++] = ce[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case srsran_dmrs_sch_type_2:
|
||||
|
@ -803,14 +855,20 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
|
|||
}
|
||||
for (uint32_t i = grant->nof_dmrs_cdm_groups_without_data * 2; i < nof_re_x_symbol; i += 6) {
|
||||
uint32_t nof_re = (3 - grant->nof_dmrs_cdm_groups_without_data) * 2;
|
||||
srsran_vec_cf_copy(&chest_res->ce[0][0][count], &ce[i], nof_re);
|
||||
count += nof_re;
|
||||
for (uint32_t j = 0; j < nof_re; j++) {
|
||||
if (!rvd_mask[i + j]) {
|
||||
chest_res->ce[0][0][count++] = ce[i + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
srsran_vec_cf_copy(&chest_res->ce[0][0][count], ce, nof_re_x_symbol);
|
||||
count += nof_re_x_symbol;
|
||||
for (uint32_t i = 0; i < nof_re_x_symbol; i++) {
|
||||
if (!rvd_mask[i]) {
|
||||
chest_res->ce[0][0][count++] = ce[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set other values in the estimation result
|
||||
|
|
|
@ -77,7 +77,7 @@ add_lte_test(chest_test_sl_psbch chest_test_sl)
|
|||
add_executable(dmrs_pdsch_test dmrs_pdsch_test.c)
|
||||
target_link_libraries(dmrs_pdsch_test srsran_phy)
|
||||
|
||||
add_lte_test(dmrs_pdsch_test dmrs_pdsch_test)
|
||||
add_nr_test(dmrs_pdsch_test dmrs_pdsch_test)
|
||||
|
||||
|
||||
########################################################################
|
||||
|
@ -87,7 +87,7 @@ add_lte_test(dmrs_pdsch_test dmrs_pdsch_test)
|
|||
add_executable(dmrs_pdcch_test dmrs_pdcch_test.c)
|
||||
target_link_libraries(dmrs_pdcch_test srsran_phy)
|
||||
|
||||
add_lte_test(dmrs_pdcch_test dmrs_pdcch_test)
|
||||
add_nr_test(dmrs_pdcch_test dmrs_pdcch_test)
|
||||
|
||||
|
||||
########################################################################
|
||||
|
@ -97,5 +97,15 @@ add_lte_test(dmrs_pdcch_test dmrs_pdcch_test)
|
|||
add_executable(csi_rs_test csi_rs_test.c)
|
||||
target_link_libraries(csi_rs_test srsran_phy)
|
||||
|
||||
add_lte_test(csi_rs_test csi_rs_test -o 3 -S 0 -L 150 -f 3 -p 15)
|
||||
add_nr_test(csi_rs_test csi_rs_test -o 3 -S 0 -L 150 -f 3 -p 15)
|
||||
|
||||
|
||||
########################################################################
|
||||
# NR CSI RS Pattern test
|
||||
########################################################################
|
||||
|
||||
add_executable(csi_rs_pattern_test csi_rs_pattern_test.c)
|
||||
target_link_libraries(csi_rs_pattern_test srsran_phy)
|
||||
|
||||
add_nr_test(csi_rs_pattern_test csi_rs_pattern_test)
|
||||
|
||||
|
|
|
@ -0,0 +1,229 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/ch_estimation/csi_rs.h"
|
||||
|
||||
static srsran_carrier_nr_t carrier = {};
|
||||
|
||||
static int test_row1()
|
||||
{
|
||||
for (uint32_t k = 0; k < SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW1; k++) {
|
||||
// Create CSI-RS mapping
|
||||
srsran_csi_rs_resource_mapping_t m; // Dont initialise for detecting not initialised memory
|
||||
m.row = srsran_csi_rs_resource_mapping_row_1;
|
||||
for (uint32_t j = 0; j < SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW1; j++) {
|
||||
m.frequency_domain_alloc[j] = (k == j);
|
||||
}
|
||||
m.nof_ports = 1;
|
||||
m.first_symbol_idx = 0;
|
||||
m.cdm = srsran_csi_rs_cdm_nocdm;
|
||||
m.density = srsran_csi_rs_resource_mapping_density_three;
|
||||
m.freq_band.start_rb = carrier.start;
|
||||
m.freq_band.nof_rb = carrier.nof_prb;
|
||||
|
||||
// Create Pattern list and initialise
|
||||
srsran_re_pattern_list_t patterns;
|
||||
srsran_re_pattern_reset(&patterns);
|
||||
|
||||
// Generate pattern list from CSI-RS mapping
|
||||
TESTASSERT(srsran_csi_rs_append_resource_to_pattern(&carrier, &m, &patterns) == SRSRAN_SUCCESS);
|
||||
|
||||
// Assert generated pattern
|
||||
TESTASSERT(patterns.count == 1);
|
||||
TESTASSERT(patterns.data[0].rb_begin == m.freq_band.start_rb);
|
||||
TESTASSERT(patterns.data[0].rb_end == m.freq_band.start_rb + m.freq_band.nof_rb);
|
||||
TESTASSERT(patterns.data[0].rb_stride == 1);
|
||||
for (uint32_t j = 0; j < SRSRAN_NRE; j++) {
|
||||
TESTASSERT(patterns.data[0].sc[j] ==
|
||||
(j % SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW1 == (SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW1 - 1 - k)));
|
||||
}
|
||||
for (uint32_t j = 0; j < SRSRAN_NSYMB_PER_SLOT_NR; j++) {
|
||||
TESTASSERT(patterns.data[0].symbol[j] == (j == m.first_symbol_idx));
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_row2()
|
||||
{
|
||||
for (srsran_csi_rs_density_t density = srsran_csi_rs_resource_mapping_density_dot5_even;
|
||||
density <= srsran_csi_rs_resource_mapping_density_one;
|
||||
density++) {
|
||||
for (uint32_t k = 0; k < SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW2; k++) {
|
||||
// Create CSI-RS mapping
|
||||
srsran_csi_rs_resource_mapping_t m; // Dont initialise for detecting not initialised memory
|
||||
m.row = srsran_csi_rs_resource_mapping_row_2;
|
||||
for (uint32_t j = 0; j < SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW2; j++) {
|
||||
m.frequency_domain_alloc[j] = (k == j);
|
||||
}
|
||||
m.nof_ports = 1;
|
||||
m.first_symbol_idx = 0;
|
||||
m.cdm = srsran_csi_rs_cdm_nocdm;
|
||||
m.density = density;
|
||||
m.freq_band.start_rb = carrier.start;
|
||||
m.freq_band.nof_rb = carrier.nof_prb;
|
||||
|
||||
// Create Pattern list and initialise
|
||||
srsran_re_pattern_list_t patterns;
|
||||
srsran_re_pattern_reset(&patterns);
|
||||
|
||||
// Generate pattern list from CSI-RS mapping
|
||||
TESTASSERT(srsran_csi_rs_append_resource_to_pattern(&carrier, &m, &patterns) == SRSRAN_SUCCESS);
|
||||
|
||||
// Assert generated pattern
|
||||
uint32_t rb_stride = (density == srsran_csi_rs_resource_mapping_density_one) ? 1 : 2;
|
||||
uint32_t rb_start = carrier.start;
|
||||
if ((rb_start % 2 == 0 && density == srsran_csi_rs_resource_mapping_density_dot5_odd) ||
|
||||
(rb_start % 2 == 1 && density == srsran_csi_rs_resource_mapping_density_dot5_even)) {
|
||||
rb_start++;
|
||||
}
|
||||
TESTASSERT(patterns.count == 1);
|
||||
TESTASSERT(patterns.data[0].rb_begin == rb_start);
|
||||
TESTASSERT(patterns.data[0].rb_end == m.freq_band.start_rb + m.freq_band.nof_rb);
|
||||
TESTASSERT(patterns.data[0].rb_stride == rb_stride);
|
||||
for (uint32_t j = 0; j < SRSRAN_NRE; j++) {
|
||||
TESTASSERT(patterns.data[0].sc[j] == (j == (SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW2 - 1 - k)));
|
||||
}
|
||||
for (uint32_t j = 0; j < SRSRAN_NSYMB_PER_SLOT_NR; j++) {
|
||||
TESTASSERT(patterns.data[0].symbol[j] == (j == m.first_symbol_idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_row4()
|
||||
{
|
||||
for (uint32_t k = 0; k < SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW4; k++) {
|
||||
// Create CSI-RS mapping
|
||||
srsran_csi_rs_resource_mapping_t m; // Dont initialise for detecting not initialised memory
|
||||
m.row = srsran_csi_rs_resource_mapping_row_4;
|
||||
for (uint32_t j = 0; j < SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW4; j++) {
|
||||
m.frequency_domain_alloc[j] = (k == j);
|
||||
}
|
||||
m.nof_ports = 4;
|
||||
m.first_symbol_idx = 0;
|
||||
m.cdm = srsran_csi_rs_cdm_fd_cdm2;
|
||||
m.density = srsran_csi_rs_resource_mapping_density_one;
|
||||
m.freq_band.start_rb = carrier.start;
|
||||
m.freq_band.nof_rb = carrier.nof_prb;
|
||||
|
||||
// Create Pattern list and initialise
|
||||
srsran_re_pattern_list_t patterns;
|
||||
srsran_re_pattern_reset(&patterns);
|
||||
|
||||
// Generate pattern list from CSI-RS mapping
|
||||
TESTASSERT(srsran_csi_rs_append_resource_to_pattern(&carrier, &m, &patterns) == SRSRAN_SUCCESS);
|
||||
|
||||
// Assert generated pattern
|
||||
TESTASSERT(patterns.count == 1);
|
||||
TESTASSERT(patterns.data[0].rb_begin == m.freq_band.start_rb);
|
||||
TESTASSERT(patterns.data[0].rb_end == m.freq_band.start_rb + m.freq_band.nof_rb);
|
||||
TESTASSERT(patterns.data[0].rb_stride == 1);
|
||||
for (uint32_t j = 0; j < SRSRAN_NRE; j++) {
|
||||
uint32_t k_begin = (SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW4 - 1 - k) * 4;
|
||||
uint32_t k_end = k_begin + 4;
|
||||
TESTASSERT(patterns.data[0].sc[j] == (j >= k_begin && j < k_end));
|
||||
}
|
||||
for (uint32_t j = 0; j < SRSRAN_NSYMB_PER_SLOT_NR; j++) {
|
||||
TESTASSERT(patterns.data[0].symbol[j] == (j == m.first_symbol_idx));
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_mix()
|
||||
{
|
||||
srsran_csi_rs_resource_mapping_t resource0 = {};
|
||||
resource0.row = srsran_csi_rs_resource_mapping_row_4;
|
||||
resource0.frequency_domain_alloc[0] = true;
|
||||
resource0.frequency_domain_alloc[1] = false;
|
||||
resource0.frequency_domain_alloc[2] = false;
|
||||
resource0.nof_ports = 4;
|
||||
resource0.first_symbol_idx = 8;
|
||||
resource0.cdm = srsran_csi_rs_cdm_fd_cdm2;
|
||||
resource0.density = srsran_csi_rs_resource_mapping_density_one;
|
||||
resource0.freq_band.start_rb = 0;
|
||||
resource0.freq_band.nof_rb = 52;
|
||||
|
||||
srsran_csi_rs_resource_mapping_t resource1 = {};
|
||||
resource1.row = srsran_csi_rs_resource_mapping_row_2;
|
||||
resource1.frequency_domain_alloc[0] = true;
|
||||
resource1.frequency_domain_alloc[1] = false;
|
||||
resource1.frequency_domain_alloc[2] = false;
|
||||
resource1.frequency_domain_alloc[3] = false;
|
||||
resource1.frequency_domain_alloc[4] = false;
|
||||
resource1.frequency_domain_alloc[5] = false;
|
||||
resource1.frequency_domain_alloc[6] = false;
|
||||
resource1.frequency_domain_alloc[7] = false;
|
||||
resource1.frequency_domain_alloc[8] = false;
|
||||
resource1.frequency_domain_alloc[9] = false;
|
||||
resource1.frequency_domain_alloc[10] = false;
|
||||
resource1.frequency_domain_alloc[11] = false;
|
||||
resource1.nof_ports = 1;
|
||||
resource1.first_symbol_idx = 4;
|
||||
resource1.cdm = srsran_csi_rs_cdm_nocdm;
|
||||
resource1.density = srsran_csi_rs_resource_mapping_density_one;
|
||||
resource1.freq_band.start_rb = 0;
|
||||
resource1.freq_band.nof_rb = 52;
|
||||
|
||||
// Initialise pattern list
|
||||
srsran_re_pattern_list_t patterns;
|
||||
srsran_re_pattern_reset(&patterns);
|
||||
|
||||
// Generate pattern list from CSI-RS mapping
|
||||
TESTASSERT(srsran_csi_rs_append_resource_to_pattern(&carrier, &resource0, &patterns) == SRSRAN_SUCCESS);
|
||||
TESTASSERT(srsran_csi_rs_append_resource_to_pattern(&carrier, &resource1, &patterns) == SRSRAN_SUCCESS);
|
||||
|
||||
// Assert generated pattern
|
||||
TESTASSERT(patterns.count == 2);
|
||||
|
||||
for (uint32_t l = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) {
|
||||
bool mask[SRSRAN_NRE * SRSRAN_MAX_PRB_NR] = {};
|
||||
|
||||
TESTASSERT(srsran_re_pattern_list_to_symbol_mask(&patterns, l, mask) == SRSRAN_SUCCESS);
|
||||
|
||||
if (l == resource0.first_symbol_idx) {
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE * SRSRAN_MAX_PRB_NR; k++) {
|
||||
TESTASSERT(mask[k] == ((k < 52 * SRSRAN_NRE) && (k % SRSRAN_NRE >= 8)));
|
||||
}
|
||||
} else if (l == resource1.first_symbol_idx) {
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE * SRSRAN_MAX_PRB_NR; k++) {
|
||||
TESTASSERT(mask[k] == ((k < 52 * SRSRAN_NRE) && (k % SRSRAN_NRE == 11)));
|
||||
}
|
||||
} else {
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE * SRSRAN_MAX_PRB_NR; k++) {
|
||||
TESTASSERT(mask[k] == false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Initialise carrier
|
||||
carrier.start = 0;
|
||||
carrier.nof_prb = 52;
|
||||
|
||||
TESTASSERT(test_row1() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(test_row2() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(test_row4() == SRSRAN_SUCCESS);
|
||||
TESTASSERT(test_mix() == SRSRAN_SUCCESS);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
|
@ -136,10 +136,10 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
// Fixed parameters, other params are not implemented
|
||||
resource.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm;
|
||||
resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three;
|
||||
resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1;
|
||||
resource.resource_mapping.ports = 1;
|
||||
resource.resource_mapping.cdm = srsran_csi_rs_cdm_nocdm;
|
||||
resource.resource_mapping.density = srsran_csi_rs_resource_mapping_density_three;
|
||||
resource.resource_mapping.row = srsran_csi_rs_resource_mapping_row_1;
|
||||
resource.resource_mapping.nof_ports = 1;
|
||||
|
||||
// Row 1 supported only!
|
||||
uint32_t nof_freq_dom_alloc = SRSRAN_CSI_RS_NOF_FREQ_DOMAIN_ALLOC_ROW1;
|
||||
|
|
|
@ -164,41 +164,44 @@ static int assert_cfg(const srsran_sch_cfg_nr_t* pdsch_cfg, const srsran_sch_gra
|
|||
continue;
|
||||
}
|
||||
|
||||
if (grant->mapping != gold[i].mapping_type) {
|
||||
// Skip golden sample if one of the parameters does not match
|
||||
if (grant->mapping != gold[i].mapping_type || pdsch_cfg->dmrs.typeA_pos != gold[i].typeA_pos ||
|
||||
pdsch_cfg->dmrs.additional_pos != gold[i].additional_pos || pdsch_cfg->dmrs.length != gold[i].max_length ||
|
||||
pdsch_cfg->dmrs.type != gold[i].type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pdsch_cfg->dmrs.typeA_pos != gold[i].typeA_pos) {
|
||||
continue;
|
||||
// Generate subcarrier mask from golden sample
|
||||
bool sc_mask[SRSRAN_NRE] = {};
|
||||
if (grant->nof_dmrs_cdm_groups_without_data == 1) {
|
||||
for (uint32_t j = 0; j < gold[i].nof_sc; j++) {
|
||||
sc_mask[gold[i].sc_idx[j] % SRSRAN_NRE] = true;
|
||||
}
|
||||
} else if (pdsch_cfg->dmrs.type == srsran_dmrs_sch_type_1) {
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE; k++) {
|
||||
sc_mask[k] = true;
|
||||
}
|
||||
} else if (pdsch_cfg->dmrs.type == srsran_dmrs_sch_type_2) {
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE; k++) {
|
||||
sc_mask[k] = ((k % 6) < grant->nof_dmrs_cdm_groups_without_data * 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (pdsch_cfg->dmrs.additional_pos != gold[i].additional_pos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pdsch_cfg->dmrs.length != gold[i].max_length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pdsch_cfg->dmrs.type != gold[i].type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t symbols[SRSRAN_DMRS_SCH_MAX_SYMBOLS] = {};
|
||||
int nof_symbols = srsran_dmrs_sch_get_symbols_idx(&pdsch_cfg->dmrs, grant, symbols);
|
||||
|
||||
TESTASSERT(nof_symbols == gold[i].nof_symbols);
|
||||
|
||||
// Generate symbol mask from golden sample
|
||||
bool symbol_mask[SRSRAN_NSYMB_PER_SLOT_NR] = {};
|
||||
for (uint32_t j = 0; j < gold[i].nof_symbols; j++) {
|
||||
TESTASSERT(symbols[j] == gold[i].symbol_idx[j]);
|
||||
symbol_mask[gold[i].symbol_idx[j] % SRSRAN_NSYMB_PER_SLOT_NR] = true;
|
||||
}
|
||||
|
||||
uint32_t sc[SRSRAN_NRE] = {};
|
||||
srsran_dmrs_sch_get_sc_idx(&pdsch_cfg->dmrs, SRSRAN_NRE, sc);
|
||||
// Generate DMRS pattern
|
||||
srsran_re_pattern_t pattern = {};
|
||||
TESTASSERT(srsran_dmrs_sch_rvd_re_pattern(&pdsch_cfg->dmrs, grant, &pattern) == SRSRAN_SUCCESS);
|
||||
|
||||
for (uint32_t j = 0; j < gold[i].nof_sc; j++) {
|
||||
TESTASSERT(sc[j] == gold[i].sc_idx[j]);
|
||||
}
|
||||
// Assert subcarrier mask
|
||||
TESTASSERT(memcmp(pattern.sc, sc_mask, sizeof(bool) * SRSRAN_NRE) == 0);
|
||||
|
||||
// Assert symbol mask
|
||||
TESTASSERT(memcmp(pattern.symbol, symbol_mask, sizeof(bool) * SRSRAN_NSYMB_PER_SLOT_NR) == 0);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
@ -307,7 +310,15 @@ int main(int argc, char** argv)
|
|||
for (grant.nof_dmrs_cdm_groups_without_data = 1; grant.nof_dmrs_cdm_groups_without_data <= 3;
|
||||
grant.nof_dmrs_cdm_groups_without_data++) {
|
||||
// Load default type A grant
|
||||
srsran_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &grant);
|
||||
if (srsran_ra_dl_nr_time_default_A(m, pdsch_cfg.dmrs.typeA_pos, &grant) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error loading time resource");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mapping type B is not supported
|
||||
if (grant.mapping == srsran_sch_mapping_type_B) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int n = run_test(&dmrs_pdsch, &pdsch_cfg, &grant, sf_symbols, &chest_dl_res);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
#include "srsran/phy/phch/pdsch_nr.h"
|
||||
#include "srsran/phy/ch_estimation/csi_rs.h"
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
#include "srsran/phy/mimo/layermap.h"
|
||||
#include "srsran/phy/mimo/precoding.h"
|
||||
|
@ -174,171 +175,25 @@ void srsran_pdsch_nr_free(srsran_pdsch_nr_t* q)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief copies a number of countiguous Resource Elements
|
||||
* @param sf_symbols slot symbols in frequency domain
|
||||
* @param symbols resource elements
|
||||
* @param count number of resource elements to copy
|
||||
* @param put Direction, symbols are copied into sf_symbols if put is true, otherwise sf_symbols are copied into symbols
|
||||
*/
|
||||
static void srsran_pdsch_re_cp(cf_t* sf_symbols, cf_t* symbols, uint32_t count, bool put)
|
||||
{
|
||||
if (put) {
|
||||
srsran_vec_cf_copy(sf_symbols, symbols, count);
|
||||
} else {
|
||||
srsran_vec_cf_copy(symbols, sf_symbols, count);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with group 2:
|
||||
*
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 |
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* -- k -->
|
||||
*
|
||||
* If the number of DMRS CDM groups without data is set to:
|
||||
* - 1, data is mapped in RE marked as 2
|
||||
* - Otherwise, no data is mapped in this symbol
|
||||
*/
|
||||
static uint32_t srsran_pdsch_nr_cp_dmrs_type1(const srsran_pdsch_nr_t* q,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
cf_t* symbols,
|
||||
cf_t* sf_symbols,
|
||||
bool put)
|
||||
static inline uint32_t pdsch_nr_put_rb(cf_t* dst, cf_t* src, bool* rvd_mask)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
uint32_t delta = 0;
|
||||
|
||||
if (grant->nof_dmrs_cdm_groups_without_data != 1) {
|
||||
return count;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < q->carrier.nof_prb; i++) {
|
||||
if (grant->prb_idx[i]) {
|
||||
for (uint32_t j = 0; j < SRSRAN_NRE; j += 2) {
|
||||
if (put) {
|
||||
sf_symbols[i * SRSRAN_NRE + delta + j + 1] = symbols[count++];
|
||||
} else {
|
||||
symbols[count++] = sf_symbols[i * SRSRAN_NRE + delta + j + 1];
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < SRSRAN_NRE; i++) {
|
||||
if (!rvd_mask[i]) {
|
||||
dst[i] = src[count++];
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with groups 2 and 3:
|
||||
*
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* | 1 | 1 | 2 | 2 | 3 | 3 | 1 | 1 | 2 | 2 | 3 | 3 |
|
||||
* +---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
* -- k -->
|
||||
*
|
||||
* If the number of DMRS CDM groups without data is set to:
|
||||
* - 1, data is mapped in RE marked as 2 and 3
|
||||
* - 2, data is mapped in RE marked as 3
|
||||
* - otherwise, no data is mapped in this symbol
|
||||
*/
|
||||
static uint32_t srsran_pdsch_nr_cp_dmrs_type2(const srsran_pdsch_nr_t* q,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
cf_t* symbols,
|
||||
cf_t* sf_symbols,
|
||||
bool put)
|
||||
static inline uint32_t pdsch_nr_get_rb(cf_t* dst, cf_t* src, bool* rvd_mask)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
||||
if (grant->nof_dmrs_cdm_groups_without_data != 1 && grant->nof_dmrs_cdm_groups_without_data != 2) {
|
||||
return count;
|
||||
}
|
||||
|
||||
uint32_t re_offset = (grant->nof_dmrs_cdm_groups_without_data == 1) ? 2 : 4;
|
||||
uint32_t re_count = (grant->nof_dmrs_cdm_groups_without_data == 1) ? 4 : 2;
|
||||
|
||||
for (uint32_t i = 0; i < q->carrier.nof_prb; i++) {
|
||||
if (grant->prb_idx[i]) {
|
||||
// Copy RE between pilot pairs
|
||||
srsran_pdsch_re_cp(&sf_symbols[i * SRSRAN_NRE + re_offset], &symbols[count], re_count, put);
|
||||
count += re_count;
|
||||
|
||||
// Copy RE after second pilot
|
||||
srsran_pdsch_re_cp(&sf_symbols[(i + 1) * SRSRAN_NRE - re_count], &symbols[count], re_count, put);
|
||||
count += re_count;
|
||||
for (uint32_t i = 0; i < SRSRAN_NRE; i++) {
|
||||
if (!rvd_mask[i]) {
|
||||
dst[count++] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static uint32_t srsran_pdsch_nr_cp_dmrs(const srsran_pdsch_nr_t* q,
|
||||
const srsran_sch_cfg_nr_t* cfg,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
cf_t* symbols,
|
||||
cf_t* sf_symbols,
|
||||
bool put)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
||||
const srsran_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs;
|
||||
|
||||
switch (dmrs_cfg->type) {
|
||||
case srsran_dmrs_sch_type_1:
|
||||
count = srsran_pdsch_nr_cp_dmrs_type1(q, grant, symbols, sf_symbols, put);
|
||||
break;
|
||||
case srsran_dmrs_sch_type_2:
|
||||
count = srsran_pdsch_nr_cp_dmrs_type2(q, grant, symbols, sf_symbols, put);
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static uint32_t srsran_pdsch_nr_cp_clean(const srsran_pdsch_nr_t* q,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
cf_t* symbols,
|
||||
cf_t* sf_symbols,
|
||||
bool put)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
uint32_t start = 0; // Index of the start of continuous data
|
||||
uint32_t length = 0; // End of continuous RE
|
||||
|
||||
for (uint32_t i = 0; i < q->carrier.nof_prb; i++) {
|
||||
if (grant->prb_idx[i]) {
|
||||
// If fist continuous block, save start
|
||||
if (length == 0) {
|
||||
start = i * SRSRAN_NRE;
|
||||
}
|
||||
length += SRSRAN_NRE;
|
||||
} else {
|
||||
// Consecutive block is finished
|
||||
if (put) {
|
||||
srsran_vec_cf_copy(&sf_symbols[start], &symbols[count], length);
|
||||
} else {
|
||||
srsran_vec_cf_copy(&symbols[count], &sf_symbols[start], length);
|
||||
}
|
||||
|
||||
// Increase RE count
|
||||
count += length;
|
||||
|
||||
// Reset consecutive block
|
||||
length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy last contiguous block
|
||||
if (length > 0) {
|
||||
if (put) {
|
||||
srsran_vec_cf_copy(&sf_symbols[start], &symbols[count], length);
|
||||
} else {
|
||||
srsran_vec_cf_copy(&symbols[count], &sf_symbols[start], length);
|
||||
}
|
||||
count += length;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -349,35 +204,40 @@ static int srsran_pdsch_nr_cp(const srsran_pdsch_nr_t* q,
|
|||
cf_t* sf_symbols,
|
||||
bool put)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
uint32_t dmrs_l_idx[SRSRAN_DMRS_SCH_MAX_SYMBOLS] = {};
|
||||
uint32_t dmrs_l_count = 0;
|
||||
|
||||
// Get symbol indexes carrying DMRS
|
||||
int32_t nof_dmrs_symbols = srsran_dmrs_sch_get_symbols_idx(&cfg->dmrs, grant, dmrs_l_idx);
|
||||
if (nof_dmrs_symbols < SRSRAN_SUCCESS) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
|
||||
DEBUG("dmrs_l_idx=");
|
||||
srsran_vec_fprint_i(stdout, (int32_t*)dmrs_l_idx, nof_dmrs_symbols);
|
||||
}
|
||||
uint32_t count = 0;
|
||||
|
||||
for (uint32_t l = grant->S; l < grant->S + grant->L; l++) {
|
||||
// Advance DMRS symbol counter until:
|
||||
// - the current DMRS symbol index is greater or equal than current symbol l
|
||||
// - no more DMRS symbols
|
||||
while (dmrs_l_idx[dmrs_l_count] < l && dmrs_l_count < nof_dmrs_symbols) {
|
||||
dmrs_l_count++;
|
||||
// Initialise reserved RE mask to all false
|
||||
bool rvd_mask[SRSRAN_NRE * SRSRAN_MAX_PRB_NR] = {};
|
||||
|
||||
// Reserve DMRS
|
||||
if (srsran_re_pattern_to_symbol_mask(&q->dmrs_re_pattern, l, rvd_mask) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error generating DMRS reserved RE mask");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
if (l == dmrs_l_idx[dmrs_l_count]) {
|
||||
count += srsran_pdsch_nr_cp_dmrs(
|
||||
q, cfg, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSRAN_NRE], put);
|
||||
} else {
|
||||
count +=
|
||||
srsran_pdsch_nr_cp_clean(q, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSRAN_NRE], put);
|
||||
// Reserve RE from configuration
|
||||
if (srsran_re_pattern_list_to_symbol_mask(&cfg->rvd_re, l, rvd_mask) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error generating reserved RE mask");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Actual copy
|
||||
for (uint32_t rb = 0; rb < q->carrier.nof_prb; rb++) {
|
||||
// Skip PRB if not available in grant
|
||||
if (!grant->prb_idx[rb]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate RE index at the begin of the symbol
|
||||
uint32_t re_idx = (q->carrier.nof_prb * l + rb) * SRSRAN_NRE;
|
||||
|
||||
// Put or get
|
||||
if (put) {
|
||||
count += pdsch_nr_put_rb(&sf_symbols[re_idx], &symbols[count], &rvd_mask[rb * SRSRAN_NRE]);
|
||||
} else {
|
||||
count += pdsch_nr_get_rb(&symbols[count], &sf_symbols[re_idx], &rvd_mask[rb * SRSRAN_NRE]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,6 +347,12 @@ int srsran_pdsch_nr_encode(srsran_pdsch_nr_t* q,
|
|||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Compute DMRS pattern
|
||||
if (srsran_dmrs_sch_rvd_re_pattern(&cfg->dmrs, grant, &q->dmrs_re_pattern) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error computing DMRS pattern");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// 7.3.1.1 and 7.3.1.2
|
||||
uint32_t nof_cw = 0;
|
||||
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
|
||||
|
@ -571,10 +437,8 @@ static inline int pdsch_nr_decode_codeword(srsran_pdsch_nr_t* q,
|
|||
res->evm = srsran_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits);
|
||||
}
|
||||
|
||||
// Change LLR sign
|
||||
for (uint32_t i = 0; i < tb->nof_bits; i++) {
|
||||
llr[i] = -llr[i];
|
||||
}
|
||||
// Change LLR sign and set to zero the LLR that are not used
|
||||
srsran_vec_neg_bb(llr, llr, tb->nof_bits);
|
||||
|
||||
// Descrambling
|
||||
srsran_sequence_apply_c(llr, llr, tb->nof_bits, pdsch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx));
|
||||
|
@ -610,12 +474,18 @@ int srsran_pdsch_nr_decode(srsran_pdsch_nr_t* q,
|
|||
gettimeofday(&t[1], NULL);
|
||||
}
|
||||
|
||||
// Compute DMRS pattern
|
||||
if (srsran_dmrs_sch_rvd_re_pattern(&cfg->dmrs, grant, &q->dmrs_re_pattern) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error computing DMRS pattern");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t nof_cw = 0;
|
||||
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
|
||||
nof_cw += grant->tb[tb].enabled ? 1 : 0;
|
||||
}
|
||||
|
||||
uint32_t nof_re = srsran_ra_dl_nr_slot_nof_re(cfg, grant);
|
||||
uint32_t nof_re = grant->tb[0].nof_re;
|
||||
|
||||
if (channel->nof_re != nof_re) {
|
||||
ERROR("Inconsistent number of RE (%d!=%d)", channel->nof_re, nof_re);
|
||||
|
@ -723,6 +593,12 @@ uint32_t srsran_pdsch_nr_rx_info(const srsran_pdsch_nr_t* q,
|
|||
|
||||
len += srsran_pdsch_nr_grant_info(cfg, grant, &str[len], str_len - len);
|
||||
|
||||
if (cfg->rvd_re.count != 0) {
|
||||
len = srsran_print_check(str, str_len, len, ", Reserved={");
|
||||
len += srsran_re_pattern_list_info(&cfg->rvd_re, &str[len], str_len - len);
|
||||
len = srsran_print_check(str, str_len, len, "}");
|
||||
}
|
||||
|
||||
if (q->evm_buffer != NULL) {
|
||||
len = srsran_print_check(str, str_len, len, ",evm={", 0);
|
||||
for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) {
|
||||
|
@ -766,13 +642,5 @@ uint32_t srsran_pdsch_nr_tx_info(const srsran_pdsch_nr_t* q,
|
|||
char* str,
|
||||
uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
|
||||
len += srsran_pdsch_nr_grant_info(cfg, grant, &str[len], str_len - len);
|
||||
|
||||
if (q->meas_time_en) {
|
||||
len = srsran_print_check(str, str_len, len, ", t=%d us", q->meas_time_us);
|
||||
}
|
||||
|
||||
return len;
|
||||
return srsran_pdsch_nr_rx_info(q, cfg, grant, NULL, str, str_len);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*/
|
||||
|
||||
#include "srsran/phy/phch/ra_nr.h"
|
||||
#include "srsran/phy/ch_estimation/csi_rs.h"
|
||||
#include "srsran/phy/phch/csi.h"
|
||||
#include "srsran/phy/phch/pdsch_nr.h"
|
||||
#include "srsran/phy/phch/ra_dl_nr.h"
|
||||
|
@ -245,6 +246,27 @@ static ra_nr_table_t ra_nr_select_table(srsran_mcs_table_t mcs_table,
|
|||
return ra_nr_select_table_pdsch(mcs_table, dci_format, search_space_type, rnti_type);
|
||||
}
|
||||
|
||||
static int ra_nr_dmrs_power_offset(srsran_sch_grant_nr_t* grant)
|
||||
{
|
||||
if (grant == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Defined by TS 38.214 V15.10.0:
|
||||
// - Table 4.1-1: The ratio of PDSCH EPRE to DM-RS EPRE
|
||||
// - Table 6.2.2-1: The ratio of PUSCH EPRE to DM-RS EPRE
|
||||
float ratio_dB[3] = {0, -3, -4.77};
|
||||
|
||||
if (grant->nof_dmrs_cdm_groups_without_data < 1 || grant->nof_dmrs_cdm_groups_without_data > 3) {
|
||||
ERROR("Invalid number of DMRS CDM groups without data (%d)", grant->nof_dmrs_cdm_groups_without_data);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
grant->beta_dmrs = srsran_convert_dB_to_amplitude(-ratio_dB[grant->nof_dmrs_cdm_groups_without_data - 1]);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
double srsran_ra_nr_R_from_mcs(srsran_mcs_table_t mcs_table,
|
||||
srsran_dci_format_nr_t dci_format,
|
||||
srsran_search_space_type_t search_space_type,
|
||||
|
@ -405,6 +427,34 @@ uint32_t srsran_ra_nr_tbs(uint32_t N_re, double S, double R, uint32_t Qm, uint32
|
|||
return ra_nr_tbs_from_n_info4(n_info, R);
|
||||
}
|
||||
|
||||
static int ra_nr_assert_csi_rs_dmrs_collision(const srsran_sch_cfg_nr_t* pdsch_cfg)
|
||||
{
|
||||
// Generate DMRS pattern
|
||||
srsran_re_pattern_t dmrs_re_pattern = {};
|
||||
if (srsran_dmrs_sch_rvd_re_pattern(&pdsch_cfg->dmrs, &pdsch_cfg->grant, &dmrs_re_pattern) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error computing DMRS pattern");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Check for collision
|
||||
if (srsran_re_pattern_check_collision(&pdsch_cfg->rvd_re, &dmrs_re_pattern) < SRSRAN_SUCCESS) {
|
||||
// Create reserved info string
|
||||
char str_rvd[512] = {};
|
||||
srsran_re_pattern_list_info(&pdsch_cfg->rvd_re, str_rvd, (uint32_t)sizeof(str_rvd));
|
||||
|
||||
// Create DMRS info string
|
||||
char str_dmrs[512] = {};
|
||||
srsran_re_pattern_info(&dmrs_re_pattern, str_dmrs, (uint32_t)sizeof(str_dmrs));
|
||||
|
||||
ERROR("Error. The UE is not expected to receive CSI-RS (%s) and DM-RS (%s) on the same resource elements.",
|
||||
str_rvd,
|
||||
str_dmrs);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_ra_nr_fill_tb(const srsran_sch_cfg_nr_t* pdsch_cfg,
|
||||
const srsran_sch_grant_nr_t* grant,
|
||||
uint32_t mcs_idx,
|
||||
|
@ -451,7 +501,7 @@ int srsran_ra_nr_fill_tb(const srsran_sch_cfg_nr_t* pdsch_cfg,
|
|||
// 1) The UE shall first determine the number of REs (N RE ) within the slot.
|
||||
int N_re = srsran_ra_dl_nr_slot_nof_re(pdsch_cfg, grant);
|
||||
if (N_re <= SRSRAN_SUCCESS) {
|
||||
ERROR("Invalid number of RE");
|
||||
ERROR("Invalid number of RE (%d)", N_re);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
|
@ -461,55 +511,141 @@ int srsran_ra_nr_fill_tb(const srsran_sch_cfg_nr_t* pdsch_cfg,
|
|||
uint32_t nof_layers_cw2 = grant->nof_layers - nof_layers_cw1;
|
||||
tb->N_L = (cw_idx == 0) ? nof_layers_cw1 : nof_layers_cw2;
|
||||
|
||||
// Check DMRS and CSI-RS collision according to TS 38.211 7.4.1.5.3 Mapping to physical resources
|
||||
// If there was a collision, the number of RE in the grant would be wrong
|
||||
if (ra_nr_assert_csi_rs_dmrs_collision(pdsch_cfg) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error: CSI-RS and DMRS collision detected");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Calculate reserved RE
|
||||
uint32_t N_re_rvd = srsran_re_pattern_list_count(&pdsch_cfg->rvd_re, grant->S, grant->S + grant->L, grant->prb_idx);
|
||||
|
||||
// Steps 2,3,4
|
||||
tb->tbs = (int)srsran_ra_nr_tbs(N_re, S, R, Qm, tb->N_L);
|
||||
tb->R = R;
|
||||
tb->mod = m;
|
||||
tb->nof_re = N_re * grant->nof_layers;
|
||||
tb->nof_re = (N_re - N_re_rvd) * grant->nof_layers;
|
||||
tb->nof_bits = tb->nof_re * Qm;
|
||||
tb->enabled = true;
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int ra_dl_dmrs(const srsran_sch_hl_cfg_nr_t* pdsch_hl_cfg,
|
||||
srsran_sch_grant_nr_t* pdsch_grant,
|
||||
srsran_dmrs_sch_cfg_t* dmrs_cfg)
|
||||
static int ra_dl_dmrs(const srsran_sch_hl_cfg_nr_t* hl_cfg, srsran_sch_grant_nr_t* grant, srsran_sch_cfg_nr_t* cfg)
|
||||
{
|
||||
const bool dedicated_dmrs_present = (pdsch_grant->mapping == srsran_sch_mapping_type_A)
|
||||
? pdsch_hl_cfg->dmrs_typeA.present
|
||||
: pdsch_hl_cfg->dmrs_typeB.present;
|
||||
const bool dedicated_dmrs_present =
|
||||
(grant->mapping == srsran_sch_mapping_type_A) ? hl_cfg->dmrs_typeA.present : hl_cfg->dmrs_typeB.present;
|
||||
|
||||
if (pdsch_grant->dci_format == srsran_dci_format_nr_1_0 || !dedicated_dmrs_present) {
|
||||
if (pdsch_grant->mapping == srsran_sch_mapping_type_A) {
|
||||
if (grant->dci_format == srsran_dci_format_nr_1_0 || !dedicated_dmrs_present) {
|
||||
if (grant->mapping == srsran_sch_mapping_type_A) {
|
||||
// Absent default values are defined is TS 38.331 - DMRS-DownlinkConfig
|
||||
dmrs_cfg->additional_pos = srsran_dmrs_sch_add_pos_2;
|
||||
dmrs_cfg->type = srsran_dmrs_sch_type_1;
|
||||
dmrs_cfg->length = srsran_dmrs_sch_len_1;
|
||||
dmrs_cfg->scrambling_id0_present = false;
|
||||
dmrs_cfg->scrambling_id1_present = false;
|
||||
|
||||
if (pdsch_grant->dci_format == srsran_dci_format_nr_1_0) {
|
||||
if (srsran_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(dmrs_cfg, pdsch_grant) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error loading number of DMRS CDM groups");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
} else {
|
||||
ERROR("Invalid case");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
cfg->dmrs.additional_pos = srsran_dmrs_sch_add_pos_2;
|
||||
cfg->dmrs.type = srsran_dmrs_sch_type_1;
|
||||
cfg->dmrs.length = srsran_dmrs_sch_len_1;
|
||||
cfg->dmrs.scrambling_id0_present = false;
|
||||
cfg->dmrs.scrambling_id1_present = false;
|
||||
} else {
|
||||
ERROR("Unsupported configuration");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
} else {
|
||||
if (grant->mapping == srsran_sch_mapping_type_A) {
|
||||
cfg->dmrs.additional_pos = hl_cfg->dmrs_typeA.additional_pos;
|
||||
cfg->dmrs.type = hl_cfg->dmrs_typeA.type;
|
||||
cfg->dmrs.length = hl_cfg->dmrs_typeA.length;
|
||||
cfg->dmrs.scrambling_id0_present = false;
|
||||
cfg->dmrs.scrambling_id1_present = false;
|
||||
} else {
|
||||
cfg->dmrs.additional_pos = hl_cfg->dmrs_typeB.additional_pos;
|
||||
cfg->dmrs.type = hl_cfg->dmrs_typeB.type;
|
||||
cfg->dmrs.length = hl_cfg->dmrs_typeB.length;
|
||||
cfg->dmrs.scrambling_id0_present = false;
|
||||
cfg->dmrs.scrambling_id1_present = false;
|
||||
}
|
||||
}
|
||||
|
||||
ERROR("Unsupported configuration");
|
||||
// Set number of DMRS CDM groups without data
|
||||
if (grant->dci_format == srsran_dci_format_nr_1_0) {
|
||||
if (srsran_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(&cfg->dmrs, grant) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error loading number of DMRS CDM groups");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
} else {
|
||||
ERROR("Invalid case");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return SRSRAN_ERROR;
|
||||
// Set DMRS power offset Table 6.2.2-1: The ratio of PUSCH EPRE to DM-RS EPRE
|
||||
if (ra_nr_dmrs_power_offset(grant) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error setting DMRS power offset");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
static int ra_dl_resource_mapping(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot,
|
||||
const srsran_sch_hl_cfg_nr_t* pdsch_hl_cfg,
|
||||
srsran_sch_cfg_nr_t* pdsch_cfg)
|
||||
{
|
||||
// SS/PBCH block transmission resources not available for PDSCH
|
||||
// ... Not implemented
|
||||
|
||||
// 5.1.4.1 PDSCH resource mapping with RB symbol level granularity
|
||||
// rateMatchPatternToAddModList ... Not implemented
|
||||
|
||||
// 5.1.4.2 PDSCH resource mapping with RE level granularity
|
||||
// RateMatchingPatternLTE-CRS ... Not implemented
|
||||
|
||||
// Append periodic ZP-CSI-RS
|
||||
for (uint32_t i = 0; i < pdsch_hl_cfg->p_zp_csi_rs_set.count; i++) {
|
||||
// Select resource
|
||||
const srsran_csi_rs_zp_resource_t* resource = &pdsch_hl_cfg->p_zp_csi_rs_set.data[i];
|
||||
|
||||
// Check if the periodic ZP-CSI is transmitted
|
||||
if (srsran_csi_rs_send(&resource->periodicity, slot)) {
|
||||
INFO("Tx/Rx ZP-CSI-RS @slot=%d\n", slot->idx);
|
||||
if (srsran_csi_rs_append_resource_to_pattern(carrier, &resource->resource_mapping, &pdsch_cfg->rvd_re)) {
|
||||
ERROR("Error appending ZP-CSI-RS as RE pattern");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append semi-persistent ZP-CSI-RS here
|
||||
// ... not implemented
|
||||
|
||||
// Append aperiodic ZP-CSI-RS here
|
||||
// ... not implemented
|
||||
|
||||
// Append periodic NZP-CSI-RS according to TS 38.211 clause 7.3.1.5 Mapping to virtual resource blocks
|
||||
// Only aplicable if CRC is scrambled by C-RNTI, MCS-C-RNTI, CS-RNTI, or PDSCH with SPS
|
||||
bool nzp_rvd_valid = pdsch_cfg->grant.rnti_type == srsran_rnti_type_c ||
|
||||
pdsch_cfg->grant.rnti_type == srsran_rnti_type_mcs_c ||
|
||||
pdsch_cfg->grant.rnti_type == srsran_rnti_type_cs;
|
||||
for (uint32_t set_id = 0; set_id < SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_SETS && nzp_rvd_valid; set_id++) {
|
||||
for (uint32_t res_id = 0; res_id < pdsch_hl_cfg->nzp_csi_rs_sets[set_id].count; res_id++) {
|
||||
// Select resource
|
||||
const srsran_csi_rs_nzp_resource_t* resource = &pdsch_hl_cfg->nzp_csi_rs_sets[set_id].data[res_id];
|
||||
|
||||
// Check if the periodic ZP-CSI is transmitted
|
||||
if (srsran_csi_rs_send(&resource->periodicity, slot)) {
|
||||
INFO("Tx/Rx NZP-CSI-RS set_id=%d; res=%d; @slot=%d\n", set_id, res_id, slot->idx);
|
||||
if (srsran_csi_rs_append_resource_to_pattern(carrier, &resource->resource_mapping, &pdsch_cfg->rvd_re)) {
|
||||
ERROR("Error appending ZP-CSI-RS as RE pattern");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_ra_dl_dci_to_grant_nr(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot,
|
||||
const srsran_sch_hl_cfg_nr_t* pdsch_hl_cfg,
|
||||
const srsran_dci_dl_nr_t* dci_dl,
|
||||
srsran_sch_cfg_nr_t* pdsch_cfg,
|
||||
|
@ -541,8 +677,14 @@ int srsran_ra_dl_dci_to_grant_nr(const srsran_carrier_nr_t* carrier,
|
|||
pdsch_grant->rnti_type = dci_dl->rnti_type;
|
||||
pdsch_grant->tb[0].rv = dci_dl->rv;
|
||||
|
||||
// 5.1.4 PDSCH resource mapping
|
||||
if (ra_dl_resource_mapping(carrier, slot, pdsch_hl_cfg, pdsch_cfg) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error in resource mapping");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// 5.1.6.2 DM-RS reception procedure
|
||||
if (ra_dl_dmrs(pdsch_hl_cfg, pdsch_grant, &pdsch_cfg->dmrs) < SRSRAN_SUCCESS) {
|
||||
if (ra_dl_dmrs(pdsch_hl_cfg, pdsch_grant, pdsch_cfg) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error selecting DMRS configuration");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
@ -603,7 +745,7 @@ ra_ul_dmrs(const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg, srsran_sch_grant_nr_t* pu
|
|||
}
|
||||
|
||||
// Set DMRS power offset Table 6.2.2-1: The ratio of PUSCH EPRE to DM-RS EPRE
|
||||
if (srsran_ra_ul_nr_dmrs_power_offset(pusch_grant) < SRSRAN_SUCCESS) {
|
||||
if (ra_nr_dmrs_power_offset(pusch_grant) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error setting DMRS power offset");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
@ -746,4 +888,4 @@ int srsran_ra_ul_set_grant_uci_nr(const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg,
|
|||
pusch_cfg->uci = *uci_cfg;
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,24 +222,6 @@ int srsran_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srsran_sch
|
|||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_ra_ul_nr_dmrs_power_offset(srsran_sch_grant_nr_t* grant)
|
||||
{
|
||||
if (grant == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
float ratio_dB[3] = {0, -3, -4.77};
|
||||
|
||||
if (grant->nof_dmrs_cdm_groups_without_data < 1 || grant->nof_dmrs_cdm_groups_without_data > 3) {
|
||||
ERROR("Invalid number of DMRS CDM groups without data (%d)", grant->nof_dmrs_cdm_groups_without_data);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
grant->beta_dmrs = srsran_convert_dB_to_amplitude(-ratio_dB[grant->nof_dmrs_cdm_groups_without_data - 1]);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
#define RA_UL_PUCCH_CODE_RATE_N 8
|
||||
#define RA_UL_PUCCH_CODE_RATE_RESERVED NAN
|
||||
|
||||
|
|
|
@ -28,11 +28,10 @@ static srsran_carrier_nr_t carrier = {
|
|||
1 // max_mimo_layers
|
||||
};
|
||||
|
||||
static uint32_t n_prb = 0; // Set to 0 for steering
|
||||
static uint32_t mcs = 30; // Set to 30 for steering
|
||||
static srsran_sch_cfg_nr_t pdsch_cfg = {};
|
||||
static srsran_sch_grant_nr_t pdsch_grant = {};
|
||||
static uint16_t rnti = 0x1234;
|
||||
static uint32_t n_prb = 0; // Set to 0 for steering
|
||||
static uint32_t mcs = 30; // Set to 30 for steering
|
||||
static srsran_sch_cfg_nr_t pdsch_cfg = {};
|
||||
static uint16_t rnti = 0x1234;
|
||||
|
||||
void usage(char* prog)
|
||||
{
|
||||
|
@ -153,20 +152,20 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
// Use grant default A time resources with m=0
|
||||
if (srsran_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &pdsch_grant) < SRSRAN_SUCCESS) {
|
||||
if (srsran_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &pdsch_cfg.grant) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error loading default grant");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// Load number of DMRS CDM groups without data
|
||||
if (srsran_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(&pdsch_cfg.dmrs, &pdsch_grant) < SRSRAN_SUCCESS) {
|
||||
if (srsran_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(&pdsch_cfg.dmrs, &pdsch_cfg.grant) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error loading number of DMRS CDM groups without data");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
pdsch_grant.nof_layers = carrier.max_mimo_layers;
|
||||
pdsch_grant.dci_format = srsran_dci_format_nr_1_0;
|
||||
pdsch_grant.rnti = rnti;
|
||||
pdsch_cfg.grant.nof_layers = carrier.max_mimo_layers;
|
||||
pdsch_cfg.grant.dci_format = srsran_dci_format_nr_1_0;
|
||||
pdsch_cfg.grant.rnti = rnti;
|
||||
|
||||
uint32_t n_prb_start = 1;
|
||||
uint32_t n_prb_end = carrier.nof_prb + 1;
|
||||
|
@ -190,10 +189,10 @@ int main(int argc, char** argv)
|
|||
for (n_prb = n_prb_start; n_prb < n_prb_end; n_prb++) {
|
||||
for (mcs = mcs_start; mcs < mcs_end; mcs++) {
|
||||
for (uint32_t n = 0; n < SRSRAN_MAX_PRB_NR; n++) {
|
||||
pdsch_grant.prb_idx[n] = (n < n_prb);
|
||||
pdsch_cfg.grant.prb_idx[n] = (n < n_prb);
|
||||
}
|
||||
|
||||
if (srsran_ra_nr_fill_tb(&pdsch_cfg, &pdsch_grant, mcs, &pdsch_grant.tb[0]) < SRSRAN_SUCCESS) {
|
||||
if (srsran_ra_nr_fill_tb(&pdsch_cfg, &pdsch_cfg.grant, mcs, &pdsch_cfg.grant.tb[0]) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error filing tb");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
@ -204,28 +203,29 @@ int main(int argc, char** argv)
|
|||
continue;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < pdsch_grant.tb[tb].tbs; i++) {
|
||||
for (uint32_t i = 0; i < pdsch_cfg.grant.tb[tb].tbs; i++) {
|
||||
data_tx[tb][i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, UINT8_MAX);
|
||||
}
|
||||
pdsch_grant.tb[tb].softbuffer.tx = &softbuffer_tx;
|
||||
pdsch_cfg.grant.tb[tb].softbuffer.tx = &softbuffer_tx;
|
||||
}
|
||||
|
||||
if (srsran_pdsch_nr_encode(&pdsch_tx, &pdsch_cfg, &pdsch_grant, data_tx, sf_symbols) < SRSRAN_SUCCESS) {
|
||||
if (srsran_pdsch_nr_encode(&pdsch_tx, &pdsch_cfg, &pdsch_cfg.grant, data_tx, sf_symbols) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error encoding");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
|
||||
pdsch_grant.tb[tb].softbuffer.rx = &softbuffer_rx;
|
||||
srsran_softbuffer_rx_reset(pdsch_grant.tb[tb].softbuffer.rx);
|
||||
pdsch_cfg.grant.tb[tb].softbuffer.rx = &softbuffer_rx;
|
||||
srsran_softbuffer_rx_reset(pdsch_cfg.grant.tb[tb].softbuffer.rx);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < pdsch_grant.tb->nof_re; i++) {
|
||||
for (uint32_t i = 0; i < pdsch_cfg.grant.tb->nof_re; i++) {
|
||||
chest.ce[0][0][i] = 1.0f;
|
||||
}
|
||||
chest.nof_re = pdsch_grant.tb->nof_re;
|
||||
chest.nof_re = pdsch_cfg.grant.tb->nof_re;
|
||||
|
||||
if (srsran_pdsch_nr_decode(&pdsch_rx, &pdsch_cfg, &pdsch_grant, &chest, sf_symbols, pdsch_res) < SRSRAN_SUCCESS) {
|
||||
if (srsran_pdsch_nr_decode(&pdsch_rx, &pdsch_cfg, &pdsch_cfg.grant, &chest, sf_symbols, pdsch_res) <
|
||||
SRSRAN_SUCCESS) {
|
||||
ERROR("Error encoding");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
@ -236,18 +236,18 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
float mse = 0.0f;
|
||||
uint32_t nof_re = srsran_ra_dl_nr_slot_nof_re(&pdsch_cfg, &pdsch_grant);
|
||||
for (uint32_t i = 0; i < pdsch_grant.nof_layers; i++) {
|
||||
uint32_t nof_re = srsran_ra_dl_nr_slot_nof_re(&pdsch_cfg, &pdsch_cfg.grant);
|
||||
for (uint32_t i = 0; i < pdsch_cfg.grant.nof_layers; i++) {
|
||||
for (uint32_t j = 0; j < nof_re; j++) {
|
||||
mse += cabsf(pdsch_tx.d[i][j] - pdsch_rx.d[i][j]);
|
||||
}
|
||||
}
|
||||
if (nof_re * pdsch_grant.nof_layers > 0) {
|
||||
mse = mse / (nof_re * pdsch_grant.nof_layers);
|
||||
if (nof_re * pdsch_cfg.grant.nof_layers > 0) {
|
||||
mse = mse / (nof_re * pdsch_cfg.grant.nof_layers);
|
||||
}
|
||||
if (mse > 0.001) {
|
||||
ERROR("MSE error (%f) is too high", mse);
|
||||
for (uint32_t i = 0; i < pdsch_grant.nof_layers; i++) {
|
||||
for (uint32_t i = 0; i < pdsch_cfg.grant.nof_layers; i++) {
|
||||
printf("d_tx[%d]=", i);
|
||||
srsran_vec_fprint_c(stdout, pdsch_tx.d[i], nof_re);
|
||||
printf("d_rx[%d]=", i);
|
||||
|
@ -257,20 +257,20 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
if (!pdsch_res[0].crc) {
|
||||
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_grant.tb[0].tbs);
|
||||
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs);
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (memcmp(data_tx[0], data_rx[0], pdsch_grant.tb[0].tbs / 8) != 0) {
|
||||
ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_grant.tb[0].tbs);
|
||||
if (memcmp(data_tx[0], data_rx[0], pdsch_cfg.grant.tb[0].tbs / 8) != 0) {
|
||||
ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs);
|
||||
printf("Tx data: ");
|
||||
srsran_vec_fprint_byte(stdout, data_tx[0], pdsch_grant.tb[0].tbs / 8);
|
||||
srsran_vec_fprint_byte(stdout, data_tx[0], pdsch_cfg.grant.tb[0].tbs / 8);
|
||||
printf("Rx data: ");
|
||||
srsran_vec_fprint_byte(stdout, data_rx[0], pdsch_grant.tb[0].tbs / 8);
|
||||
srsran_vec_fprint_byte(stdout, data_rx[0], pdsch_cfg.grant.tb[0].tbs / 8);
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pdsch_grant.tb[0].tbs, pdsch_res[0].evm);
|
||||
INFO("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs, pdsch_res[0].evm);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,320 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsran/phy/utils/re_pattern.h"
|
||||
#include "srsran/phy/utils/debug.h"
|
||||
#include "srsran/phy/utils/vector.h"
|
||||
|
||||
bool srsran_re_pattern_to_mask(const srsran_re_pattern_list_t* list, uint32_t l, uint32_t k)
|
||||
{
|
||||
uint32_t rb_idx = k % SRSRAN_NRE;
|
||||
uint32_t sc_idx = k / SRSRAN_NRE;
|
||||
|
||||
// Check pattern list is valid
|
||||
if (list == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Iterate all given patterns
|
||||
for (uint32_t i = 0; i < list->count; i++) {
|
||||
const srsran_re_pattern_t* pattern = &list->data[i];
|
||||
|
||||
// Skip pattern if it is not active in this OFDM symbol
|
||||
if (!pattern->symbol[l]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip pattern if RB index is put of the pattern bounds
|
||||
if (rb_idx < pattern->rb_begin || rb_idx >= pattern->rb_end) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Matched SC, early return
|
||||
if (pattern->sc[sc_idx]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If reached here, no pattern was matched
|
||||
return false;
|
||||
}
|
||||
|
||||
int srsran_re_pattern_to_symbol_mask(const srsran_re_pattern_t* pattern, uint32_t l, bool* mask)
|
||||
{
|
||||
// Check inputs
|
||||
if (pattern == NULL || mask == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Check symbol index is in range
|
||||
if (l >= SRSRAN_NSYMB_PER_SLOT_NR) {
|
||||
ERROR("Symbol index is out of range");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Skip pattern if it is not active in this OFDM symbol
|
||||
if (!pattern->symbol[l]) {
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
// Make sure RB end is bounded
|
||||
if (pattern->rb_end > SRSRAN_MAX_PRB_NR) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Add mask for pattern
|
||||
for (uint32_t rb_idx = pattern->rb_begin; rb_idx < pattern->rb_end; rb_idx += pattern->rb_stride) {
|
||||
for (uint32_t sc_idx = 0; sc_idx < SRSRAN_NRE; sc_idx++) {
|
||||
mask[rb_idx * SRSRAN_NRE + sc_idx] |= pattern->sc[sc_idx];
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_re_pattern_list_to_symbol_mask(const srsran_re_pattern_list_t* list, uint32_t l, bool* mask)
|
||||
{
|
||||
// Check inputs
|
||||
if (list == NULL || mask == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Iterate all given patterns
|
||||
for (uint32_t i = 0; i < list->count; i++) {
|
||||
if (srsran_re_pattern_to_symbol_mask(&list->data[i], l, mask) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error calculating mask");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_re_pattern_merge(srsran_re_pattern_list_t* list, const srsran_re_pattern_t* p)
|
||||
{
|
||||
// Check inputs are valid
|
||||
if (list == NULL || p == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Count number of subcarrier mask
|
||||
uint32_t kcount = 0;
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE; k++) {
|
||||
kcount += p->sc[k] ? 1 : 0;
|
||||
}
|
||||
|
||||
// Count number of symbol mask
|
||||
uint32_t lcount = 0;
|
||||
for (uint32_t l = 0; l < SRSRAN_NRE; l++) {
|
||||
lcount += p->symbol[l] ? 1 : 0;
|
||||
}
|
||||
|
||||
// If any mask is empty, ignore
|
||||
if (kcount == 0 || lcount == 0) {
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
// Iterate all given patterns
|
||||
for (uint32_t i = 0; i < list->count; i++) {
|
||||
srsran_re_pattern_t* pattern = &list->data[i];
|
||||
|
||||
// Skip if RB parameters dont match
|
||||
if (pattern->rb_begin != p->rb_begin || pattern->rb_end != p->rb_end || pattern->rb_stride != p->rb_stride) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if symbol mask matches
|
||||
bool lmatch = (memcmp(pattern->symbol, p->symbol, SRSRAN_NSYMB_PER_SLOT_NR) == 0);
|
||||
|
||||
// Check if sc mask matches
|
||||
bool kmatch = (memcmp(pattern->sc, p->sc, SRSRAN_NRE) == 0);
|
||||
|
||||
// If OFDM symbols and subcarriers mask match, it means that the patterns are completely overlapped and no merging
|
||||
// is required
|
||||
if (kmatch && lmatch) {
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
// If OFDM symbols mask matches, merge subcarrier mask
|
||||
if (lmatch) {
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE; k++) {
|
||||
pattern->sc[k] |= p->sc[k];
|
||||
}
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
// If subcarriers mask matches, merge OFDM symbols mask
|
||||
if (kmatch) {
|
||||
for (uint32_t l = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) {
|
||||
pattern->symbol[l] |= p->symbol[l];
|
||||
}
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// If reached here, no pattern was matched. Try appending
|
||||
if (list->count >= SRSRAN_RE_PATTERN_LIST_SIZE) {
|
||||
ERROR("Insufficient number of available RE patterns in list");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Append
|
||||
list->data[list->count] = *p;
|
||||
list->count++;
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_re_pattern_check_collision(const srsran_re_pattern_list_t* list, const srsran_re_pattern_t* p)
|
||||
{
|
||||
// Check inputs are valid
|
||||
if (list == NULL || p == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
// Count number of subcarrier mask
|
||||
uint32_t kcount = 0;
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE; k++) {
|
||||
kcount += p->sc[k] ? 1 : 0;
|
||||
}
|
||||
|
||||
// Count number of symbol mask
|
||||
uint32_t lcount = 0;
|
||||
for (uint32_t l = 0; l < SRSRAN_NRE; l++) {
|
||||
lcount += p->symbol[l] ? 1 : 0;
|
||||
}
|
||||
|
||||
// If any mask is empty, no collision
|
||||
if (kcount == 0 || lcount == 0) {
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
// Iterate all given patterns
|
||||
for (uint32_t i = 0; i < list->count; i++) {
|
||||
const srsran_re_pattern_t* pattern = &list->data[i];
|
||||
|
||||
// Skip if RB do not overlap
|
||||
if (pattern->rb_begin > p->rb_end || p->rb_begin > pattern->rb_end) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if symbol are matched
|
||||
bool lmatch = false;
|
||||
for (uint32_t l = 0; l < SRSRAN_NSYMB_PER_SLOT_NR && !lmatch; l++) {
|
||||
// Consider match if both patterns have a positive symbol in common
|
||||
lmatch = (p->symbol[l] && pattern->symbol[l]);
|
||||
}
|
||||
|
||||
// If the symbols are not matched, skip pattern
|
||||
if (!lmatch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if any subcarrier mask matches
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE; k++) {
|
||||
// Consider a collision if both subcarrier mask are true
|
||||
if (p->sc[k] && pattern->sc[k]) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If reached here, means no collision
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
void srsran_re_pattern_reset(srsran_re_pattern_list_t* list)
|
||||
{
|
||||
if (list == NULL) {
|
||||
return;
|
||||
}
|
||||
SRSRAN_MEM_ZERO(list, srsran_re_pattern_list_t, 1);
|
||||
}
|
||||
|
||||
uint32_t srsran_re_pattern_info(const srsran_re_pattern_t* pattern, char* str, uint32_t str_len)
|
||||
{
|
||||
if (pattern == NULL || str == NULL || str_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char subc[SRSRAN_NRE + 1] = {};
|
||||
srsran_vec_sprint_bin(subc, SRSRAN_NRE + 1, (uint8_t*)pattern->sc, SRSRAN_NRE);
|
||||
|
||||
char symb[SRSRAN_NSYMB_PER_SLOT_NR + 1] = {};
|
||||
srsran_vec_sprint_bin(symb, SRSRAN_NSYMB_PER_SLOT_NR + 1, (uint8_t*)pattern->symbol, SRSRAN_NSYMB_PER_SLOT_NR);
|
||||
|
||||
return srsran_print_check(str,
|
||||
str_len,
|
||||
0,
|
||||
"begin=%d end=%d stride=%d sc=%s symb=%s ",
|
||||
pattern->rb_begin,
|
||||
pattern->rb_end,
|
||||
pattern->rb_stride,
|
||||
subc,
|
||||
symb);
|
||||
}
|
||||
|
||||
uint32_t srsran_re_pattern_list_info(const srsran_re_pattern_list_t* list, char* str, uint32_t str_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
if (list == NULL || str == NULL || str_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < list->count; i++) {
|
||||
len = srsran_print_check(str, str_len, len, "RE%d: ", i);
|
||||
len += srsran_re_pattern_info(&list->data[i], &str[len], str_len - len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
uint32_t srsran_re_pattern_list_count(const srsran_re_pattern_list_t* list,
|
||||
uint32_t symbol_begin,
|
||||
uint32_t symbol_end,
|
||||
const bool prb_mask[SRSRAN_MAX_PRB_NR])
|
||||
{
|
||||
uint32_t count = 0;
|
||||
if (list == NULL || prb_mask == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Iterate over all symbols and create a symbol mask
|
||||
for (uint32_t l = symbol_begin; l < symbol_end; l++) {
|
||||
// Entire symbol mask to prevent overlapped RE to count twice
|
||||
bool symbol_mask[SRSRAN_NRE * SRSRAN_MAX_PRB_NR] = {};
|
||||
|
||||
// For each pattern, compute symbol mask
|
||||
for (uint32_t i = 0; i < list->count; i++) {
|
||||
if (srsran_re_pattern_to_symbol_mask(&list->data[i], l, symbol_mask) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error calculating symbol mask");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Count number of masked elements
|
||||
for (uint32_t rb = 0; rb < SRSRAN_MAX_PRB_NR; rb++) {
|
||||
// Skip PRB if disabled
|
||||
if (!prb_mask[rb]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Iterate all subcarriers in the PRB
|
||||
for (uint32_t k = rb * SRSRAN_NRE; k < (rb + 1) * SRSRAN_NRE; k++) {
|
||||
// Count only the true masked RE
|
||||
count += (uint32_t)symbol_mask[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
|
@ -36,10 +36,19 @@ target_link_libraries(vector_test srsran_phy)
|
|||
add_test(vector_test vector_test)
|
||||
|
||||
|
||||
########################################################################
|
||||
# Ring-Buffer TEST
|
||||
########################################################################
|
||||
|
||||
add_executable(ringbuffer_test ring_buffer_test.c)
|
||||
target_link_libraries(ringbuffer_test srsran_phy)
|
||||
|
||||
add_test(ringbuffer_tester ringbuffer_test)
|
||||
|
||||
########################################################################
|
||||
# RE-Pattern TEST
|
||||
########################################################################
|
||||
add_executable(re_pattern_test re_pattern_test.c)
|
||||
target_link_libraries(re_pattern_test srsran_phy)
|
||||
|
||||
add_test(re_pattern_test re_pattern_test)
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/test_common.h"
|
||||
#include "srsran/phy/utils/re_pattern.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
srsran_re_pattern_list_t pattern_list;
|
||||
|
||||
// Reset list
|
||||
srsran_re_pattern_reset(&pattern_list);
|
||||
|
||||
// Create first pattern and merge
|
||||
srsran_re_pattern_t pattern_1 = {};
|
||||
pattern_1.rb_begin = 1;
|
||||
pattern_1.rb_end = 50;
|
||||
pattern_1.rb_stride = 1;
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE; k++) {
|
||||
pattern_1.sc[k] = (k % 2 == 0); // Only even subcarriers
|
||||
}
|
||||
for (uint32_t l = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) {
|
||||
pattern_1.symbol[l] = (l % 2 == 0); // Only even symbols
|
||||
}
|
||||
TESTASSERT(srsran_re_pattern_merge(&pattern_list, &pattern_1) == SRSRAN_SUCCESS);
|
||||
TESTASSERT(pattern_list.count == 1);
|
||||
|
||||
// Create second pattern and merge
|
||||
srsran_re_pattern_t pattern_2 = pattern_1;
|
||||
for (uint32_t l = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) {
|
||||
pattern_2.symbol[l] = (l % 2 == 1); // Only odd symbols
|
||||
}
|
||||
TESTASSERT(srsran_re_pattern_merge(&pattern_list, &pattern_2) == SRSRAN_SUCCESS);
|
||||
TESTASSERT(pattern_list.count == 1);
|
||||
|
||||
// Assert generated mask
|
||||
for (uint32_t l = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) {
|
||||
bool mask[SRSRAN_NRE * SRSRAN_MAX_PRB_NR] = {};
|
||||
TESTASSERT(srsran_re_pattern_list_to_symbol_mask(&pattern_list, l, mask) == SRSRAN_SUCCESS);
|
||||
for (uint32_t k = 0; k < SRSRAN_NRE * SRSRAN_MAX_PRB_NR; k++) {
|
||||
if (k >= pattern_1.rb_begin * SRSRAN_NRE && k < pattern_1.rb_end * SRSRAN_NRE &&
|
||||
(k / SRSRAN_NRE - pattern_1.rb_begin) % pattern_1.rb_stride == 0) {
|
||||
TESTASSERT(mask[k] == (k % 2 == 0));
|
||||
} else {
|
||||
TESTASSERT(mask[k] == false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
|
@ -211,6 +211,44 @@ TEST(
|
|||
free(y);
|
||||
free(z);)
|
||||
|
||||
TEST(
|
||||
srsran_vec_neg_bbb, MALLOC(int8_t, x); MALLOC(int8_t, y); MALLOC(int8_t, z);
|
||||
|
||||
int16_t gold = 0.0f;
|
||||
for (int i = 0; i < block_size; i++) {
|
||||
x[i] = RANDOM_B();
|
||||
do {
|
||||
y[i] = RANDOM_B();
|
||||
} while (!y[i]);
|
||||
}
|
||||
|
||||
TEST_CALL(srsran_vec_neg_bbb(x, y, z, block_size))
|
||||
|
||||
for (int i = 0; i < block_size; i++) {
|
||||
gold = y[i] < 0 ? -x[i] : x[i];
|
||||
mse += abs(gold - z[i]);
|
||||
}
|
||||
|
||||
free(x);
|
||||
free(y);
|
||||
free(z);)
|
||||
|
||||
TEST(
|
||||
srsran_vec_neg_bb, MALLOC(int8_t, x); MALLOC(int8_t, z);
|
||||
|
||||
int16_t gold = 0.0f;
|
||||
for (int i = 0; i < block_size; i++) { x[i] = RANDOM_B(); }
|
||||
|
||||
TEST_CALL(srsran_vec_neg_bb(x, z, block_size))
|
||||
|
||||
for (int i = 0; i < block_size; i++) {
|
||||
gold = -x[i];
|
||||
mse += abs(gold - z[i]);
|
||||
}
|
||||
|
||||
free(x);
|
||||
free(z);)
|
||||
|
||||
TEST(
|
||||
srsran_vec_acc_cc, MALLOC(cf_t, x); cf_t z = 0.0f;
|
||||
|
||||
|
@ -836,6 +874,14 @@ int main(int argc, char** argv)
|
|||
test_srsran_vec_neg_sss(func_names[func_count], &timmings[func_count][size_count], block_size);
|
||||
func_count++;
|
||||
|
||||
passed[func_count][size_count] =
|
||||
test_srsran_vec_neg_bbb(func_names[func_count], &timmings[func_count][size_count], block_size);
|
||||
func_count++;
|
||||
|
||||
passed[func_count][size_count] =
|
||||
test_srsran_vec_neg_bb(func_names[func_count], &timmings[func_count][size_count], block_size);
|
||||
func_count++;
|
||||
|
||||
passed[func_count][size_count] =
|
||||
test_srsran_vec_acc_cc(func_names[func_count], &timmings[func_count][size_count], block_size);
|
||||
func_count++;
|
||||
|
|
|
@ -465,11 +465,19 @@ void srsran_vec_neg_sss(const int16_t* x, const int16_t* y, int16_t* z, const ui
|
|||
{
|
||||
srsran_vec_neg_sss_simd(x, y, z, len);
|
||||
}
|
||||
|
||||
void srsran_vec_neg_bbb(const int8_t* x, const int8_t* y, int8_t* z, const uint32_t len)
|
||||
{
|
||||
srsran_vec_neg_bbb_simd(x, y, z, len);
|
||||
}
|
||||
|
||||
void srsran_vec_neg_bb(const int8_t* x, int8_t* z, const uint32_t len)
|
||||
{
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
z[i] = -x[i];
|
||||
}
|
||||
}
|
||||
|
||||
// CFO and OFDM processing
|
||||
void srsran_vec_prod_ccc(const cf_t* x, const cf_t* y, cf_t* z, const uint32_t len)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 Software Radio Systems Limited
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright 2013-2021 Software Radio Systems Limited
|
||||
# Copyright 2013-2020 Software Radio Systems Limited
|
||||
#
|
||||
# By using this file, you agree to the terms and conditions set
|
||||
# forth in the LICENSE file which can be found at the top level of
|
||||
|
@ -52,4 +52,7 @@ add_lte_test(pucch_ca_test pucch_ca_test)
|
|||
|
||||
add_executable(phy_dl_nr_test phy_dl_nr_test.c)
|
||||
target_link_libraries(phy_dl_nr_test srsran_phy srsran_common srsran_phy ${SEC_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
add_nr_test(phy_dl_nr_test phy_dl_nr_test -p 100 -m 28)
|
||||
add_nr_test(phy_dl_nr_test phy_dl_nr_test -p 100 -m 28)
|
||||
add_nr_test(phy_dl_nr_test_rvd phy_dl_nr_test -P 52 -p 52 -m 0
|
||||
-R 0 52 1 010010010010 00000000010000
|
||||
-R 0 52 1 100100100100 00000010000000)
|
|
@ -20,20 +20,18 @@
|
|||
#include <getopt.h>
|
||||
|
||||
static srsran_carrier_nr_t carrier = {
|
||||
0, // cell_id
|
||||
501, // cell_id
|
||||
0, // numerology
|
||||
100, // nof_prb
|
||||
52, // nof_prb
|
||||
0, // start
|
||||
1 // max_mimo_layers
|
||||
|
||||
};
|
||||
|
||||
static uint32_t n_prb = 0; // Set to 0 for steering
|
||||
static uint32_t mcs = 30; // Set to 30 for steering
|
||||
static srsran_sch_cfg_nr_t pdsch_cfg = {};
|
||||
static srsran_sch_grant_nr_t pdsch_grant = {};
|
||||
static uint16_t rnti = 0x1234;
|
||||
static uint32_t nof_slots = 10;
|
||||
static uint32_t n_prb = 0; // Set to 0 for steering
|
||||
static uint32_t mcs = 30; // Set to 30 for steering
|
||||
static srsran_sch_cfg_nr_t pdsch_cfg = {};
|
||||
static uint32_t nof_slots = 10;
|
||||
|
||||
static void usage(char* prog)
|
||||
{
|
||||
|
@ -44,6 +42,7 @@ static void usage(char* prog)
|
|||
printf("\t-m MCS PRB, set to >28 for steering [Default %d]\n", mcs);
|
||||
printf("\t-T Provide MCS table (64qam, 256qam, 64qamLowSE) [Default %s]\n",
|
||||
srsran_mcs_table_to_str(pdsch_cfg.sch_cfg.mcs_table));
|
||||
printf("\t-R Reserve RE: [rb_begin] [rb_end] [rb_stride] [sc_mask] [symbol_mask]\n");
|
||||
printf("\t-L Provide number of layers [Default %d]\n", carrier.max_mimo_layers);
|
||||
printf("\t-v [set srsran_verbose to debug, default none]\n");
|
||||
}
|
||||
|
@ -51,7 +50,7 @@ static void usage(char* prog)
|
|||
static int parse_args(int argc, char** argv)
|
||||
{
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "PpmnTLv")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "RPpmnTLv")) != -1) {
|
||||
switch (opt) {
|
||||
case 'P':
|
||||
carrier.nof_prb = (uint32_t)strtol(argv[optind], NULL, 10);
|
||||
|
@ -68,6 +67,24 @@ static int parse_args(int argc, char** argv)
|
|||
case 'T':
|
||||
pdsch_cfg.sch_cfg.mcs_table = srsran_mcs_table_from_str(argv[optind]);
|
||||
break;
|
||||
case 'R': {
|
||||
srsran_re_pattern_t pattern = {};
|
||||
pattern.rb_begin = (uint32_t)strtol(argv[optind++], NULL, 10);
|
||||
pattern.rb_end = (uint32_t)strtol(argv[optind++], NULL, 10);
|
||||
pattern.rb_stride = (uint32_t)strtol(argv[optind++], NULL, 10);
|
||||
uint32_t sc_mask = (uint32_t)strtol(argv[optind++], NULL, 2);
|
||||
for (uint32_t i = 0; i < SRSRAN_NRE; i++) {
|
||||
pattern.sc[i] = ((sc_mask >> (SRSRAN_NRE - 1U - i)) & 0x1) == 0x1;
|
||||
}
|
||||
uint32_t symbol_mask = (uint32_t)strtol(argv[optind], NULL, 2);
|
||||
for (uint32_t i = 0; i < SRSRAN_NSYMB_PER_SLOT_NR; i++) {
|
||||
pattern.symbol[i] = ((symbol_mask >> (SRSRAN_NSYMB_PER_SLOT_NR - 1U - i)) & 0x1) == 0x1;
|
||||
}
|
||||
if (srsran_re_pattern_merge(&pdsch_cfg.rvd_re, &pattern) < SRSRAN_ERROR) {
|
||||
ERROR("Error adding pattern");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
} break;
|
||||
case 'L':
|
||||
carrier.max_mimo_layers = (uint32_t)strtol(argv[optind], NULL, 10);
|
||||
break;
|
||||
|
@ -86,7 +103,6 @@ static int parse_args(int argc, char** argv)
|
|||
static int work_gnb_dl(srsran_enb_dl_nr_t* enb_dl,
|
||||
srsran_slot_cfg_t* slot,
|
||||
srsran_search_space_t* search_space,
|
||||
srsran_dci_dl_nr_t* dci_dl,
|
||||
srsran_dci_location_t* dci_location,
|
||||
uint8_t** data_tx)
|
||||
{
|
||||
|
@ -96,20 +112,26 @@ static int work_gnb_dl(srsran_enb_dl_nr_t* enb_dl,
|
|||
}
|
||||
|
||||
// Hard-coded values
|
||||
dci_dl->format = srsran_dci_format_nr_1_0;
|
||||
dci_dl->rnti_type = srsran_rnti_type_c;
|
||||
dci_dl->location = *dci_location;
|
||||
dci_dl->search_space = search_space->type;
|
||||
dci_dl->rnti = rnti;
|
||||
srsran_dci_dl_nr_t dci_dl = {};
|
||||
dci_dl.rnti = pdsch_cfg.grant.rnti;
|
||||
dci_dl.rnti_type = pdsch_cfg.grant.rnti_type;
|
||||
dci_dl.format = srsran_dci_format_nr_1_0;
|
||||
dci_dl.location = *dci_location;
|
||||
dci_dl.search_space = search_space->type;
|
||||
dci_dl.coreset_id = 1;
|
||||
dci_dl.freq_domain_assigment = 0;
|
||||
dci_dl.time_domain_assigment = 0;
|
||||
dci_dl.vrb_to_prb_mapping = 0;
|
||||
dci_dl.mcs = mcs;
|
||||
dci_dl.rv = 0;
|
||||
|
||||
// Put actual DCI
|
||||
if (srsran_enb_dl_nr_pdcch_put(enb_dl, slot, dci_dl) < SRSRAN_SUCCESS) {
|
||||
if (srsran_enb_dl_nr_pdcch_put(enb_dl, slot, &dci_dl) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error putting PDCCH");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Put PDSCH transmission
|
||||
pdsch_cfg.grant = pdsch_grant;
|
||||
if (srsran_enb_dl_nr_pdsch_put(enb_dl, slot, &pdsch_cfg, data_tx) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error putting PDSCH");
|
||||
return SRSRAN_ERROR;
|
||||
|
@ -124,8 +146,9 @@ static int work_ue_dl(srsran_ue_dl_nr_t* ue_dl, srsran_slot_cfg_t* slot, srsran_
|
|||
{
|
||||
srsran_ue_dl_nr_estimate_fft(ue_dl, slot);
|
||||
|
||||
srsran_dci_dl_nr_t dci_dl_rx = {};
|
||||
int nof_found_dci = srsran_ue_dl_nr_find_dl_dci(ue_dl, slot, rnti, srsran_rnti_type_c, &dci_dl_rx, 1);
|
||||
srsran_dci_dl_nr_t dci_dl_rx = {};
|
||||
int nof_found_dci =
|
||||
srsran_ue_dl_nr_find_dl_dci(ue_dl, slot, pdsch_cfg.grant.rnti, pdsch_cfg.grant.rnti_type, &dci_dl_rx, 1);
|
||||
if (nof_found_dci < SRSRAN_SUCCESS) {
|
||||
ERROR("Error decoding");
|
||||
return SRSRAN_ERROR;
|
||||
|
@ -136,7 +159,6 @@ static int work_ue_dl(srsran_ue_dl_nr_t* ue_dl, srsran_slot_cfg_t* slot, srsran_
|
|||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
pdsch_cfg.grant = pdsch_grant;
|
||||
if (srsran_ue_dl_nr_decode_pdsch(ue_dl, slot, &pdsch_cfg, pdsch_res) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error decoding");
|
||||
return SRSRAN_ERROR;
|
||||
|
@ -192,8 +214,8 @@ int main(int argc, char** argv)
|
|||
srsran_ue_dl_nr_pdcch_cfg_t pdcch_cfg = {};
|
||||
|
||||
// Configure CORESET
|
||||
srsran_coreset_t* coreset = &pdcch_cfg.coreset[0];
|
||||
pdcch_cfg.coreset_present[0] = true;
|
||||
srsran_coreset_t* coreset = &pdcch_cfg.coreset[1];
|
||||
pdcch_cfg.coreset_present[1] = true;
|
||||
coreset->duration = 2;
|
||||
for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) {
|
||||
coreset->freq_resources[i] = i < carrier.nof_prb / 6;
|
||||
|
@ -202,7 +224,9 @@ int main(int argc, char** argv)
|
|||
// Configure Search Space
|
||||
srsran_search_space_t* search_space = &pdcch_cfg.search_space[0];
|
||||
pdcch_cfg.search_space_present[0] = true;
|
||||
search_space->type = srsran_search_space_type_ue;
|
||||
search_space->id = 0;
|
||||
search_space->coreset_id = 1;
|
||||
search_space->type = srsran_search_space_type_common_3;
|
||||
for (uint32_t L = 0; L < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; L++) {
|
||||
search_space->nof_candidates[L] = srsran_pdcch_nr_max_candidates_coreset(coreset, L);
|
||||
}
|
||||
|
@ -264,13 +288,16 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
// Use grant default A time resources with m=0
|
||||
if (srsran_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &pdsch_grant) < SRSRAN_SUCCESS) {
|
||||
pdsch_cfg.dmrs.typeA_pos = srsran_dmrs_sch_typeA_pos_2;
|
||||
if (srsran_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &pdsch_cfg.grant) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error loading default grant");
|
||||
goto clean_exit;
|
||||
}
|
||||
pdsch_grant.nof_layers = carrier.max_mimo_layers;
|
||||
pdsch_grant.dci_format = srsran_dci_format_nr_1_0;
|
||||
pdsch_grant.nof_dmrs_cdm_groups_without_data = 1;
|
||||
pdsch_cfg.grant.nof_layers = carrier.max_mimo_layers;
|
||||
pdsch_cfg.grant.dci_format = srsran_dci_format_nr_1_0;
|
||||
pdsch_cfg.grant.nof_dmrs_cdm_groups_without_data = 1;
|
||||
pdsch_cfg.grant.rnti_type = srsran_rnti_type_c;
|
||||
pdsch_cfg.grant.rnti = 0x4601;
|
||||
|
||||
uint32_t n_prb_start = 1;
|
||||
uint32_t n_prb_end = carrier.nof_prb + 1;
|
||||
|
@ -291,10 +318,11 @@ int main(int argc, char** argv)
|
|||
for (n_prb = n_prb_start; n_prb < n_prb_end; n_prb++) {
|
||||
for (mcs = mcs_start; mcs < mcs_end; mcs++, slot_count++) {
|
||||
for (uint32_t n = 0; n < SRSRAN_MAX_PRB_NR; n++) {
|
||||
pdsch_grant.prb_idx[n] = (n < n_prb);
|
||||
pdsch_cfg.grant.prb_idx[n] = (n < n_prb);
|
||||
}
|
||||
pdsch_cfg.grant.nof_prb = n_prb;
|
||||
|
||||
if (srsran_ra_nr_fill_tb(&pdsch_cfg, &pdsch_grant, mcs, &pdsch_grant.tb[0]) < SRSRAN_SUCCESS) {
|
||||
if (srsran_ra_nr_fill_tb(&pdsch_cfg, &pdsch_cfg.grant, mcs, &pdsch_cfg.grant.tb[0]) < SRSRAN_SUCCESS) {
|
||||
ERROR("Error filing tb");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
@ -305,17 +333,17 @@ int main(int argc, char** argv)
|
|||
continue;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < pdsch_grant.tb[tb].tbs; i++) {
|
||||
for (uint32_t i = 0; i < pdsch_cfg.grant.tb[tb].tbs; i++) {
|
||||
data_tx[tb][i] = (uint8_t)srsran_random_uniform_int_dist(rand_gen, 0, UINT8_MAX);
|
||||
}
|
||||
pdsch_grant.tb[tb].softbuffer.tx = &softbuffer_tx;
|
||||
pdsch_cfg.grant.tb[tb].softbuffer.tx = &softbuffer_tx;
|
||||
}
|
||||
|
||||
// Compute PDCCH candidate locations
|
||||
uint32_t L = 0;
|
||||
uint32_t ncce_candidates[SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR] = {};
|
||||
int nof_candidates =
|
||||
srsran_pdcch_nr_locations_coreset(coreset, search_space, rnti, L, slot.idx, ncce_candidates);
|
||||
int nof_candidates = srsran_pdcch_nr_locations_coreset(
|
||||
coreset, search_space, pdsch_cfg.grant.rnti, L, slot.idx, ncce_candidates);
|
||||
if (nof_candidates < SRSRAN_SUCCESS) {
|
||||
ERROR("Error getting PDCCH candidates");
|
||||
goto clean_exit;
|
||||
|
@ -326,11 +354,8 @@ int main(int argc, char** argv)
|
|||
dci_location.ncce = ncce_candidates[0];
|
||||
dci_location.L = L;
|
||||
|
||||
// Setup DCI
|
||||
srsran_dci_dl_nr_t dci_dl = {};
|
||||
|
||||
gettimeofday(&t[1], NULL);
|
||||
if (work_gnb_dl(&enb_dl, &slot, search_space, &dci_dl, &dci_location, data_tx) < SRSRAN_ERROR) {
|
||||
if (work_gnb_dl(&enb_dl, &slot, search_space, &dci_location, data_tx) < SRSRAN_ERROR) {
|
||||
ERROR("Error running eNb DL");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
@ -339,8 +364,8 @@ int main(int argc, char** argv)
|
|||
pdsch_encode_us += (size_t)(t[0].tv_sec * 1e6 + t[0].tv_usec);
|
||||
|
||||
for (uint32_t tb = 0; tb < SRSRAN_MAX_TB; tb++) {
|
||||
pdsch_grant.tb[tb].softbuffer.rx = &softbuffer_rx;
|
||||
srsran_softbuffer_rx_reset(pdsch_grant.tb[tb].softbuffer.rx);
|
||||
pdsch_cfg.grant.tb[tb].softbuffer.rx = &softbuffer_rx;
|
||||
srsran_softbuffer_rx_reset(pdsch_cfg.grant.tb[tb].softbuffer.rx);
|
||||
}
|
||||
|
||||
gettimeofday(&t[1], NULL);
|
||||
|
@ -358,23 +383,23 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
if (!pdsch_res[0].crc) {
|
||||
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_grant.tb[0].tbs);
|
||||
ERROR("Failed to match CRC; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs);
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
if (memcmp(data_tx[0], data_rx[0], pdsch_grant.tb[0].tbs / 8) != 0) {
|
||||
ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_grant.tb[0].tbs);
|
||||
if (memcmp(data_tx[0], data_rx[0], pdsch_cfg.grant.tb[0].tbs / 8) != 0) {
|
||||
ERROR("Failed to match Tx/Rx data; n_prb=%d; mcs=%d; TBS=%d;", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs);
|
||||
printf("Tx data: ");
|
||||
srsran_vec_fprint_byte(stdout, data_tx[0], pdsch_grant.tb[0].tbs / 8);
|
||||
srsran_vec_fprint_byte(stdout, data_tx[0], pdsch_cfg.grant.tb[0].tbs / 8);
|
||||
printf("Rx data: ");
|
||||
srsran_vec_fprint_byte(stdout, data_rx[0], pdsch_grant.tb[0].tbs / 8);
|
||||
srsran_vec_fprint_byte(stdout, data_rx[0], pdsch_cfg.grant.tb[0].tbs / 8);
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
INFO("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!", n_prb, mcs, pdsch_grant.tb[0].tbs, pdsch_res[0].evm);
|
||||
INFO("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!", n_prb, mcs, pdsch_cfg.grant.tb[0].tbs, pdsch_res[0].evm);
|
||||
|
||||
// Count the Tx/Rx'd number of bits
|
||||
nof_bits += pdsch_grant.tb[0].tbs;
|
||||
nof_bits += pdsch_cfg.grant.tb[0].tbs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,8 +125,11 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui
|
|||
srsran_sch_cfg_nr_t pdsch_cfg = {};
|
||||
|
||||
// Compute DL grant
|
||||
if (srsran_ra_dl_dci_to_grant_nr(&enb_dl.carrier, &pdsch_hl_cfg, &grants[i].dci, &pdsch_cfg, &pdsch_cfg.grant)) {
|
||||
if (srsran_ra_dl_dci_to_grant_nr(
|
||||
&enb_dl.carrier, &dl_slot_cfg, &pdsch_hl_cfg, &grants[i].dci, &pdsch_cfg, &pdsch_cfg.grant) <
|
||||
SRSRAN_SUCCESS) {
|
||||
ERROR("Computing DL grant");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set soft buffer
|
||||
|
|
|
@ -142,11 +142,11 @@ public:
|
|||
* @param tti_rx The TTI in which the grant was received
|
||||
* @param dci_dl The DL DCI message to store
|
||||
*/
|
||||
void set_dl_pending_grant(uint32_t tti_rx, const srsran_dci_dl_nr_t& dci_dl)
|
||||
void set_dl_pending_grant(const srsran_slot_cfg_t& slot, const srsran_dci_dl_nr_t& dci_dl)
|
||||
{
|
||||
// Convert DL DCI to grant
|
||||
srsran_sch_cfg_nr_t pdsch_cfg = {};
|
||||
if (srsran_ra_dl_dci_to_grant_nr(&carrier, &cfg.pdsch, &dci_dl, &pdsch_cfg, &pdsch_cfg.grant)) {
|
||||
if (srsran_ra_dl_dci_to_grant_nr(&carrier, &slot, &cfg.pdsch, &dci_dl, &pdsch_cfg, &pdsch_cfg.grant)) {
|
||||
ERROR("Computing UL grant");
|
||||
return;
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ public:
|
|||
}
|
||||
|
||||
// Calculate Receive TTI
|
||||
tti_rx = TTI_ADD(tti_rx, pdsch_cfg.grant.k);
|
||||
uint32_t tti_rx = TTI_ADD(slot.idx, pdsch_cfg.grant.k);
|
||||
|
||||
// Scope mutex to protect read/write the list
|
||||
std::lock_guard<std::mutex> lock(pending_dl_grant_mutex);
|
||||
|
|
|
@ -143,7 +143,7 @@ void cc_worker::decode_pdcch_dl()
|
|||
}
|
||||
|
||||
// Enqueue UL grants
|
||||
phy->set_dl_pending_grant(dl_slot_cfg.idx, dci_rx[i]);
|
||||
phy->set_dl_pending_grant(dl_slot_cfg, dci_rx[i]);
|
||||
}
|
||||
|
||||
if (logger.debug.enabled()) {
|
||||
|
|
Loading…
Reference in New Issue