Commit 34c2f0be authored by Thomas Schlichter's avatar Thomas Schlichter

Merge remote-tracking branch 'fhg-KPI-GUI'

parents 4be8cb64 044be0d1
...@@ -2484,6 +2484,24 @@ set (SIMUSRC ...@@ -2484,6 +2484,24 @@ set (SIMUSRC
########################## ##########################
add_library(SIMU SHARED ${SIMUSRC} ) add_library(SIMU SHARED ${SIMUSRC} )
# Qt-based scope
set(QTSCOPE_SOURCE_NR
${OPENAIR1_DIR}/PHY/TOOLS/nr_phy_qt_scope.cpp
)
find_package(Qt5 COMPONENTS Widgets Charts)
if (Qt5_FOUND)
message ("Qt5 Packages found.")
# Creates rules for calling the Meta-Object Compiler (moc) on the given source files
qt5_wrap_cpp(QTSCOPE_SOURCE_NR ${OPENAIR1_DIR}/PHY/TOOLS/nr_phy_qt_scope.h)
add_library(nrqtscope MODULE ${QTSCOPE_SOURCE_NR})
# Use the Widgets module from Qt5.
target_link_libraries(nrqtscope Qt5::Widgets Qt5::Charts)
else (Qt5_FOUND)
message ("WARNING: Qt5 Packages NOT found, so qt scope can NOT be displayed.")
endif ()
add_library(SIMU_ETH add_library(SIMU_ETH
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c
......
...@@ -58,7 +58,7 @@ CMAKE_CMD="$CMAKE" ...@@ -58,7 +58,7 @@ CMAKE_CMD="$CMAKE"
NOAVX512="False" NOAVX512="False"
BUILD_ECLIPSE=0 BUILD_ECLIPSE=0
NR="False" NR="False"
OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope" OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope"
RU=0 RU=0
CMAKE_C_FLAGS=() CMAKE_C_FLAGS=()
CMAKE_CXX_FLAGS=() CMAKE_CXX_FLAGS=()
...@@ -752,11 +752,24 @@ function main() { ...@@ -752,11 +752,24 @@ function main() {
###################### ######################
# Optional libraries # # Optional libraries #
###################### ######################
if [ ! -z "$BUILD_OPTLIB" ] ; then if [ ! -z "$BUILD_OPTLIB" ] ; then
for oklib in $BUILD_OPTLIB ; do for oklib in $BUILD_OPTLIB ; do
compilations \ if [ "$oklib" != "nrqtscope" ]; then
$BUILD_DIR $oklib \ compilations \
lib${oklib}.so $dbin/lib${oklib}.so $BUILD_DIR $oklib \
lib${oklib}.so $dbin/lib${oklib}.so
fi
if [ "$oklib" = "nrqtscope" ]; then
HEAD_PATH="$(find /usr/ -iname qwidget.h)"
if [ "$HEAD_PATH" != "" ]; then
compilations \
$BUILD_DIR $oklib \
lib${oklib}.so $dbin/lib${oklib}.so
else
echo_warning "qt scope could not compile; make sure to install the Qt packages!"
fi
fi
done done
fi fi
......
...@@ -764,6 +764,16 @@ int main( int argc, char **argv ) { ...@@ -764,6 +764,16 @@ int main( int argc, char **argv ) {
load_softscope("nr",&p); load_softscope("nr",&p);
} }
if(IS_SOFTMODEM_DOSCOPE_QT) {
sleep(1);
scopeParms_t p;
p.argc=&argc;
p.argv=argv;
p.gNB=RC.gNB[0];
p.ru=RC.ru[0];
load_softscope("nrqt",&p);
}
if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF) { if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF) {
printf("Not NFAPI mode - call init_eNB_afterRU()\n"); printf("Not NFAPI mode - call init_eNB_afterRU()\n");
init_eNB_afterRU(); init_eNB_afterRU();
......
...@@ -518,6 +518,10 @@ int main( int argc, char **argv ) { ...@@ -518,6 +518,10 @@ int main( int argc, char **argv ) {
set_latency_target(); set_latency_target();
mlockall(MCL_CURRENT | MCL_FUTURE); mlockall(MCL_CURRENT | MCL_FUTURE);
if(IS_SOFTMODEM_DOSCOPE_QT) {
load_softscope("nrqt",PHY_vars_UE_g[0][0]);
}
if(IS_SOFTMODEM_DOSCOPE) { if(IS_SOFTMODEM_DOSCOPE) {
load_softscope("nr",PHY_vars_UE_g[0][0]); load_softscope("nr",PHY_vars_UE_g[0][0]);
} }
......
...@@ -90,7 +90,7 @@ void get_common_options(uint32_t execmask) { ...@@ -90,7 +90,7 @@ void get_common_options(uint32_t execmask) {
uint32_t glog_level=0 ; uint32_t glog_level=0 ;
uint32_t start_telnetsrv = 0, start_telnetclt = 0; uint32_t start_telnetsrv = 0, start_telnetclt = 0;
uint32_t noS1 = 0, nokrnmod = 1, nonbiot = 0; uint32_t noS1 = 0, nokrnmod = 1, nonbiot = 0;
uint32_t rfsim = 0, do_forms = 0; uint32_t rfsim = 0, do_forms = 0, do_forms_qt = 0;
char *logmem_filename = NULL; char *logmem_filename = NULL;
paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ; paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ; paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
...@@ -146,6 +146,10 @@ void get_common_options(uint32_t execmask) { ...@@ -146,6 +146,10 @@ void get_common_options(uint32_t execmask) {
set_softmodem_optmask(SOFTMODEM_DOSCOPE_BIT); set_softmodem_optmask(SOFTMODEM_DOSCOPE_BIT);
} }
if (do_forms_qt) {
set_softmodem_optmask(SOFTMODEM_DOSCOPE_QT_BIT);
}
if(parallel_config != NULL) set_parallel_conf(parallel_config); if(parallel_config != NULL) set_parallel_conf(parallel_config);
if(worker_config != NULL) set_worker_conf(worker_config); if(worker_config != NULL) set_worker_conf(worker_config);
......
...@@ -68,6 +68,7 @@ extern "C" ...@@ -68,6 +68,7 @@ extern "C"
#define CONFIG_HLP_ULF "Set the uplink frequency offset for all component carriers\n" #define CONFIG_HLP_ULF "Set the uplink frequency offset for all component carriers\n"
#define CONFIG_HLP_CHOFF "Channel id offset\n" #define CONFIG_HLP_CHOFF "Channel id offset\n"
#define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n" #define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n"
#define CONFIG_HLP_SOFTS_QT "Enable soft scope and L1 and L2 stats (QT)\n"
#define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n" #define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n"
#define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n" #define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n"
#define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" #define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n"
...@@ -166,6 +167,7 @@ extern int usrp_tx_thread; ...@@ -166,6 +167,7 @@ extern int usrp_tx_thread;
{"CO" , CONFIG_HLP_ULF, 0, iptr:&(uplink_frequency_offset[0][0]), defintval:0, TYPE_INT, 0}, \ {"CO" , CONFIG_HLP_ULF, 0, iptr:&(uplink_frequency_offset[0][0]), defintval:0, TYPE_INT, 0}, \
{"a" , CONFIG_HLP_CHOFF, 0, iptr:&CHAIN_OFFSET, defintval:0, TYPE_INT, 0}, \ {"a" , CONFIG_HLP_CHOFF, 0, iptr:&CHAIN_OFFSET, defintval:0, TYPE_INT, 0}, \
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \ {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
{"dqt" , CONFIG_HLP_SOFTS_QT, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms_qt, defintval:0, TYPE_INT8, 0}, \
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:1, TYPE_INT, 0}, \ {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:1, TYPE_INT, 0}, \
{"band" , CONFIG_HLP_BAND, PARAMFLAG_BOOL, iptr:&BAND, defintval:78, TYPE_INT, 0}, \ {"band" , CONFIG_HLP_BAND, PARAMFLAG_BOOL, iptr:&BAND, defintval:78, TYPE_INT, 0}, \
...@@ -238,6 +240,8 @@ extern int usrp_tx_thread; ...@@ -238,6 +240,8 @@ extern int usrp_tx_thread;
#define SOFTMODEM_4GUE_BIT (1<<22) #define SOFTMODEM_4GUE_BIT (1<<22)
#define SOFTMODEM_5GUE_BIT (1<<23) #define SOFTMODEM_5GUE_BIT (1<<23)
#define SOFTMODEM_NOSTATS_BIT (1<<24) #define SOFTMODEM_NOSTATS_BIT (1<<24)
#define SOFTMODEM_DOSCOPE_QT_BIT (1<<25)
#define SOFTMODEM_FUNC_BITS (SOFTMODEM_ENB_BIT | SOFTMODEM_GNB_BIT | SOFTMODEM_5GUE_BIT | SOFTMODEM_4GUE_BIT) #define SOFTMODEM_FUNC_BITS (SOFTMODEM_ENB_BIT | SOFTMODEM_GNB_BIT | SOFTMODEM_5GUE_BIT | SOFTMODEM_4GUE_BIT)
#define MAPPING_SOFTMODEM_FUNCTIONS {{"enb",SOFTMODEM_ENB_BIT},{"gnb",SOFTMODEM_GNB_BIT},{"4Gue",SOFTMODEM_4GUE_BIT},{"5Gue",SOFTMODEM_5GUE_BIT}} #define MAPPING_SOFTMODEM_FUNCTIONS {{"enb",SOFTMODEM_ENB_BIT},{"gnb",SOFTMODEM_GNB_BIT},{"4Gue",SOFTMODEM_4GUE_BIT},{"5Gue",SOFTMODEM_5GUE_BIT}}
...@@ -249,6 +253,7 @@ extern int usrp_tx_thread; ...@@ -249,6 +253,7 @@ extern int usrp_tx_thread;
#define IS_SOFTMODEM_SIML1 ( get_softmodem_optmask() & SOFTMODEM_SIML1_BIT) #define IS_SOFTMODEM_SIML1 ( get_softmodem_optmask() & SOFTMODEM_SIML1_BIT)
#define IS_SOFTMODEM_DLSIM ( get_softmodem_optmask() & SOFTMODEM_DLSIM_BIT) #define IS_SOFTMODEM_DLSIM ( get_softmodem_optmask() & SOFTMODEM_DLSIM_BIT)
#define IS_SOFTMODEM_DOSCOPE ( get_softmodem_optmask() & SOFTMODEM_DOSCOPE_BIT) #define IS_SOFTMODEM_DOSCOPE ( get_softmodem_optmask() & SOFTMODEM_DOSCOPE_BIT)
#define IS_SOFTMODEM_DOSCOPE_QT ( get_softmodem_optmask() & SOFTMODEM_DOSCOPE_QT_BIT)
#define IS_SOFTMODEM_IQPLAYER ( get_softmodem_optmask() & SOFTMODEM_RECPLAY_BIT) #define IS_SOFTMODEM_IQPLAYER ( get_softmodem_optmask() & SOFTMODEM_RECPLAY_BIT)
#define IS_SOFTMODEM_TELNETCLT_BIT ( get_softmodem_optmask() & SOFTMODEM_TELNETCLT_BIT) #define IS_SOFTMODEM_TELNETCLT_BIT ( get_softmodem_optmask() & SOFTMODEM_TELNETCLT_BIT)
#define IS_SOFTMODEM_ENB_BIT ( get_softmodem_optmask() & SOFTMODEM_ENB_BIT) #define IS_SOFTMODEM_ENB_BIT ( get_softmodem_optmask() & SOFTMODEM_ENB_BIT)
......
...@@ -300,6 +300,7 @@ void nr_sort_asc_int16_1D_array_ind(int32_t *matrix, ...@@ -300,6 +300,7 @@ void nr_sort_asc_int16_1D_array_ind(int32_t *matrix,
void nr_free_double_2D_array(double **input, uint16_t xlen); void nr_free_double_2D_array(double **input, uint16_t xlen);
#ifndef __cplusplus
void updateLLR(uint8_t listSize, void updateLLR(uint8_t listSize,
uint16_t row, uint16_t row,
uint16_t col, uint16_t col,
...@@ -327,7 +328,7 @@ void updatePathMetric2(double *pathMetric, ...@@ -327,7 +328,7 @@ void updatePathMetric2(double *pathMetric,
int ylen, int ylen,
int zlen, int zlen,
double llr[xlen][ylen][zlen]); double llr[xlen][ylen][zlen]);
#endif
//Also nr_polar_rate_matcher //Also nr_polar_rate_matcher
static inline void nr_polar_interleaver(uint8_t *input, static inline void nr_polar_interleaver(uint8_t *input,
uint8_t *output, uint8_t *output,
......
...@@ -51,6 +51,8 @@ ...@@ -51,6 +51,8 @@
#include "nfapi/oai_integration/vendor_ext.h" #include "nfapi/oai_integration/vendor_ext.h"
#include "PHY/TOOLS/phy_scope_interface.h"
#include "T.h" #include "T.h"
//#define DEBUG_NR_PUCCH_RX 1 //#define DEBUG_NR_PUCCH_RX 1
...@@ -1688,6 +1690,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB, ...@@ -1688,6 +1690,7 @@ void nr_decode_pucch2(PHY_VARS_gNB *gNB,
((int16_t*)&llrs[half_prb])[7]); ((int16_t*)&llrs[half_prb])[7]);
} // half_prb } // half_prb
} // symb } // symb
// run polar decoder on llrs // run polar decoder on llrs
decoderState = polar_decoder_int16((int16_t*)llrs, decodedPayload, 0, 2,nb_bit,pucch_pdu->prb_size); decoderState = polar_decoder_int16((int16_t*)llrs, decodedPayload, 0, 2,nb_bit,pucch_pdu->prb_size);
LOG_D(PHY,"UCI decoderState %d, payload[0] %llu\n",decoderState,(unsigned long long)decodedPayload[0]); LOG_D(PHY,"UCI decoderState %d, payload[0] %llu\n",decoderState,(unsigned long long)decodedPayload[0]);
......
...@@ -459,8 +459,12 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, ...@@ -459,8 +459,12 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
} }
} }
if (dmrss == 2) scopeData_t *scope=(scopeData_t *)ue->scopeData;
UEscopeCopy(ue, pbchDlChEstimateTime, (void*)dl_ch_estimates_time, sizeof(struct complex16), ue->frame_parms.nb_antennas_rx, ue->frame_parms.ofdm_symbol_size); if ((scope) && (dmrss == 2)){
int istreamingFlag = scope->flag_streaming[pbchDlChEstimateTime];
if (istreamingFlag == 1)
UEscopeCopy(ue, pbchDlChEstimateTime, (void*)dl_ch_estimates_time, sizeof(struct complex16), ue->frame_parms.nb_antennas_rx, ue->frame_parms.ofdm_symbol_size);
}
return(0); return(0);
} }
......
...@@ -749,8 +749,12 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, ...@@ -749,8 +749,12 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
log2_maxh, log2_maxh,
n_rb); // log2_maxh+I0_shift n_rb); // log2_maxh+I0_shift
UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), frame_parms->nb_antennas_rx, rx_size); scopeData_t *scope=(scopeData_t *)ue->scopeData;
if (scope){
int istreamingFlag = scope->flag_streaming[pdcchRxdataF_comp];
if (istreamingFlag == 1)
UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), frame_parms->nb_antennas_rx, rx_size);
}
if (frame_parms->nb_antennas_rx > 1) { if (frame_parms->nb_antennas_rx > 1) {
LOG_D(PHY,"we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); LOG_D(PHY,"we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx);
nr_pdcch_detection_mrc(frame_parms, rx_size, rxdataF_comp,s); nr_pdcch_detection_mrc(frame_parms, rx_size, rxdataF_comp,s);
...@@ -765,7 +769,11 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, ...@@ -765,7 +769,11 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
s, s,
n_rb); n_rb);
UEscopeCopy(ue, pdcchLlr, llr, sizeof(int16_t), 1, llr_size); if (scope){
int istreamingFlag = scope->flag_streaming[pdcchLlr];
if (istreamingFlag == 1)
UEscopeCopy(ue, pdcchLlr, llr, sizeof(int16_t), 1, llr_size);
}
#if T_TRACER #if T_TRACER
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "executables/nr-uesoftmodem.h" #include "executables/nr-uesoftmodem.h"
#include "PHY/CODING/nrLDPC_extern.h" #include "PHY/CODING/nrLDPC_extern.h"
#include "common/utils/nr/nr_common.h" #include "common/utils/nr/nr_common.h"
#include "openair1/PHY/TOOLS/phy_scope_interface.h"
//#define ENABLE_PHY_PAYLOAD_DEBUG 1 //#define ENABLE_PHY_PAYLOAD_DEBUG 1
...@@ -53,10 +54,51 @@ ...@@ -53,10 +54,51 @@
static uint64_t nb_total_decod =0; static uint64_t nb_total_decod =0;
static uint64_t nb_error_decod =0; static uint64_t nb_error_decod =0;
static int nb_ack = 0;
static int nb_nack = 0;
static uint32_t blockSize = 0;
static uint8_t dl_mcs = 0;
static uint16_t nofRBs = 0;
notifiedFIFO_t freeBlocks_dl; notifiedFIFO_t freeBlocks_dl;
notifiedFIFO_elt_t *msgToPush_dl; notifiedFIFO_elt_t *msgToPush_dl;
int nbDlProcessing =0; int nbDlProcessing =0;
static tpool_t pool_dl;
//extern double cpuf;
void getKPIUE(extended_kpi_ue* kpiStructure)
{
float dl_bler = 1.0;
if (nb_ack > 0){
dl_bler = (float)nb_nack / (float)nb_ack;
}
kpiStructure->DL_BLER = dl_bler;
kpiStructure->blockSize = blockSize;
kpiStructure->dl_mcs = dl_mcs;
kpiStructure->nofRBs = nofRBs;
}
void init_dlsch_tpool(uint8_t num_dlsch_threads) {
char *params = NULL;
if( num_dlsch_threads==0) {
params = calloc(1,2);
memcpy(params,"N",1);
}
else {
params = calloc(1,(num_dlsch_threads*3)+1);
for (int i=0; i<num_dlsch_threads; i++) {
memcpy(params+(i*3),"-1,",3);
}
}
initNamedTpool(params, &pool_dl, false,"dlsch");
free(params);
}
void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr, uint16_t N_RB_DL) { void free_nr_ue_dlsch(NR_UE_DLSCH_t **dlschptr, uint16_t N_RB_DL) {
uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS; uint16_t a_segments = MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER*NR_MAX_NB_LAYERS;
...@@ -194,6 +236,11 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool ...@@ -194,6 +236,11 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool
// if all segments are done // if all segments are done
if (last) { if (last) {
nb_ack++;
blockSize = harq_process->TBS;
dl_mcs = harq_process->mcs;
nofRBs = harq_process->nb_rb;
if (decodeSuccess) { if (decodeSuccess) {
//LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d TBS %d mcs %d nb_rb %d harq_process->round %d\n", //LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for nr_slot_rx %d TBS %d mcs %d nb_rb %d harq_process->round %d\n",
// phy_vars_ue->Mod_id,nr_slot_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round); // phy_vars_ue->Mod_id,nr_slot_rx,harq_process->TBS,harq_process->mcs,harq_process->nb_rb, harq_process->round);
...@@ -209,6 +256,7 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool ...@@ -209,6 +256,7 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool
dlsch->last_iteration_cnt = rdata->decodeIterations; dlsch->last_iteration_cnt = rdata->decodeIterations;
LOG_D(PHY, "DLSCH received ok \n"); LOG_D(PHY, "DLSCH received ok \n");
} else { } else {
nb_nack++;
//LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n", //LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d, mcs %d) Kr %d r %d harq_process->round %d\n",
// phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round); // phy_vars_ue->Mod_id, frame, nr_slot_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,harq_process->mcs,Kr,r,harq_process->round);
harq_process->ack = 0; harq_process->ack = 0;
......
...@@ -487,8 +487,17 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, ...@@ -487,8 +487,17 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue,
} }
// legacy code use int16, but it is complex16 // legacy code use int16, but it is complex16
UEscopeCopy(ue, pbchRxdataF_comp, pbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, pbch_e_rx_idx/2); scopeData_t *scope=(scopeData_t *)ue->scopeData;
UEscopeCopy(ue, pbchLlr, pbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, pbch_e_rx_idx); if (scope)
{
int istreamingFlag = scope->flag_streaming[pbchRxdataF_comp];
if (istreamingFlag == 1)
UEscopeCopy(ue, pbchRxdataF_comp, pbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, pbch_e_rx_idx/2);
istreamingFlag = scope->flag_streaming[pbchLlr];
if (istreamingFlag == 1)
UEscopeCopy(ue, pbchLlr, pbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, pbch_e_rx_idx);
}
#ifdef DEBUG_PBCH #ifdef DEBUG_PBCH
write_output("rxdataF_comp.m","rxFcomp",rxdataF_comp[0],240*3,1,1); write_output("rxdataF_comp.m","rxFcomp",rxdataF_comp[0],240*3,1,1);
short *p = (short *)rxdataF_comp[0]); short *p = (short *)rxdataF_comp[0]);
......
#include <QApplication>
#include <QtWidgets>
#include <QPainter>
#include <QtGui>
#include "nr_phy_qt_scope.h"
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <cassert>
#include <cmath>
#include <QtCharts>
#include <qchart.h>
#include <QValueAxis>
extern "C" {
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
#include <openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h>
}
typedef struct complex16 scopeSample_t;
#define ScaleZone 4;
#define SquaredNorm(VaR) ((VaR).r*(VaR).r+(VaR).i*(VaR).i)
const float Limits_KPI_gNB[4][2]={ // {lower Limit, Upper Limit}
{0.02, 0.8}, // UL BLER
{0.2, 10}, // UL Throughput in Mbs
{0.02, 0.8}, // DL BLER
{0.2, 10} // DL Throughput in Mbs
};
const float Limits_KPI_ue[2][2]={ // {lower Limit, Upper Limit}
{0.02, 0.8}, // DL BLER
{0.2, 10} // Throughput in Mbs
};
typedef struct {
int dataSize;
int elementSz;
int colSz;
int lineSz;
} scopeGraphData_t;
KPIListSelect::KPIListSelect(QWidget *parent) : QComboBox(parent)
{
this->addItem("I/Q PBCH", 0);
this->addItem("LLR PBCH", 1);
this->addItem("I/Q PDSCH", 2);
this->addItem("LLR PDSCH", 3);
this->addItem("I/Q PDCCH", 4);
this->addItem("LLR PDCCH", 5);
this->addItem("RX Signal-Time", 6);
this->addItem("Channel Response", 7);
this->addItem("DL BLER", 8);
this->addItem("Throughput", 9);
this->addItem("DL MCS", 10);
this->addItem("Nof Sched. RBs", 11);
}
KPIListSelect::~KPIListSelect()
{
}
KPIListSelectgNB::KPIListSelectgNB(QWidget *parent) : QComboBox(parent)
{
this->addItem("I/Q PUSCH", 0);
this->addItem("LLR PUSCH", 1);
this->addItem("Channel Response", 2);
this->addItem("UL BLER", 3);
this->addItem("DL BLER", 4);
this->addItem("DL MCS", 5);
this->addItem("UL MCS", 6);
this->addItem("UL Throughput", 7);
this->addItem("DL Throughput", 8);
this->addItem("Nof Sched. RBs", 9);
this->addItem("UL SNR", 10);
this->addItem("DL SNR (CQI)", 11);
this->addItem("UL Retrans.", 12);
this->addItem("DL Retrans.", 13);
}
KPIListSelectgNB::~KPIListSelectgNB()
{
}
PainterWidgetgNB::PainterWidgetgNB(QComboBox *parent, scopeData_t *p)
{
timer = new QTimer(this);
timerRetrans = new QTimer(this);
this->chartHight = 300;
this->chartWidth = 300;
this->pix = new QPixmap(this->chartWidth,this->chartHight);
this->pix->fill(QColor(240,240,240));
this->parentWindow = parent;
this->p = p;
this->nb_UEs = 1;
this->indexToPlot = this->parentWindow->currentIndex();
this->previousIndex = this->parentWindow->currentIndex();
// UL BLER
this->ULBLER.plot_idx = 0;
resetKPIPlot(&this->ULBLER);
// UL MCS
this->ULMCS.plot_idx = 0;
resetKPIPlot(&this->ULMCS);
resetKPIValues(&this->ULMCS);
// DL BLER
this->DLBLER.plot_idx = 0;
resetKPIPlot(&this->DLBLER);
// DL MCS
this->DLMCS.plot_idx = 0;
resetKPIPlot(&this->DLMCS);
resetKPIValues(&this->DLMCS);
// UL Throughput
this->ULThrou.plot_idx = 0;
resetKPIPlot(&this->ULThrou);
resetKPIValues(&this->ULThrou);
// DL Throughput
this->DLThrou.plot_idx = 0;
resetKPIPlot(&this->DLThrou);
resetKPIValues(&this->DLThrou);
// nof scheduled RBs
this->nofRBs.plot_idx = 0;
resetKPIPlot(&this->nofRBs);
resetKPIValues(&this->nofRBs);
// UL SNR
this->ULSNR.plot_idx = 0;
resetKPIPlot(&this->ULSNR);
resetKPIValues(&this->ULSNR);
// DL SNR
this->DLSNR.plot_idx = 0;
resetKPIPlot(&this->DLSNR);
resetKPIValues(&this->DLSNR);
// UL Retrans
this->ULRetrans[0].plot_idx = 0;
for (int i=0; i<4; i++)
{
resetKPIPlot(&this->ULRetrans[i]);
resetKPIValues(&this->ULRetrans[i]);
}
this->ULRetrans[0].series->setName("R. 1");
this->ULRetrans[1].series->setName("R. 2");
this->ULRetrans[2].series->setName("R. 3");
this->ULRetrans[3].series->setName("R. 4");
// DL Retrans
this->DLRetrans[0].plot_idx = 0;
for (int i=0; i<4; i++)
{
resetKPIPlot(&this->DLRetrans[i]);
resetKPIValues(&this->DLRetrans[i]);
}
this->DLRetrans[0].series->setName("R. 1");
this->DLRetrans[1].series->setName("R. 2");
this->DLRetrans[2].series->setName("R. 3");
this->DLRetrans[3].series->setName("R. 4");
makeConnections();
}
void PainterWidgetgNB::resetKPIPlot(KPI_elements *inputStruct)
{
inputStruct->series = new QLineSeries();
inputStruct->series->setColor(QColor(0,0,0));
inputStruct->seriesMin = new QLineSeries();
inputStruct->seriesMin->setColor(QColor(255,0,0));
inputStruct->seriesMin->setName("Min.");
inputStruct->seriesMax = new QLineSeries();
inputStruct->seriesMax->setColor(QColor(0,255,0));
inputStruct->seriesMax->setName("Max.");
inputStruct->seriesAvg = new QLineSeries();
inputStruct->seriesAvg->setColor(QColor(0,0,255));
inputStruct->seriesAvg->setName("Avg.");
}
void PainterWidgetgNB::resetKPIValues(KPI_elements *inputStruct)
{
inputStruct->max_value = 0.0;
inputStruct->min_value = 0.0;
inputStruct->avg_value = 0.0;
inputStruct->avg_idx = 0;
inputStruct->nof_retrans = 0;
}
void PainterWidgetgNB::resizeEvent(QResizeEvent *event)
{
if ((width() != this->chartWidth) || (height() != this->chartHight))
{
this->chartHight = height();
this->chartWidth = width();
update();
}
QWidget::resizeEvent(event);
}
void PainterWidgetgNB::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawPixmap( (this->width()-this->pix->width())/2,
(this->height()-this->pix->height())/2, *this->pix); // paint pixmap on widget
this->indexToPlot = this->parentWindow->currentIndex();
makeConnections();
}
void PainterWidgetgNB::makeConnections()
{
disconnect(timer, nullptr, nullptr, nullptr);
if (this->indexToPlot == 0)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_PuschIQ);
}
else if (this->indexToPlot == 1)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_PuschLLR); // paintPixmap_uePbchIQ
}
else if (this->indexToPlot == 2)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_ChannelResponse);
}
else if (this->indexToPlot == 3)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_UL_BLER);
}
else if (this->indexToPlot == 4)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_DL_BLER);
}
else if (this->indexToPlot == 5)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_DL_MCS);
}
else if (this->indexToPlot == 6)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_UL_MCS);
}
else if (this->indexToPlot == 7)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_UL_Throu);
}
else if (this->indexToPlot == 8)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_DL_Throu);
}
else if (this->indexToPlot == 9)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_Nof_RBs);
}
else if (this->indexToPlot == 10)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_UL_SNR);
}
else if (this->indexToPlot == 11)
{
connect(timer, &QTimer::timeout, this, &PainterWidgetgNB::KPI_DL_SNR);
}
else if (this->indexToPlot == 12)
{
connect(timerRetrans, &QTimer::timeout, this, &PainterWidgetgNB::KPI_UL_Retrans);
}
else if (this->indexToPlot == 13)
{
connect(timerRetrans, &QTimer::timeout, this, &PainterWidgetgNB::KPI_DL_Retrans);
}
timer->start(200);
timerRetrans->start(1000);
}
void PainterWidgetgNB::KPI_DL_Retrans()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
if ((this->DLRetrans[0].plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->DLRetrans[0].plot_idx = 0;
for (int i=0; i<4; i++)
{
resetKPIPlot(&this->DLRetrans[i]);
resetKPIValues(&this->DLRetrans[i]);
}
this->DLRetrans[0].series->setName("R. 1");
this->DLRetrans[1].series->setName("R. 2");
this->DLRetrans[2].series->setName("R. 3");
this->DLRetrans[3].series->setName("R. 4");
}
float Xpaint = this->DLRetrans[0].plot_idx;
float Ypaint[4];
uint64_t nrRetrans;
for (int i=0; i<4;i++){
nrRetrans = targetUE->mac_stats.dl.rounds[i] - this->DLRetrans[i].nof_retrans;
Ypaint[i] = (float)nrRetrans;
this->DLRetrans[i].nof_retrans = targetUE->mac_stats.dl.rounds[i];
}
if (this->DLRetrans[0].plot_idx != 0)
{
this->DLRetrans[0].max_value = std::max(this->DLRetrans[0].max_value, Ypaint[0]);
for (int i=0; i<4;i++){
this->DLRetrans[i].series->append(Xpaint, Ypaint[i]);
}
}
QChart *chart = new QChart();
chart->legend()->setVisible(true);
chart->legend()->setAlignment(Qt::AlignBottom);
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, this->DLRetrans[0].max_value + 5);
axisY->setTitleText("Nof Retrans.");
chart->addAxis(axisY, Qt::AlignLeft);
if (this->DLRetrans[0].plot_idx != 0)
{
for (int i=0; i<4;i++){
chart->addSeries(this->DLRetrans[i].series);
this->DLRetrans[i].series->attachAxis(axisX);
this->DLRetrans[i].series->attachAxis(axisY);
}
}
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->DLRetrans[0].plot_idx++;
update();
}
void PainterWidgetgNB::KPI_UL_Retrans()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
if ((this->ULRetrans[0].plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->ULRetrans[0].plot_idx = 0;
for (int i=0; i<4; i++)
{
resetKPIPlot(&this->ULRetrans[i]);
resetKPIValues(&this->ULRetrans[i]);
}
this->ULRetrans[0].series->setName("R. 1");
this->ULRetrans[1].series->setName("R. 2");
this->ULRetrans[2].series->setName("R. 3");
this->ULRetrans[3].series->setName("R. 4");
}
float Xpaint = this->ULRetrans[0].plot_idx;
float Ypaint[4];
uint64_t nrRetrans;
for (int i=0; i<4;i++){
nrRetrans = targetUE->mac_stats.ul.rounds[i] - this->ULRetrans[i].nof_retrans;
Ypaint[i] = (float)nrRetrans;
this->ULRetrans[i].nof_retrans = targetUE->mac_stats.ul.rounds[i];
}
if (this->ULRetrans[0].plot_idx != 0)
{
this->ULRetrans[0].max_value = std::max(this->ULRetrans[0].max_value, Ypaint[0]);
for (int i=0; i<4;i++){
this->ULRetrans[i].series->append(Xpaint, Ypaint[i]);
}
}
QChart *chart = new QChart();
chart->legend()->setVisible(true);
chart->legend()->setAlignment(Qt::AlignBottom);
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, this->ULRetrans[0].max_value + 5);
axisY->setTitleText("Nof Retrans.");
chart->addAxis(axisY, Qt::AlignLeft);
if (this->ULRetrans[0].plot_idx != 0)
{
for (int i=0; i<4;i++){
chart->addSeries(this->ULRetrans[i].series);
this->ULRetrans[i].series->attachAxis(axisX);
this->ULRetrans[i].series->attachAxis(axisY);
}
}
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->ULRetrans[0].plot_idx++;
update();
}
void PainterWidgetgNB::KPI_DL_SNR()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
NR_UE_sched_ctrl_t *sched_ctrl = &targetUE->UE_sched_ctrl;
if ((this->DLSNR.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->DLSNR.plot_idx = 0;
resetKPIPlot(&this->DLSNR);
}
float Xpaint, Ypaint;
Xpaint = this->DLSNR.plot_idx;
Ypaint = (float)sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb;
this->DLSNR.max_value = std::max(this->DLSNR.max_value, Ypaint);
this->DLSNR.series->append(Xpaint, Ypaint);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, this->DLSNR.max_value + 2);
axisY->setTitleText("DL SNR (CQI)");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->DLSNR.series);
this->DLSNR.series->attachAxis(axisX);
this->DLSNR.series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->DLSNR.plot_idx++;
update();
}
void PainterWidgetgNB::KPI_UL_SNR()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
NR_UE_sched_ctrl_t *sched_ctrl = &targetUE->UE_sched_ctrl;
if ((this->ULSNR.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->ULSNR.plot_idx = 0;
resetKPIPlot(&this->ULSNR);
}
float Xpaint, Ypaint;
Xpaint = this->ULSNR.plot_idx;
Ypaint = (float)sched_ctrl->pusch_snrx10/10.0;
this->ULSNR.max_value = std::max(this->ULSNR.max_value, Ypaint);
this->ULSNR.series->append(Xpaint, Ypaint);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, 1.2*this->ULSNR.max_value);
axisY->setTitleText("PUSCH SNR dB");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->ULSNR.series);
this->ULSNR.series->attachAxis(axisX);
this->ULSNR.series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->ULSNR.plot_idx++;
update();
}
void PainterWidgetgNB::KPI_Nof_RBs()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
NR_UE_sched_ctrl_t *sched_ctrl = &targetUE->UE_sched_ctrl;
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
int current_harq_pid = (int)sched_pdsch->dl_harq_pid;
uint16_t rbSize = (uint16_t)sched_ctrl->harq_processes[current_harq_pid].sched_pdsch.rbSize;
if ((this->nofRBs.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->nofRBs.plot_idx = 0;
resetKPIPlot(&this->nofRBs);
}
float Xpaint, Ypaint;
Xpaint = this->nofRBs.plot_idx;
Ypaint = (float)rbSize;
this->nofRBs.max_value = std::max(this->nofRBs.max_value, Ypaint);
this->nofRBs.series->append(Xpaint, Ypaint);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, this->nofRBs.max_value + 10);
axisY->setTitleText("Nof Scheduled RBs");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->nofRBs.series);
this->nofRBs.series->attachAxis(axisX);
this->nofRBs.series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->nofRBs.plot_idx++;
update();
}
void PainterWidgetgNB::KPI_DL_Throu()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
NR_UE_sched_ctrl_t *sched_ctrl = &targetUE->UE_sched_ctrl;
uint32_t blockSize = (uint32_t)targetUE->mac_stats.dl.current_bytes;
float bler_dl = (float)sched_ctrl->dl_bler_stats.bler;
NR_DL_FRAME_PARMS *frame_parms = &this->p->gNB->frame_parms;
uint16_t slots_per_frame = frame_parms->slots_per_frame;
float slotDuration = 10.0/(float)slots_per_frame; // slot duration in msec
double blerTerm = 1.0 - (double)bler_dl;
double blockSizeBits = (double)(blockSize << 3);
double ThrouputKBitSec = blerTerm * blockSizeBits / (double)slotDuration;
if ((this->DLThrou.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->DLThrou.plot_idx = 0;
resetKPIPlot(&this->DLThrou);
}
float Xpaint, Ypaint;
Xpaint = this->DLThrou.plot_idx;
Ypaint = (float)(ThrouputKBitSec/1000); // Throughput in MBit/sec
this->DLThrou.max_value = std::max(this->DLThrou.max_value, Ypaint);
this->DLThrou.series->append(Xpaint, Ypaint);
QLineSeries *series_LowLim = new QLineSeries();
series_LowLim->append(0, Limits_KPI_gNB[3][0]);
series_LowLim->append(this->chartWidth, Limits_KPI_gNB[3][0]);
series_LowLim->setColor(QColor(0, 255, 0));
QLineSeries *series_UppLim = new QLineSeries();
series_UppLim->append(0, Limits_KPI_gNB[3][1]);
series_UppLim->append(this->chartWidth, Limits_KPI_gNB[3][1]);
series_UppLim->setColor(QColor(255, 0, 0));
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, 1.2*this->DLThrou.max_value);
axisY->setTitleText("UL Throughput Mbit/sec");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->DLThrou.series);
this->DLThrou.series->attachAxis(axisX);
this->DLThrou.series->attachAxis(axisY);
chart->addSeries(series_LowLim);
series_LowLim->attachAxis(axisX);
series_LowLim->attachAxis(axisY);
chart->addSeries(series_UppLim);
series_UppLim->attachAxis(axisX);
series_UppLim->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->DLThrou.plot_idx++;
update();
}
void PainterWidgetgNB::KPI_UL_Throu()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
NR_UE_sched_ctrl_t *sched_ctrl = &targetUE->UE_sched_ctrl;
uint32_t blockSize = (uint32_t)targetUE->mac_stats.ul.current_bytes;
float bler_ul = (float)sched_ctrl->ul_bler_stats.bler;
NR_DL_FRAME_PARMS *frame_parms = &this->p->gNB->frame_parms;
uint16_t slots_per_frame = frame_parms->slots_per_frame;
float slotDuration = 10.0/(float)slots_per_frame; // slot duration in msec
double blerTerm = 1.0 - (double)bler_ul;
double blockSizeBits = (double)(blockSize << 3);
double ThrouputKBitSec = blerTerm * blockSizeBits / (double)slotDuration;
if ((this->ULThrou.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->ULThrou.plot_idx = 0;
resetKPIPlot(&this->ULThrou);
}
float Xpaint, Ypaint;
Xpaint = this->ULThrou.plot_idx;
Ypaint = (float)(ThrouputKBitSec/1000); // Throughput in MBit/sec
this->ULThrou.max_value = std::max(this->ULThrou.max_value, Ypaint);
this->ULThrou.series->append(Xpaint, Ypaint);
QLineSeries *series_LowLim = new QLineSeries();
series_LowLim->append(0, Limits_KPI_gNB[1][0]);
series_LowLim->append(this->chartWidth, Limits_KPI_gNB[1][0]);
series_LowLim->setColor(QColor(0, 255, 0));
QLineSeries *series_UppLim = new QLineSeries();
series_UppLim->append(0, Limits_KPI_gNB[1][1]);
series_UppLim->append(this->chartWidth, Limits_KPI_gNB[1][1]);
series_UppLim->setColor(QColor(255, 0, 0));
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, 1.2*this->ULThrou.max_value);
axisY->setTitleText("UL Throughput Mbit/sec");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->ULThrou.series);
this->ULThrou.series->attachAxis(axisX);
this->ULThrou.series->attachAxis(axisY);
chart->addSeries(series_LowLim);
series_LowLim->attachAxis(axisX);
series_LowLim->attachAxis(axisY);
chart->addSeries(series_UppLim);
series_UppLim->attachAxis(axisX);
series_UppLim->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->ULThrou.plot_idx++;
update();
}
void PainterWidgetgNB::KPI_DL_MCS()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
NR_UE_sched_ctrl_t *sched_ctrl = &targetUE->UE_sched_ctrl;
if ((this->DLMCS.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->DLMCS.plot_idx = 0;
resetKPIPlot(&this->DLMCS);
if(this->indexToPlot != this->previousIndex)
resetKPIValues(&this->DLMCS);
}
float Xpaint, Ypaint;
Xpaint = this->DLMCS.plot_idx;
Ypaint = (float)sched_ctrl->dl_bler_stats.mcs;
this->DLMCS.max_value = std::max(this->DLMCS.max_value, Ypaint);
this->DLMCS.min_value = std::min(this->DLMCS.min_value, Ypaint);
this->DLMCS.series->append(Xpaint, Ypaint);
this->DLMCS.seriesMin->append(Xpaint, this->DLMCS.min_value);
this->DLMCS.seriesMax->append(Xpaint, this->DLMCS.max_value);
QChart *chart = new QChart();
chart->legend()->show();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, this->DLMCS.max_value + 2.0);
axisY->setTitleText("DL MCS");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->DLMCS.series);
this->DLMCS.series->attachAxis(axisX);
this->DLMCS.series->attachAxis(axisY);
chart->addSeries(this->DLMCS.seriesMin);
this->DLMCS.seriesMin->attachAxis(axisX);
this->DLMCS.seriesMin->attachAxis(axisY);
chart->addSeries(this->DLMCS.seriesMax);
this->DLMCS.seriesMax->attachAxis(axisX);
this->DLMCS.seriesMax->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->DLMCS.plot_idx++;
update();
}
void PainterWidgetgNB::KPI_DL_BLER()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
NR_UE_sched_ctrl_t *sched_ctrl = &targetUE->UE_sched_ctrl;
if ((this->DLBLER.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->DLBLER.plot_idx = 0;
resetKPIPlot(&this->DLBLER);
}
float Xpaint, Ypaint;
Xpaint = this->DLBLER.plot_idx;
Ypaint = (float)sched_ctrl->dl_bler_stats.bler;
this->DLBLER.series->append(Xpaint, Ypaint);
QLineSeries *series_LowLim = new QLineSeries();
series_LowLim->append(0, Limits_KPI_gNB[2][0]);
series_LowLim->append(this->chartWidth, Limits_KPI_gNB[2][0]);
series_LowLim->setColor(QColor(0, 255, 0));
QLineSeries *series_UppLim = new QLineSeries();
series_UppLim->append(0, Limits_KPI_gNB[2][1]);
series_UppLim->append(this->chartWidth, Limits_KPI_gNB[2][1]);
series_UppLim->setColor(QColor(255, 0, 0));
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index (calc window: 100 ms)");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, 1.5);
axisY->setTitleText("DL BLER");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->DLBLER.series);
this->DLBLER.series->attachAxis(axisX);
this->DLBLER.series->attachAxis(axisY);
chart->addSeries(series_LowLim);
series_LowLim->attachAxis(axisX);
series_LowLim->attachAxis(axisY);
chart->addSeries(series_UppLim);
series_UppLim->attachAxis(axisX);
series_UppLim->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->DLBLER.plot_idx++;
update();
}
void PainterWidgetgNB::KPI_UL_BLER()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
NR_UE_sched_ctrl_t *sched_ctrl = &targetUE->UE_sched_ctrl;
if ((this->ULBLER.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->ULBLER.plot_idx = 0;
resetKPIPlot(&this->ULBLER);
}
float Xpaint, Ypaint;
Xpaint = this->ULBLER.plot_idx;
Ypaint = (float)sched_ctrl->ul_bler_stats.bler;
this->ULBLER.series->append(Xpaint, Ypaint);
QLineSeries *series_LowLim = new QLineSeries();
series_LowLim->append(0, Limits_KPI_gNB[0][0]);
series_LowLim->append(this->chartWidth, Limits_KPI_gNB[0][0]);
series_LowLim->setColor(QColor(0, 255, 0));
QLineSeries *series_UppLim = new QLineSeries();
series_UppLim->append(0, Limits_KPI_gNB[0][1]);
series_UppLim->append(this->chartWidth, Limits_KPI_gNB[0][1]);
series_UppLim->setColor(QColor(255, 0, 0));
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index (calc window: 100 ms)");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, 1.5);
axisY->setTitleText("UL BLER");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->ULBLER.series);
this->ULBLER.series->attachAxis(axisX);
this->ULBLER.series->attachAxis(axisY);
chart->addSeries(series_LowLim);
series_LowLim->attachAxis(axisX);
series_LowLim->attachAxis(axisY);
chart->addSeries(series_UppLim);
series_UppLim->attachAxis(axisX);
series_UppLim->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->ULBLER.plot_idx++;
update();
}
void PainterWidgetgNB::KPI_UL_MCS()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
gNB_MAC_INST *gNBMac = (gNB_MAC_INST *)RC.nrmac[0];
NR_UE_info_t *targetUE = gNBMac->UE_info.list[0];
NR_UE_sched_ctrl_t *sched_ctrl = &targetUE->UE_sched_ctrl;
if ((this->ULMCS.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->ULMCS.plot_idx = 0;
resetKPIPlot(&this->ULMCS);
if (this->indexToPlot != this->previousIndex)
resetKPIValues(&this->ULMCS);
}
float Xpaint, Ypaint;
Xpaint = this->ULMCS.plot_idx;
Ypaint = (float)sched_ctrl->ul_bler_stats.mcs;
this->ULMCS.max_value = std::max(this->ULMCS.max_value, Ypaint);
this->ULMCS.min_value = std::min(this->ULMCS.min_value, Ypaint);
this->ULMCS.series->append(Xpaint, Ypaint);
this->ULMCS.seriesMin->append(Xpaint, this->ULMCS.min_value);
this->ULMCS.seriesMax->append(Xpaint, this->ULMCS.max_value);
QChart *chart = new QChart();
chart->legend()->show();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, this->ULMCS.max_value + 2.0);
axisY->setTitleText("UL MCS");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->ULMCS.series);
this->ULMCS.series->attachAxis(axisX);
this->ULMCS.series->attachAxis(axisY);
chart->addSeries(this->ULMCS.seriesMin);
this->ULMCS.seriesMin->attachAxis(axisX);
this->ULMCS.seriesMin->attachAxis(axisY);
chart->addSeries(this->ULMCS.seriesMax);
this->ULMCS.seriesMax->attachAxis(axisX);
this->ULMCS.seriesMax->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->ULMCS.plot_idx++;
update();
}
void PainterWidgetgNB::KPI_PuschIQ()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
//paint the axis and I/Q samples
NR_DL_FRAME_PARMS *frame_parms=&this->p->gNB->frame_parms;
int sz=frame_parms->N_RB_UL*12*frame_parms->symbols_per_slot;
int ue = 0;
float *I, *Q;
float FIinit[sz] = { 0 }, FQinit[sz] = { 0 };
I = FIinit;
Q = FQinit;
if ((this->p->gNB->pusch_vars) &&
(this->p->gNB->pusch_vars[ue]) &&
(this->p->gNB->pusch_vars[ue]->rxdataF_comp) &&
(this->p->gNB->pusch_vars[ue]->rxdataF_comp[0]))
{
scopeSample_t *pusch_comp = (scopeSample_t *) this->p->gNB->pusch_vars[ue]->rxdataF_comp[0];
for (int k=0; k<sz; k++ )
{
I[k] = pusch_comp[k].r;
Q[k] = pusch_comp[k].i;
}
}
QColor MarkerColor(0, 255, 0);
const QString xLabel = QString("Real");
const QString yLabel = QString("Img");
createPixMap(I, Q, sz, MarkerColor, xLabel, yLabel, true);
update();
}
void PainterWidgetgNB::KPI_PuschLLR()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
//paint the axis LLRs
int coded_bits_per_codeword =3*8*6144+12;
int sz = coded_bits_per_codeword;
int ue = 0;
float *llr, *bit;
float llrBuffer[sz] = { 0 }, bitBuffer[sz] = { 0 };
llr = llrBuffer;
bit = bitBuffer;
if ((this->p->gNB->pusch_vars) &&
(this->p->gNB->pusch_vars[ue]) &&
(this->p->gNB->pusch_vars[ue]->llr))
{
int16_t *pusch_llr = (int16_t *)p->gNB->pusch_vars[ue]->llr;
for (int i=0; i<sz; i++)
{
llr[i] = (float) pusch_llr[i];
bit[i] = (float) i;
}
}
QColor MarkerColor(0, 255, 0);
const QString xLabel = QString("Sample Index");
const QString yLabel = QString("LLR");
createPixMap(bit, llr, sz, MarkerColor, xLabel, yLabel, false);
update();
}
void PainterWidgetgNB::KPI_ChannelResponse()
{
this->pix->fill(QColor(240,240,240));
const int len=2*this->p->gNB->frame_parms.ofdm_symbol_size;
float *values, *time;
float valuesBuffer[len] = { 0 }, timeBuffer[len] = { 0 };
values = valuesBuffer;
time = timeBuffer;
const int ant=0;
int ue = 0;
if ((this->p->gNB->pusch_vars && p->gNB->pusch_vars[ue]) &&
(this->p->gNB->pusch_vars[ue]->ul_ch_estimates_time) &&
(this->p->gNB->pusch_vars[ue]->ul_ch_estimates_time[ant]))
{
scopeSample_t *data= (scopeSample_t *)this->p->gNB->pusch_vars[ue]->ul_ch_estimates_time[ant];
if (data != NULL)
{
for (int i=0; i<len; i++)
{
values[i] = SquaredNorm(data[i]);
time[i] = (float) i;
}
}
}
float maxY=0, minY=0;
for (int k=0; k<len; k++) {
maxY=std::max(maxY,values[k]);
minY=std::min(minY,values[k]);
}
float maxYAbs = std::max(abs(maxY),abs(minY));
QLineSeries *series = new QLineSeries();
QColor MarkerColor(255, 0, 0);
series->setColor(MarkerColor);
float Xpaint, Ypaint;
float minYScaled=0, maxYScaled=0;
for (int k=0; k<len; k++) {
Xpaint = time[k];
Ypaint = values[k]/maxYAbs*50;
series->append(Xpaint, Ypaint);
maxYScaled=std::max(maxYScaled,Ypaint);
minYScaled=std::min(minYScaled,Ypaint);
}
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , len);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange((minYScaled + 0.4*minYScaled), (maxYScaled + 0.4*maxYScaled));
axisY->setTitleText("abs Channel");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
update();
}
void PainterWidgetgNB::createPixMap(float *xData, float *yData, int len, QColor MarkerColor,
const QString xLabel, const QString yLabel, bool scaleX)
{
float maxX=0, maxY=0, minX=0, minY=0;
for (int k=0; k<len; k++) {
maxX=std::max(maxX,xData[k]);
minX=std::min(minX,xData[k]);
maxY=std::max(maxY,yData[k]);
minY=std::min(minY,yData[k]);
}
float maxYAbs = std::max(abs(maxY),abs(minY));
float maxXAbs = std::max(abs(maxX),abs(minX));
QScatterSeries *series = new QScatterSeries();
series->setUseOpenGL(true);
series->setColor(MarkerColor);
series->setMarkerSize(2);
series->setBorderColor(Qt::transparent);
series->setMarkerShape(QScatterSeries::MarkerShapeCircle);
float Xpaint, Ypaint;
QVector<QPointF> points(len);
float minYScaled=0, maxYScaled=0, maxXScaled = 0, minXScaled = 0;
for (int k=0; k<len; k++) {
if (maxYAbs != 0)
Ypaint = yData[k]/maxYAbs*50;
else
Ypaint = yData[k];
if ((maxXAbs != 0) && (scaleX))
Xpaint = xData[k]/maxXAbs*50;
else
Xpaint = xData[k];
points[k] = QPointF(Xpaint, Ypaint);
//series->append(Xpaint, Ypaint);
maxYScaled=std::max(maxYScaled,Ypaint);
minYScaled=std::min(minYScaled,Ypaint);
maxXScaled=std::max(maxXScaled,Xpaint);
minXScaled=std::min(minXScaled,Xpaint);
}
series->replace(points);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
if (!scaleX)
axisX->setRange(0 , len);
else
{
if ((minXScaled != 0) && (maxXScaled != 0))
axisX->setRange((minXScaled + 0.4*minXScaled) , (maxXScaled + 0.4*maxXScaled));
else
axisX->setRange(-10,10);
}
axisX->setTitleText(xLabel);
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
if ((minYScaled != 0) && (maxYScaled != 0))
axisY->setRange((minYScaled + 0.4*minYScaled), (maxYScaled + 0.4*maxYScaled));
else
axisY->setRange(-10, 10);
axisY->setTitleText(yLabel);
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
QChartView *chartView = new QChartView();
chartView->resize(this->chartWidth, this->chartHight);
chartView->setChart(chart);
QPixmap pixFromChart = chartView->grab();
*this->pix = pixFromChart;
}
void PainterWidget::paintPixmap_ueWaterFallTime()
{
QPainter PixPainter(this->pix);
PixPainter.translate(0, this->pix->height()/2);
scopeSample_t *values = (scopeSample_t *) this->ue->common_vars.rxdata[0];
const int datasize = this->ue->frame_parms.samples_per_frame;
if (values == NULL)
return;
this->waterFallh = this->chartHight/3 - 15;
const int samplesPerPixel = datasize/this->chartWidth;
int displayPart = this->waterFallh - ScaleZone;
int row = this->iteration%displayPart;
double avg=0;
for (int i=0; i < displayPart; i++)
avg+=this->waterFallAvg[i];
avg/=displayPart;
this->waterFallAvg[row]=0;
for (int pix=0; pix<this->chartWidth; pix++)
{
scopeSample_t *end=values+(pix+1)*samplesPerPixel;
end-=2;
double val=0;
for (scopeSample_t *s=values+(pix)*samplesPerPixel; s <end; s++)
val += SquaredNorm(*s);
val/=samplesPerPixel;
this->waterFallAvg[row]+=val/this->chartWidth;
if (val > avg*2 )
{
QColor IQColor(0,0,255);
PixPainter.setPen(IQColor);
}
if (val > avg*10 ){
QColor IQColor(0,255,0);
PixPainter.setPen(IQColor);
}
if (val > avg*100 ){
QColor IQColor(255,255,0);
PixPainter.setPen(IQColor);
}
PixPainter.drawEllipse( QPoint(pix, this->iteration%displayPart), 2, 2 );
}
this->iteration++;
repaint();
}
void PainterWidget::resetKPIPlot(KPI_elements *inputStruct)
{
inputStruct->series = new QLineSeries();
inputStruct->series->setColor(QColor(0,0,0));
inputStruct->seriesMin = new QLineSeries();
inputStruct->seriesMin->setColor(QColor(255,0,0));
inputStruct->seriesMin->setName("Min.");
inputStruct->seriesMax = new QLineSeries();
inputStruct->seriesMax->setColor(QColor(0,255,0));
inputStruct->seriesMax->setName("Max.");
inputStruct->seriesAvg = new QLineSeries();
inputStruct->seriesAvg->setColor(QColor(0,0,255));
inputStruct->seriesAvg->setName("Avg.");
}
void PainterWidget::resetKPIValues(KPI_elements *inputStruct)
{
inputStruct->max_value = 0.0;
inputStruct->min_value = 0.0;
inputStruct->avg_value = 0.0;
inputStruct->avg_idx = 0;
inputStruct->nof_retrans = 0;
}
PainterWidget::PainterWidget(QComboBox *parent, PHY_VARS_NR_UE *ue)
{
timer = new QTimer(this);
timerWaterFallTime = new QTimer(this);
this->chartHight = 300;
this->chartWidth = 300;
this->pix = new QPixmap(this->chartWidth,this->chartHight);
this->pix->fill(QColor(240,240,240));
this->ue = ue;
this->parentWindow = parent;
// settings for waterfall graph
this->iteration = 0;
this->waterFallh = this->chartHight/3 - 15;
this->waterFallAvg= (double*) malloc(sizeof(*this->waterFallAvg) * this->waterFallh);
this->isWaterFallTimeActive = false;
for (int i=0; i< this->waterFallh; i++)
this->waterFallAvg[i]=0;
this->previousIndex = this->parentWindow->currentIndex();
this->indexToPlot = this->parentWindow->currentIndex();
this->extendKPIUE.DL_BLER = -1;
this->extendKPIUE.blockSize = 0;
this->extendKPIUE.dl_mcs = 100;
this->extendKPIUE.nofRBs = 34;
// DL BLER
this->DLBLER.plot_idx = 0;
resetKPIPlot(&this->DLBLER);
// DL MCS
this->DLMCS.plot_idx = 0;
resetKPIPlot(&this->DLMCS);
resetKPIValues(&this->DLMCS);
// Throughput
this->Throu.plot_idx = 0;
resetKPIPlot(&this->Throu);
resetKPIValues(&this->Throu);
// nof scheduled RBs
this->nofRBs.plot_idx = 0;
resetKPIPlot(&this->nofRBs);
resetKPIValues(&this->nofRBs);
makeConnections();
}
void PainterWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawPixmap( (this->width()-this->pix->width())/2,
(this->height()-this->pix->height())/2, *this->pix); // paint pixmap on widget
this->indexToPlot = this->parentWindow->currentIndex();
makeConnections();
this->previousIndex = this->parentWindow->currentIndex();
}
void PainterWidget::makeConnections()
{
getKPIUE(&this->extendKPIUE);
disconnect(timer, nullptr, nullptr, nullptr);
disconnect(timerWaterFallTime, nullptr, nullptr, nullptr);
if ((this->indexToPlot != this->previousIndex) && (this->indexToPlot == 6)) // reset settings
{
this->pix->fill(QColor(240,240,240));
this->iteration = 0;
for (int i=0; i< this->waterFallh; i++)
this->waterFallAvg[i]=0;
}
if (this->indexToPlot == 2)
{
if (this->isWaterFallTimeActive)
this->iteration++;
connect(timer, &QTimer::timeout, this, &PainterWidget::paintPixmap_uePdschIQ); // paintPixmap_uePdschIQ
}
else if (this->indexToPlot == 0)
{
if (this->isWaterFallTimeActive)
this->iteration++;
connect(timer, &QTimer::timeout, this, &PainterWidget::paintPixmap_uePbchIQ); // paintPixmap_uePbchIQ
}
else if (this->indexToPlot == 4)
{
if (this->isWaterFallTimeActive)
this->iteration++;
connect(timer, &QTimer::timeout, this, &PainterWidget::paintPixmap_uePdcchIQ);
}
else if (this->indexToPlot == 3)
{
if (this->isWaterFallTimeActive)
this->iteration++;
connect(timer, &QTimer::timeout, this, &PainterWidget::paintPixmap_uePdschLLR); // paintPixmap_uePdschLLR
}
else if (this->indexToPlot == 1)
{
if (this->isWaterFallTimeActive)
this->iteration++;
connect(timer, &QTimer::timeout, this, &PainterWidget::paintPixmap_uePbchLLR); // paintPixmap_uePbchLLR
}
else if (this->indexToPlot == 5)
{
if (this->isWaterFallTimeActive)
this->iteration++;
connect(timer, &QTimer::timeout, this, &PainterWidget::paintPixmap_uePdcchLLR);
}
else if (this->indexToPlot == 6)
{
this->isWaterFallTimeActive = true;
connect(timerWaterFallTime, &QTimer::timeout, this, &PainterWidget::paintPixmap_ueWaterFallTime); // water fall time domain
}
else if (this->indexToPlot == 7)
{
if (this->isWaterFallTimeActive)
this->iteration++;
connect(timer, &QTimer::timeout, this, &PainterWidget::paintPixmap_ueChannelResponse); // Channel Response
}
else if (this->indexToPlot == 8)
{
connect(timer, &QTimer::timeout, this, &PainterWidget::KPI_DL_BLER);
}
else if (this->indexToPlot == 9)
{
connect(timer, &QTimer::timeout, this, &PainterWidget::KPI_DL_Throu);
}
else if (this->indexToPlot == 10)
{
connect(timer, &QTimer::timeout, this, &PainterWidget::KPI_DL_MCS);
}
else if (this->indexToPlot == 11)
{
connect(timer, &QTimer::timeout, this, &PainterWidget::KPI_Nof_RBs);
}
timer->start(200);
timerWaterFallTime->start(10);
}
void PainterWidget::KPI_Nof_RBs()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
if ((this->nofRBs.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->nofRBs.plot_idx = 0;
resetKPIPlot(&this->nofRBs);
}
float Xpaint, Ypaint;
Xpaint = this->nofRBs.plot_idx;
Ypaint = (float)this->extendKPIUE.nofRBs;
this->nofRBs.max_value = std::max(this->nofRBs.max_value, Ypaint);
this->nofRBs.series->append(Xpaint, Ypaint);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, this->nofRBs.max_value + 10);
axisY->setTitleText("Nof Scheduled RBs");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->nofRBs.series);
this->nofRBs.series->attachAxis(axisX);
this->nofRBs.series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->nofRBs.plot_idx++;
update();
}
void PainterWidget::KPI_DL_Throu()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
uint32_t blockSize = (uint32_t)this->extendKPIUE.blockSize;
float bler_dl = this->extendKPIUE.DL_BLER;
NR_DL_FRAME_PARMS *frame_parms = &this->ue->frame_parms;
uint16_t slots_per_frame = frame_parms->slots_per_frame;
float slotDuration = 10.0/(float)slots_per_frame; // slot duration in msec
double blerTerm = 1.0 - (double)bler_dl;
double blockSizeBits = (double)(blockSize << 3);
double ThrouputKBitSec = blerTerm * blockSizeBits / (double)slotDuration;
if ((this->Throu.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->Throu.plot_idx = 0;
resetKPIPlot(&this->Throu);
}
float Xpaint, Ypaint;
Xpaint = this->Throu.plot_idx;
Ypaint = (float)(ThrouputKBitSec/1000); // Throughput in MBit/sec
this->Throu.max_value = std::max(this->Throu.max_value, Ypaint);
this->Throu.series->append(Xpaint, Ypaint);
QLineSeries *series_LowLim = new QLineSeries();
series_LowLim->append(0, Limits_KPI_gNB[1][0]);
series_LowLim->append(this->chartWidth, Limits_KPI_gNB[1][0]);
series_LowLim->setColor(QColor(0, 255, 0));
QLineSeries *series_UppLim = new QLineSeries();
series_UppLim->append(0, Limits_KPI_gNB[1][1]);
series_UppLim->append(this->chartWidth, Limits_KPI_gNB[1][1]);
series_UppLim->setColor(QColor(255, 0, 0));
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, 1.2*this->Throu.max_value);
axisY->setTitleText("UL Throughput Mbit/sec");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->Throu.series);
this->Throu.series->attachAxis(axisX);
this->Throu.series->attachAxis(axisY);
chart->addSeries(series_LowLim);
series_LowLim->attachAxis(axisX);
series_LowLim->attachAxis(axisY);
chart->addSeries(series_UppLim);
series_UppLim->attachAxis(axisX);
series_UppLim->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->Throu.plot_idx++;
update();
}
void PainterWidget::KPI_DL_MCS()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
if ((this->DLMCS.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->DLMCS.plot_idx = 0;
resetKPIPlot(&this->DLMCS);
if(this->indexToPlot != this->previousIndex)
resetKPIValues(&this->DLMCS);
}
float Xpaint, Ypaint;
Xpaint = this->DLMCS.plot_idx;
Ypaint = (float)this->extendKPIUE.dl_mcs;
this->DLMCS.max_value = std::max(this->DLMCS.max_value, Ypaint);
this->DLMCS.min_value = std::min(this->DLMCS.min_value, Ypaint);
this->DLMCS.series->append(Xpaint, Ypaint);
this->DLMCS.seriesMin->append(Xpaint, this->DLMCS.min_value);
this->DLMCS.seriesMax->append(Xpaint, this->DLMCS.max_value);
QChart *chart = new QChart();
chart->legend()->show();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, this->DLMCS.max_value + 2.0);
axisY->setTitleText("DL MCS");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->DLMCS.series);
this->DLMCS.series->attachAxis(axisX);
this->DLMCS.series->attachAxis(axisY);
chart->addSeries(this->DLMCS.seriesMin);
this->DLMCS.seriesMin->attachAxis(axisX);
this->DLMCS.seriesMin->attachAxis(axisY);
chart->addSeries(this->DLMCS.seriesMax);
this->DLMCS.seriesMax->attachAxis(axisX);
this->DLMCS.seriesMax->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->DLMCS.plot_idx++;
update();
}
void PainterWidget::KPI_DL_BLER()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
if ((this->DLBLER.plot_idx > this->chartWidth) ||
(this->indexToPlot != this->previousIndex))
{
this->DLBLER.plot_idx = 0;
resetKPIPlot(&this->DLBLER);
}
float Xpaint, Ypaint;
Xpaint = this->DLBLER.plot_idx;
Ypaint = this->extendKPIUE.DL_BLER;
this->DLBLER.series->append(Xpaint, Ypaint);
QLineSeries *series_LowLim = new QLineSeries();
series_LowLim->append(0, Limits_KPI_ue[0][0]);
series_LowLim->append(this->chartWidth, Limits_KPI_ue[0][0]);
series_LowLim->setColor(QColor(0, 255, 0));
QLineSeries *series_UppLim = new QLineSeries();
series_UppLim->append(0, Limits_KPI_ue[0][1]);
series_UppLim->append(this->chartWidth, Limits_KPI_ue[0][1]);
series_UppLim->setColor(QColor(255, 0, 0));
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , this->chartWidth);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange(-1, 1.5);
axisY->setTitleText("DL BLER");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(this->DLBLER.series);
this->DLBLER.series->attachAxis(axisX);
this->DLBLER.series->attachAxis(axisY);
chart->addSeries(series_LowLim);
series_LowLim->attachAxis(axisX);
series_LowLim->attachAxis(axisY);
chart->addSeries(series_UppLim);
series_UppLim->attachAxis(axisX);
series_UppLim->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
this->previousIndex = this->parentWindow->currentIndex();
this->DLBLER.plot_idx++;
update();
}
void PainterWidget::paintPixmap_ueChannelResponse()
{
scopeData_t *scope=(scopeData_t *) this->ue->scopeData;
scope->flag_streaming[pbchDlChEstimateTime] = 1;
scopeGraphData_t **UELiveData = (scopeGraphData_t**)(( scopeData_t *)this->ue->scopeData)->liveDataUE;
if (!UELiveData[pbchDlChEstimateTime])
return;
const scopeSample_t *tmp=(scopeSample_t *)(UELiveData[pbchDlChEstimateTime]+1);
const scopeSample_t **data=&tmp;
const int len = UELiveData[pbchDlChEstimateTime]->lineSz;
float *values, *time;
float valuesBuffer[len] = { 0 }, timeBuffer[len] = { 0 };
values = valuesBuffer;
time = timeBuffer;
int idx = 0;
int nb_ant = 1;
int eNB_id = 0;
for (int ant=0; ant<nb_ant; ant++)
{
if (data[ant] != NULL)
{
for (int i=0; i<len; i++)
{
values[i] = SquaredNorm(data[ant][i]);
time[i] = (float) idx;
idx++;
}
}
}
float maxY=0, minY=0;
for (int k=0; k<len; k++) {
maxY=std::max(maxY,values[k]);
minY=std::min(minY,values[k]);
}
float maxYAbs = std::max(abs(maxY),abs(minY));
QLineSeries *series = new QLineSeries();
QColor MarkerColor(255, 0, 0);
series->setColor(MarkerColor);
float Xpaint, Ypaint;
float minYScaled=0, maxYScaled=0;
for (int k=0; k<len; k++) {
Xpaint = time[k];
Ypaint = values[k]/maxYAbs*50;
series->append(Xpaint, Ypaint);
maxYScaled=std::max(maxYScaled,Ypaint);
minYScaled=std::min(minYScaled,Ypaint);
}
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , len);
axisX->setTitleText("Time Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange((minYScaled + 0.4*minYScaled), (maxYScaled + 0.4*maxYScaled));
axisY->setTitleText("abs Channel");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
QPainter PixPainter(&p);
float freq_offset = (float)this->ue->common_vars.freq_offset;
std::string strFreq = "Freq. Offset= " + std::to_string(freq_offset);
QString qstrFreq = QString::fromStdString(strFreq);
PixPainter.drawText(100, 1.6*maxYScaled, qstrFreq);
float timing_advance = (float)this->ue->timing_advance;
std::string strTime = "Timing Advance= " + std::to_string(timing_advance);
QString qstrTime = QString::fromStdString(strTime);
PixPainter.drawText(100, 1.3*maxYScaled, qstrTime);
*this->pix = p;
update(); //call paintEvent()
}
void PainterWidget::paintPixmap_uePdschIQ()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
//paint the axis and I/Q samples
if (!this->ue->pdsch_vars[0][0]->rxdataF_comp0[0])
return;
NR_DL_FRAME_PARMS *frame_parms = &this->ue->frame_parms;
int sz=7*2*frame_parms->N_RB_DL*12; // size of the malloced buffer
int base = 0;
float *I, *Q;
float FIinit[sz * RX_NB_TH_MAX * sizeof(*I)] = { 0 }, FQinit[sz * RX_NB_TH_MAX * sizeof(*Q)] = { 0 };
I = FIinit;
Q = FQinit;
for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) {
scopeSample_t *pdsch_comp = (scopeSample_t *) this->ue->pdsch_vars[thr][0]->rxdataF_comp0[0];
for (int s=0; s<sz; s++) {
I[s+base] += pdsch_comp[s].r;
Q[s+base] += pdsch_comp[s].i;
}
base += sz;
}
float maxX=0, maxY=0, minX=0, minY=0;
for (int k=0; k<base; k++) {
maxX=std::max(maxX,I[k]);
minX=std::min(minX,I[k]);
maxY=std::max(maxY,Q[k]);
minY=std::min(minY,Q[k]);
}
float maxXAbs = std::max(abs(maxX),abs(minX));
float maxYAbs = std::max(abs(maxY),abs(minY));
float Ipaint, Qpaint;
QScatterSeries *series = new QScatterSeries();
series->setUseOpenGL(true);
float maxXScaled=0, maxYScaled=0, minXScaled=0, minYScaled=0;
QVector<QPointF> points(base); // sz * RX_NB_TH_MAX * sizeof(*I)
for (int k=0; k<base; k++) { //scale the I/Q samples!
Ipaint = I[k]/maxXAbs*50;
Qpaint = Q[k]/maxYAbs*50;
points[k] = QPointF(Ipaint, Qpaint);
maxXScaled=std::max(maxXScaled,Ipaint);
minXScaled=std::min(minXScaled,Ipaint);
maxYScaled=std::max(maxYScaled,Qpaint);
minYScaled=std::min(minYScaled,Qpaint);
}
series->replace(points);
QColor MarkerColor(0, 255, 0);
series->setColor(MarkerColor);
series->setMarkerSize(2);
series->setBorderColor(Qt::transparent);
series->setMarkerShape(QScatterSeries::MarkerShapeCircle);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange((minXScaled + 0.4*minXScaled) , (maxXScaled + 0.4*maxXScaled));
axisX->setTitleText("Real");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange((minYScaled + 0.4*minYScaled), (maxYScaled + 0.4*maxYScaled));
axisY->setTitleText("Imag");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
QChartView *chartView = new QChartView();
chartView->resize(this->chartWidth, this->chartHight);
chartView->setChart(chart);
QPixmap p = chartView->grab();
*this->pix = p;
update(); //call paintEvent()
}
void PainterWidget::resizeEvent(QResizeEvent *event)
{
if ((width() != this->chartWidth) || (height() != this->chartHight))
{
this->chartHight = height();
this->chartWidth = width();
// reset for waterfall plot
if (this->indexToPlot == 6)
{
QPixmap *newPix = new QPixmap(this->chartWidth,this->chartHight);
this->pix = newPix;
this->pix->fill(QColor(240,240,240));
this->iteration = 0;
this->waterFallh = this->chartHight/3 - 15;
for (int i=0; i< this->waterFallh; i++)
this->waterFallAvg[i]=0;
}
update();
}
QWidget::resizeEvent(event);
}
void PainterWidget::paintPixmap_uePdcchIQ()
{
this->pix->fill(QColor(240,240,240));
scopeData_t *scope=(scopeData_t *) this->ue->scopeData;
scope->flag_streaming[pdcchRxdataF_comp] = 1;
scopeGraphData_t **UELiveData = (scopeGraphData_t**)(( scopeData_t *)this->ue->scopeData)->liveDataUE;
if (!UELiveData[pdcchRxdataF_comp])
return;
const int len=UELiveData[pdcchRxdataF_comp]->lineSz;
scopeSample_t *pdcch_comp = (scopeSample_t *) (UELiveData[pdcchRxdataF_comp]+1);
float *I, *Q;
float FIinit[len] = { 0 }, FQinit[len] = { 0 };
I = FIinit;
Q = FQinit;
for (int i=0; i<len; i++) {
I[i] = pdcch_comp[i].r;
Q[i] = pdcch_comp[i].i;
}
float maxX=0, maxY=0, minX=0, minY=0;
for (int k=0; k<len; k++) {
maxX=std::max(maxX,I[k]);
minX=std::min(minX,I[k]);
maxY=std::max(maxY,Q[k]);
minY=std::min(minY,Q[k]);
}
float maxXAbs = std::max(abs(maxX),abs(minX));
float maxYAbs = std::max(abs(maxY),abs(minY));
QScatterSeries *series = new QScatterSeries();
series->setUseOpenGL(true);
QColor MarkerColor(0, 0, 255);
series->setColor(MarkerColor);
series->setMarkerSize(2);
series->setBorderColor(Qt::transparent);
series->setMarkerShape(QScatterSeries::MarkerShapeCircle);
float maxXScaled=0, maxYScaled=0, minXScaled=0, minYScaled=0;
float Ipaint, Qpaint;
QVector<QPointF> points(len);
for (int k=0; k<len; k++) { //scale the I/Q samples!
if (abs(maxXAbs - 0.0) > 100e-6)
Ipaint = I[k]/maxXAbs*50;
else
Ipaint = I[k];
if (abs(maxYAbs - 0.0) > 100e-6)
Qpaint = Q[k]/maxYAbs*50;
else
Qpaint = Q[k];
//series->append(Ipaint, Qpaint);
points[k] = QPointF(Ipaint, Qpaint);
maxXScaled=std::max(maxXScaled,Ipaint);
minXScaled=std::min(minXScaled,Ipaint);
maxYScaled=std::max(maxYScaled,Qpaint);
minYScaled=std::min(minYScaled,Qpaint);
}
series->replace(points);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
if ( (minXScaled != 0) && (maxXScaled != 0))
{
axisX->setRange((minXScaled + 0.4*minXScaled) , (maxXScaled + 0.4*maxXScaled));
}
else
{
axisX->setRange(-10,10);
}
axisX->setTitleText("Real");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
if ((minYScaled != 0) && (maxYScaled != 0))
{
axisY->setRange((minYScaled + 0.4*minYScaled), (maxYScaled + 0.4*maxYScaled));
}
else
{
axisY->setRange(-10,10);
}
axisY->setTitleText("Imag");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
update(); //call paintEvent()
}
void PainterWidget::paintPixmap_uePbchIQ()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
scopeData_t *scope=(scopeData_t *) this->ue->scopeData;
scope->flag_streaming[pbchRxdataF_comp] = 1;
scopeGraphData_t **data = (scopeGraphData_t**)(( scopeData_t *)this->ue->scopeData)->liveDataUE;
if (!data[pbchRxdataF_comp])
return;
const int len=data[pbchRxdataF_comp]->lineSz;
scopeSample_t *pbch_comp = (scopeSample_t *) (data[pbchRxdataF_comp]+1);
float *I, *Q;
float FIinit[len] = { 0 }, FQinit[len] = { 0 };
I = FIinit;
Q = FQinit;
for (int i=0; i<len; i++) {
I[i] = pbch_comp[i].r;
Q[i] = pbch_comp[i].i;
}
float maxX=0, maxY=0, minX=0, minY=0;
for (int k=0; k<len; k++) {
maxX=std::max(maxX,I[k]);
minX=std::min(minX,I[k]);
maxY=std::max(maxY,Q[k]);
minY=std::min(minY,Q[k]);
}
float maxXAbs = std::max(abs(maxX),abs(minX));
float maxYAbs = std::max(abs(maxY),abs(minY));
QScatterSeries *series = new QScatterSeries();
series->setUseOpenGL(true);
QColor MarkerColor(255, 0, 0);
series->setColor(MarkerColor);
series->setMarkerSize(2);
series->setBorderColor(Qt::transparent);
series->setMarkerShape(QScatterSeries::MarkerShapeCircle);
int Ipaint, Qpaint;
QVector<QPointF> points(len);
for (int k=0; k<len; k++) {
Ipaint = I[k]/maxXAbs*50;
Qpaint = Q[k]/maxYAbs*50;
points[k] = QPointF(Ipaint, Qpaint);
}
series->replace(points);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange((minX + 0.4*minX) , (maxX + 0.4*maxX));
axisX->setTitleText("Real");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange((minY + 0.4*minY), (maxY + 0.4*maxY));
axisY->setTitleText("Imag");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
update(); //call paintEvent()
}
void PainterWidget::paintPixmap_uePdschLLR()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
//paint the axis and LLR values
if (!this->ue->pdsch_vars[0][0]->llr[0])
return;
int num_re = 4500;
int Qm = 2;
int coded_bits_per_codeword = num_re*Qm;
float *llr, *bit;
float FBitinit[coded_bits_per_codeword * RX_NB_TH_MAX ] = { 0 }, FLlrinit[coded_bits_per_codeword * RX_NB_TH_MAX] = { 0 };
bit = FBitinit;
llr = FLlrinit;
int base=0;
for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ )
{
int16_t *pdsch_llr = (int16_t *) this->ue->pdsch_vars[thr][0]->llr[0]; // stream 0
for (int i=0; i<coded_bits_per_codeword; i++)
{
llr[base+i] = (float) pdsch_llr[i];
bit[base+i] = (float) base+i;
}
base+=coded_bits_per_codeword;
}
float maxY=0, minY=0;
for (int k=0; k<base; k++) {
maxY=std::max(maxY,llr[k]);
minY=std::min(minY,llr[k]);
}
float maxYAbs = std::max(abs(maxY),abs(minY));
QScatterSeries *series = new QScatterSeries();
series->setUseOpenGL(true);
QColor MarkerColor(0, 255, 0);
series->setColor(MarkerColor);
series->setMarkerSize(2);
series->setBorderColor(Qt::transparent);
series->setMarkerShape(QScatterSeries::MarkerShapeCircle);
float Xpaint, Ypaint;
QVector<QPointF> points(base);
float minYScaled=0, maxYScaled=0;
for (int k=0; k<base; k++) {
Xpaint = bit[k];
Ypaint = llr[k]/maxYAbs*50;
points[k] = QPointF(Xpaint, Ypaint);
maxYScaled=std::max(maxYScaled,Ypaint);
minYScaled=std::min(minYScaled,Ypaint);
}
series->replace(points);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , base);
axisX->setTitleText("Sample Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange((minYScaled + 0.4*minYScaled), (maxYScaled + 0.4*maxYScaled));
axisY->setTitleText("LLR");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
update(); //call paintEvent()
}
void PainterWidget::paintPixmap_uePdcchLLR()
{
// erase the previous paint
this->pix->fill(QColor(240,240,240));
scopeData_t *scope=(scopeData_t *) this->ue->scopeData;
scope->flag_streaming[pdcchLlr] = 1;
scopeGraphData_t **data = (scopeGraphData_t**)(( scopeData_t *)this->ue->scopeData)->liveDataUE;
if (!data[pdcchLlr])
return;
const int len=data[pdcchLlr]->lineSz;
float *llr, *bit;
float FBitinit[len] = { 0 }, FLlrinit[len] = { 0 };
bit = FBitinit;
llr = FLlrinit;
int16_t *pdcch_llr = (int16_t *)(data[pdcchLlr]+1);
for (int i=0; i<len; i++)
{
llr[i] = (float) pdcch_llr[i];
bit[i] = (float) i;
}
float maxY=0, minY=0;
for (int k=0; k<len; k++) {
maxY=std::max(maxY,llr[k]);
minY=std::min(minY,llr[k]);
}
float maxYAbs = std::max(abs(maxY),abs(minY));
QScatterSeries *series = new QScatterSeries();
series->setUseOpenGL(true);
QColor MarkerColor(0, 0, 255);
series->setColor(MarkerColor);
series->setMarkerSize(2);
series->setBorderColor(Qt::transparent);
series->setMarkerShape(QScatterSeries::MarkerShapeCircle);
float minYScaled=0, maxYScaled=0;
float Xpaint, Ypaint;
QVector<QPointF> points(len);
for (int k=0; k<len; k++) {
Xpaint = bit[k];
Ypaint = llr[k]/maxYAbs*50;
points[k] = QPointF(Xpaint, Ypaint);
maxYScaled=std::max(maxYScaled,Ypaint);
minYScaled=std::min(minYScaled,Ypaint);
}
series->replace(points);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , len);
axisX->setTitleText("Sample Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange((minYScaled + 0.4*minYScaled), (maxYScaled + 0.4*maxYScaled));
axisY->setTitleText("LLR");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
update(); //call paintEvent()
}
void PainterWidget::paintPixmap_uePbchLLR()
{
this->pix->fill(QColor(240,240,240));
scopeData_t *scope=(scopeData_t *) this->ue->scopeData;
scope->flag_streaming[pbchLlr] = 1;
scopeGraphData_t **data = (scopeGraphData_t**)(( scopeData_t *)this->ue->scopeData)->liveDataUE;
if (!data[pbchLlr])
return;
const int len=data[pbchLlr]->lineSz;
float *llr, *bit;
float FBitinit[len] = { 0 }, FLlrinit[len] = { 0 };
bit = FBitinit;
llr = FLlrinit;
int16_t *llr_pbch = (int16_t *)(data[pbchLlr]+1);
for (int i=0; i<len; i++)
{
llr[i] = (float) llr_pbch[i];
bit[i] = (float) i;
}
float maxX=0, maxY=0, minX=0, minY=0;
for (int k=0; k<len; k++) {
maxX=std::max(maxX,bit[k]);
minX=std::min(minX,bit[k]);
maxY=std::max(maxY,llr[k]);
minY=std::min(minY,llr[k]);
}
float maxYAbs = std::max(abs(maxY),abs(minY));
QScatterSeries *series = new QScatterSeries();
series->setUseOpenGL(true);
QColor MarkerColor(255, 0, 0);
series->setColor(MarkerColor);
series->setMarkerSize(2);
series->setMarkerShape(QScatterSeries::MarkerShapeCircle);
series->setBorderColor(Qt::transparent);
QVector<QPointF> points(len);
float Xpaint, Ypaint;
float minYScaled=0, maxYScaled=0;
for (int k=0; k<len; k++) {
Xpaint = bit[k];
Ypaint = llr[k]/maxYAbs*50;
points[k] = QPointF(Xpaint, Ypaint);
maxYScaled=std::max(maxYScaled,Ypaint);
minYScaled=std::min(minYScaled,Ypaint);
}
series->replace(points);
QChart *chart = new QChart();
chart->legend()->hide();
int nofTicks = 6;
QValueAxis *axisX = new QValueAxis;
axisX->setTickCount(nofTicks);
axisX->setRange(0 , len);
axisX->setTitleText("Sample Index");
chart->addAxis(axisX, Qt::AlignBottom);
QValueAxis *axisY = new QValueAxis;
axisY->setTickCount(nofTicks);
axisY->setRange((minYScaled + 0.4*minYScaled), (maxYScaled + 0.4*maxYScaled));
axisY->setTitleText("LLR");
chart->addAxis(axisY, Qt::AlignLeft);
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
QChartView *chartView = new QChartView(chart);
chartView->resize(this->chartWidth, this->chartHight);
QPixmap p = chartView->grab();
*this->pix = p;
update(); //call paintEvent()
}
void *nrUEQtscopeThread(void *arg)
{
PHY_VARS_NR_UE *ue=(PHY_VARS_NR_UE *)arg;
int argc = 1;
char *argv[] = { (char*)"nrqt_scopeUE"};
QApplication a(argc, argv);
// Create a main window (widget)
QWidget *window = new QWidget();
window->setBaseSize(QSize(600, 900));
window->resize(600, 900);
window->setSizeIncrement(20, 20);
// Window title
window->setWindowTitle("UE Scope");
// create the popup lists
KPIListSelect * combo1 = new KPIListSelect(window);
combo1->setCurrentIndex(0);
KPIListSelect * combo2 = new KPIListSelect(window);
combo2->setCurrentIndex(1);
KPIListSelect * combo3 = new KPIListSelect(window);
combo3->setCurrentIndex(2);
KPIListSelect * combo4 = new KPIListSelect(window);
combo4->setCurrentIndex(3);
KPIListSelect * combo5 = new KPIListSelect(window);
combo5->setCurrentIndex(4);
KPIListSelect * combo6 = new KPIListSelect(window);
combo6->setCurrentIndex(7);
// Initial Plots
PainterWidget pwidgetueCombo3(combo3, ue); // I/Q PDSCH
PainterWidget pwidgetueCombo4(combo4, ue); // LLR PDSCH */
PainterWidget pwidgetueCombo1(combo1, ue); // I/Q PBCH
PainterWidget pwidgetueCombo2(combo2, ue); // LLR PBCH
PainterWidget pwidgetueCombo5(combo5, ue); // I/Q PDCCH
PainterWidget pwidgetueCombo6(combo6, ue); // LLR PDCCH
while (true)
{
// Main layout
QHBoxLayout *mainLayout = new QHBoxLayout;
// left and right layouts
QVBoxLayout *LeftLayout = new QVBoxLayout;
QVBoxLayout *RightLayout = new QVBoxLayout;
LeftLayout->addWidget(combo1);
LeftLayout->addWidget(&pwidgetueCombo1,20);
LeftLayout->addStretch(); // space for later plots
LeftLayout->addWidget(combo3);
LeftLayout->addWidget(&pwidgetueCombo3,20);
LeftLayout->addStretch(); // space for later plots
LeftLayout->addWidget(combo5);
LeftLayout->addWidget(&pwidgetueCombo5,20);
LeftLayout->addStretch(); // space for later plots
RightLayout->addWidget(combo2);
RightLayout->addWidget(&pwidgetueCombo2,20);
RightLayout->addStretch(); // space for later plots
RightLayout->addWidget(combo4);
RightLayout->addWidget(&pwidgetueCombo4,20);
RightLayout->addStretch(); // space for later plots
RightLayout->addWidget(combo6);
RightLayout->addWidget(&pwidgetueCombo6,20);
RightLayout->addStretch(); // space for later plots
// add the left and right layouts to the main layout
mainLayout->addLayout(LeftLayout);
mainLayout->addLayout(RightLayout);
// set the layout of the main window
window->setLayout(mainLayout);
pwidgetueCombo1.makeConnections();
pwidgetueCombo2.makeConnections();
pwidgetueCombo3.makeConnections();
pwidgetueCombo4.makeConnections();
pwidgetueCombo5.makeConnections();
pwidgetueCombo6.makeConnections();
// display the main window
window->show();
a.exec();
}
pthread_exit((void *)arg);
//return NULL;
}
void *nrgNBQtscopeThread(void *arg)
{
scopeData_t *p=(scopeData_t *)arg;
int argc = 1;
char *argv[] = { (char*)"nrqt_scopegNB"};
QApplication a(argc, argv);
// Create a main window (widget)
QWidget *window = new QWidget();
window->resize(600, 900);
// Window title
window->setWindowTitle("gNB Scope");
// create the popup lists
KPIListSelectgNB * combo1 = new KPIListSelectgNB(window);
combo1->setCurrentIndex(0);
KPIListSelectgNB * combo2 = new KPIListSelectgNB(window);
combo2->setCurrentIndex(1);
KPIListSelectgNB * combo3 = new KPIListSelectgNB(window);
combo3->setCurrentIndex(2);
KPIListSelectgNB * combo4 = new KPIListSelectgNB(window);
combo4->setCurrentIndex(3);
KPIListSelectgNB * combo5 = new KPIListSelectgNB(window);
combo5->setCurrentIndex(4);
KPIListSelectgNB * combo6 = new KPIListSelectgNB(window);
combo6->setCurrentIndex(5);
PainterWidgetgNB pwidgetgnbCombo1(combo1, p); // I/Q PUSCH
PainterWidgetgNB pwidgetgnbCombo2(combo2, p); // LLR PUSCH
PainterWidgetgNB pwidgetgnbCombo3(combo3, p); // Channel Response
PainterWidgetgNB pwidgetgnbCombo4(combo4, p); //
PainterWidgetgNB pwidgetgnbCombo5(combo5, p); //
PainterWidgetgNB pwidgetgnbCombo6(combo6, p); //
while (true)
{
// Main layout
QHBoxLayout *mainLayout = new QHBoxLayout;
// left and right layouts
QVBoxLayout *LeftLayout = new QVBoxLayout;
QVBoxLayout *RightLayout = new QVBoxLayout;
LeftLayout->addWidget(combo1);
LeftLayout->addWidget(&pwidgetgnbCombo1,20);
LeftLayout->addStretch(); // space for later plots
LeftLayout->addWidget(combo3);
LeftLayout->addWidget(&pwidgetgnbCombo3,20);
LeftLayout->addStretch(); // space for later plots
LeftLayout->addWidget(combo5);
LeftLayout->addWidget(&pwidgetgnbCombo5,20);
LeftLayout->addStretch(); // space for later plots
RightLayout->addWidget(combo2);
RightLayout->addWidget(&pwidgetgnbCombo2,20);
RightLayout->addStretch(); // space for later plots
RightLayout->addWidget(combo4);
RightLayout->addWidget(&pwidgetgnbCombo4,20);
RightLayout->addStretch(); // space for later plots
RightLayout->addWidget(combo6); //
RightLayout->addWidget(&pwidgetgnbCombo6,20);
RightLayout->addStretch(); // space for later plots
// add the left and right layouts to the main layout
mainLayout->addLayout(LeftLayout);
mainLayout->addLayout(RightLayout);
// set the layout of the main window
window->setLayout(mainLayout);
pwidgetgnbCombo1.makeConnections();
pwidgetgnbCombo2.makeConnections();
pwidgetgnbCombo3.makeConnections();
pwidgetgnbCombo4.makeConnections();
pwidgetgnbCombo5.makeConnections();
pwidgetgnbCombo6.makeConnections();
// display the main window
window->show();
a.exec();
}
return NULL;
}
void UEcopyData(PHY_VARS_NR_UE *ue, enum UEdataType type, void *dataIn, int elementSz, int colSz, int lineSz) {
// Local static copy of the scope data bufs
// The active data buf is alterned to avoid interference between the Scope thread (display) and the Rx thread (data input)
// Index of "2" could be set to the number of Rx threads + 1
static scopeGraphData_t *copyDataBufs[UEdataTypeNumberOfItems][2] = {0};
static int copyDataBufsIdx[UEdataTypeNumberOfItems] = {0};
scopeData_t *tmp=(scopeData_t *)ue->scopeData;
if (tmp) {
// Begin of critical zone between UE Rx threads that might copy new data at the same time: might require a mutex
int newCopyDataIdx = (copyDataBufsIdx[type]==0)?1:0;
copyDataBufsIdx[type] = newCopyDataIdx;
// End of critical zone between UE Rx threads
// New data will be copied in a different buffer than the live one
scopeGraphData_t *copyData= copyDataBufs[type][newCopyDataIdx];
if (copyData == NULL || copyData->dataSize < elementSz*colSz*lineSz) {
scopeGraphData_t *ptr= (scopeGraphData_t*) realloc(copyData, sizeof(scopeGraphData_t) + elementSz*colSz*lineSz);
if (!ptr) {
LOG_E(PHY,"can't realloc\n");
return;
} else {
copyData=ptr;
}
}
copyData->dataSize=elementSz*colSz*lineSz;
copyData->elementSz=elementSz;
copyData->colSz=colSz;
copyData->lineSz=lineSz;
memcpy(copyData+1, dataIn, elementSz*colSz*lineSz);
copyDataBufs[type][newCopyDataIdx] = copyData;
// The new data just copied in the local static buffer becomes live now
((scopeGraphData_t **)tmp->liveDataUE)[type]=copyData;
}
}
void nrUEinitQtScope(PHY_VARS_NR_UE *ue) {
ue->scopeData=malloc(sizeof(scopeData_t));
scopeData_t *scope=(scopeData_t *) ue->scopeData;
scope->copyData=UEcopyData;
scope->liveDataUE=calloc(sizeof(scopeGraphData_t *), UEdataTypeNumberOfItems);
for (int i=0; i<UEdataTypeNumberOfItems; i++){
scope->flag_streaming[i] = 0;
}
pthread_t qtscope_thread;
threadCreate(&qtscope_thread, nrUEQtscopeThread, ue, (char*)"qtscope", -1, sched_get_priority_min(SCHED_RR));
}
void nrgNBinitQtScope(scopeParms_t *p) {
p->gNB->scopeData=malloc(sizeof(scopeData_t));
scopeData_t *scope=(scopeData_t *) p->gNB->scopeData;
scope->gNB=p->gNB;
scope->argc=p->argc;
scope->argv=p->argv;
scope->ru=p->ru;
pthread_t qtscope_thread;
threadCreate(&qtscope_thread, nrgNBQtscopeThread, p->gNB->scopeData, (char*)"qtscope", -1, sched_get_priority_min(SCHED_RR));
}
extern "C" void nrqtscope_autoinit(void *dataptr) {
AssertFatal( (IS_SOFTMODEM_GNB_BIT||IS_SOFTMODEM_5GUE_BIT),"Scope cannot find NRUE or GNB context");
if (IS_SOFTMODEM_GNB_BIT)
nrgNBinitQtScope((scopeParms_t *)dataptr);
else
nrUEinitQtScope((PHY_VARS_NR_UE *)dataptr);
//nrUEinitQtScope((PHY_VARS_NR_UE *)dataptr);
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/* Header file generated by Bo Zhao (Fraunhofer IIS) on Wed. Dec. 08, 2021*/
#ifndef QT_SCOPE_MAINWINDOW_H
#define QT_SCOPE_MAINWINDOW_H
#include <QComboBox>
#include <QMessageBox>
#include <QtCharts>
#include <QChartView>
#include <QLineSeries>
extern "C" {
#include <simple_executable.h>
#include <common/utils/system.h>
#include "common/ran_context.h"
#include <openair1/PHY/defs_gNB.h>
#include "PHY/defs_gNB.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/defs_RU.h"
#include "executables/softmodem-common.h"
#include "phy_scope_interface.h"
#include <openair2/LAYER2/NR_MAC_gNB/mac_proto.h>
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
extern RAN_CONTEXT_t RC;
}
typedef struct {
float max_value;
float min_value;
float avg_value;
int plot_idx;
uint64_t avg_idx;
uint64_t nof_retrans; // especially for the KPI: nof retransmissions
QLineSeries *series;
QLineSeries *seriesMin;
QLineSeries *seriesMax;
QLineSeries *seriesAvg;
}KPI_elements;
// drop-down list UE
class KPIListSelect : public QComboBox
{
Q_OBJECT
public:
explicit KPIListSelect(QWidget *parent = 0);
~KPIListSelect();
private:
};
// drop-down list gNB
class KPIListSelectgNB : public QComboBox
{
Q_OBJECT
public:
explicit KPIListSelectgNB(QWidget *parent = 0);
~KPIListSelectgNB();
private:
};
// Paint first on a pixmap, then on the widget. Previous paint is erased
class PainterWidget : public QWidget
{
Q_OBJECT
public:
PainterWidget(QComboBox *parent, PHY_VARS_NR_UE *ue);
void makeConnections();
void resetKPIPlot(KPI_elements *inputStruct);
void resetKPIValues(KPI_elements *inputStruct);
QPixmap *pix;
QTimer *timer;
int chartHight, chartWidth;
QComboBox *parentWindow;
QTimer *timerWaterFallTime;
// for waterfill graphs
int waterFallh;
int iteration;
double *waterFallAvg;
bool isWaterFallTimeActive;
extended_kpi_ue extendKPIUE;
KPI_elements DLBLER;
KPI_elements DLMCS;
KPI_elements Throu;
KPI_elements nofRBs;
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event) override;
public slots:
// IQ constellations
void paintPixmap_uePdschIQ();
void paintPixmap_uePbchIQ();
void paintPixmap_uePdcchIQ();
// LLR plots
void paintPixmap_uePdschLLR();
void paintPixmap_uePbchLLR();
void paintPixmap_uePdcchLLR();
// Waterfall
void paintPixmap_ueWaterFallTime();
void paintPixmap_ueChannelResponse();
// Extended KPIs
void KPI_DL_BLER();
void KPI_DL_MCS();
void KPI_DL_Throu();
void KPI_Nof_RBs();
private:
PHY_VARS_NR_UE *ue;
int indexToPlot;
int previousIndex;
};
// Paint class for gNB
class PainterWidgetgNB : public QWidget
{
Q_OBJECT
public:
PainterWidgetgNB(QComboBox *parent, scopeData_t *p);
void makeConnections();
void createPixMap(float *xData, float *yData, int len, QColor MarkerColor, const QString xLabel, const QString yLabel, bool scaleX);
void resetKPIPlot(KPI_elements *inputStruct);
void resetKPIValues(KPI_elements *inputStruct);
QPixmap *pix;
QTimer *timer;
QTimer *timerRetrans;
int chartHight, chartWidth;
int nb_UEs;
QComboBox *parentWindow;
KPI_elements ULBLER;
KPI_elements ULMCS;
KPI_elements DLBLER;
KPI_elements DLMCS;
KPI_elements ULThrou;
KPI_elements DLThrou;
KPI_elements nofRBs;
KPI_elements ULSNR;
KPI_elements DLSNR;
KPI_elements ULRetrans[4];
KPI_elements DLRetrans[4];
protected:
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *event) override;
public slots:
void KPI_PuschIQ();
void KPI_PuschLLR();
void KPI_ChannelResponse();
void KPI_UL_BLER();
void KPI_UL_MCS();
void KPI_DL_BLER();
void KPI_DL_MCS();
void KPI_UL_Throu();
void KPI_DL_Throu();
void KPI_Nof_RBs();
void KPI_UL_SNR();
void KPI_DL_SNR();
void KPI_UL_Retrans();
void KPI_DL_Retrans();
private:
scopeData_t *p;
int indexToPlot;
int previousIndex;
};
#endif // QT_SCOPE_MAINWINDOW_H
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
/* Form definition file generated by fdesign */ /* Form definition file generated by fdesign */
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include "nr_phy_scope.h" #include "nr_phy_scope.h"
#include "executables/softmodem-common.h" #include "executables/softmodem-common.h"
#include "executables/nr-softmodem-common.h" #include "executables/nr-softmodem-common.h"
...@@ -290,6 +291,8 @@ static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const sc ...@@ -290,6 +291,8 @@ static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const sc
float *values, *time; float *values, *time;
oai_xygraph_getbuff(graph, &time, &values, len, 0); oai_xygraph_getbuff(graph, &time, &values, len, 0);
printf("************Number of Antennas: %i", nb_ant);
for (int ant=0; ant<nb_ant; ant++) { for (int ant=0; ant<nb_ant; ant++) {
if (data[ant] != NULL) { if (data[ant] != NULL) {
for (int i=0; i<len; i++) { for (int i=0; i<len; i++) {
...@@ -757,6 +760,8 @@ static void uePdschIQ (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_ ...@@ -757,6 +760,8 @@ static void uePdschIQ (scopeGraphData_t **data, OAIgraph_t *graph, PHY_VARS_NR_
memset(I+base, 0, sz*RX_NB_TH_MAX * sizeof(*I)); memset(I+base, 0, sz*RX_NB_TH_MAX * sizeof(*I));
memset(Q+base, 0, sz*RX_NB_TH_MAX * sizeof(*Q)); memset(Q+base, 0, sz*RX_NB_TH_MAX * sizeof(*Q));
//printf("sz: %i, sizeof(*I): %i\n", sz, sizeof(*I));
for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) { for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) {
scopeSample_t *pdsch_comp = (scopeSample_t *) phy_vars_ue->pdsch_vars[thr][eNB_id]->rxdataF_comp0[0]; scopeSample_t *pdsch_comp = (scopeSample_t *) phy_vars_ue->pdsch_vars[thr][eNB_id]->rxdataF_comp0[0];
...@@ -829,6 +834,7 @@ static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) { ...@@ -829,6 +834,7 @@ static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) {
// LLR of PDCCH // LLR of PDCCH
fdui->graph[5] = nrUEcommonGraph(uePcchLLR, fdui->graph[5] = nrUEcommonGraph(uePcchLLR,
FL_POINTS_XYPLOT, 0, curY, 500, 100, "PDCCH Log-Likelihood Ratios (LLR, mag)", FL_CYAN ); FL_POINTS_XYPLOT, 0, curY, 500, 100, "PDCCH Log-Likelihood Ratios (LLR, mag)", FL_CYAN );
fl_set_xyplot_xgrid(fdui->graph[5].graph,FL_GRID_MAJOR);
// I/Q PDCCH comp // I/Q PDCCH comp
fdui->graph[6] = nrUEcommonGraph(uePcchIQ, fdui->graph[6] = nrUEcommonGraph(uePcchIQ,
FL_POINTS_XYPLOT, 500, curY, 300, 100, "PDCCH I/Q of MF Output", FL_CYAN ); FL_POINTS_XYPLOT, 500, curY, 300, 100, "PDCCH I/Q of MF Output", FL_CYAN );
...@@ -837,6 +843,7 @@ static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) { ...@@ -837,6 +843,7 @@ static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) {
// LLR of PDSCH // LLR of PDSCH
fdui->graph[7] = nrUEcommonGraph(uePdschLLR, fdui->graph[7] = nrUEcommonGraph(uePdschLLR,
FL_POINTS_XYPLOT, 0, curY, 500, 200, "PDSCH Log-Likelihood Ratios (LLR, mag)", FL_YELLOW ); FL_POINTS_XYPLOT, 0, curY, 500, 200, "PDSCH Log-Likelihood Ratios (LLR, mag)", FL_YELLOW );
fl_set_xyplot_xgrid(fdui->graph[7].graph,FL_GRID_MAJOR);
// I/Q PDSCH comp // I/Q PDSCH comp
fdui->graph[8] = nrUEcommonGraph(uePdschIQ, fdui->graph[8] = nrUEcommonGraph(uePdschIQ,
FL_POINTS_XYPLOT, 500, curY, 300, 200, "PDSCH I/Q of MF Output", FL_YELLOW ); FL_POINTS_XYPLOT, 500, curY, 300, 200, "PDSCH I/Q of MF Output", FL_YELLOW );
...@@ -891,7 +898,7 @@ void phy_scope_nrUE(scopeGraphData_t **UEliveData, ...@@ -891,7 +898,7 @@ void phy_scope_nrUE(scopeGraphData_t **UEliveData,
} }
static void *nrUEscopeThread(void *arg) { static void *nrUEscopeThread(void *arg) {
PHY_VARS_NR_UE *ue=(PHY_VARS_NR_UE *)arg; PHY_VARS_NR_UE *ue=(PHY_VARS_NR_UE *)arg; // local structure with all top-level phy date for UE, as passed through arg
size_t stksize; size_t stksize;
pthread_attr_t atr= {0}; pthread_attr_t atr= {0};
pthread_attr_getstacksize(&atr, &stksize); pthread_attr_getstacksize(&atr, &stksize);
...@@ -899,7 +906,7 @@ static void *nrUEscopeThread(void *arg) { ...@@ -899,7 +906,7 @@ static void *nrUEscopeThread(void *arg) {
int fl_argc=1; int fl_argc=1;
char *name="5G-UE-scope"; char *name="5G-UE-scope";
fl_initialize (&fl_argc, &name, NULL, 0, 0); fl_initialize (&fl_argc, &name, NULL, 0, 0);
OAI_phy_scope_t *form_nrue=create_phy_scope_nrue(0); OAI_phy_scope_t *form_nrue=create_phy_scope_nrue(0); // build scope, in which one figure is created for each KPI. Here, 9 KPI for UE
while (!oai_exit) { while (!oai_exit) {
fl_freeze_form(form_nrue->phy_scope); fl_freeze_form(form_nrue->phy_scope);
...@@ -961,6 +968,8 @@ void nrUEinitScope(PHY_VARS_NR_UE *ue) { ...@@ -961,6 +968,8 @@ void nrUEinitScope(PHY_VARS_NR_UE *ue) {
scopeData_t *scope=(scopeData_t *) ue->scopeData; scopeData_t *scope=(scopeData_t *) ue->scopeData;
scope->copyData=UEcopyData; scope->copyData=UEcopyData;
AssertFatal(scope->liveData=calloc(sizeof(scopeGraphData_t *), UEdataTypeNumberOfItems),""); AssertFatal(scope->liveData=calloc(sizeof(scopeGraphData_t *), UEdataTypeNumberOfItems),"");
for (int i=0; i<UEdataTypeNumberOfItems; i++)
scope->flag_streaming[i] = 1;
pthread_t forms_thread; pthread_t forms_thread;
threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW); threadCreate(&forms_thread, nrUEscopeThread, ue, "scope", -1, OAI_PRIORITY_RT_LOW);
} }
......
...@@ -29,11 +29,19 @@ ...@@ -29,11 +29,19 @@
* \note * \note
* \warning * \warning
*/ */
#ifndef __PHY_SCOPE_INTERFACE_H__ #ifndef __PHY_SCOPE_INTERFACE_H
#define __PHY_SCOPE_INTERFACE_H__ #define __PHY_SCOPE_INTERFACE_H
#include <openair1/PHY/defs_gNB.h> #include <openair1/PHY/defs_gNB.h>
#include <openair1/PHY/defs_nr_UE.h> #include <openair1/PHY/defs_nr_UE.h>
typedef struct {
float DL_BLER;
uint32_t blockSize; // block size, to be used for throughput calculation
uint8_t dl_mcs;
uint16_t nofRBs;
}extended_kpi_ue;
typedef struct { typedef struct {
int *argc; int *argc;
char **argv; char **argv;
...@@ -43,18 +51,20 @@ typedef struct { ...@@ -43,18 +51,20 @@ typedef struct {
enum UEdataType { enum UEdataType {
pbchDlChEstimateTime, pbchDlChEstimateTime,
pbchLlr,
pbchRxdataF_comp,
pdcchLlr,
pdcchRxdataF_comp, pdcchRxdataF_comp,
pdcchLlr,
pbchRxdataF_comp,
pbchLlr,
UEdataTypeNumberOfItems UEdataTypeNumberOfItems
}; };
typedef struct scopeData_s { typedef struct scopeData_s {
int flag_streaming[UEdataTypeNumberOfItems];
int *argc; int *argc;
char **argv; char **argv;
RU_t *ru; RU_t *ru;
PHY_VARS_gNB *gNB; PHY_VARS_gNB *gNB;
void *liveDataUE;
void *liveData; void *liveData;
void (*slotFunc)(int32_t *data, int slot, void *scopeData); void (*slotFunc)(int32_t *data, int slot, void *scopeData);
void (*copyData)(PHY_VARS_NR_UE *,enum UEdataType, void *data, int elementSz, int colSz, int lineSz); void (*copyData)(PHY_VARS_NR_UE *,enum UEdataType, void *data, int elementSz, int colSz, int lineSz);
...@@ -64,4 +74,7 @@ int load_softscope(char *exectype, void *initarg); ...@@ -64,4 +74,7 @@ int load_softscope(char *exectype, void *initarg);
int end_forms(void) ; int end_forms(void) ;
#define UEscopeCopy(ue, type, ...) if(ue->scopeData) ((scopeData_t*)ue->scopeData)->copyData(ue, type, ##__VA_ARGS__); #define UEscopeCopy(ue, type, ...) if(ue->scopeData) ((scopeData_t*)ue->scopeData)->copyData(ue, type, ##__VA_ARGS__);
void getKPIUE(extended_kpi_ue* kpiStructure);
#endif #endif
...@@ -36,8 +36,6 @@ ...@@ -36,8 +36,6 @@
#include "defs_nr_common.h" #include "defs_nr_common.h"
#include "CODING/nrPolar_tools/nr_polar_pbch_defs.h" #include "CODING/nrPolar_tools/nr_polar_pbch_defs.h"
#define _GNU_SOURCE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h> #include <malloc.h>
......
...@@ -139,7 +139,7 @@ typedef struct TDD_UL_DL_configCommon_s { ...@@ -139,7 +139,7 @@ typedef struct TDD_UL_DL_configCommon_s {
struct TDD_UL_DL_configCommon_s *p_next; struct TDD_UL_DL_configCommon_s *p_next;
} TDD_UL_DL_configCommon_t; } TDD_UL_DL_configCommon_t;
typedef struct { typedef struct TDD_UL_DL_SlotConfig_s {
/// \ Identifies a slot within a dl-UL-TransmissionPeriodicity (given in tdd-UL-DL-configurationCommon) /// \ Identifies a slot within a dl-UL-TransmissionPeriodicity (given in tdd-UL-DL-configurationCommon)
uint16_t slotIndex; uint16_t slotIndex;
/// \ The direction (downlink or uplink) for the symbols in this slot. "allDownlink" indicates that all symbols in this slot are used /// \ The direction (downlink or uplink) for the symbols in this slot. "allDownlink" indicates that all symbols in this slot are used
...@@ -154,7 +154,7 @@ typedef struct { ...@@ -154,7 +154,7 @@ typedef struct {
/// Corresponds to L1 parameter 'number-of-UL-symbols-dedicated' (see 38.211, section FFS_Section) /// Corresponds to L1 parameter 'number-of-UL-symbols-dedicated' (see 38.211, section FFS_Section)
uint16_t nrofUplinkSymbols; uint16_t nrofUplinkSymbols;
/// \ for setting a sequence /// \ for setting a sequence
struct TDD_UL_DL_SlotConfig_t *p_next_TDD_UL_DL_SlotConfig; struct TDD_UL_DL_SlotConfig_s *p_next_TDD_UL_DL_SlotConfig;
} TDD_UL_DL_SlotConfig_t; } TDD_UL_DL_SlotConfig_t;
/*********************************************************************** /***********************************************************************
......
...@@ -221,7 +221,7 @@ void add_tdd_dedicated_configuration_nr(NR_DL_FRAME_PARMS *frame_parms, int slot ...@@ -221,7 +221,7 @@ void add_tdd_dedicated_configuration_nr(NR_DL_FRAME_PARMS *frame_parms, int slot
if (next == 0) { if (next == 0) {
frame_parms->p_TDD_UL_DL_ConfigDedicated = p_TDD_UL_DL_ConfigDedicated; frame_parms->p_TDD_UL_DL_ConfigDedicated = p_TDD_UL_DL_ConfigDedicated;
} else { } else {
p_previous_TDD_UL_DL_ConfigDedicated->p_next_TDD_UL_DL_SlotConfig = (struct TDD_UL_DL_SlotConfig_t *)p_TDD_UL_DL_ConfigDedicated; p_previous_TDD_UL_DL_ConfigDedicated->p_next_TDD_UL_DL_SlotConfig = (TDD_UL_DL_SlotConfig_t *)p_TDD_UL_DL_ConfigDedicated;
} }
p_TDD_UL_DL_ConfigDedicated->slotIndex = slotIndex; p_TDD_UL_DL_ConfigDedicated->slotIndex = slotIndex;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment