diff --git a/executables/nr-ru.c b/executables/nr-ru.c index ebe6fbbb74..6c527defca 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1845,6 +1845,16 @@ static void NRRCconfig_RU(void) { RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); } + if (config_isparamset(RUParamList.paramarray[j], RU_TX_SUBDEV)) { + RC.ru[j]->openair0_cfg.tx_subdev = strdup(*(RUParamList.paramarray[j][RU_TX_SUBDEV].strptr)); + LOG_I(PHY, "RU USRP tx subdev == %s\n", RC.ru[j]->openair0_cfg.tx_subdev); + } + + if (config_isparamset(RUParamList.paramarray[j], RU_RX_SUBDEV)) { + RC.ru[j]->openair0_cfg.rx_subdev = strdup(*(RUParamList.paramarray[j][RU_RX_SUBDEV].strptr)); + LOG_I(PHY, "RU USRP rx subdev == %s\n", RC.ru[j]->openair0_cfg.rx_subdev); + } + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) { if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) { RC.ru[j]->openair0_cfg.clock_source = internal; diff --git a/maketags b/maketags index 87f445dd21..4c25bf6292 100755 --- a/maketags +++ b/maketags @@ -1,4 +1,4 @@ #!/bin/sh echo "building ctags for openair1 and openair2 ..." -ctags -e -R --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair1/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common nfapi executables sdr +ctags -e -R --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair1/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common nfapi executables radio diff --git a/radio/USRP/README.md b/radio/USRP/README.md new file mode 100644 index 0000000000..131be06436 --- /dev/null +++ b/radio/USRP/README.md @@ -0,0 +1,36 @@ +USRP device documentation + +OAI works with the most common USRP models like, B200, B200mini, B210, X310, N300, N310, N320, X410. This is achieved by using the Ettus Universal Hardware Driver (UHD) (https://github.com/EttusResearch/uhd). The file usrp_lib.cpp provides an abstraction layer of UHD to OAI. + +The USRP can be configured in the RU section of the config file. The field "sdr_addrs" uses the same syntax as the USRP device identification string (https://files.ettus.com/manual/page_identification.html). Here are a few examples + +sdr_addrs = "addr=192.168.10.2" # uses a single 10Gb Ethernet interface on an N3x0 or X3x0 or X4x0 + +sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2" # uses 2 10Gb Ethernet interfaces on a N3x0 or X3x0 or X4x0 (requires that you flashed the FPGA wth the XG image) + +you can also use the multi USRP feature and specify multiple USRPs, in which case you will get the aggregated number of channels on all the devices + +sdr_addrs = "addr0=192.168.10.2,addr1=192.168.30.2" + +You can specify if you want to use external or interal clock or time source either by adding the parameters in the sdr_addrs field or by using the fields clock_src or time_src + +sdr_addrs = "addr=192.168.10.2,clock_source=external,time_source=external" + +is equivalent to + +sdr_addrs = "addr=192.168.10.2" +clock_src = "external" +time_src = "external" + +Valid choices for clock and time source are "internal", "external", and "gpsdo" + +Careful: the USRP remembers the choice of the clock source. If you want to make sure it uses always the same, always specify the clock_source and time_source. + +Last but not least you may specify that only a specfic subdevice of the USRP is used. See also https://files.ettus.com/manual/page_configuration.html#config_subdev + +For example on a USRP N310 the following fields will specify that you use channel 0 of subdevice A. + +tx_subdev = "A:0" +rx_subdev = "A:0" + +When combining this with the multi USRP feature you can easily create a distributed antenna array with only 1 channel used at each USRP. \ No newline at end of file diff --git a/radio/USRP/USERSPACE/LIB/usrp_lib.cpp b/radio/USRP/USERSPACE/LIB/usrp_lib.cpp index a51ed53b8d..802604b2af 100644 --- a/radio/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/radio/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -1077,18 +1077,28 @@ extern "C" { return -1; } - LOG_I(HW,"Found USRP %s\n", device_adds[0].get("type").c_str()); + std::string type_str, product_str; + if (args.find("addr0") != std::string::npos) { + type_str = "type0"; + product_str = "product0"; + } + else { + type_str = "type"; + product_str = "product"; + } + + LOG_I(HW,"Found USRP %s\n", device_adds[0].get(type_str).c_str()); double usrp_master_clock; - if (device_adds[0].get("type") == "b200") { + if (device_adds[0].get(type_str) == "b200") { device->type = USRP_B200_DEV; usrp_master_clock = 30.72e6; args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=7680, recv_frame_size=7680" ; } - if (device_adds[0].get("type") == "n3xx") { - const std::string product = device_adds[0].get("product"); + if (device_adds[0].get(type_str) == "n3xx") { + const std::string product = device_adds[0].get(product_str); printf("Found USRP %s\n", product.c_str()); device->type=USRP_N300_DEV; if (product == "n320") @@ -1101,7 +1111,7 @@ extern "C" { LOG_W(HW,"Can't set kernel parameters for N3x0\n"); } - if (device_adds[0].get("type") == "x300") { + if (device_adds[0].get(type_str) == "x300") { printf("Found USRP x300\n"); device->type=USRP_X300_DEV; usrp_master_clock = 184.32e6; @@ -1112,7 +1122,7 @@ extern "C" { LOG_W(HW,"Can't set kernel parameters for X3xx\n"); } - if (device_adds[0].get("type") == "x4xx") { + if (device_adds[0].get(type_str) == "x4xx") { printf("Found USRP x400\n"); device->type = USRP_X400_DEV; usrp_master_clock = 245.76e6;