From 7986a4de8e6382f5a3c5439eb1522d0b92b8a3c0 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Mon, 30 Sep 2024 20:34:09 +0200 Subject: [PATCH 1/4] Time domain samples scope for NR UE Add a new scope data source (ueTimeDomainSamples) which provides time domain samples for antenna 0 to the scope. Add graphical representation of the data in imscope. Removed C-define from ENABLE_IMSCOPE cmake option, the #define was unused and this way code does not have to be recompiled when imscope enable state changes. --- CMakeLists.txt | 2 +- executables/nr-ue.c | 2 ++ openair1/PHY/TOOLS/imscope/imscope.cpp | 10 ++++++++++ openair1/PHY/TOOLS/phy_scope_interface.h | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 627b87593d..fcae675910 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -293,7 +293,7 @@ set_property(CACHE KPM_VERSION PROPERTY STRINGS "KPM_V2_03" "KPM_V3_00") message(STATUS "Selected KPM Version: ${KPM_VERSION}") -add_boolean_option(ENABLE_IMSCOPE OFF "Enable phy scope based on imgui" ON) +add_boolean_option(ENABLE_IMSCOPE OFF "Enable phy scope based on imgui" OFF) ################################################## # ASN.1 grammar C code generation & dependencies # diff --git a/executables/nr-ue.c b/executables/nr-ue.c index a742ea2e9d..16fef82eea 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -37,6 +37,7 @@ #include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "RRC/NR/MESSAGES/asn1_msg.h" +#include "openair1/PHY/TOOLS/phy_scope_interface.h" /* * NR SLOT PROCESSING SEQUENCE @@ -958,6 +959,7 @@ void *UE_thread(void *arg) const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply; openair0_timestamp rx_timestamp; int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx); + UEscopeCopy(UE, ueTimeDomainSamples, rxp[0], sizeof(c16_t), 1, readBlockSize, 0); AssertFatal(readBlockSize == tmp, ""); if(slot_nr == (nb_slot_frame - 1)) { diff --git a/openair1/PHY/TOOLS/imscope/imscope.cpp b/openair1/PHY/TOOLS/imscope/imscope.cpp index 8205c85b9e..c216156777 100644 --- a/openair1/PHY/TOOLS/imscope/imscope.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope.cpp @@ -480,6 +480,16 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) pdsch_iq_hist->Draw(iq_data, t, new_data); ImGui::TreePop(); } + if (ImGui::TreeNode("Time domain samples")) { + static auto iq_data = new IQData(); + static auto time_domain_iq = new IQHist("Time domain samples"); + bool new_data = false; + if (time_domain_iq->ShouldReadData()) { + new_data = iq_data->TryCollect(&scope_array[ueTimeDomainSamples], t, time_domain_iq->GetEpsilon()); + } + time_domain_iq->Draw(iq_data, t, new_data); + ImGui::TreePop(); + } if (ImGui::TreeNode("Broadcast channel")) { ImGui::Text("RSRP %d", ue->measurements.ssb_rsrp_dBm[ue->frame_parms.ssb_index]); if (ImGui::TreeNode("IQ")) { diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index 2f8378e7b7..2d648faa90 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -73,6 +73,7 @@ enum scopeDataType { MAX_SCOPE_TYPES, gNBPuschRxIq = MAX_SCOPE_TYPES, gNBPuschLlr, + ueTimeDomainSamples, EXTRA_SCOPE_TYPES }; From 43a9236963aea7e280fb405ba902eb66a97f924c Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 13 Sep 2024 13:50:01 +0200 Subject: [PATCH 2/4] Improve imscope's scatterplot - Reduce point size to 1 pixel - call ImPlot::PlotScatter as many times as needed --- openair1/PHY/TOOLS/imscope/imscope.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/TOOLS/imscope/imscope.cpp b/openair1/PHY/TOOLS/imscope/imscope.cpp index c216156777..bba22402a3 100644 --- a/openair1/PHY/TOOLS/imscope/imscope.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope.cpp @@ -279,8 +279,17 @@ class IQHist { } } else if (plot_type == 1) { if (ImPlot::BeginPlot(label.c_str(), {(float)ImGui::GetWindowWidth() * 0.3f, (float)ImGui::GetWindowWidth() * 0.3f})) { - // Limit the amount of data plotted with scatterplot (issue with vertices/draw call) - ImPlot::PlotScatter(label.c_str(), iq_data->real.data(), iq_data->imag.data(), std::min(16000, iq_data->len)); + int points_drawn = 0; + while (points_drawn < iq_data->len) { + // Limit the amount of data plotted with PlotScatter call (issue with vertices/draw call) + int points_to_draw = std::min(iq_data->len - points_drawn, 16000); + ImPlot::SetNextMarkerStyle(ImPlotMarker_Circle, 1, IMPLOT_AUTO_COL, 1); + ImPlot::PlotScatter(label.c_str(), + iq_data->real.data() + points_drawn, + iq_data->imag.data() + points_drawn, + points_to_draw); + points_drawn += points_to_draw; + } ImPlot::EndPlot(); } } else if (plot_type == 2) { From 80f90b55991d1e9c9e8b8f7c20265d24ddd34372 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Fri, 13 Sep 2024 14:03:18 +0200 Subject: [PATCH 3/4] Add time domain sample scope before sync Added new data sync for UE which displays time domain samples read from RF device before synchronization to PSS/SSS --- executables/nr-ue.c | 6 ++++-- openair1/PHY/TOOLS/imscope/imscope.cpp | 10 ++++++++++ openair1/PHY/TOOLS/phy_scope_interface.h | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 16fef82eea..d4c3b964fd 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -707,8 +707,10 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) + 4 * ((x * fp->samples_per_subframe) + fp->get_samples_slot_timestamp(slot, fp, 0)); } - int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, rxp, fp->get_samples_per_slot(slot, fp), fp->nb_antennas_rx); - AssertFatal(fp->get_samples_per_slot(slot, fp) == tmp, ""); + int read_block_size = fp->get_samples_per_slot(slot, fp); + int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, rxp, read_block_size, fp->nb_antennas_rx); + UEscopeCopy(UE, ueTimeDomainSamplesBeforeSync, rxp[0], sizeof(c16_t), 1, read_block_size, 0); + AssertFatal(read_block_size == tmp, ""); if (IS_SOFTMODEM_RFSIM) dummyWrite(UE, *timestamp, fp->get_samples_per_slot(slot, fp)); diff --git a/openair1/PHY/TOOLS/imscope/imscope.cpp b/openair1/PHY/TOOLS/imscope/imscope.cpp index bba22402a3..de555332bc 100644 --- a/openair1/PHY/TOOLS/imscope/imscope.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope.cpp @@ -499,6 +499,16 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) time_domain_iq->Draw(iq_data, t, new_data); ImGui::TreePop(); } + if (ImGui::TreeNode("Time domain samples - before sync")) { + static auto iq_data = new IQData(); + static auto time_domain_iq = new IQHist("Time domain samples - before sync"); + bool new_data = false; + if (time_domain_iq->ShouldReadData()) { + new_data = iq_data->TryCollect(&scope_array[ueTimeDomainSamplesBeforeSync], t, time_domain_iq->GetEpsilon()); + } + time_domain_iq->Draw(iq_data, t, new_data); + ImGui::TreePop(); + } if (ImGui::TreeNode("Broadcast channel")) { ImGui::Text("RSRP %d", ue->measurements.ssb_rsrp_dBm[ue->frame_parms.ssb_index]); if (ImGui::TreeNode("IQ")) { diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index 2d648faa90..5602ed40de 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -74,6 +74,7 @@ enum scopeDataType { gNBPuschRxIq = MAX_SCOPE_TYPES, gNBPuschLlr, ueTimeDomainSamples, + ueTimeDomainSamplesBeforeSync, EXTRA_SCOPE_TYPES }; From b2c49fbc27493ee6f8dfc9604b5512a0ad3ba8b1 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Mon, 30 Sep 2024 20:41:08 +0200 Subject: [PATCH 4/4] Add time-domain scope to gNB imscope. --- executables/nr-ru.c | 1 + openair1/PHY/TOOLS/imscope/imscope.cpp | 11 +++++++++++ openair1/PHY/TOOLS/phy_scope_interface.h | 5 +++-- openair1/PHY/defs_RU.h | 3 ++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 8a29e6ac2f..ee78346cf4 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -622,6 +622,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot) rxp, samples_per_slot, ru->nb_rx); + gNBscopeCopy(ru, gNbTimeDomainSamples, rxp[0], sizeof(c16_t), 1, samples_per_slot, 0); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); diff --git a/openair1/PHY/TOOLS/imscope/imscope.cpp b/openair1/PHY/TOOLS/imscope/imscope.cpp index de555332bc..054fcdad79 100644 --- a/openair1/PHY/TOOLS/imscope/imscope.cpp +++ b/openair1/PHY/TOOLS/imscope/imscope.cpp @@ -581,6 +581,16 @@ void ShowGnbScope(PHY_VARS_gNB *gNB, float t) pusch_llr_plot->Draw(t, gNBPuschLlr, "PUSCH LLR"); ImGui::TreePop(); } + if (ImGui::TreeNode("Time domain samples")) { + static auto iq_data = new IQData(); + static auto time_domain_iq = new IQHist("Time domain samples"); + bool new_data = false; + if (time_domain_iq->ShouldReadData()) { + new_data = iq_data->TryCollect(&scope_array[gNbTimeDomainSamples], t, time_domain_iq->GetEpsilon()); + } + time_domain_iq->Draw(iq_data, t, new_data); + ImGui::TreePop(); + } } void *imscope_thread(void *data_void_ptr) @@ -751,6 +761,7 @@ extern "C" void imscope_autoinit(void *dataptr) scope->copyDataUnsafeWithOffset = copyDataUnsafeWithOffset; scope->unlockScopeData = unlockScopeData; scope_params->gNB->scopeData = scope; + scope_params->ru->scopeData = scope; } else { PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)dataptr; scopeData_t *scope = (scopeData_t *)calloc(1, sizeof(scopeData_t)); diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index 5602ed40de..2fa97880b4 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -75,6 +75,7 @@ enum scopeDataType { gNBPuschLlr, ueTimeDomainSamples, ueTimeDomainSamplesBeforeSync, + gNbTimeDomainSamples, EXTRA_SCOPE_TYPES }; @@ -129,12 +130,12 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int } #define gNBscopeCopyWithMetadata(gnb, type, ...) \ if (gnb->scopeData) { \ - ((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gNB->scopeData, type, ##__VA_ARGS__); \ + ((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gnb->scopeData, type, ##__VA_ARGS__); \ } #define gNBscopeCopy(gnb, type, ...) \ if (gnb->scopeData) { \ metadata mt = {.slot = -1, .frame = -1}; \ - ((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gNB->scopeData, type, ##__VA_ARGS__, &mt); \ + ((scopeData_t *)gnb->scopeData)->copyData((scopeData_t *)gnb->scopeData, type, ##__VA_ARGS__, &mt); \ } #define GnbScopeUpdate(gnb, type, numElt) \ if (gnb->scopeData) \ diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index 2f564eac6b..3b7b7f2ba0 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -661,7 +661,8 @@ typedef struct RU_t_s { /// number of cores for RU ThreadPool int num_tpcores; /// structure for analyzing high-level RT measurements - rt_ru_profiling_t rt_ru_profiling; + rt_ru_profiling_t rt_ru_profiling; + void* scopeData; } RU_t;