Add UE PDSCH ChanEst and pre-compensation IQ to imscope

This commit is contained in:
Bartosz Podrygajlo
2025-06-03 13:15:33 +02:00
parent 114ac4d1bb
commit 456fe094bc
6 changed files with 90 additions and 11 deletions
@@ -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 --------------------
//----------------------------------------------------------
@@ -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);
+23
View File
@@ -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
@@ -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";
}
}
+2
View File
@@ -77,6 +77,8 @@ enum scopeDataType {
ueTimeDomainSamples,
ueTimeDomainSamplesBeforeSync,
gNbTimeDomainSamples,
pdschChanEstimates,
pdschRxdataF,
EXTRA_SCOPE_TYPES
};
+34 -2
View File
@@ -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);
}