fix rfsim ue initial sync and legacy OAI C struct syntax
This commit is contained in:
@@ -174,7 +174,7 @@ set(CMAKE_C_FLAGS
|
||||
"${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -D${MKVER}"
|
||||
)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 -D${MKVER}"
|
||||
"${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -Wno-packed-bitfield-compat -fPIC -Wall -fno-strict-aliasing -rdynamic -std=c++11 -D${MKVER}"
|
||||
)
|
||||
|
||||
|
||||
@@ -604,7 +604,6 @@ set(HWLIB_TCP_BRIDGE_OAI_SOURCE
|
||||
add_library(tcp_bridge_oai MODULE ${HWLIB_TCP_BRIDGE_OAI_SOURCE} )
|
||||
set_target_properties(tcp_bridge_oai PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
||||
|
||||
add_library(rfsimulator MODULE ${OPENAIR_TARGETS}/ARCH/rfsimulator/simulator.c)
|
||||
|
||||
##########################################################
|
||||
|
||||
@@ -1986,6 +1985,11 @@ add_library(uescope MODULE ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} ${XFORMS_
|
||||
target_link_libraries(enbscope ${XFORMS_LIBRARIES})
|
||||
target_link_libraries(uescope ${XFORMS_LIBRARIES})
|
||||
|
||||
add_library(rfsimulator MODULE
|
||||
${OPENAIR_TARGETS}/ARCH/rfsimulator/simulator.c
|
||||
)
|
||||
target_link_libraries(rfsimulator SIMU ${ATLAS_LIBRARIES})
|
||||
|
||||
set(CMAKE_MODULE_PATH "${OPENAIR_DIR}/cmake_targets/tools/MODULES" "${CMAKE_MODULE_PATH}")
|
||||
|
||||
#include T directory even if the T is off because T macros are in the code
|
||||
@@ -2029,6 +2033,25 @@ add_definitions(-DASN1_MINIMUM_VERSION=924)
|
||||
#################################
|
||||
# add executables for operation
|
||||
#################################
|
||||
add_library(minimal_lib
|
||||
${OPENAIR_DIR}/common/utils/backtrace.c
|
||||
${OPENAIR_DIR}/common/utils/LOG/log.c
|
||||
${OPENAIR_DIR}/common/config/config_userapi.c
|
||||
${OPENAIR_DIR}/common/config/config_load_configmodule.c
|
||||
${OPENAIR_DIR}/common/config/config_cmdline.c
|
||||
${OPENAIR_DIR}/common/utils/minimal_stub.c
|
||||
${T_SOURCE}
|
||||
)
|
||||
target_link_libraries(minimal_lib pthread dl ${T_LIB})
|
||||
|
||||
add_executable(replay_node
|
||||
${OPENAIR_TARGETS}/ARCH/rfsimulator/stored_node.c
|
||||
)
|
||||
target_link_libraries (replay_node minimal_lib)
|
||||
|
||||
add_executable(measurement_display
|
||||
${OPENAIR_DIR}/common/utils/threadPool/measurement_display.c)
|
||||
target_link_libraries (measurement_display minimal_lib)
|
||||
|
||||
# lte-softmodem is both eNB and UE implementation
|
||||
###################################################
|
||||
|
||||
@@ -450,7 +450,7 @@ int config_setdefault_double(paramdef_t *cfgoptions, char *prefix) {
|
||||
config_check_valptr(cfgoptions, (char **)&(cfgoptions->dblptr),sizeof(double));
|
||||
|
||||
if( ((cfgoptions->paramflags & PARAMFLAG_MANDATORY) == 0)) {
|
||||
*(cfgoptions->u64ptr)=cfgoptions->defdblval;
|
||||
*(cfgoptions->dblptr)=cfgoptions->defdblval;
|
||||
status=1;
|
||||
printf_params("[CONFIG] %s set to default value %lf\n",cfgoptions->optname , *(cfgoptions->dblptr));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
int T_stdout;
|
||||
|
||||
void exit_function(const char *file, const char *function, const int line, const char *s) {
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef __SIMPLE_EXE_H__
|
||||
#define __SIMPLE_EXE_H__
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <common/utils/assertions.h>
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include "common_lib.h"
|
||||
|
||||
#ifdef T
|
||||
#undef T
|
||||
#define T(...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -33,7 +33,9 @@
|
||||
#define __PHY_DEFS_ENB__H__
|
||||
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -415,7 +415,7 @@ typedef struct {
|
||||
/// nprach_CP_Length_r13, for the CP length(unit us) only 66.7 and 266.7 is implemented
|
||||
uint16_t nprach_CP_Length;
|
||||
/// The criterion for UEs to select a NPRACH resource. Up to 2 RSRP threshold values can be signalled. \vr{[1..2]}
|
||||
struct rsrp_ThresholdsNPrachInfoList *rsrp_ThresholdsPrachInfoList;
|
||||
rsrp_ThresholdsNPrachInfoList *rsrp_ThresholdsPrachInfoList;
|
||||
/// NPRACH Parameters List
|
||||
NPRACH_List_NB_IoT_t nprach_ParametersList;
|
||||
|
||||
|
||||
@@ -282,8 +282,16 @@ typedef struct {
|
||||
#define cmax(a,b) ((a>b) ? (a) : (b))
|
||||
#define cmax3(a,b,c) ((cmax(a,b)>c) ? (cmax(a,b)) : (c))
|
||||
#define cmin(a,b) ((a<b) ? (a) : (b))
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef min
|
||||
#undef min
|
||||
#undef max
|
||||
#endif
|
||||
#else
|
||||
#define max(a,b) cmax(a,b)
|
||||
#define min(a,b) cmin(a,b)
|
||||
#endif
|
||||
|
||||
#ifndef malloc16
|
||||
# ifdef __AVX2__
|
||||
|
||||
@@ -1001,7 +1001,7 @@ void eNB_Config_Local_DRX(
|
||||
{
|
||||
UE_list_t *UE_list_mac = NULL;
|
||||
int UE_id = -1;
|
||||
UE_sched_ctrl *UE_scheduling_control = NULL;
|
||||
UE_sched_ctrl_t *UE_scheduling_control = NULL;
|
||||
|
||||
UE_list_mac = &(RC.mac[Mod_id]->UE_list);
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ void schedule_SRS(module_id_t module_idP,
|
||||
eNB_MAC_INST *eNB = RC.mac[module_idP];
|
||||
UE_list_t *UE_list = &(eNB->UE_list);
|
||||
nfapi_ul_config_request_body_t *ul_req = NULL;
|
||||
UE_sched_ctrl *UE_scheduling_control = NULL;
|
||||
UE_sched_ctrl_t *UE_scheduling_control = NULL;
|
||||
COMMON_channels_t *cc = eNB->common_channels;
|
||||
LTE_SoundingRS_UL_ConfigCommon_t *soundingRS_UL_ConfigCommon = NULL;
|
||||
struct LTE_SoundingRS_UL_ConfigDedicated *soundingRS_UL_ConfigDedicated = NULL;
|
||||
@@ -198,7 +198,7 @@ void schedule_CSI(module_id_t module_idP,
|
||||
UE_list_t *UE_list = &eNB->UE_list;
|
||||
COMMON_channels_t *cc = NULL;
|
||||
nfapi_ul_config_request_body_t *ul_req = NULL;
|
||||
UE_sched_ctrl *UE_scheduling_control = NULL;
|
||||
UE_sched_ctrl_t *UE_scheduling_control = NULL;
|
||||
|
||||
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
cc = &eNB->common_channels[CC_id];
|
||||
@@ -571,7 +571,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
eNB_MAC_INST *eNB = RC.mac[module_idP];
|
||||
UE_list_t *UE_list = &(eNB->UE_list);
|
||||
COMMON_channels_t *cc = eNB->common_channels;
|
||||
UE_sched_ctrl *UE_scheduling_control = NULL;
|
||||
UE_sched_ctrl_t *UE_scheduling_control = NULL;
|
||||
|
||||
start_meas(&(eNB->eNB_scheduler));
|
||||
|
||||
|
||||
@@ -480,7 +480,7 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
eNB_UE_STATS *eNB_UE_stats = NULL;
|
||||
UE_TEMPLATE *ue_template = NULL;
|
||||
eNB_STATS *eNB_stats = NULL;
|
||||
RRC_release_ctrl *release_ctrl = NULL;
|
||||
RRC_release_ctrl_t *release_ctrl = NULL;
|
||||
DLSCH_PDU *dlsch_pdu = NULL;
|
||||
RA_t *ra = NULL;
|
||||
int sdu_length_total = 0;
|
||||
@@ -490,7 +490,7 @@ schedule_ue_spec(module_id_t module_idP,
|
||||
int continue_flag = 0;
|
||||
int32_t normalized_rx_power, target_rx_power;
|
||||
int tpc = 1;
|
||||
UE_sched_ctrl *ue_sched_ctrl;
|
||||
UE_sched_ctrl_t *ue_sched_ctrl;
|
||||
int mcs;
|
||||
int i;
|
||||
int min_rb_unit[NFAPI_CC_MAX];
|
||||
@@ -1688,7 +1688,7 @@ dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id,
|
||||
int nb_mac_CC = RC.nb_mac_CC[Mod_id];
|
||||
UE_list_t *UE_list = &eNB->UE_list;
|
||||
slice_info_t *sli = &eNB->slice_info;
|
||||
UE_sched_ctrl *ue_sched_ctl;
|
||||
UE_sched_ctrl_t *ue_sched_ctl;
|
||||
COMMON_channels_t *cc;
|
||||
int N_RBG[NFAPI_CC_MAX];
|
||||
int slice_sorted_list[MAX_NUM_SLICES];
|
||||
@@ -1914,7 +1914,7 @@ schedule_ue_spec_br(module_id_t module_idP,
|
||||
COMMON_channels_t *cc = mac->common_channels;
|
||||
UE_list_t *UE_list = &mac->UE_list;
|
||||
UE_TEMPLATE *UE_template = NULL;
|
||||
UE_sched_ctrl *ue_sched_ctl = NULL;
|
||||
UE_sched_ctrl_t *ue_sched_ctl = NULL;
|
||||
nfapi_dl_config_request_pdu_t *dl_config_pdu = NULL;
|
||||
nfapi_ul_config_request_pdu_t *ul_config_pdu = NULL;
|
||||
nfapi_tx_request_pdu_t *TX_req = NULL;
|
||||
|
||||
@@ -179,7 +179,7 @@ void dlsch_scheduler_pre_ue_select_fairRR(
|
||||
eNB_MAC_INST *eNB = RC.mac[module_idP];
|
||||
COMMON_channels_t *cc = eNB->common_channels;
|
||||
UE_list_t *UE_list = &eNB->UE_list;
|
||||
UE_sched_ctrl *ue_sched_ctl;
|
||||
UE_sched_ctrl_t *ue_sched_ctl;
|
||||
uint8_t CC_id;
|
||||
int UE_id;
|
||||
unsigned char round = 0;
|
||||
@@ -585,7 +585,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
|
||||
// uint16_t r1=0;
|
||||
uint8_t CC_id;
|
||||
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||
UE_sched_ctrl *ue_sched_ctl;
|
||||
UE_sched_ctrl_t *ue_sched_ctl;
|
||||
// int rrc_status = RRC_IDLE;
|
||||
COMMON_channels_t *cc;
|
||||
#ifdef TM5
|
||||
@@ -596,7 +596,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id,
|
||||
rnti_t rnti1, rnti2;
|
||||
LTE_eNB_UE_stats *eNB_UE_stats1 = NULL;
|
||||
LTE_eNB_UE_stats *eNB_UE_stats2 = NULL;
|
||||
UE_sched_ctrl *ue_sched_ctl1, *ue_sched_ctl2;
|
||||
UE_sched_ctrl_t *ue_sched_ctl1, *ue_sched_ctl2;
|
||||
#endif
|
||||
memset(rballoc_sub[0],0,(MAX_NUM_CCs)*(N_RBG_MAX)*sizeof(unsigned char));
|
||||
memset(min_rb_unit,0,sizeof(min_rb_unit));
|
||||
@@ -828,7 +828,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP,
|
||||
int32_t normalized_rx_power, target_rx_power;
|
||||
int32_t tpc = 1;
|
||||
static int32_t tpc_accumulated = 0;
|
||||
UE_sched_ctrl *ue_sched_ctl;
|
||||
UE_sched_ctrl_t *ue_sched_ctl;
|
||||
int mcs;
|
||||
int i;
|
||||
int min_rb_unit[MAX_NUM_CCs];
|
||||
@@ -1968,7 +1968,7 @@ void ulsch_scheduler_pre_ue_select_fairRR(
|
||||
uint8_t ulsch_ue_max_num[MAX_NUM_CCs];
|
||||
uint16_t saved_ulsch_dci[MAX_NUM_CCs];
|
||||
rnti_t rnti;
|
||||
UE_sched_ctrl *UE_sched_ctl = NULL;
|
||||
UE_sched_ctrl_t *UE_sched_ctl = NULL;
|
||||
uint8_t cc_id_flag[MAX_NUM_CCs];
|
||||
uint8_t harq_pid = 0,round = 0;
|
||||
UE_list_t *UE_list= &eNB->UE_list;
|
||||
@@ -2627,7 +2627,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP,
|
||||
COMMON_channels_t *cc;
|
||||
UE_list_t *UE_list=&eNB->UE_list;
|
||||
UE_TEMPLATE *UE_template;
|
||||
UE_sched_ctrl *UE_sched_ctrl;
|
||||
UE_sched_ctrl_t *UE_sched_ctrl;
|
||||
int sched_frame=frameP;
|
||||
int rvidx_tab[4] = {0,2,3,1};
|
||||
uint16_t ul_req_index;
|
||||
|
||||
@@ -208,7 +208,7 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s
|
||||
COMMON_channels_t *cc = &mac->common_channels[0];
|
||||
UE_list_t *UE_list=&mac->UE_list;
|
||||
UE_TEMPLATE *UE_template;
|
||||
UE_sched_ctrl *UE_sched_ctrl;
|
||||
UE_sched_ctrl_t *UE_sched_ctrl;
|
||||
int sched_frame=frameP;
|
||||
int sched_subframe = (subframeP+4)%10;
|
||||
uint16_t ul_req_index;
|
||||
|
||||
@@ -1073,7 +1073,7 @@ get_dl_cqi_pmi_size_pusch(COMMON_channels_t *cc,
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint8_t
|
||||
get_rel8_dl_cqi_pmi_size(UE_sched_ctrl *sched_ctl,
|
||||
get_rel8_dl_cqi_pmi_size(UE_sched_ctrl_t *sched_ctl,
|
||||
int CC_idP,
|
||||
COMMON_channels_t *cc,
|
||||
uint8_t tmode,
|
||||
@@ -2182,7 +2182,7 @@ add_new_ue(module_id_t mod_idP,
|
||||
#endif
|
||||
memset((void *) &UE_list->UE_sched_ctrl[UE_id],
|
||||
0,
|
||||
sizeof(UE_sched_ctrl));
|
||||
sizeof(UE_sched_ctrl_t));
|
||||
memset((void *) &UE_list->eNB_UE_stats[cc_idP][UE_id],
|
||||
0,
|
||||
sizeof(eNB_UE_STATS));
|
||||
@@ -2520,7 +2520,7 @@ UE_is_to_be_scheduled(module_id_t module_idP,
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
UE_TEMPLATE *UE_template = &RC.mac[module_idP]->UE_list.UE_template[CC_id][UE_id];
|
||||
UE_sched_ctrl *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id];
|
||||
UE_sched_ctrl_t *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id];
|
||||
|
||||
// do not schedule UE if UL is not working
|
||||
if (UE_sched_ctl->ul_failure_timer > 0 || UE_sched_ctl->ul_out_of_sync > 0)
|
||||
@@ -3928,7 +3928,7 @@ extract_harq(module_id_t mod_idP,
|
||||
{
|
||||
eNB_MAC_INST *eNB = RC.mac[mod_idP];
|
||||
UE_list_t *UE_list = &eNB->UE_list;
|
||||
UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
rnti_t rnti = UE_RNTI(mod_idP, UE_id);
|
||||
COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
|
||||
nfapi_harq_indication_fdd_rel13_t *harq_indication_fdd;
|
||||
@@ -4573,7 +4573,7 @@ extract_pucch_csi(module_id_t mod_idP,
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
|
||||
UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP];
|
||||
int no_pmi;
|
||||
uint8_t Ltab[6] = { 0, 2, 4, 4, 4, 4 };
|
||||
@@ -4685,7 +4685,7 @@ extract_pusch_csi(module_id_t mod_idP,
|
||||
{
|
||||
UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
|
||||
COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP];
|
||||
UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
int Ntab[6] = { 0, 4, 7, 9, 10, 13 };
|
||||
int Ntab_uesel[6] = { 0, 8, 13, 17, 19, 25 };
|
||||
int Ltab_uesel[6] = { 0, 6, 9, 13, 15, 18 };
|
||||
@@ -4980,7 +4980,7 @@ cqi_indication(module_id_t mod_idP,
|
||||
return;
|
||||
}
|
||||
|
||||
UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
|
||||
if (UE_id >= 0) {
|
||||
LOG_D(MAC,"%s() UE_id:%d channel:%d cqi:%d\n",
|
||||
@@ -5047,7 +5047,7 @@ SR_indication(module_id_t mod_idP,
|
||||
T_INT(rntiP));
|
||||
int UE_id = find_UE_id(mod_idP, rntiP);
|
||||
UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
|
||||
UE_sched_ctrl *UE_scheduling_ctrl = NULL;
|
||||
UE_sched_ctrl_t *UE_scheduling_ctrl = NULL;
|
||||
|
||||
if (UE_id != -1) {
|
||||
UE_scheduling_ctrl = &(UE_list->UE_sched_ctrl[UE_id]);
|
||||
@@ -5178,7 +5178,7 @@ harq_indication(module_id_t mod_idP,
|
||||
}
|
||||
|
||||
UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
|
||||
UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP];
|
||||
// extract HARQ Information
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ rx_sdu(const module_id_t enb_mod_idP,
|
||||
eNB_MAC_INST *mac = NULL;
|
||||
UE_list_t *UE_list = NULL;
|
||||
rrc_eNB_ue_context_t *ue_contextP = NULL;
|
||||
UE_sched_ctrl *UE_scheduling_control = NULL;
|
||||
UE_sched_ctrl_t *UE_scheduling_control = NULL;
|
||||
UE_TEMPLATE *UE_template_ptr = NULL;
|
||||
|
||||
/* Init */
|
||||
@@ -1340,7 +1340,7 @@ schedule_ulsch_rnti(module_id_t module_idP,
|
||||
UE_list_t *UE_list = NULL;
|
||||
slice_info_t *sli = NULL;
|
||||
UE_TEMPLATE *UE_template_ptr = NULL;
|
||||
UE_sched_ctrl *UE_sched_ctrl_ptr = NULL;
|
||||
UE_sched_ctrl_t *UE_sched_ctrl_ptr = NULL;
|
||||
int rvidx_tab[4] = {0, 2, 3, 1};
|
||||
int first_rb_slice[NFAPI_CC_MAX];
|
||||
int n_rb_ul_tab[NFAPI_CC_MAX];
|
||||
@@ -1954,7 +1954,7 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP,
|
||||
COMMON_channels_t *cc = eNB->common_channels;
|
||||
UE_list_t *UE_list = &(eNB->UE_list);
|
||||
UE_TEMPLATE *UE_template = NULL;
|
||||
UE_sched_ctrl *UE_sched_ctrl = NULL;
|
||||
UE_sched_ctrl_t *UE_sched_ctrl = NULL;
|
||||
|
||||
if (sched_subframeP < subframeP) {
|
||||
sched_frame++;
|
||||
|
||||
@@ -1070,7 +1070,7 @@ typedef struct {
|
||||
/// DRX UL retransmission timer, one per UL HARQ process
|
||||
/* Not implemented yet */
|
||||
/* End of C-DRX related timers */
|
||||
} UE_sched_ctrl;
|
||||
} UE_sched_ctrl_t;
|
||||
|
||||
/*! \brief eNB template for the Random access information */
|
||||
typedef struct {
|
||||
@@ -1168,7 +1168,7 @@ typedef struct {
|
||||
/// eNB to UE statistics
|
||||
eNB_UE_STATS eNB_UE_stats[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
|
||||
/// scheduling control info
|
||||
UE_sched_ctrl UE_sched_ctrl[MAX_MOBILES_PER_ENB];
|
||||
UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_ENB];
|
||||
int next[MAX_MOBILES_PER_ENB];
|
||||
int head;
|
||||
int next_ul[MAX_MOBILES_PER_ENB];
|
||||
@@ -1191,11 +1191,11 @@ typedef struct {
|
||||
rnti_t rnti;
|
||||
///remove UE context flag
|
||||
boolean_t removeContextFlg;
|
||||
} UE_free_ctrl;
|
||||
} UE_free_ctrl_t;
|
||||
/*! \brief REMOVE UE list used by eNB to order UEs/CC for deleting*/
|
||||
typedef struct {
|
||||
/// deleting control info
|
||||
UE_free_ctrl UE_free_ctrl[NUMBER_OF_UE_MAX+1];
|
||||
UE_free_ctrl_t UE_free_ctrl[NUMBER_OF_UE_MAX+1];
|
||||
int num_UEs;
|
||||
int head_freelist; ///the head position of the delete list
|
||||
int tail_freelist; ///the tail position of the delete list
|
||||
@@ -1772,11 +1772,11 @@ typedef struct {
|
||||
volatile uint8_t flag;
|
||||
rnti_t rnti;
|
||||
mui_t rrc_eNB_mui;
|
||||
}RRC_release_ctrl;
|
||||
}RRC_release_ctrl_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t num_UEs;
|
||||
RRC_release_ctrl RRC_release_ctrl[NUMBER_OF_UE_MAX];
|
||||
RRC_release_ctrl_t RRC_release_ctrl[NUMBER_OF_UE_MAX];
|
||||
} RRC_release_list_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -1160,7 +1160,7 @@ void get_csi_params(COMMON_channels_t * cc,
|
||||
struct LTE_CQI_ReportPeriodic *cqi_PMI_ConfigIndex,
|
||||
uint16_t * Npd, uint16_t * N_OFFSET_CQI, int *H);
|
||||
|
||||
uint8_t get_rel8_dl_cqi_pmi_size(UE_sched_ctrl * sched_ctl, int CC_idP,
|
||||
uint8_t get_rel8_dl_cqi_pmi_size(UE_sched_ctrl_t * sched_ctl, int CC_idP,
|
||||
COMMON_channels_t * cc, uint8_t tmode,
|
||||
struct LTE_CQI_ReportPeriodic
|
||||
*cqi_ReportPeriodic);
|
||||
|
||||
@@ -505,7 +505,7 @@ void sort_UEs(module_id_t Mod_idP,
|
||||
int list_size = 0;
|
||||
struct sort_ue_dl_params params = {Mod_idP, frameP, subframeP, slice_idx};
|
||||
UE_list_t *UE_list = &(RC.mac[Mod_idP]->UE_list);
|
||||
UE_sched_ctrl *UE_scheduling_control = NULL;
|
||||
UE_sched_ctrl_t *UE_scheduling_control = NULL;
|
||||
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) {
|
||||
|
||||
@@ -546,7 +546,7 @@ void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id,
|
||||
const uint8_t rbs_retx[NFAPI_CC_MAX]) {
|
||||
int UE_id, CC_id, N_RB_DL, i;
|
||||
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||
UE_sched_ctrl *ue_sched_ctl;
|
||||
UE_sched_ctrl_t *ue_sched_ctl;
|
||||
uint16_t available_rbs;
|
||||
|
||||
for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
|
||||
@@ -590,7 +590,7 @@ void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id,
|
||||
int ue_count_retx[NFAPI_CC_MAX];
|
||||
//uint8_t ue_retx_flag[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB];
|
||||
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||
UE_sched_ctrl *ue_sched_ctl;
|
||||
UE_sched_ctrl_t *ue_sched_ctl;
|
||||
COMMON_channels_t *cc;
|
||||
|
||||
// Reset
|
||||
@@ -1226,7 +1226,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
uint8_t (*MIMO_mode_indicator)[N_RBG_MAX] = sli->pre_processor_results[slice_idx].MIMO_mode_indicator;
|
||||
|
||||
UE_list_t *UE_list = &eNB->UE_list;
|
||||
UE_sched_ctrl *ue_sched_ctl;
|
||||
UE_sched_ctrl_t *ue_sched_ctl;
|
||||
// int rrc_status = RRC_IDLE;
|
||||
#ifdef TM5
|
||||
int harq_pid1 = 0;
|
||||
@@ -1236,7 +1236,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id,
|
||||
rnti_t rnti1, rnti2;
|
||||
LTE_eNB_UE_stats *eNB_UE_stats1 = NULL;
|
||||
LTE_eNB_UE_stats *eNB_UE_stats2 = NULL;
|
||||
UE_sched_ctrl *ue_sched_ctl1, *ue_sched_ctl2;
|
||||
UE_sched_ctrl_t *ue_sched_ctl1, *ue_sched_ctl2;
|
||||
#endif
|
||||
// Initialize scheduling information for all active UEs
|
||||
memset(&sli->pre_processor_results[slice_idx], 0, sizeof(sli->pre_processor_results[slice_idx]));
|
||||
@@ -1391,7 +1391,7 @@ dlsch_scheduler_pre_processor_reset(module_id_t module_idP,
|
||||
uint8_t CC_id;
|
||||
int i, j;
|
||||
UE_list_t *UE_list;
|
||||
UE_sched_ctrl *ue_sched_ctl;
|
||||
UE_sched_ctrl_t *ue_sched_ctl;
|
||||
int N_RB_DL, RBGsize, RBGsize_last;
|
||||
int N_RBG[NFAPI_CC_MAX];
|
||||
#ifdef SF0_LIMIT
|
||||
@@ -1615,7 +1615,7 @@ dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id,
|
||||
int i;
|
||||
int tm = get_tmode(Mod_id, CC_id, UE_id);
|
||||
UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list;
|
||||
UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
|
||||
int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
|
||||
|
||||
for (i = 0; i < N_RBG; i++) {
|
||||
@@ -1685,7 +1685,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP,
|
||||
UE_list_t *UE_list = &eNB->UE_list;
|
||||
slice_info_t *sli = &eNB->slice_info;
|
||||
UE_TEMPLATE *UE_template = 0;
|
||||
UE_sched_ctrl *ue_sched_ctl;
|
||||
UE_sched_ctrl_t *ue_sched_ctl;
|
||||
int N_RB_UL = 0;
|
||||
uint16_t available_rbs, first_rb_offset;
|
||||
rnti_t rntiTable[MAX_MOBILES_PER_ENB];
|
||||
@@ -1865,7 +1865,7 @@ assign_max_mcs_min_rb(module_id_t module_idP,
|
||||
UE_list_t *UE_list = &eNB->UE_list;
|
||||
slice_info_t *sli = &eNB->slice_info;
|
||||
UE_TEMPLATE *UE_template;
|
||||
UE_sched_ctrl *ue_sched_ctl;
|
||||
UE_sched_ctrl_t *ue_sched_ctl;
|
||||
int Ncp;
|
||||
int N_RB_UL;
|
||||
int first_rb_offset, available_rbs;
|
||||
@@ -2042,7 +2042,7 @@ void sort_ue_ul(module_id_t module_idP,
|
||||
int list_size = 0;
|
||||
struct sort_ue_ul_params params = { module_idP, sched_frameP, sched_subframeP };
|
||||
UE_list_t *UE_list = &RC.mac[module_idP]->UE_list;
|
||||
UE_sched_ctrl *UE_scheduling_control = NULL;
|
||||
UE_sched_ctrl_t *UE_scheduling_control = NULL;
|
||||
|
||||
for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) {
|
||||
|
||||
|
||||
@@ -5814,7 +5814,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
|
||||
LOG_E(RRC,PROTOCOL_RRC_CTXT_UE_FMT" rrc_eNB_process_RRCConnectionReconfigurationComplete without UE_id(MAC) rnti %x, let's return\n",PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ue_context_pP->ue_context.rnti);
|
||||
return;
|
||||
}
|
||||
UE_sched_ctrl *UE_scheduling_control = &(RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id_mac]);
|
||||
UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id_mac]);
|
||||
|
||||
if (UE_scheduling_control->cdrx_waiting_ack == TRUE) {
|
||||
UE_scheduling_control->cdrx_waiting_ack = FALSE;
|
||||
|
||||
@@ -42,35 +42,35 @@
|
||||
int set_device(openair0_device *device) {
|
||||
switch (device->type) {
|
||||
case EXMIMO_DEV:
|
||||
printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
LOG_I(HW,"[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case USRP_B200_DEV:
|
||||
printf("[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
LOG_I(HW,"[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case USRP_X300_DEV:
|
||||
printf("[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
LOG_I(HW,"[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case BLADERF_DEV:
|
||||
printf("[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
LOG_I(HW,"[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case LMSSDR_DEV:
|
||||
printf("[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
LOG_I(HW,"[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case IRIS_DEV:
|
||||
printf("[%s] has loaded Iris device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
LOG_I(HW,"[%s] has loaded Iris device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case NONE_DEV:
|
||||
printf("[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
LOG_I(HW,"[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
LOG_E(HW,"[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ int set_transport(openair0_device *device) {
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
LOG_E(HW,"[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
@@ -119,7 +119,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param
|
||||
ret=load_module_shlib(libname,shlib_fdesc,1,NULL);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr,"Library %s couldn't be loaded\n",libname);
|
||||
LOG_E(HW,"Library %s couldn't be loaded\n",libname);
|
||||
} else {
|
||||
ret=((devfunc_t)shlib_fdesc[0].fptr)(device,openair0_cfg,cfg);
|
||||
}
|
||||
@@ -135,7 +135,7 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf
|
||||
|
||||
if ( rc >= 0) {
|
||||
if ( set_device(device) < 0) {
|
||||
fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__);
|
||||
LOG_E(HW, "%s %d:Unsupported radio head\n",__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -149,7 +149,7 @@ int openair0_transport_load(openair0_device *device, openair0_config_t *openair0
|
||||
|
||||
if ( rc >= 0) {
|
||||
if ( set_transport(device) < 0) {
|
||||
fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__);
|
||||
LOG_E(HW, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define COMMON_LIB_H
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <openair1/PHY/TOOLS/tools_defs.h>
|
||||
|
||||
/* name of shared library implementing the radio front end */
|
||||
#define OAI_RF_LIBNAME "oai_device"
|
||||
@@ -83,9 +84,6 @@ typedef enum {
|
||||
*/
|
||||
/*!\brief RF device types
|
||||
*/
|
||||
#ifdef OCP_FRAMEWORK
|
||||
#include <enums.h>
|
||||
#else
|
||||
typedef enum {
|
||||
MIN_RF_DEV_TYPE = 0,
|
||||
/*!\brief device is ExpressMIMO */
|
||||
@@ -102,10 +100,13 @@ typedef enum {
|
||||
IRIS_DEV,
|
||||
/*!\brief device is NONE*/
|
||||
NONE_DEV,
|
||||
/*!\brief device is ADRV9371_ZC706 */
|
||||
ADRV9371_ZC706_DEV,
|
||||
/*!\brief device is UEDv2 */
|
||||
UEDv2_DEV,
|
||||
MAX_RF_DEV_TYPE
|
||||
|
||||
} dev_type_t;
|
||||
#endif
|
||||
|
||||
/*!\brief transport protocol types
|
||||
*/
|
||||
@@ -397,6 +398,31 @@ struct openair0_device_t {
|
||||
typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
/* type of transport init function, implemented in shared lib */
|
||||
typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params);
|
||||
#define UE_MAGICDL_FDD 0xA5A5A5A5A5A5A5A5 // UE DL FDD record
|
||||
#define UE_MAGICUL_FDD 0x5A5A5A5A5A5A5A5A // UE UL FDD record
|
||||
#define UE_MAGICDL_TDD 0xA6A6A6A6A6A6A6A6 // UE DL TDD record
|
||||
#define UE_MAGICUL_TDD 0x6A6A6A6A6A6A6A6A // UE UL TDD record
|
||||
|
||||
#define ENB_MAGICDL_FDD 0xB5B5B5B5B5B5B5B5 // eNB DL FDD record
|
||||
#define ENB_MAGICUL_FDD 0x5B5B5B5B5B5B5B5B // eNB UL FDD record
|
||||
#define ENB_MAGICDL_TDD 0xB6B6B6B6B6B6B6B6 // eNB DL TDD record
|
||||
#define ENB_MAGICUL_TDD 0x6B6B6B6B6B6B6B6B // eNB UL TDD record
|
||||
|
||||
#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size)
|
||||
|
||||
#define sample_t struct complex16 // 2*16 bits complex number
|
||||
|
||||
typedef struct {
|
||||
uint64_t magic; // Magic value (see defines above)
|
||||
uint32_t size; // Number of samples per antenna to follow this header
|
||||
uint32_t nbAnt; // Total number of antennas following this header
|
||||
// Samples per antenna follow this header,
|
||||
// i.e. nbAnt = 2 => this header+samples_antenna_0+samples_antenna_1
|
||||
// data following this header in bytes is nbAnt*size*sizeof(sample_t)
|
||||
uint64_t timestamp; // Timestamp value of first sample
|
||||
uint32_t option_value; // Option value
|
||||
uint32_t option_flag; // Option flag
|
||||
} samplesBlockHeader_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
## General
|
||||
|
||||
#General
|
||||
This is a RF simulator that allows to test OAI without a RF board.
|
||||
It replaces a actual RF board driver.
|
||||
|
||||
As much as possible, it works like a RF board, but not in realtime: it can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound)
|
||||
|
||||
## build
|
||||
#build
|
||||
|
||||
No specific build is required, use the [oai softmodem build procedure](../../../doc/BUILD.md)
|
||||
## From build_oai
|
||||
You can build it the same way, and together with actual RF driver
|
||||
|
||||
Example:
|
||||
```bash
|
||||
./build_oai --ue-nas-use-tun --UE --eNB -w SIMU
|
||||
```
|
||||
It is also possible to build actual RF and use choose on each run:
|
||||
```bash
|
||||
./build_oai --ue-nas-use-tun --UE --eNB -w USRP --rfsimulator
|
||||
```
|
||||
Will build both the eNB (lte-softmodem) and the UE (lte-uesoftmodem)
|
||||
We recommend to use the option --ue-nas-use-tun that is much simpler to use than the OAI kernel driver.
|
||||
|
||||
## Add the rfsimulator after initial build
|
||||
After any regular build, you can compile the driver
|
||||
```bash
|
||||
cd <the_compilation_dir_from_bouild_oai_script>/build
|
||||
@@ -18,25 +30,15 @@ Then, you can use it freely
|
||||
|
||||
# Usage
|
||||
Setting the env variable RFSIMULATOR enables the RF board simulator
|
||||
It should the set to "enb" in the eNB
|
||||
It should the set to "server" in the eNB or gNB
|
||||
|
||||
## 4G case
|
||||
For the UE, it should be set to the IP address of the eNB
|
||||
example:
|
||||
|
||||
```bash
|
||||
sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50 --rfsim
|
||||
sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50
|
||||
```
|
||||
For the eNodeB, use a valid configuration file setup for USRP board tests and start the softmodem as usual, but adding the `--rfsim` option.
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
sudo RFSIMULATOR=enb ./lte-softmodem -O <config file> --rfsim
|
||||
```
|
||||
|
||||
|
||||
|
||||
Except this, the UE and the eNB can be used as it the RF is real
|
||||
|
||||
If you reach 'RA not active' on UE, be careful to generate a valid SIM
|
||||
@@ -55,7 +57,7 @@ make rfsimulator
|
||||
```
|
||||
### Launch gNB in one window
|
||||
```bash
|
||||
sudo RFSIMULATOR=enb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD
|
||||
sudo RFSIMULATOR=server ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD
|
||||
```
|
||||
### Launch UE in another window
|
||||
```bash
|
||||
@@ -64,8 +66,40 @@ sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C 3510000000
|
||||
Of course, set the gNB machine IP address if the UE and the gNB are not on the same machine
|
||||
In UE, you can add "-d" to get the softscope
|
||||
|
||||
## Caveacts
|
||||
### store and replay
|
||||
|
||||
You can store emitted I/Q samples:
|
||||
|
||||
If you set the environment variable: saveIQfile to a file name
|
||||
The simulator will write all IQ samples into this file
|
||||
|
||||
Then, you can replay with the executable "replay_node"
|
||||
|
||||
First compile it, as the other binaries
|
||||
```
|
||||
make replay_node
|
||||
```
|
||||
You can use this binary as I/Q data source to feed whatever UE or NB with recorded I/Q samples.
|
||||
|
||||
The file format is successive blocks of a header followed by the I/Q array.
|
||||
If you have existing stored I/Q, you can adpat the tool "replay_node" to convert your format to the rfsimulator format.
|
||||
|
||||
The format intend to be compatible with the OAI store/replay feature on USRP
|
||||
|
||||
### Channel simulation
|
||||
The RF channel simulator is called.
|
||||
In current version all channel paramters are hard coded in the call to:
|
||||
```
|
||||
new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels,
|
||||
AWGN,
|
||||
bridge->sample_rate,
|
||||
bridge->tx_bw,
|
||||
0.0, // forgetting_factor
|
||||
0, // maybe used for TA
|
||||
0); // path_loss in dB
|
||||
```
|
||||
Only the input noise can be changed on command line with -s parameter.
|
||||
With path loss = 0 set "-s 5" to see a little noise
|
||||
|
||||
#Caveacts
|
||||
Still issues in power control: txgain, rxgain are not used
|
||||
|
||||
|
||||
|
||||
@@ -21,63 +21,172 @@
|
||||
#include "common_lib.h"
|
||||
#include <openair1/PHY/defs_eNB.h>
|
||||
#include "openair1/PHY/defs_UE.h"
|
||||
#include <openair1/SIMULATION/TOOLS/sim.h>
|
||||
|
||||
#define PORT 4043 //TCP port for this simulator
|
||||
#define CirSize 3072000 // 100ms is enough
|
||||
#define sample_t uint32_t // 2*16 bits complex number
|
||||
#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
|
||||
#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
|
||||
#define MAGICeNB 0xA5A5A5A5A5A5A5A5
|
||||
#define MAGICUE 0x5A5A5A5A5A5A5A5A
|
||||
|
||||
typedef struct {
|
||||
uint64_t magic;
|
||||
uint32_t size;
|
||||
uint32_t nbAnt;
|
||||
uint64_t timestamp;
|
||||
} transferHeader;
|
||||
#define MAX_SIMULATION_CONNECTED_NODES 5
|
||||
#define GENERATE_CHANNEL 10 //each frame in DL
|
||||
|
||||
// Fixme: datamodel, external variables in .h files, ...
|
||||
#include <common/ran_context.h>
|
||||
extern double snr_dB;
|
||||
extern RAN_CONTEXT_t RC;
|
||||
//
|
||||
|
||||
pthread_mutex_t Sockmutex;
|
||||
|
||||
typedef struct buffer_s {
|
||||
int conn_sock;
|
||||
bool alreadyRead;
|
||||
uint64_t lastReceivedTS;
|
||||
bool headerMode;
|
||||
transferHeader th;
|
||||
samplesBlockHeader_t th;
|
||||
char *transferPtr;
|
||||
uint64_t remainToTransfer;
|
||||
char *circularBufEnd;
|
||||
sample_t *circularBuf;
|
||||
channel_desc_t *channel_model;
|
||||
} buffer_t;
|
||||
|
||||
typedef struct {
|
||||
int listen_sock, epollfd;
|
||||
uint64_t nextTimestamp;
|
||||
uint64_t typeStamp;
|
||||
uint64_t initialAhead;
|
||||
char *ip;
|
||||
int saveIQfile;
|
||||
buffer_t buf[FD_SETSIZE];
|
||||
int rx_num_channels;
|
||||
int tx_num_channels;
|
||||
double sample_rate;
|
||||
double tx_bw;
|
||||
} rfsimulator_state_t;
|
||||
|
||||
/*
|
||||
Legacy study:
|
||||
The parameters are:
|
||||
gain&loss (decay, signal power, ...)
|
||||
either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average
|
||||
=> don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE
|
||||
will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop)
|
||||
lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas);
|
||||
a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain
|
||||
|
||||
multi_path (auto convolution, ISI, ...)
|
||||
either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes
|
||||
legacy: we regenerate each sub frame in UL, and each frame only in DL
|
||||
*/
|
||||
void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_sig,
|
||||
int rxAnt,
|
||||
channel_desc_t *channelDesc,
|
||||
int nbSamples,
|
||||
uint64_t TS
|
||||
) {
|
||||
// channelDesc->path_loss_dB should contain the total path gain
|
||||
// so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...)
|
||||
// UE and NB gain control to be added
|
||||
// Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...)
|
||||
const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0);
|
||||
// Energy in one sample to calibrate input noise
|
||||
//Fixme: modified the N0W computation, not understand the origin value
|
||||
const double KT=1.38e-23*290; //Boltzman*temperature
|
||||
// sampling rate is linked to acquisition band (the input pass band filter)
|
||||
const double noise_figure_watt = KT*channelDesc->sampling_rate;
|
||||
// Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ?
|
||||
// the parameter "-s" is declared as SNR, but the input power is not well defined
|
||||
// −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise)
|
||||
const double rxGain= 132.24 - snr_dB;
|
||||
// sqrt(4*noise_figure_watt) is the thermal noise factor (volts)
|
||||
// fixme: the last constant is pure trial results to make decent noise
|
||||
const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10;
|
||||
// Fixme: we don't fill the offset length samples at begining ?
|
||||
// anyway, in today code, channel_offset=0
|
||||
const int dd = abs(channelDesc->channel_offset);
|
||||
const int nbTx=channelDesc->nb_tx;
|
||||
|
||||
for (int i=0; i<((int)nbSamples-dd); i++) {
|
||||
struct complex16 *out_ptr=after_channel_sig+dd+i;
|
||||
struct complex rx_tmp= {0};
|
||||
|
||||
for (int txAnt=0; txAnt < nbTx; txAnt++) {
|
||||
const struct complex *channelModel= channelDesc->ch[rxAnt+(txAnt*channelDesc->nb_rx)];
|
||||
|
||||
//const struct complex *channelModelEnd=channelModel+channelDesc->channel_length;
|
||||
for (int l = 0; l<(int)channelDesc->channel_length; l++) {
|
||||
// let's assume TS+i >= l
|
||||
// fixme: the rfsimulator current structure is interleaved antennas
|
||||
// this has been designed to not have to wait a full block transmission
|
||||
// but it is not very usefull
|
||||
// it would be better to split out each antenna in a separate flow
|
||||
// that will allow to mix ru antennas freely
|
||||
struct complex16 tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize];
|
||||
rx_tmp.x += tx16.r * channelModel[l].x - tx16.i * channelModel[l].y;
|
||||
rx_tmp.y += tx16.i * channelModel[l].x + tx16.r * channelModel[l].y;
|
||||
} //l
|
||||
}
|
||||
|
||||
out_ptr->r += round(rx_tmp.x*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
|
||||
out_ptr->i += round(rx_tmp.y*pathLossLinear + noise_per_sample*gaussdouble(0.0,1.0));
|
||||
out_ptr++;
|
||||
}
|
||||
|
||||
if ( (TS*nbTx)%CirSize+nbSamples <= CirSize )
|
||||
// Cast to a wrong type for compatibility !
|
||||
LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n",
|
||||
10*log10((double)signal_energy((int32_t *)&input_sig[(TS*nbTx)%CirSize], nbSamples)),
|
||||
10*log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)),
|
||||
channelDesc->path_loss_dB,
|
||||
10*log10(noise_per_sample));
|
||||
}
|
||||
|
||||
void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
|
||||
buffer_t *ptr=&bridge->buf[sock];
|
||||
AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
|
||||
ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
|
||||
ptr->conn_sock=sock;
|
||||
ptr->alreadyRead=false;
|
||||
ptr->lastReceivedTS=0;
|
||||
ptr->headerMode=true;
|
||||
ptr->transferPtr=(char *)&ptr->th;
|
||||
ptr->remainToTransfer=sizeof(transferHeader);
|
||||
ptr->remainToTransfer=sizeof(samplesBlockHeader_t);
|
||||
int sendbuff=1000*1000*10;
|
||||
AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, "");
|
||||
struct epoll_event ev= {0};
|
||||
ev.events = EPOLLIN | EPOLLRDHUP;
|
||||
ev.data.fd = sock;
|
||||
AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, "");
|
||||
// create channel simulation model for this mode reception
|
||||
// snr_dB is pure global, coming from configuration paramter "-s"
|
||||
// Fixme: referenceSignalPower should come from the right place
|
||||
// but the datamodel is inconsistant
|
||||
// legacy: RC.ru[ru_id]->frame_parms.pdsch_config_common.referenceSignalPower
|
||||
// (must not come from ru[]->frame_parms as it doesn't belong to ru !!!)
|
||||
// Legacy sets it as:
|
||||
// ptr->channel_model->path_loss_dB = -132.24 + snr_dB - RC.ru[0]->frame_parms->pdsch_config_common.referenceSignalPower;
|
||||
// we use directly the paramter passed on the command line ("-s")
|
||||
// the value channel_model->path_loss_dB seems only a storage place (new_channel_desc_scm() only copy the passed value)
|
||||
// Legacy changes directlty the variable channel_model->path_loss_dB place to place
|
||||
// while calling new_channel_desc_scm() with path losses = 0
|
||||
ptr->channel_model=new_channel_desc_scm(bridge->tx_num_channels,bridge->rx_num_channels,
|
||||
AWGN,
|
||||
bridge->sample_rate,
|
||||
bridge->tx_bw,
|
||||
0.0, // forgetting_factor
|
||||
0, // maybe used for TA
|
||||
0); // path_loss in dB
|
||||
random_channel(ptr->channel_model,false);
|
||||
}
|
||||
|
||||
void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
|
||||
AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, "");
|
||||
close(sock);
|
||||
free(bridge->buf[sock].circularBuf);
|
||||
// Fixme: no free_channel_desc_scm(bridge->buf[sock].channel_model) implemented
|
||||
// a lot of mem leaks
|
||||
free(bridge->buf[sock].channel_model);
|
||||
memset(&bridge->buf[sock], 0, sizeof(buffer_t));
|
||||
bridge->buf[sock].conn_sock=-1;
|
||||
}
|
||||
@@ -87,12 +196,11 @@ void socketError(rfsimulator_state_t *bridge, int sock) {
|
||||
LOG_W(HW,"Lost socket \n");
|
||||
removeCirBuf(bridge, sock);
|
||||
|
||||
if (bridge->typeStamp==MAGICUE)
|
||||
if (bridge->typeStamp==UE_MAGICDL_FDD)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define helpTxt "\
|
||||
\x1b[31m\
|
||||
rfsimulator: error: you have to run one UE and one eNB\n\
|
||||
@@ -117,11 +225,18 @@ void setblocking(int sock, enum blocking_t active) {
|
||||
AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, "");
|
||||
}
|
||||
|
||||
static bool flushInput(rfsimulator_state_t *t);
|
||||
static bool flushInput(rfsimulator_state_t *t, int timeout);
|
||||
|
||||
void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) {
|
||||
void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) {
|
||||
if (t->saveIQfile != -1) {
|
||||
if (write(t->saveIQfile, _buf, count) != count )
|
||||
LOG_E(HW,"write in save iq file failed (%s)\n",strerror(errno));
|
||||
}
|
||||
|
||||
AssertFatal(fd>=0 && _buf && count >0 && t,
|
||||
"Bug: %d/%p/%zd/%p", fd, _buf, count, t);
|
||||
char *buf = _buf;
|
||||
int l;
|
||||
ssize_t l;
|
||||
setblocking(fd, notBlocking);
|
||||
|
||||
while (count) {
|
||||
@@ -132,7 +247,9 @@ void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) {
|
||||
continue;
|
||||
|
||||
if(errno==EAGAIN) {
|
||||
flushInput(t);
|
||||
// The opposite side is saturated
|
||||
// we read incoming sockets meawhile waiting
|
||||
flushInput(t, 5);
|
||||
continue;
|
||||
} else
|
||||
return;
|
||||
@@ -145,7 +262,7 @@ void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) {
|
||||
|
||||
int server_start(openair0_device *device) {
|
||||
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
|
||||
t->typeStamp=MAGICeNB;
|
||||
t->typeStamp=ENB_MAGICDL_FDD;
|
||||
AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
|
||||
int enable = 1;
|
||||
AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, "");
|
||||
@@ -168,7 +285,7 @@ sin_addr:
|
||||
|
||||
int start_ue(openair0_device *device) {
|
||||
rfsimulator_state_t *t = device->priv;
|
||||
t->typeStamp=MAGICUE;
|
||||
t->typeStamp=UE_MAGICDL_FDD;
|
||||
int sock;
|
||||
AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
|
||||
struct sockaddr_in addr = {
|
||||
@@ -200,14 +317,16 @@ sin_addr:
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t lastW=-1;
|
||||
int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
|
||||
rfsimulator_state_t *t = device->priv;
|
||||
LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp);
|
||||
|
||||
for (int i=0; i<FD_SETSIZE; i++) {
|
||||
buffer_t *ptr=&t->buf[i];
|
||||
|
||||
if (ptr->conn_sock >= 0 ) {
|
||||
transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp};
|
||||
samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
|
||||
fullwrite(ptr->conn_sock,&header, sizeof(header), t);
|
||||
sample_t tmpSamples[nsamps][nbAnt];
|
||||
|
||||
@@ -223,21 +342,27 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi
|
||||
}
|
||||
}
|
||||
|
||||
lastW=timestamp;
|
||||
LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n",
|
||||
nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) );
|
||||
// Let's verify we don't have incoming data
|
||||
// This is mandatory when the opposite side don't transmit
|
||||
// This is mandatory when the opposite side don't transmit
|
||||
flushInput(t, 0);
|
||||
pthread_mutex_unlock(&Sockmutex);
|
||||
return nsamps;
|
||||
}
|
||||
|
||||
static bool flushInput(rfsimulator_state_t *t) {
|
||||
static bool flushInput(rfsimulator_state_t *t, int timeout) {
|
||||
// Process all incoming events on sockets
|
||||
// store the data in lists
|
||||
struct epoll_event events[FD_SETSIZE]= {0};
|
||||
int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 200);
|
||||
int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, timeout);
|
||||
|
||||
if ( nfds==-1 ) {
|
||||
if ( errno==EINTR || errno==EAGAIN )
|
||||
if ( errno==EINTR || errno==EAGAIN ) {
|
||||
return false;
|
||||
else
|
||||
} else
|
||||
AssertFatal(false,"error in epoll_wait\n");
|
||||
}
|
||||
|
||||
@@ -263,7 +388,7 @@ static bool flushInput(rfsimulator_state_t *t) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int blockSz;
|
||||
ssize_t blockSz;
|
||||
|
||||
if ( b->headerMode)
|
||||
blockSz=b->remainToTransfer;
|
||||
@@ -272,7 +397,7 @@ static bool flushInput(rfsimulator_state_t *t) {
|
||||
b->remainToTransfer :
|
||||
b->circularBufEnd - 1 - b->transferPtr ;
|
||||
|
||||
int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
|
||||
ssize_t sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
|
||||
|
||||
if ( sz < 0 ) {
|
||||
if ( errno != EAGAIN ) {
|
||||
@@ -282,6 +407,7 @@ static bool flushInput(rfsimulator_state_t *t) {
|
||||
} else if ( sz == 0 )
|
||||
continue;
|
||||
|
||||
LOG_D(HW, "Socket rcv %zd bytes\n", sz);
|
||||
AssertFatal((b->remainToTransfer-=sz) >= 0, "");
|
||||
b->transferPtr+=sz;
|
||||
|
||||
@@ -290,39 +416,44 @@ static bool flushInput(rfsimulator_state_t *t) {
|
||||
|
||||
// check the header and start block transfer
|
||||
if ( b->headerMode==true && b->remainToTransfer==0) {
|
||||
AssertFatal( (t->typeStamp == MAGICUE && b->th.magic==MAGICeNB) ||
|
||||
(t->typeStamp == MAGICeNB && b->th.magic==MAGICUE), "Socket Error in protocol");
|
||||
AssertFatal( (t->typeStamp == UE_MAGICDL_FDD && b->th.magic==ENB_MAGICDL_FDD) ||
|
||||
(t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol");
|
||||
b->headerMode=false;
|
||||
b->alreadyRead=true;
|
||||
|
||||
if ( b->lastReceivedTS != b->th.timestamp) {
|
||||
int nbAnt= b->th.nbAnt;
|
||||
|
||||
for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ )
|
||||
for (int a=0; a < nbAnt; a++)
|
||||
b->circularBuf[(index*nbAnt+a)%CirSize]=0;
|
||||
for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) {
|
||||
for (int a=0; a < nbAnt; a++) {
|
||||
b->circularBuf[(index*nbAnt+a)%CirSize].r=0;
|
||||
b->circularBuf[(index*nbAnt+a)%CirSize].i=0;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS );
|
||||
}
|
||||
|
||||
b->lastReceivedTS=b->th.timestamp;
|
||||
AssertFatal(lastW == -1 || ( abs((double)lastW-b->lastReceivedTS) < (double)CirSize),
|
||||
"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", lastW, b->lastReceivedTS);
|
||||
b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize];
|
||||
b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt);
|
||||
}
|
||||
|
||||
if ( b->headerMode==false ) {
|
||||
LOG_D(HW,"Set b->lastReceivedTS %ld\n", b->lastReceivedTS);
|
||||
b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt);
|
||||
|
||||
if ( b->remainToTransfer==0) {
|
||||
LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS);
|
||||
|
||||
|
||||
// First block in UE, resync with the eNB current TS
|
||||
if ( t->nextTimestamp == 0 )
|
||||
t->nextTimestamp=b->lastReceivedTS-b->th.size;
|
||||
|
||||
if ( b->remainToTransfer==0) {
|
||||
LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS);
|
||||
b->headerMode=true;
|
||||
b->transferPtr=(char *)&b->th;
|
||||
b->remainToTransfer=sizeof(transferHeader);
|
||||
b->remainToTransfer=sizeof(samplesBlockHeader_t);
|
||||
b->th.magic=-1;
|
||||
}
|
||||
}
|
||||
@@ -334,10 +465,10 @@ static bool flushInput(rfsimulator_state_t *t) {
|
||||
|
||||
int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) {
|
||||
if (nbAnt != 1) {
|
||||
LOG_E(HW, "rfsimulator: only 1 antenna tested\n");
|
||||
exit(1);
|
||||
LOG_W(HW, "rfsimulator: only 1 antenna tested\n");
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&Sockmutex);
|
||||
rfsimulator_state_t *t = device->priv;
|
||||
LOG_D(HW, "Enter rfsimulator_read, expect %d samples, will release at TS: %ld\n", nsamps, t->nextTimestamp+nsamps);
|
||||
// deliver data from received data
|
||||
@@ -350,13 +481,14 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
|
||||
|
||||
if ( first_sock == FD_SETSIZE ) {
|
||||
// no connected device (we are eNB, no UE is connected)
|
||||
if (!flushInput(t)) {
|
||||
if (!flushInput(t, 10)) {
|
||||
for (int x=0; x < nbAnt; x++)
|
||||
memset(samplesVoid[x],0,sampleToByte(nsamps,1));
|
||||
|
||||
t->nextTimestamp+=nsamps;
|
||||
LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp);
|
||||
*ptimestamp = t->nextTimestamp-nsamps;
|
||||
pthread_mutex_unlock(&Sockmutex);
|
||||
return nsamps;
|
||||
}
|
||||
} else {
|
||||
@@ -365,12 +497,13 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
|
||||
do {
|
||||
have_to_wait=false;
|
||||
|
||||
for ( int sock=0; sock<FD_SETSIZE; sock++)
|
||||
if ( t->buf[sock].circularBuf &&
|
||||
t->buf[sock].alreadyRead && //>= t->initialAhead &&
|
||||
for ( int sock=0; sock<FD_SETSIZE; sock++) {
|
||||
if ( t->buf[sock].circularBuf && t->buf[sock].alreadyRead )
|
||||
if ( t->buf[sock].lastReceivedTS == 0 ||
|
||||
(t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) {
|
||||
have_to_wait=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (have_to_wait)
|
||||
@@ -378,7 +511,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
|
||||
ptr->lastReceivedTS,
|
||||
t->nextTimestamp+nsamps);
|
||||
*/
|
||||
flushInput(t);
|
||||
flushInput(t, 3);
|
||||
} while (have_to_wait);
|
||||
}
|
||||
|
||||
@@ -391,12 +524,20 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
|
||||
buffer_t *ptr=&t->buf[sock];
|
||||
|
||||
if ( ptr->circularBuf && ptr->alreadyRead ) {
|
||||
for (int a=0; a<nbAnt; a++) {
|
||||
sample_t *out=(sample_t *)samplesVoid[a];
|
||||
bool reGenerateChannel=false;
|
||||
|
||||
for ( int i=0; i < nsamps; i++ )
|
||||
out[i]+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize]<<1;
|
||||
}
|
||||
//fixme: when do we regenerate
|
||||
// it seems legacy behavior is: never in UL, each frame in DL
|
||||
if (reGenerateChannel)
|
||||
random_channel(ptr->channel_model,0);
|
||||
|
||||
for (int a=0; a<nbAnt; a++)
|
||||
rxAddInput( ptr->circularBuf, (struct complex16 *) samplesVoid[a],
|
||||
a,
|
||||
ptr->channel_model,
|
||||
nsamps,
|
||||
t->nextTimestamp
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,10 +547,9 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
|
||||
nsamps,
|
||||
*ptimestamp, t->nextTimestamp,
|
||||
signal_energy(samplesVoid[0], nsamps));
|
||||
pthread_mutex_unlock(&Sockmutex);
|
||||
return nsamps;
|
||||
}
|
||||
|
||||
|
||||
int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) {
|
||||
abort();
|
||||
return 0;
|
||||
@@ -434,10 +574,10 @@ int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cf
|
||||
int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
__attribute__((__visibility__("default")))
|
||||
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
// to change the log level, use this on command line
|
||||
// --log_config.hw_log_level debug
|
||||
//set_log(HW,OAILOG_DEBUG);
|
||||
rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1);
|
||||
|
||||
@@ -446,11 +586,28 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rfsimulator->typeStamp = strncasecmp(rfsimulator->ip,"enb",3) == 0 ?
|
||||
MAGICeNB:
|
||||
MAGICUE;
|
||||
LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == MAGICeNB ? "eNB" : "UE");
|
||||
device->trx_start_func = rfsimulator->typeStamp == MAGICeNB ?
|
||||
pthread_mutex_init(&Sockmutex, NULL);
|
||||
|
||||
if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 ||
|
||||
strncasecmp(rfsimulator->ip,"server",3) == 0 )
|
||||
rfsimulator->typeStamp = ENB_MAGICDL_FDD;
|
||||
else
|
||||
rfsimulator->typeStamp = UE_MAGICDL_FDD;
|
||||
|
||||
LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "(eg)NB" : "UE");
|
||||
char *saveF;
|
||||
|
||||
if ((saveF=getenv("saveIQfile")) != NULL) {
|
||||
rfsimulator->saveIQfile=open(saveF,O_APPEND| O_CREAT|O_TRUNC | O_WRONLY, 0666);
|
||||
|
||||
if ( rfsimulator->saveIQfile != -1 )
|
||||
LOG_I(HW,"rfsimulator: will save written IQ samples in %s\n", saveF);
|
||||
else
|
||||
LOG_E(HW, "can't open %s for IQ saving (%s)\n", saveF, strerror(errno));
|
||||
} else
|
||||
rfsimulator->saveIQfile = -1;
|
||||
|
||||
device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL_FDD ?
|
||||
server_start :
|
||||
start_ue;
|
||||
device->trx_get_stats_func = rfsimulator_get_stats;
|
||||
@@ -470,6 +627,12 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
rfsimulator->buf[i].conn_sock=-1;
|
||||
|
||||
AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,"");
|
||||
rfsimulator->initialAhead=openair0_cfg[0].sample_rate/1000; // One sub frame
|
||||
// initialize channel simulation
|
||||
rfsimulator->tx_num_channels=openair0_cfg->tx_num_channels;
|
||||
rfsimulator->rx_num_channels=openair0_cfg->rx_num_channels;
|
||||
rfsimulator->sample_rate=openair0_cfg->sample_rate;
|
||||
rfsimulator->tx_bw=openair0_cfg->tx_bw;
|
||||
randominit(0);
|
||||
set_taus_seed(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
Author: Laurent THOMAS, Open Cells
|
||||
copyleft: OpenAirInterface Software Alliance and it's licence
|
||||
*/
|
||||
|
||||
#include <common/utils/simple_executable.h>
|
||||
|
||||
|
||||
void fullwrite(int fd, void *_buf, int count) {
|
||||
char *buf = _buf;
|
||||
int l;
|
||||
|
||||
while (count) {
|
||||
l = write(fd, buf, count);
|
||||
|
||||
if (l <= 0) {
|
||||
if (errno==EINTR)
|
||||
continue;
|
||||
|
||||
if(errno==EAGAIN) {
|
||||
continue;
|
||||
} else {
|
||||
AssertFatal(false,"Lost socket\n");
|
||||
}
|
||||
} else {
|
||||
count -= l;
|
||||
buf += l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int server_start(short port) {
|
||||
int listen_sock;
|
||||
AssertFatal((listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
|
||||
int enable = 1;
|
||||
AssertFatal(setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, "");
|
||||
struct sockaddr_in addr = {
|
||||
sin_family:
|
||||
AF_INET,
|
||||
sin_port:
|
||||
htons(port),
|
||||
sin_addr:
|
||||
{ s_addr: INADDR_ANY }
|
||||
};
|
||||
bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
AssertFatal(listen(listen_sock, 5) == 0, "");
|
||||
return accept(listen_sock,NULL,NULL);
|
||||
}
|
||||
|
||||
int client_start(char *IP, short port) {
|
||||
int sock;
|
||||
AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
|
||||
struct sockaddr_in addr = {
|
||||
sin_family:
|
||||
AF_INET,
|
||||
sin_port:
|
||||
htons(port),
|
||||
sin_addr:
|
||||
{ s_addr: INADDR_ANY }
|
||||
};
|
||||
addr.sin_addr.s_addr = inet_addr(IP);
|
||||
bool connected=false;
|
||||
|
||||
while(!connected) {
|
||||
LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", IP, port);
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
|
||||
LOG_I(HW,"rfsimulator: connection established\n");
|
||||
connected=true;
|
||||
}
|
||||
|
||||
perror("simulated node");
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
enum blocking_t {
|
||||
notBlocking,
|
||||
blocking
|
||||
};
|
||||
|
||||
void setblocking(int sock, enum blocking_t active) {
|
||||
int opts;
|
||||
AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,"");
|
||||
|
||||
if (active==blocking)
|
||||
opts = opts & ~O_NONBLOCK;
|
||||
else
|
||||
opts = opts | O_NONBLOCK;
|
||||
|
||||
AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, "");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc != 4) {
|
||||
printf("Need parameters: source file, server or destination IP, TCP port\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int fd;
|
||||
AssertFatal((fd=open(argv[1],O_RDONLY)) != -1, "file: %s", argv[1]);
|
||||
off_t fileSize=lseek(fd, 0, SEEK_END);
|
||||
int serviceSock;
|
||||
|
||||
if (strcmp(argv[2],"server")==0) {
|
||||
serviceSock=server_start(atoi(argv[3]));
|
||||
} else {
|
||||
client_start(argv[2],atoi(argv[3]));
|
||||
}
|
||||
|
||||
samplesBlockHeader_t header;
|
||||
int bufSize=100000;
|
||||
void *buff=malloc(bufSize);
|
||||
|
||||
while (1) {
|
||||
//Rewind the file to loop on the samples
|
||||
if ( lseek(fd, 0, SEEK_CUR) >= fileSize )
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
// Read one block and send it
|
||||
setblocking(serviceSock, blocking);
|
||||
AssertFatal(read(fd,&header,sizeof(header)), "");
|
||||
fullwrite(serviceSock, &header, sizeof(header));
|
||||
int dataSize=sizeof(sample_t)*header.size*header.nbAnt;
|
||||
|
||||
if (dataSize>bufSize)
|
||||
buff=realloc(buff,dataSize);
|
||||
|
||||
AssertFatal(read(fd,buff,dataSize) == dataSize, "");
|
||||
fullwrite(serviceSock, buff, dataSize);
|
||||
// Purge incoming samples
|
||||
setblocking(serviceSock, notBlocking);
|
||||
|
||||
while(recv(serviceSock,buff, bufSize, MSG_DONTWAIT) > 0) {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -34,9 +34,11 @@
|
||||
#include "UTIL/OPT/opt.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
#include <dlfcn.h>
|
||||
static softmodem_params_t softmodem_params;
|
||||
char *parallel_config=NULL;
|
||||
char *worker_config=NULL;
|
||||
double snr_dB=25;
|
||||
|
||||
uint64_t get_softmodem_optmask(void) {
|
||||
return softmodem_params.optmask;
|
||||
|
||||
@@ -152,7 +152,6 @@
|
||||
{"usrp-clksrc", CONFIG_HLP_USRP_CLK_SRC,0, strptr:(char **)&usrp_clksrc, defstrval:"internal", TYPE_STRING, 0}, \
|
||||
{"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \
|
||||
{"clock", CONFIG_HLP_CLK, 0, uptr:&clock_source, defintval:0, TYPE_UINT, 0}, \
|
||||
{"s" , CONFIG_HLP_SNR, 0, iptr:&snr_dB, defintval:25, TYPE_INT, 0}, \
|
||||
{"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \
|
||||
{"A", CONFIG_HLP_TADV, 0, iptr:&(timingadv), defintval:0, TYPE_INT, 0} \
|
||||
}
|
||||
@@ -201,6 +200,7 @@
|
||||
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, uptr:(uint32_t *)&do_forms, defintval:0, TYPE_INT8, 0}, \
|
||||
{"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \
|
||||
{"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \
|
||||
{"s" , CONFIG_HLP_SNR, 0, dblptr:&snr_dB, defdblval:25, TYPE_DOUBLE, 0}, \
|
||||
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \
|
||||
{"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \
|
||||
{"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
|
||||
@@ -283,6 +283,7 @@ uint64_t get_pdcp_optmask(void);
|
||||
extern pthread_cond_t sync_cond;
|
||||
extern pthread_mutex_t sync_mutex;
|
||||
extern int sync_var;
|
||||
extern double snr_dB;
|
||||
|
||||
|
||||
extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
|
||||
@@ -132,8 +132,6 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
int UE_scan = 1;
|
||||
int UE_scan_carrier = 0;
|
||||
|
||||
int snr_dB=25;
|
||||
|
||||
runmode_t mode = normal_txrx;
|
||||
|
||||
FILE *input_fd=NULL;
|
||||
|
||||
Reference in New Issue
Block a user