diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index a690c85ee3..d266d443e9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -323,7 +323,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT], int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT], int G, - uint32_t nvar) + uint32_t nvar, + pdsch_scope_req_t *scope_req) { const int nl = dlsch[0].Nl; const int matrixSz = ue->frame_parms.nb_antennas_rx * nl; @@ -463,6 +464,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, csi_res_bitmap, ue->chest_time); stop_meas_nr_ue_phy(ue, DLSCH_EXTRACT_RBS_STATS); + if (scope_req->copy_chanest_to_scope) { + size_t size = sizeof(c16_t) * dlsch_config->number_rbs * NR_NB_SC_PER_RB; + int copy_index = symbol - dlsch_config->start_symbol; + int offset = copy_index * size; + UEscopeCopyUnsafe(ue, pdschChanEstimates, dl_ch_estimates_ext[0], size, offset, copy_index); + } if (meas_enabled) { LOG_D(PHY, "[AbsSFN %u.%d] Slot%d Symbol %d: Pilot/Data extraction %5.2f \n", @@ -481,6 +488,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, nb_re_pdsch = (pilots == 1) ? ((config_type == NFAPI_NR_DMRS_TYPE1) ? nb_rb_pdsch * (12 - 6 * dlsch_config->n_dmrs_cdm_groups) : nb_rb_pdsch * (12 - 4 * dlsch_config->n_dmrs_cdm_groups)) : (nb_rb_pdsch * 12); + if (scope_req->copy_rxdataF_to_scope) { + size_t size = sizeof(c16_t) * nb_re_pdsch; + int copy_index = symbol - dlsch_config->start_symbol; + UEscopeCopyUnsafe(ue, pdschRxdataF, rxdataF_ext[0], size, scope_req->scope_rxdataF_offset, copy_index); + scope_req->scope_rxdataF_offset += size; + } //---------------------------------------------------------- //--------------------- Channel Scaling -------------------- //---------------------------------------------------------- diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 9c6e0c1454..8e266a57a3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -41,6 +41,13 @@ #define NR_PUSCH_x 2 // UCI placeholder bit TS 38.212 V15.4.0 subclause 5.3.3.1 #define NR_PUSCH_y 3 // UCI placeholder bit +// Specifies the data that should be copied to the scope during PDSCH RX +typedef struct pdsch_scope_req_s { + bool copy_chanest_to_scope; + bool copy_rxdataF_to_scope; + size_t scope_rxdataF_offset; +} pdsch_scope_req_t; + // Functions below implement 36-211 and 36-212 /** @addtogroup _PHY_TRANSPORT_ @@ -314,7 +321,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, c16_t ptrs_phase_per_slot[][NR_SYMBOLS_PER_SLOT], int32_t ptrs_re_per_slot[][NR_SYMBOLS_PER_SLOT], int G, - uint32_t nvar); + uint32_t nvar, + pdsch_scope_req_t *scope_req); int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int frame, uint8_t slot, c16_t **txData); diff --git a/openair1/PHY/TOOLS/imscope/imscope.cpp b/openair1/PHY/TOOLS/imscope/imscope.cpp index 9b5aeb0366..cce7a595f7 100644 --- a/openair1/PHY/TOOLS/imscope/imscope.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope.cpp @@ -455,6 +455,29 @@ void ShowUeScope(void *data_void_ptr, float t) } ImGui::End(); + if (ImGui::Begin("UE PDSCH Chan est")) { + static auto iq_data = new IQData(); + static auto iq_hist = new IQHist("PDSCH Chan est IQ"); + bool new_data = false; + if (iq_hist->ShouldReadData()) { + new_data = iq_data->TryCollect(&scope_array[pdschChanEstimates], t, iq_hist->GetEpsilon(), iq_procedure_timer); + } + iq_hist->Draw(iq_data, t, new_data); + } + ImGui::End(); + + if (ImGui::Begin("UE PDSCH IQ before compensation")) { + static auto iq_data = new IQData(); + static auto iq_hist = new IQHist("PDSCH IQ before compensation"); + bool new_data = false; + if (iq_hist->ShouldReadData()) { + new_data = iq_data->TryCollect(&scope_array[pdschRxdataF], t, iq_hist->GetEpsilon(), iq_procedure_timer); + } + iq_hist->Draw(iq_data, t, new_data); + } + ImGui::End(); + + if (ImGui::Begin("Time domain samples")) { static auto iq_data = new IQData(); // Issue with imgui deferring draw calls until the end of the frame - cases segfault if scatterplot has too many points diff --git a/openair1/PHY/TOOLS/imscope/imscope_common.cpp b/openair1/PHY/TOOLS/imscope/imscope_common.cpp index b1bdda0905..a480abbf5e 100644 --- a/openair1/PHY/TOOLS/imscope/imscope_common.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope_common.cpp @@ -131,12 +131,9 @@ void unlockScopeData(enum scopeDataType type) total_size += scope_data.data.data_copied_per_offset[i]; } if (total_size != (uint64_t)scope_data.data.scope_graph_data->dataSize) { - LOG_E(PHY, - "Scope is missing data - not all data that was expected was copied - possibly missed copyDataUnsafeWithOffset call. " - "scope = %s, total_size = %lu, dataSize = %d\n", - scope_id_to_string(type), - total_size, - scope_data.data.scope_graph_data->dataSize); + scope_data.data.scope_graph_data->dataSize = total_size; + scope_data.data.scope_graph_data->lineSz = + total_size / scope_data.data.scope_graph_data->elementSz / scope_data.data.scope_graph_data->colSz; } scope_data.data.scope_id = type; scope_data.is_data_ready = true; @@ -179,8 +176,12 @@ const char *scope_id_to_string(scopeDataType type) { return "ueTimeDomainSamplesBeforeSync"; case gNbTimeDomainSamples: return "gNbTimeDomainSamples"; + case pdschChanEstimates: + return "pdschChanEstimates"; + case pdschRxdataF: + return "pdschRxdataF"; default: - return "unknown type"; + return "unknown scope type"; } } diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index 181bf5985b..731a6250e5 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -77,6 +77,8 @@ enum scopeDataType { ueTimeDomainSamples, ueTimeDomainSamplesBeforeSync, gNbTimeDomainSamples, + pdschChanEstimates, + pdschRxdataF, EXTRA_SCOPE_TYPES }; diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 8484a13101..976a5f8d88 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -606,6 +606,24 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, int32_t log2_maxh = 0; start_meas_nr_ue_phy(ue, RX_PDSCH_STATS); + pdsch_scope_req_t scope_req = { .copy_chanest_to_scope = false, + .copy_rxdataF_to_scope = false, + .scope_rxdataF_offset = 0 }; + if (UEScopeHasTryLock(ue)) { + metadata mt = {.frame = proc->frame_rx, .slot = proc->nr_slot_rx}; + scope_req.copy_chanest_to_scope = UETryLockScopeData(ue, + pdschChanEstimates, + sizeof(c16_t), + 1, + dlschCfg->number_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols, + &mt); + scope_req.copy_rxdataF_to_scope = UETryLockScopeData(ue, + pdschRxdataF, + sizeof(c16_t), + 1, + dlschCfg->number_rbs * NR_NB_SC_PER_RB * dlschCfg->number_symbols, + &mt); + } for (int m = dlschCfg->start_symbol; m < (dlschCfg->number_symbols + dlschCfg->start_symbol); m++) { bool first_symbol_flag = false; if (m == first_symbol_with_data) @@ -632,11 +650,25 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, ptrs_phase_per_slot, ptrs_re_per_slot, G, - nvar) - < 0) + nvar, + &scope_req) + < 0) { + if (scope_req.copy_chanest_to_scope) { + UEunlockScopeData(ue, pdschChanEstimates); + } + if (scope_req.copy_rxdataF_to_scope) { + UEunlockScopeData(ue, pdschRxdataF); + } return -1; + } } // CRNTI active stop_meas_nr_ue_phy(ue, RX_PDSCH_STATS); + if (scope_req.copy_chanest_to_scope) { + UEunlockScopeData(ue, pdschChanEstimates); + } + if (scope_req.copy_rxdataF_to_scope) { + UEunlockScopeData(ue, pdschRxdataF); + } free(toFree); free(toFree2); }