diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 1886c46052..0b858d0879 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -56,7 +56,7 @@ CMAKE_CMD="$CMAKE" MAKE_CMD=make BUILD_ECLIPSE=0 NR="False" -OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 websrv" +OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope nrqtscope ldpc_cuda ldpc_t1 websrv oai_iqplayer" RU=0 CMAKE_C_FLAGS=() CMAKE_CXX_FLAGS=() @@ -576,7 +576,7 @@ function main() { echo_info "Compiling UE specific part" - if [ $UE_ip -eq 1 ] + if [ "$UE_ip" = 1 ] then echo_info "Building ue_ip module" compilations $BUILD_DIR ue_ip diff --git a/common/utils/T/check_vcd.c b/common/utils/T/check_vcd.c index 1460d7e20a..4a21e4d2f5 100644 --- a/common/utils/T/check_vcd.c +++ b/common/utils/T/check_vcd.c @@ -19,7 +19,19 @@ #define ENABLE_USE_CPU_EXECUTION_TIME #include "../LOG/vcd_signal_dumper.c" -void err(char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +/* + * Dummy needed by assertions.h + */ +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + if (assert) { + abort(); + } else { + exit(EXIT_SUCCESS); + } +} + +void err(char *fmt, ...) __attribute__((format(printf, 1, 2))); void err(char *fmt, ...) { va_list ap; diff --git a/common/utils/assertions.h b/common/utils/assertions.h index b2916139e0..3424392e7a 100644 --- a/common/utils/assertions.h +++ b/common/utils/assertions.h @@ -29,6 +29,9 @@ #include #include +#define OAI_EXIT_NORMAL 0 +#define OAI_EXIT_ASSERT 1 + #define _Assert_Exit_ \ if (getenv("gdbStacks")) { \ char tmp [1000]; \ @@ -38,7 +41,8 @@ fprintf(stderr, "\nExiting execution\n"); \ fflush(stdout); \ fflush(stderr); \ - abort(); + exit_function(__FILE__, __FUNCTION__, __LINE__, "_Assert_Exit_", OAI_EXIT_ASSERT); \ + abort(); // to avoid gcc warnings - never executed unless app-specific exit_function() does not exit() nor abort() #define _Assert_(cOND, aCTION, fORMAT, aRGS...) \ do { \ diff --git a/common/utils/minimal_stub.c b/common/utils/minimal_stub.c index 79e35bf7a6..be9c1b399d 100644 --- a/common/utils/minimal_stub.c +++ b/common/utils/minimal_stub.c @@ -2,5 +2,11 @@ int T_stdout; #endif -void exit_function(const char *file, const char *function, const int line, const char *s) { +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + if (assert) { + abort(); + } else { + exit(EXIT_SUCCESS); + } } diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index 3cd18fab02..b351a667b5 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -176,7 +176,13 @@ void initFloatingCoresTpool(int nbThreads,tpool_t *pool, bool performanceMeas, c #ifdef TEST_THREAD_POOL volatile int oai_exit=0; -void exit_function(const char *file, const char *function, const int line, const char *s) { +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + if (assert) { + abort(); + } else { + exit(EXIT_SUCCESS); + } } struct testData { diff --git a/executables/lte-softmodem.c b/executables/lte-softmodem.c index 7c25548349..2e882c13cc 100644 --- a/executables/lte-softmodem.c +++ b/executables/lte-softmodem.c @@ -241,8 +241,8 @@ unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) { return (dcoff_i_rxfe + (dcoff_q_rxfe<<8)); } - -void exit_function(const char *file, const char *function, const int line, const char *s) { +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ int ru_id; if (s != NULL) { @@ -266,8 +266,12 @@ void exit_function(const char *file, const char *function, const int line, const } } - sleep(1); //allow lte-softmodem threads to exit first - exit(1); + if (assert) { + abort(); + } else { + sleep(1); // allow lte-softmodem threads to exit first + exit(EXIT_SUCCESS); + } } diff --git a/executables/lte-uesoftmodem.c b/executables/lte-uesoftmodem.c index 04358c7ec9..1141a82dd1 100644 --- a/executables/lte-uesoftmodem.c +++ b/executables/lte-uesoftmodem.c @@ -244,7 +244,7 @@ unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) { } -void exit_function(const char *file, const char *function, const int line, const char *s) { +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { int CC_id; logClean(); printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, ((s==NULL)?"":s)); @@ -258,12 +258,15 @@ void exit_function(const char *file, const char *function, const int line, const PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); } - sleep(1); //allow lte-softmodem threads to exit first - if(PHY_vars_UE_g != NULL ) itti_terminate_tasks (TASK_UNKNOWN); - exit(1); + if (assert) { + abort(); + } else { + sleep(1); // allow lte-softmodem threads to exit first + exit(EXIT_SUCCESS); + } } extern int16_t dlsch_demod_shift; diff --git a/executables/main_ru.c b/executables/main_ru.c index ee2e6dc39c..fcb65dd626 100644 --- a/executables/main_ru.c +++ b/executables/main_ru.c @@ -85,7 +85,7 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; void nfapi_setmode(nfapi_mode_t nfapi_mode) { return; } -void exit_function(const char *file, const char *function, const int line, const char *s) { +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { if (s != NULL) { printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); @@ -102,11 +102,15 @@ void exit_function(const char *file, const char *function, const int line, const ru_m.ifdevice.trx_end_func(&ru_m.ifdevice); ru_m.ifdevice.trx_end_func = NULL; } - + pthread_mutex_destroy(ru_m.ru_mutex); - pthread_cond_destroy(ru_m.ru_cond); - sleep(1); //allow lte-softmodem threads to exit first - exit(1); + pthread_cond_destroy(ru_m.ru_cond); + if (assert) { + abort(); + } else { + sleep(1); // allow lte-softmodem threads to exit first + exit(EXIT_SUCCESS); + } } diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 14fff00a70..e3abf512eb 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -38,8 +38,14 @@ int oai_exit = 0; instance_t CUuniqInstance = 0; RRC_release_list_t rrc_release_info; -void exit_function(const char *file, const char *function, const int line, const char *s) +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { + if (assert) { + abort(); + } else { + sleep(1); // allow other threads to exit first + exit(EXIT_SUCCESS); + } } nfapi_mode_t nfapi_mod = -1; diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 7d75dfbe36..9cefc7ce4c 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -249,8 +249,8 @@ unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) { #define KBLU "\x1B[34m" #define RESET "\033[0m" - -void exit_function(const char *file, const char *function, const int line, const char *s) { +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ int ru_id; if (s != NULL) { @@ -274,8 +274,12 @@ void exit_function(const char *file, const char *function, const int line, const } } - sleep(1); //allow lte-softmodem threads to exit first - exit(1); + if (assert) { + abort(); + } else { + sleep(1); // allow nr-softmodem threads to exit first + exit(EXIT_SUCCESS); + } } diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 61e12a158f..0e8d903803 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -687,21 +687,33 @@ void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); - *timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms); - for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { - int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ; - // we write before read because gNB waits for UE to write and both executions halt - // this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot - if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer); - AssertFatal(unitTransfer == - UE->rfdevice.trx_read_func(&UE->rfdevice, - timestamp, - (void **)UE->common_vars.rxdata, - unitTransfer, - UE->frame_parms.nb_antennas_rx),""); - *timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write + if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { + // Resynchonize by slot (will work with numerology 1 only) + for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe/2 ) { + int unitTransfer=size>UE->frame_parms.samples_per_subframe/2 ? UE->frame_parms.samples_per_subframe/2 : size ; + AssertFatal(unitTransfer == + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + (void **)UE->common_vars.rxdata, + unitTransfer, + UE->frame_parms.nb_antennas_rx),""); + } + } else { + *timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms); + for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { + int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ; + // we write before read because gNB waits for UE to write and both executions halt + // this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot + if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer); + AssertFatal(unitTransfer == + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + (void **)UE->common_vars.rxdata, + unitTransfer, + UE->frame_parms.nb_antennas_rx),""); + *timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write + } } - } int computeSamplesShift(PHY_VARS_NR_UE *UE) { @@ -773,6 +785,11 @@ void *UE_thread(void *arg) { syncRunning=false; syncData_t *tmp=(syncData_t *)NotifiedFifoData(res); if (UE->is_synchronized) { + LOG_I(PHY,"UE synchronized decoded_frame_rx=%d UE->init_sync_frame=%d trashed_frames=%d\n", + decoded_frame_rx, + UE->init_sync_frame, + trashed_frames); + decoded_frame_rx=(((mac->mib->systemFrameNumber.buf[0] >> mac->mib->systemFrameNumber.bits_unused)<<4) | tmp->proc.decoded_frame_rx); // shift the frame index with all the frames we trashed meanwhile we perform the synch search decoded_frame_rx=(decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER; @@ -780,8 +797,16 @@ void *UE_thread(void *arg) { delNotifiedFIFO_elt(res); start_rx_stream=0; } else { - readFrame(UE, ×tamp, true); - trashed_frames+=2; + if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { + // For IQ recorder/player we force synchronization to happen in 280 ms + while (trashed_frames != 28) { + readFrame(UE, ×tamp, true); + trashed_frames+=2; + } + } else { + readFrame(UE, ×tamp, true); + trashed_frames+=2; + } continue; } } diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index d64d2cdb2e..d7ee572b76 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -213,7 +213,8 @@ int create_tasks_nrue(uint32_t ue_nb) { return 0; } -void exit_function(const char *file, const char *function, const int line, const char *s) { +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ int CC_id; if (s != NULL) { @@ -229,8 +230,12 @@ void exit_function(const char *file, const char *function, const int line, const } } - sleep(1); //allow lte-softmodem threads to exit first - exit(1); + if (assert) { + abort(); + } else { + sleep(1); // allow lte-softmodem threads to exit first + exit(EXIT_SUCCESS); + } } uint64_t get_nrUE_optmask(void) { diff --git a/executables/softmodem-common.c b/executables/softmodem-common.c index 2b289b5352..825faf6cf9 100644 --- a/executables/softmodem-common.c +++ b/executables/softmodem-common.c @@ -219,7 +219,7 @@ void signal_handler(int sig) { softmodem_printresources(sig,(telnet_printfunc_t)printf); if (sig != SOFTMODEM_RTSIGNAL) { printf("Linux signal %s...\n",strsignal(sig)); - exit_function(__FILE__, __FUNCTION__, __LINE__,"softmodem starting exit procedure\n"); + exit_function(__FILE__, __FUNCTION__, __LINE__, "softmodem starting exit procedure\n", OAI_EXIT_NORMAL); } } } diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 09eaea1c92..2b022b6a9e 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -258,6 +258,7 @@ extern int usrp_tx_thread; #define SOFTMODEM_DOSCOPE_BIT (1<<15) #define SOFTMODEM_RECPLAY_BIT (1<<16) #define SOFTMODEM_TELNETCLT_BIT (1<<17) +#define SOFTMODEM_RECRECORD_BIT (1<<18) #define SOFTMODEM_ENB_BIT (1<<20) #define SOFTMODEM_GNB_BIT (1<<21) #define SOFTMODEM_4GUE_BIT (1<<22) @@ -278,6 +279,7 @@ extern int usrp_tx_thread; #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_IQRECORDER ( get_softmodem_optmask() & SOFTMODEM_RECRECORD_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_GNB_BIT ( get_softmodem_optmask() & SOFTMODEM_GNB_BIT) diff --git a/openair1/PHY/CODING/TESTBENCH/coding_unitary_defs.h b/openair1/PHY/CODING/TESTBENCH/coding_unitary_defs.h index be37f06b8d..23d02ef197 100644 --- a/openair1/PHY/CODING/TESTBENCH/coding_unitary_defs.h +++ b/openair1/PHY/CODING/TESTBENCH/coding_unitary_defs.h @@ -28,7 +28,7 @@ PHY_VARS_UE ***PHY_vars_UE_g; #include "common/ran_context.h" RAN_CONTEXT_t RC; -void exit_function(const char* file, const char* function, const int line, const char *s) { +void exit_function(const char* file, const char* function, const int line, const char* s, const int assert) { const char * msg= s==NULL ? "no comment": s; printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg); exit(-1); diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index e67adafe3f..9031ad3f12 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -572,7 +572,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) #ifndef NR_UNIT_TEST - printf("PSS execution duration %4d microseconds \n", duration_ms); + LOG_I(PHY,"PSS execution duration %4d microseconds \n", duration_ms); #endif diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 41829b68f2..3056315999 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -541,7 +541,7 @@ int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, #ifdef DEBUG_SSS_NR - printf("(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max); + LOG_D(PHY,"(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max); #endif } @@ -554,7 +554,7 @@ int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, if (*tot_metric > SSS_METRIC_FLOOR_NR) { Nid2 = GET_NID2(frame_parms->Nid_cell); Nid1 = GET_NID1(frame_parms->Nid_cell); - printf("Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max); + LOG_D(PHY,"Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max); } //#endif @@ -564,7 +564,7 @@ int rx_sss_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int32_t *tot_metric, int re = 0; int im = 0; if (Nid1 == N_ID_1_NUMBER) { - LOG_I(PHY,"Failled to detect SSS after PSS\n"); + LOG_I(PHY,"Failed to detect SSS after PSS\n"); return -1; } d = (int16_t *)&d_sss[Nid2][Nid1]; diff --git a/openair1/SIMULATION/LTE_PHY/unitary_defs.h b/openair1/SIMULATION/LTE_PHY/unitary_defs.h index d77682c89e..f0c3f32b1b 100644 --- a/openair1/SIMULATION/LTE_PHY/unitary_defs.h +++ b/openair1/SIMULATION/LTE_PHY/unitary_defs.h @@ -22,7 +22,7 @@ openair0_device openair0; int oai_exit=0; -void exit_function(const char* file, const char* function, const int line,const char *s) { +void exit_function(const char* file, const char* function, const int line,const char* s, const int assert) { const char * msg= s==NULL ? "no comment": s; printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg); exit(-1); diff --git a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h index c556f66361..6daf419ed7 100644 --- a/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h +++ b/openair1/SIMULATION/NR_PHY/nr_unitary_defs.h @@ -35,7 +35,7 @@ int oai_exit=0; -void exit_function(const char* file, const char* function, const int line, const char *s) { +void exit_function(const char* file, const char* function, const int line, const char *s, const int assert) { const char * msg= s==NULL ? "no comment": s; printf("Exiting at: %s:%d %s(), %s\n", file, line, function, msg); exit(-1); diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h index 43c313ce0c..c6308a4465 100644 --- a/openair2/COMMON/platform_types.h +++ b/openair2/COMMON/platform_types.h @@ -281,12 +281,12 @@ typedef struct protocol_ctxt_s { #define CHECK_CTXT_ARGS(CTXT_Pp) -#define exit_fun(msg) exit_function(__FILE__,__FUNCTION__,__LINE__,msg) +#define exit_fun(msg) exit_function(__FILE__, __FUNCTION__, __LINE__, "exit_fun", OAI_EXIT_NORMAL) #ifdef __cplusplus extern "C" { #endif -void exit_function(const char *file, const char *function, const int line, const char *s); +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert); #ifdef __cplusplus } #endif diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index f871796230..a0d683a8d9 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -482,8 +482,14 @@ void ra_preambles_config(NR_PRACH_RESOURCES_t *prach_resources, NR_UE_MAC_INST_t long deltaPreamble_Msg3 = 0; uint8_t noGroupB = 0; // Random seed generation - long long tmp = rdtsc_oai(); - unsigned short int *seed = (unsigned short int*)&tmp; + unsigned int seed; + + if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { + // Overwrite seed with non-random seed for IQ player/recorder + seed = 1; + } else { + seed=(unsigned int) (rdtsc_oai() && ~0); + } RA_config_t *ra = &mac->ra; NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP.rach_ConfigCommon; @@ -580,28 +586,28 @@ void ra_preambles_config(NR_PRACH_RESOURCES_t *prach_resources, NR_UE_MAC_INST_t if(ra->ra_PreambleIndex < 0 || ra->ra_PreambleIndex > 63) { if (noGroupB) { // use Group A preamble - ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r((unsigned int *)seed) % ra->cb_preambles_per_ssb); + ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % ra->cb_preambles_per_ssb); ra->RA_usedGroupA = 1; } else if ((ra->Msg3_size < messageSizeGroupA) && (dl_pathloss > PLThreshold)) { // Group B is configured and RA preamble Group A is used // - todo add condition on CCCH_sdu_size for initiation by CCCH - ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r((unsigned int *)seed) % sizeOfRA_PreamblesGroupA); + ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % sizeOfRA_PreamblesGroupA); ra->RA_usedGroupA = 1; } else { // Group B preamble is configured and used // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A // the remaining belong to RA Preambles Group B - ra->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + (rand_r((unsigned int *)seed) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); + ra->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + (rand_r(&seed) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); ra->RA_usedGroupA = 0; } } } else { // Msg3 is being retransmitted if (ra->RA_usedGroupA && noGroupB) { - ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r((unsigned int *)seed) % ra->cb_preambles_per_ssb); + ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % ra->cb_preambles_per_ssb); } else if (ra->RA_usedGroupA && !noGroupB){ - ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r((unsigned int *)seed) % sizeOfRA_PreamblesGroupA); + ra->ra_PreambleIndex = ra->starting_preamble_nb + (rand_r(&seed) % sizeOfRA_PreamblesGroupA); } else { - ra->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + (rand_r((unsigned int *)seed) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); + ra->ra_PreambleIndex = ra->starting_preamble_nb + sizeOfRA_PreamblesGroupA + (rand_r(&seed) % (ra->cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA)); } } } @@ -1033,9 +1039,15 @@ void nr_ra_failed(uint8_t mod_id, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_res NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); RA_config_t *ra = &mac->ra; // Random seed generation - long long tmp = rdtsc_oai(); - unsigned short int *seed = (unsigned short int*)&tmp; + unsigned int seed; + if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { + // Overwrite seed with non-random seed for IQ player/recorder + seed = 1; + } else { + seed=(unsigned int) (rdtsc_oai() && ~0); + } + ra->first_Msg3 = 1; ra->ra_PreambleIndex = -1; ra->ra_state = RA_UE_IDLE; @@ -1047,7 +1059,7 @@ void nr_ra_failed(uint8_t mod_id, uint8_t CC_id, NR_PRACH_RESOURCES_t *prach_res LOG_D(MAC, "In %s: [UE %d][%d.%d] Maximum number of RACH attempts (%d) reached, selecting backoff time...\n", __FUNCTION__, mod_id, frame, slot, ra->preambleTransMax); - ra->RA_backoff_cnt = rand_r((unsigned int *)seed) % (prach_resources->RA_PREAMBLE_BACKOFF + 1); + ra->RA_backoff_cnt = rand_r(&seed) % (prach_resources->RA_PREAMBLE_BACKOFF + 1); prach_resources->RA_PREAMBLE_TRANSMISSION_COUNTER = 1; prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += 2; // 2 dB increment prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 02ad48a655..f9bc506102 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3236,12 +3236,14 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, module_idP, frameP, pduP[1], pduP[2], pduP[3], pduP[4], pduP[5], pduP[6]); bool ra_success = true; - for(int i = 0; icont_res_id[i] != pduP[i+1]) { - ra_success = false; - break; - } - } + if (!IS_SOFTMODEM_IQPLAYER) { // Control is bypassed when replaying IQs (BMC) + for(int i = 0; icont_res_id[i] != pduP[i+1]) { + ra_success = false; + break; + } + } + } if ( (ra->RA_active == 1) && ra_success) { nr_ra_succeeded(module_idP, frameP, slot); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 9c6174fb53..fe50cb4177 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -194,10 +194,10 @@ int8_t nr_rrc_ue_decode_secondary_cellgroup_config(const module_id_t module_id, size, 0, 0); if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - printf("NR_CellGroupConfig decode error\n"); + LOG_E(NR_RRC, "NR_CellGroupConfig decode error\n"); for (i=0; ischedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) { - printf("SIB%li ", sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type + 2); + LOG_D(RRC, "SIB%li ", sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.array[i]->type + 2); } - printf("\n"); + LOG_D(RRC, "\n"); LOG_D(RRC, "SIBs needed by UE: "); for(int j = 0; j < 8*requested_SI_List.size; j++) { if( ((requested_SI_List.buf[j/8]>>(j%8))&1) == 1) { - printf("SIB%i ", j + 2); + LOG_D(RRC, "SIB%i ", j + 2); SIB_to_request[j] = true; for(int i = 0; i < sib1.si_SchedulingInfo->schedulingInfoList.list.array[0]->sib_MappingInfo.list.count; i++) { @@ -1045,17 +1045,17 @@ static int8_t check_requested_SI_List(module_id_t module_id, BIT_STRING_t reques } } - printf("\n"); + LOG_D(RRC, "\n"); LOG_D(RRC, "SIBs to request by UE: "); bool do_ra = false; for(int j = 0; j < 8*requested_SI_List.size; j++) { if(SIB_to_request[j]) { - printf("SIB%i ", j + 2); + LOG_D(RRC, "SIB%i ", j + 2); do_ra = true; } } - printf("\n"); + LOG_D(RRC, "\n"); if(do_ra) { @@ -1458,8 +1458,8 @@ int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) { for (i=0; irecplay_mode = read_recplayconfig(&(openair0_cfg->recplay_conf),&(device->recplay_state)); - if ( openair0_cfg->recplay_mode == RECPLAY_REPLAYMODE ) { + if (openair0_cfg->recplay_mode == RECPLAY_RECORDMODE) { + set_softmodem_optmask(SOFTMODEM_RECRECORD_BIT); // softmodem has to know we use the iqrecorder to workaround randomized algorithms + } + if (openair0_cfg->recplay_mode == RECPLAY_REPLAYMODE) { deflibname=OAI_IQPLAYER_LIBNAME; shlib_fdesc[0].fname="device_init"; set_softmodem_optmask(SOFTMODEM_RECPLAY_BIT); // softmodem has to know we use the iqplayer to workaround randomized algorithms diff --git a/radio/COMMON/record_player.c b/radio/COMMON/record_player.c index 37f985b6b2..2041ab29e1 100644 --- a/radio/COMMON/record_player.c +++ b/radio/COMMON/record_player.c @@ -40,13 +40,11 @@ * recplay_state: store recorder or player data while the device runs */ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_state) { - unsigned int u_sf_record = 0; // record mode - unsigned int u_sf_replay = 0; // replay mode *recplay_conf = calloc(sizeof(recplay_conf_t),1); paramdef_t device_recplay_params[]=DEVICE_RECPLAY_PARAMS_DESC ; config_get(device_recplay_params,sizeof(device_recplay_params)/sizeof(paramdef_t),DEVICE_RECPLAY_SECTION); - if (u_sf_record || u_sf_replay ) { + if ((*recplay_conf)->u_sf_record || (*recplay_conf)->u_sf_replay ) { struct sysinfo systeminfo; *recplay_state = calloc(sizeof(recplay_state_t),1); @@ -62,17 +60,18 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_ LOG_W(HW,"System with %f GB of mem (<6GB), mmap usage disabled\n",systeminfo.totalram/10E9); (*recplay_conf)->use_mmap = 0; } - } else { /* record player enabled */ + } else { /* player-recorder disable */ free(*recplay_conf); *recplay_conf=NULL; + return RECPLAY_DISABLED; } - if (u_sf_replay == 1) + if ((*recplay_conf)->u_sf_replay == 1) return RECPLAY_REPLAYMODE; - else if (u_sf_record == 1) + else if ((*recplay_conf)->u_sf_record == 1) return RECPLAY_RECORDMODE; - return 0; + return RECPLAY_DISABLED; } /*! \brief Terminate operation of the oai iq recorder. to be called by any device @@ -81,21 +80,15 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_ */ void iqrecorder_end(openair0_device *device) { if (device->recplay_state != NULL) { // subframes store - iqfile_header_t fh = {device->type,device->openair0_cfg->tx_sample_advance, device->openair0_cfg->rx_bw,0,OAIIQFILE_ID}; + iqfile_header_t fh = {device->type,device->openair0_cfg->tx_sample_advance, device->openair0_cfg->rx_bw,0,OAIIQFILE_ID}; recplay_state_t *rs = device->recplay_state; - recplay_conf_t *rc = device->openair0_cfg[0].recplay_conf; + recplay_conf_t *rc = device->openair0_cfg[0].recplay_conf; rs->pFile = fopen (rc->u_sf_filename,"wb+"); if (rs->pFile == NULL) { LOG_E(HW,"Cannot open %s\n", rc->u_sf_filename); } else { unsigned int i = 0; - unsigned int modu = 0; - - if ((modu = rs->nbSamplesBlocks % 10) != 0) { - rs->nbSamplesBlocks -= modu; // store entire number of frames - } - fh.nbSamplesBlocks=rs->nbSamplesBlocks; LOG_I(HW,"Writing file header to %s \n", rc->u_sf_filename ); fwrite(&fh, sizeof(fh), 1, rs->pFile); @@ -103,7 +96,7 @@ void iqrecorder_end(openair0_device *device) { uint8_t *ptr=(uint8_t *)rs->ms_sample; for (i = 0; i < rs->nbSamplesBlocks; i++) { - int blockBytes=sizeof(iqrec_t)+((iqrec_t *)ptr)->nbBytes; + int blockBytes=sizeof(iqrec_t)+BELL_LABS_IQ_BYTES_PER_SF; fwrite(ptr, sizeof(unsigned char), blockBytes, rs->pFile); ptr+=blockBytes; } diff --git a/radio/COMMON/record_player.h b/radio/COMMON/record_player.h index 2f5a6fa57b..1f76e5cf58 100644 --- a/radio/COMMON/record_player.h +++ b/radio/COMMON/record_player.h @@ -44,9 +44,8 @@ extern "C" #define RECPLAY_REPLAYMODE 2 #define BELL_LABS_IQ_HEADER 0xabababababababab -#define BELL_LABS_IQ_PER_SF 46080 // 7680 => 5MHz bw for now; 46080 => 3/4 40MHz (106 PRBs) +#define BELL_LABS_IQ_PER_SF 23040 // 23040 => 46080/2 slots => 3/4 40MHz (106 PRBs) #define BELL_LABS_IQ_BYTES_PER_SF (BELL_LABS_IQ_PER_SF * 4) -#define MAX_BELL_LABS_IQ_BYTES_PER_SF BELL_LABS_IQ_BYTES_PER_SF*10 #define OAIIQFILE_ID {'O', 'I','Q','F'} typedef struct { @@ -61,7 +60,9 @@ typedef struct { int64_t header; int64_t ts; int64_t nbBytes; - int64_t rfu2; // pad for 256 bits alignement required by AVX2 + int64_t tv_sec; // nb of secs since EPOCH + int64_t tv_usec; // nb of µsecs since EPOCH + int64_t rfu2; // pad for 256 bits alignement required by AVX2 } iqrec_t; #define DEF_NB_SF 120000 // default nb of sf or ms to capture (2 minutes at 5MHz) #define DEF_SF_FILE "/tmp/iqfile" // default subframes file name @@ -95,29 +96,31 @@ typedef struct { /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define DEVICE_RECPLAY_PARAMS_DESC { \ - {CONFIG_OPT_SF_FILE, CONFIG_HLP_SF_FILE, 0, strptr:&((*recplay_conf)->u_sf_filename), defstrval:DEF_SF_FILE, TYPE_STRING, 0}, \ - {CONFIG_OPT_SF_REC, CONFIG_HLP_SF_REC, PARAMFLAG_BOOL, uptr:&(u_sf_record), defuintval:0, TYPE_UINT, 0}, \ - {CONFIG_OPT_SF_REP, CONFIG_HLP_SF_REP, PARAMFLAG_BOOL, uptr:&(u_sf_replay), defuintval:0, TYPE_UINT, 0}, \ - {CONFIG_OPT_SF_MAX, CONFIG_HLP_SF_MAX, 0, uptr:&((*recplay_conf)->u_sf_max), defintval:DEF_NB_SF, TYPE_UINT, 0}, \ - {CONFIG_OPT_SF_LOOPS, CONFIG_HLP_SF_LOOPS, 0, uptr:&((*recplay_conf)->u_sf_loops), defintval:DEF_SF_NB_LOOP, TYPE_UINT, 0}, \ - {CONFIG_OPT_SF_RDELAY, CONFIG_HLP_SF_RDELAY, 0, uptr:&((*recplay_conf)->u_sf_read_delay), defintval:DEF_SF_DELAY_READ, TYPE_UINT, 0}, \ - {CONFIG_OPT_SF_WDELAY, CONFIG_HLP_SF_WDELAY, 0, uptr:&((*recplay_conf)->u_sf_write_delay), defintval:DEF_SF_DELAY_WRITE, TYPE_UINT, 0}, \ - {CONFIG_OPT_USE_MMAP, CONFIG_HLP_USE_MMAP, PARAMFLAG_BOOL, uptr:&((*recplay_conf)->use_mmap), defuintval:1, TYPE_UINT, 0}, \ + {CONFIG_OPT_SF_FILE, CONFIG_HLP_SF_FILE, 0, strptr:&((*recplay_conf)->u_sf_filename), defstrval:DEF_SF_FILE, TYPE_STRING, 0}, \ + {CONFIG_OPT_SF_REC, CONFIG_HLP_SF_REC, PARAMFLAG_BOOL, uptr:&((*recplay_conf)->u_sf_record), defuintval:0, TYPE_UINT, 0}, \ + {CONFIG_OPT_SF_REP, CONFIG_HLP_SF_REP, PARAMFLAG_BOOL, uptr:&((*recplay_conf)->u_sf_replay), defuintval:0, TYPE_UINT, 0}, \ + {CONFIG_OPT_SF_MAX, CONFIG_HLP_SF_MAX, 0, uptr:&((*recplay_conf)->u_sf_max), defintval:DEF_NB_SF, TYPE_UINT, 0}, \ + {CONFIG_OPT_SF_LOOPS, CONFIG_HLP_SF_LOOPS, 0, uptr:&((*recplay_conf)->u_sf_loops), defintval:DEF_SF_NB_LOOP, TYPE_UINT, 0}, \ + {CONFIG_OPT_SF_RDELAY, CONFIG_HLP_SF_RDELAY, 0, uptr:&((*recplay_conf)->u_sf_read_delay), defintval:DEF_SF_DELAY_READ, TYPE_UINT, 0}, \ + {CONFIG_OPT_SF_WDELAY, CONFIG_HLP_SF_WDELAY, 0, uptr:&((*recplay_conf)->u_sf_write_delay), defintval:DEF_SF_DELAY_WRITE, TYPE_UINT, 0}, \ + {CONFIG_OPT_USE_MMAP, CONFIG_HLP_USE_MMAP, PARAMFLAG_BOOL, uptr:&((*recplay_conf)->use_mmap), defuintval:1, TYPE_UINT, 0}, \ }/*! \brief Record Player Configuration and state */ typedef struct { - char *u_sf_filename; // subframes file path - unsigned int u_sf_max ; // max number of recorded subframes - unsigned int u_sf_loops ; // number of loops in replay mode + char *u_sf_filename; // subframes file path + unsigned int u_sf_max ; // max number of recorded subframes + unsigned int u_sf_loops ; // number of loops in replay mode unsigned int u_sf_read_delay; // read delay in replay mode unsigned int u_sf_write_delay ; // write delay in replay mode - unsigned int use_mmap; // default is to use mmap + unsigned int use_mmap; // default is to use mmap + unsigned int u_sf_replay; // replay mode (if 1) + unsigned int u_sf_record; // record mode (if 1) } recplay_conf_t; typedef struct { size_t mapsize; FILE *pFile; int fd; - iqrec_t *ms_sample; // memory for all subframes + iqrec_t *ms_sample; // memory for all subframes unsigned int nbSamplesBlocks; uint8_t *currentPtr; uint64_t currentTs; diff --git a/radio/USRP/USERSPACE/LIB/usrp_lib.cpp b/radio/USRP/USERSPACE/LIB/usrp_lib.cpp index 227c2f461c..61013ef569 100644 --- a/radio/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/radio/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -698,7 +698,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp nsamps2 = (nsamps+3)>>2; int16x8_t buff_tmp[cc<2 ? 2 : cc][nsamps2]; #endif - + static int read_count = 0; int rxshift; switch (device->type) { case USRP_B200_DEV: @@ -769,25 +769,30 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp recplay_state_t *recPlay=device->recplay_state; - if ( recPlay != NULL) { // record mode + if (device->openair0_cfg->recplay_mode == RECPLAY_RECORDMODE) { // record mode // Copy subframes to memory (later dump on a file) - if (recPlay->nbSamplesBlocks < device->openair0_cfg->recplay_conf->u_sf_max && - recPlay->maxSizeBytes > (recPlay->currentPtr-(uint8_t *)recPlay->ms_sample) + - sizeof(iqrec_t) + nsamps*4 ) { + // The number of read samples might differ from BELL_LABS_IQ_BYTES_PER_SF + // The number of read samples is always stored in nbBytes but the record is always of BELL_LABS_IQ_BYTES_PER_SF size + if (recPlay->nbSamplesBlocks <= device->openair0_cfg->recplay_conf->u_sf_max && + recPlay->maxSizeBytes >= (recPlay->currentPtr-(uint8_t *)recPlay->ms_sample) + + sizeof(iqrec_t) + BELL_LABS_IQ_BYTES_PER_SF) { iqrec_t *hdr=(iqrec_t *)recPlay->currentPtr; + struct timespec trec; + (void) clock_gettime(CLOCK_REALTIME, &trec); hdr->header = BELL_LABS_IQ_HEADER; hdr->ts = *ptimestamp; - hdr->nbBytes=nsamps*4; + hdr->nbBytes=nsamps*4; // real number of samples bytes + hdr->tv_sec = trec.tv_sec; // record secs + hdr->tv_usec = trec.tv_nsec/1000; // record µsecs memcpy(hdr+1, buff[0], nsamps*4); - recPlay->currentPtr+=sizeof(iqrec_t)+nsamps*4; + recPlay->currentPtr+=sizeof(iqrec_t)+BELL_LABS_IQ_BYTES_PER_SF; // record size is constant (BELL_LABS_IQ_BYTES_PER_SF) recPlay->nbSamplesBlocks++; -#if 0 // BMC: this is too verbose - LOG_D(HW,"recorded %d samples, for TS %lu, shift in buffer %ld\n", nsamps, hdr->ts, recPlay->currentPtr-(uint8_t *)recPlay->ms_sample); -#endif + LOG_D(HW,"recorded %d samples, for TS %lu, shift in buffer %ld nbBytes %d nbSamplesBlocks %d\n", nsamps, hdr->ts, recPlay->currentPtr-(uint8_t *)recPlay->ms_sample, (int)hdr->nbBytes, (int)recPlay->nbSamplesBlocks); } else - exit_function(__FILE__, __FUNCTION__, __LINE__,"Recording reaches max iq limit\n"); + exit_function(__FILE__, __FUNCTION__, __LINE__, "Recording reaches max iq limit\n", OAI_EXIT_NORMAL); } - + read_count++; + LOG_D(HW,"usrp_lib: returning %d samples at ts %lu read_count %d\n", samples_received, *ptimestamp, read_count); return samples_received; } diff --git a/radio/iqplayer/iqplayer_lib.c b/radio/iqplayer/iqplayer_lib.c index 8fd3da5ed1..7ac587bb95 100644 --- a/radio/iqplayer/iqplayer_lib.c +++ b/radio/iqplayer/iqplayer_lib.c @@ -35,10 +35,33 @@ #include #include #include +#include +#include #include "common_lib.h" #include "assertions.h" #include "common/utils/LOG/log.h" +static void busy_wait(uint32_t usecs) { + uint32_t elapsed_usecs; + double temp; + int j; + struct timespec requestStart, requestEnd; + + // Active wait + clock_gettime(CLOCK_REALTIME, &requestStart); + temp = 0; + while (1) { + for (j=0; j < 40; j++) + temp += sin(j); + clock_gettime(CLOCK_REALTIME, &requestEnd); + elapsed_usecs = ( requestEnd.tv_sec - requestStart.tv_sec ) / 1e-6 + + ( requestEnd.tv_nsec - requestStart.tv_nsec ) / 1e3; + if (elapsed_usecs >= usecs) + break; + } + //LOG_I(HW, "Expected: %d Elapsed: %d us\n", usecs, elapsed_usecs); +} + static void parse_iqfile_header(openair0_device *device, iqfile_header_t *iq_fh) { char tmp[4]=OAIIQFILE_ID; AssertFatal((memcmp(iq_fh->oaiid,tmp,sizeof(iq_fh->oaiid)) == 0), @@ -92,8 +115,8 @@ static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair fstat(s->fd, &sb); s->mapsize=sb.st_size; LOG_I(HW, "Loading %u subframes from %s,size=%lu bytes ...\n",s->nbSamplesBlocks, c->u_sf_filename,(uint64_t)sb.st_size); - // allocate buffer for 1 sample at a time - s->ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t)+MAX_BELL_LABS_IQ_BYTES_PER_SF*4); + // allocate buffer for 1 subframe at a time + s->ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t)+BELL_LABS_IQ_BYTES_PER_SF); if (s->ms_sample == NULL) { LOG_E(HW,"Memory allocation failed for individual subframe replay mode.\n" ); @@ -120,6 +143,56 @@ static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair return 0; } +/*! \brief print the device statistics + * \param device the hardware to use + * \returns 0 on success + */ +static int trx_iqplayer_get_stats(openair0_device *device) +{ + LOG_I(HW, "trx_iqplayer_get_stats() called, not implemented\n"); + return 0; +} + +/*! \brief Reset device statistics + * \param device the hardware to use + * \returns 0 in success + */ +static int trx_iqplayer_reset_stats(openair0_device *device) +{ + LOG_I(HW, "trx_iqplayer_reset_stats() called, not implemented\n"); + return 0; +} + +/*! \brief Stop operation of the transceiver + */ +static int trx_iqplayer_stop(openair0_device *device) +{ + LOG_I(HW, "trx_iqplayer_stop() called, not implemented\n"); + return 0; +} + +/*! \brief Set RX frequencies + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + * \returns 0 in success + */ +static int trx_iqplayer_set_freq(openair0_device *device, openair0_config_t *openair0_cfg) +{ + LOG_I(HW, "trx_iqplayer_set_freq() called, not implemented\n"); + return 0; +} + +/*! \brief Set gains + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + * \returns 0 in success + */ +static int trx_iqplayer_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) +{ + LOG_I(HW, "trx_iqplayer_set_gains() called, not implemented\n"); + return 0; +} + /*! \brief start the oai iq player * \param device, the hardware used */ @@ -181,24 +254,28 @@ static int trx_iqplayer_write(openair0_device *device, openair0_timestamp timest */ static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { recplay_state_t *s = device->recplay_state; + static struct timeval tprev; + static int read_count = 0; if (s->curSamplesBlock==0 && s->wrap_count==0) { s->currentTs=s->ms_sample->ts; + tprev.tv_sec = s->ms_sample->tv_sec; + tprev.tv_usec = s->ms_sample->tv_usec; LOG_I(HW, "First timestamp=%lu s->nbSamplesBlocks=%u\n", s->currentTs, s->nbSamplesBlocks); } if (s->curSamplesBlock == s->nbSamplesBlocks) { - LOG_I(HW, "wrapping on iq file (%ld)\n", s->wrap_count); - s->curSamplesBlock = 0; - s->wrap_count++; - if (s->wrap_count == device->openair0_cfg->recplay_conf->u_sf_loops) { LOG_W(HW, "iqplayer device terminating subframes replay after %u iteration\n", device->openair0_cfg->recplay_conf->u_sf_loops); - exit_function(__FILE__, __FUNCTION__, __LINE__,"replay ended, triggering process termination\n"); + exit_function(__FILE__, __FUNCTION__, __LINE__,"replay ended, triggering process termination\n", OAI_EXIT_NORMAL); } - LOG_I(HW,"go back at the beginning of IQ file"); + if (s->wrap_count > 0) { + LOG_I(HW, "wrapping on iq file (%ld)\n", s->wrap_count); + } + s->curSamplesBlock = 0; + s->wrap_count++; device->recplay_state->currentPtr=(uint8_t *)device->recplay_state->ms_sample; if (!(device->openair0_cfg->recplay_conf->use_mmap) ) { @@ -210,20 +287,23 @@ static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimes if (!(device->openair0_cfg->recplay_conf->use_mmap)) { // read sample from file if (read(s->fd, s->ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) { - LOG_E(HW,"pb reading iqfile at index %lu %s\n",sizeof(iqrec_t)*s->curSamplesBlock, strerror(errno) ); + LOG_E(HW,"pb reading iq record header at index %lu %s\n",sizeof(iqrec_t)*s->curSamplesBlock, strerror(errno) ); exit(-1); } else { - if (read(s->fd, s->ms_sample+1, s->ms_sample->nbBytes) != s->ms_sample->nbBytes) { - LOG_E(HW,"pb reading iqfile at index %lu %s\n",sizeof(iqrec_t)*s->curSamplesBlock, strerror(errno) ); + if (read(s->fd, s->ms_sample+1, BELL_LABS_IQ_BYTES_PER_SF) != BELL_LABS_IQ_BYTES_PER_SF) { + LOG_E(HW,"pb reading iq record data at index %lu %s\n",sizeof(iqrec_t)*s->curSamplesBlock, strerror(errno) ); exit(-1); } } } iqrec_t *curHeader=(iqrec_t *)s->currentPtr; - AssertFatal(curHeader->header==BELL_LABS_IQ_HEADER,"" ); + if (curHeader->header != BELL_LABS_IQ_HEADER) { + LOG_I(HW,"Problem iq header nsamps %d\n", nsamps); + AssertFatal(curHeader->header==BELL_LABS_IQ_HEADER,"" ); + } // the current timestamp is the stored timestamp until we wrap on input - AssertFatal(nsamps*4==curHeader->nbBytes,""); + AssertFatal(nsamps*4==curHeader->nbBytes,"nsamps=%d curHeader->nbBytes=%d", (int)nsamps, (int)curHeader->nbBytes); *ptimestamp = s->currentTs; memcpy(buff[0], curHeader+1, nsamps*4); s->curSamplesBlock++; @@ -231,33 +311,40 @@ static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimes s->currentTs+=nsamps; if (device->openair0_cfg->recplay_conf->use_mmap) - s->currentPtr+=sizeof(iqrec_t)+s->ms_sample->nbBytes; + s->currentPtr+=sizeof(iqrec_t)+BELL_LABS_IQ_BYTES_PER_SF; - // BMC TODO: support 1 second or more subframe read delay - struct timespec req; - req.tv_sec = 0; - req.tv_nsec = (device->openair0_cfg[0].recplay_conf->u_sf_read_delay) * 1000; - nanosleep(&req, NULL); - LOG_D(HW, "returning %d samples at ts %lu\n", nsamps, *ptimestamp); + // subframe read delay is not taken into account + // Real time interval is handle to mimic RF board latcency + struct timeval tcur, tdiff; + tcur.tv_sec = curHeader->tv_sec; + tcur.tv_usec = curHeader->tv_usec; + timersub(&tcur, &tprev, &tdiff); + if (tdiff.tv_usec > 0) { + busy_wait(tdiff.tv_usec); + } + tprev = tcur; + + read_count++; + LOG_D(HW, "returning %d samples at ts %lu read_count %d\n", nsamps, *ptimestamp, read_count); return nsamps; } int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { device->openair0_cfg = openair0_cfg; device->trx_start_func = trx_iqplayer_start; - device->trx_get_stats_func = NULL; - device->trx_reset_stats_func = NULL; - device->trx_end_func = trx_iqplayer_end; - device->trx_stop_func = NULL; - device->trx_set_freq_func = NULL; - device->trx_set_gains_func = NULL; + device->trx_get_stats_func = trx_iqplayer_get_stats; + device->trx_reset_stats_func = trx_iqplayer_reset_stats; + device->trx_end_func = trx_iqplayer_end; + device->trx_stop_func = trx_iqplayer_stop; + device->trx_set_freq_func = trx_iqplayer_set_freq; + device->trx_set_gains_func = trx_iqplayer_set_gains; // Replay subframes from from file // openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38; // bw_gain_adjust=1; device->trx_write_func = trx_iqplayer_write; device->trx_read_func = trx_iqplayer_read; iqplayer_loadfile(device, openair0_cfg); - LOG_UI(HW,"iqplayer device initialized, replay %s for %i iterations",openair0_cfg->recplay_conf->u_sf_filename,openair0_cfg->recplay_conf->u_sf_loops); + LOG_UI(HW,"iqplayer device initialized, replay %s for %i iteration(s)\n",openair0_cfg->recplay_conf->u_sf_filename,openair0_cfg->recplay_conf->u_sf_loops); return 0; } /*@}*/