adding beamforming support to FAPI: MAC fills ssb_beam_id_list in ssb config. PHY uses this info to fill new beam_id field. This is further copied to RU and applied there. Nothing is tested so far.
This commit is contained in:
+5
-6
@@ -757,8 +757,9 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
if (fp->freq_range==nr_FR2) {
|
||||
// the beam index is written in bits 8-10 of the flags
|
||||
// bit 11 enables the gpio programming
|
||||
// currently we switch beams every 10 slots (should = 1 TDD period in FR2) and we take the beam index of the first symbol of the first slot of this period
|
||||
int beam=0;
|
||||
if (slot==0) beam = 11; //3 for boresight & 8 to enable
|
||||
if (slot%10==0) beam = ru->common.beam_id[0][slot*fp->symbols_per_slot] & 8;
|
||||
/*
|
||||
if (slot==0 || slot==40) beam=0&8;
|
||||
if (slot==10 || slot==50) beam=1&8;
|
||||
@@ -2168,11 +2169,9 @@ void set_function_spec_param(RU_t *ru) {
|
||||
ru->nr_start_if = NULL; // no if interface
|
||||
ru->rfdevice.host_type = RAU_HOST;
|
||||
|
||||
// FK this here looks messed up. The following lines should be part of the if (ru->function == gNodeB_3GPP), shouldn't they?
|
||||
|
||||
ru->fh_south_in = rx_rf; // local synchronous RF RX
|
||||
ru->fh_south_out = tx_rf; // local synchronous RF TX
|
||||
ru->start_rf = start_rf; // need to start the local RF interface
|
||||
ru->fh_south_in = rx_rf; // local synchronous RF RX
|
||||
ru->fh_south_out = tx_rf; // local synchronous RF TX
|
||||
ru->start_rf = start_rf; // need to start the local RF interface
|
||||
ru->stop_rf = stop_rf;
|
||||
ru->start_write_thread = start_write_thread; // starting RF TX in different thread
|
||||
printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf);
|
||||
|
||||
@@ -414,13 +414,13 @@ typedef struct
|
||||
{
|
||||
nfapi_uint32_tlv_t ssb_mask;//Bitmap for actually transmitted SSB. MSB->LSB of first 32 bit number corresponds to SSB 0 to SSB 31 MSB->LSB of second 32 bit number corresponds to SSB 32 to SSB 63 Value for each bit: 0: not transmitted 1: transmitted
|
||||
|
||||
} nfapi_nr_ssb_mask_size_2_t;
|
||||
} nfapi_nr_ssb_mask_list_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
nfapi_uint8_tlv_t beam_id[64];//BeamID for each SSB in SsbMask. For example, if SSB mask bit 26 is set to 1, then BeamId[26] will be used to indicate beam ID of SSB 26. Value: from 0 to 63
|
||||
nfapi_uint8_tlv_t beam_id;//BeamID for each SSB in SsbMask. For example, if SSB mask bit 26 is set to 1, then BeamId[26] will be used to indicate beam ID of SSB 26. Value: from 0 to 63
|
||||
|
||||
} nfapi_nr_ssb_mask_size_64_t;
|
||||
} nfapi_nr_ssb_beam_id_list_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -429,8 +429,8 @@ typedef struct
|
||||
nfapi_uint8_tlv_t ssb_period;//SSB periodicity in msec Value: 0: ms5 1: ms10 2: ms20 3: ms40 4: ms80 5: ms160
|
||||
nfapi_uint8_tlv_t ssb_subcarrier_offset;//ssbSubcarrierOffset or 𝑘𝑆𝑆𝐵 (38.211, section 7.4.3.1) Value: 0->31
|
||||
nfapi_uint32_tlv_t MIB;//MIB payload, where the 24 MSB are used and represent the MIB in [38.331 MIB IE] and represent 0 1 2 3 1 , , , ,..., A− a a a a a [38.212, sec 7.1.1]
|
||||
nfapi_nr_ssb_mask_size_2_t ssb_mask_list[2];
|
||||
nfapi_nr_ssb_mask_size_64_t* ssb_beam_id_list;//64
|
||||
nfapi_nr_ssb_mask_list_t ssb_mask_list[2];
|
||||
nfapi_nr_ssb_beam_id_list_t ssb_beam_id_list[64];
|
||||
nfapi_uint8_tlv_t ss_pbch_multiple_carriers_in_a_band;//0 = disabled 1 = enabled
|
||||
nfapi_uint8_tlv_t multiple_cells_ss_pbch_in_a_carrier;//Indicates that multiple cells will be supported in a single carrier 0 = disabled 1 = enabled
|
||||
|
||||
|
||||
@@ -189,13 +189,14 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
|
||||
common_vars->rxdata = (int32_t **)malloc16(Prx*sizeof(int32_t*));
|
||||
common_vars->txdataF = (int32_t **)malloc16(Ptx*sizeof(int32_t*));
|
||||
common_vars->rxdataF = (int32_t **)malloc16(Prx*sizeof(int32_t*));
|
||||
common_vars->beam_id = (uint8_t **)malloc16(Ptx*sizeof(uint8_t*));
|
||||
|
||||
for (i=0;i<Ptx;i++){
|
||||
common_vars->txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t)); // [hna] samples_per_frame without CP
|
||||
LOG_D(PHY,"[INIT] common_vars->txdataF[%d] = %p (%lu bytes)\n",
|
||||
i,common_vars->txdataF[i],
|
||||
fp->samples_per_frame_wCP*sizeof(int32_t));
|
||||
|
||||
common_vars->beam_id[i] = (uint8_t*)malloc16_clear(fp->symbols_per_slot*fp->slots_per_frame*sizeof(uint8_t));
|
||||
}
|
||||
for (i=0;i<Prx;i++){
|
||||
common_vars->rxdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t));
|
||||
|
||||
@@ -138,7 +138,7 @@ int nr_phy_init_RU(RU_t *ru) {
|
||||
for (j=0; j<ru->nb_tx; j++) {
|
||||
ru->beam_weights[i][p][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t));
|
||||
for (re=0; re<fp->ofdm_symbol_size; re++)
|
||||
ru->beam_weights[i][p][j][re] = ru->bw_list[i][l_ind];
|
||||
ru->beam_weights[i][p][j][re] = ru->bw_list[j][l_ind];
|
||||
//printf("Beam Weight %08x for beam %d and tx %d\n",ru->bw_list[i][l_ind],p,j);
|
||||
l_ind++;
|
||||
} // for j
|
||||
@@ -146,6 +146,11 @@ int nr_phy_init_RU(RU_t *ru) {
|
||||
}
|
||||
} //for i
|
||||
}
|
||||
|
||||
ru->common.beam_id = (uint8_t**)malloc16_clear(ru->nb_tx*sizeof(uint8_t*));
|
||||
for(i=0; i< ru->nb_tx; ++i)
|
||||
ru->common.beam_id[i] = (uint8_t*)malloc16_clear(fp->symbols_per_slot*fp->slots_per_frame*sizeof(uint8_t));
|
||||
|
||||
} // !=IF5
|
||||
|
||||
ru->common.sync_corr = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*fp->samples_per_subframe_wCP );
|
||||
|
||||
+11
-7
@@ -92,17 +92,17 @@ typedef enum {
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// \brief Holds the transmit data in the frequency domain.
|
||||
/// \brief Holds the transmit data in the frequency domain (1 frame).
|
||||
/// - first index: rx antenna [0..nb_antennas_rx[
|
||||
/// - second index: ? [0..2*ofdm_symbol_size*frame_parms->symbols_per_tti[
|
||||
/// - second index: ? [0..samples_per_frame[
|
||||
int32_t **txdata;
|
||||
/// \brief holds the transmit data after beamforming in the frequency domain.
|
||||
/// \brief holds the transmit data after beamforming in the frequency domain (1 slot).
|
||||
/// - first index: tx antenna [0..nb_antennas_tx[
|
||||
/// - second index: sample [0..]
|
||||
/// - second index: sample [0..samples_per_slot_woCP]
|
||||
int32_t **txdataF_BF;
|
||||
/// \brief holds the transmit data before beamforming in the frequency domain.
|
||||
/// - first index: tx antenna [0..nb_antennas_tx[
|
||||
/// - second index: sample [0..]
|
||||
/// \brief holds the transmit data before beamforming in the frequency domain (1 frame).
|
||||
/// - first index: tx antenna [0..nb_antenna_ports[
|
||||
/// - second index: sample [0..samples_per_frame_woCP]
|
||||
int32_t **txdataF;
|
||||
/// \brief holds the transmit data before beamforming for epdcch/mpdcch
|
||||
/// - first index : tx antenna [0..nb_epdcch_antenna_ports[
|
||||
@@ -128,6 +128,10 @@ typedef struct {
|
||||
/// - second index: tx antenna [0..nb_antennas_tx[
|
||||
/// - third index: frequency [0..]
|
||||
int32_t **tdd_calib_coeffs;
|
||||
/// \brief Anaglogue beam ID for each OFDM symbol (used when beamforming not done in RU)
|
||||
/// - first index: antenna port
|
||||
/// - second index: beam_id [0.. symbols_per_frame[
|
||||
uint8_t **beam_id;
|
||||
} RU_COMMON;
|
||||
|
||||
|
||||
|
||||
@@ -383,8 +383,12 @@ typedef struct {
|
||||
/// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER. //?
|
||||
/// - first index: eNB id [0..2] (hard coded)
|
||||
/// - second index: tx antenna [0..14[ where 14 is the total supported antenna ports.
|
||||
/// - third index: sample [0..]
|
||||
/// - third index: sample [0..samples_per_frame_woCP]
|
||||
int32_t **txdataF;
|
||||
/// \brief Anaglogue beam ID for each OFDM symbol (used when beamforming not done in RU)
|
||||
/// - first index: antenna port
|
||||
/// - second index: beam_id [0.. symbols_per_frame[
|
||||
uint8_t **beam_id;
|
||||
int32_t *debugBuff;
|
||||
int32_t debugBuff_sample_offset;
|
||||
} NR_gNB_COMMON;
|
||||
|
||||
@@ -240,6 +240,7 @@ void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx) {
|
||||
memcpy((void*)&ru->common.txdataF[i][j*fp->ofdm_symbol_size],
|
||||
(void*)&gNB->common_vars.txdataF[i][j*fp->ofdm_symbol_size + txdataF_offset],
|
||||
fp->ofdm_symbol_size*sizeof(int32_t));
|
||||
|
||||
}
|
||||
|
||||
}//num_gNB == 1
|
||||
@@ -338,11 +339,20 @@ static void *nr_feptx_thread(void *param) {
|
||||
txdataF_offset = ((slot%2)*fp->samples_per_slot_wCP);
|
||||
////////////precoding////////////
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->index+1 , 1);
|
||||
|
||||
start_meas(&ru->precoding_stats);
|
||||
|
||||
for(i=0; i<ru->nb_log_antennas; ++i) {
|
||||
memcpy((void*) &ru->common.beam_id[i][slot*fp->symbols_per_slot+l],
|
||||
(void*) &ru->gNB_list[0]->common_vars.beam_id[i][slot*fp->symbols_per_slot+l],
|
||||
(fp->symbols_per_slot>>1)*sizeof(uint8_t));
|
||||
}
|
||||
|
||||
|
||||
if (ru->nb_tx == 1 && ru->nb_log_antennas == 1) {
|
||||
memcpy((void*)&ru->common.txdataF_BF[0][l*fp->ofdm_symbol_size],
|
||||
(void*)&ru->gNB_list[0]->common_vars.txdataF[0][txdataF_offset + l*fp->ofdm_symbol_size],
|
||||
(fp->samples_per_slot_wCP>>1)*sizeof(int32_t));
|
||||
memcpy((void*)&ru->common.txdataF_BF[0][l*fp->ofdm_symbol_size],
|
||||
(void*)&ru->gNB_list[0]->common_vars.txdataF[0][txdataF_offset + l*fp->ofdm_symbol_size],
|
||||
(fp->samples_per_slot_wCP>>1)*sizeof(int32_t));
|
||||
}
|
||||
else {
|
||||
bw = ru->beam_weights[0];
|
||||
@@ -491,10 +501,14 @@ void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx) {
|
||||
|
||||
if (nr_slot_select(cfg,frame_tx,slot_tx) == NR_UPLINK_SLOT) return;
|
||||
|
||||
for(i=0; i<ru->nb_log_antennas; ++i)
|
||||
for(i=0; i<ru->nb_log_antennas; ++i) {
|
||||
memcpy((void*)ru->common.txdataF[i],
|
||||
(void*)&gNB->common_vars.txdataF[i][txdataF_offset],
|
||||
fp->samples_per_slot_wCP*sizeof(int32_t));
|
||||
memcpy((void*)&ru->common.beam_id[i][slot_tx*fp->symbols_per_slot],
|
||||
(void*)&gNB->common_vars.beam_id[i][slot_tx*fp->symbols_per_slot],
|
||||
fp->symbols_per_slot*sizeof(uint8_t));
|
||||
}
|
||||
|
||||
if (ru->nb_tx == 1 && ru->nb_log_antennas == 1) {
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
|
||||
NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
int **txdataF = gNB->common_vars.txdataF;
|
||||
uint8_t ssb_index, n_hf;
|
||||
uint8_t ssb_index, ssb_per_slot=0, n_hf;
|
||||
uint16_t ssb_start_symbol, rel_slot;
|
||||
int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
|
||||
uint16_t slots_per_hf = (fp->slots_per_frame)>>1;
|
||||
@@ -94,11 +94,12 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
|
||||
|
||||
if(rel_slot<38 && rel_slot>=0) { // there is no SSB beyond slot 37
|
||||
|
||||
for (int i=0; i<2; i++) { // max two SSB per frame
|
||||
for (int i=0; i<2; i++) { // max two SSB per slot
|
||||
|
||||
ssb_index = i + SSB_Table[rel_slot]; // computing the ssb_index
|
||||
|
||||
if ((ssb_index<64) && ((fp->L_ssb >> (63-ssb_index)) & 0x01)) { // generating the ssb only if the bit of L_ssb at current ssb index is 1
|
||||
ssb_per_slot++;
|
||||
fp->ssb_index = ssb_index;
|
||||
int ssb_start_symbol_abs = nr_get_ssb_start_symbol(fp); // computing the starting symbol for current ssb
|
||||
ssb_start_symbol = ssb_start_symbol_abs % fp->symbols_per_slot; // start symbol wrt slot
|
||||
@@ -123,6 +124,16 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
|
||||
n_hf, frame, cfg, fp);
|
||||
|
||||
}
|
||||
|
||||
// SSB beamforming is handled at PHY
|
||||
// currently our PHY does not support switching more than once a slot.
|
||||
if (ssb_per_slot>1) {
|
||||
LOG_W(PHY,"beamforming currently not supported for more than one SSB per slot\n");
|
||||
}
|
||||
else if (ssb_per_slot==1) {
|
||||
for (int j=0;j<fp->symbols_per_slot;j++)
|
||||
gNB->common_vars.beam_id[0][slot*fp->symbols_per_slot+j] = cfg->ssb_table.ssb_beam_id_list[ssb_index].beam_id.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,15 +268,29 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
|
||||
}
|
||||
|
||||
cfg->ssb_table.ssb_mask_list[0].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG;
|
||||
cfg->num_tlv++;
|
||||
cfg->ssb_table.ssb_mask_list[1].ssb_mask.tl.tag = NFAPI_NR_CONFIG_SSB_MASK_TAG;
|
||||
cfg->num_tlv+=2;
|
||||
|
||||
cfg->carrier_config.num_tx_ant.value = pdsch_AntennaPorts;
|
||||
AssertFatal(pdsch_AntennaPorts > 0 && pdsch_AntennaPorts < 13, "pdsch_AntennaPorts in 1...12\n");
|
||||
cfg->carrier_config.num_tx_ant.tl.tag = NFAPI_NR_CONFIG_NUM_TX_ANT_TAG;
|
||||
|
||||
int num_ssb=0;
|
||||
for (int i=0;i<32;i++) {
|
||||
num_ssb += (cfg->ssb_table.ssb_mask_list[0].ssb_mask.value>>i)&1;
|
||||
num_ssb += (cfg->ssb_table.ssb_mask_list[1].ssb_mask.value>>i)&1;
|
||||
cfg->ssb_table.ssb_beam_id_list[i].beam_id.tl.tag = NFAPI_NR_CONFIG_BEAM_ID_TAG;
|
||||
if ((cfg->ssb_table.ssb_mask_list[0].ssb_mask.value>>i)&1) {
|
||||
cfg->ssb_table.ssb_beam_id_list[i].beam_id.value = num_ssb;
|
||||
num_ssb++;
|
||||
}
|
||||
cfg->num_tlv++;
|
||||
}
|
||||
for (int i=0;i<32;i++) {
|
||||
cfg->ssb_table.ssb_beam_id_list[32+i].beam_id.tl.tag = NFAPI_NR_CONFIG_BEAM_ID_TAG;
|
||||
if ((cfg->ssb_table.ssb_mask_list[1].ssb_mask.value>>i)&1) {
|
||||
cfg->ssb_table.ssb_beam_id_list[32+i].beam_id.value = num_ssb;
|
||||
num_ssb++;
|
||||
}
|
||||
cfg->num_tlv++;
|
||||
}
|
||||
|
||||
cfg->carrier_config.num_rx_ant.value = cfg->carrier_config.num_tx_ant.value;
|
||||
|
||||
Reference in New Issue
Block a user