UHD: Initial C++ porting

UHD: cmakefix

x3
master
Xavier Arteaga 5 years ago committed by Xavier Arteaga
parent 8512c10286
commit cd463d1b87

@ -28,4 +28,39 @@ INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(UHD DEFAULT_MSG UHD_LIBRARIES UHD_INCLUDE_DIRS) FIND_PACKAGE_HANDLE_STANDARD_ARGS(UHD DEFAULT_MSG UHD_LIBRARIES UHD_INCLUDE_DIRS)
MARK_AS_ADVANCED(UHD_LIBRARIES UHD_INCLUDE_DIRS) MARK_AS_ADVANCED(UHD_LIBRARIES UHD_INCLUDE_DIRS)
include(CheckCXXSourceCompiles)
IF(UHD_FOUND)
# Checks whether the UHD driver supports X300 reset from srsLTE. This functionality requires changing the function
# `x300_make_ctrl_iface_enet` visibility in the file `uhd/host/lib/usrp/x300_fw_ctrl.cpp`. This can be accomplished
# adding the following line:
# `UHD_API wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors);`
set(_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS})
set(CMAKE_REQUIRED_LIBRARIES uhd boost_program_options boost_system)
check_cxx_source_compiles("#include <uhd.h>
#include <uhd/usrp/multi_usrp.hpp>
#include <uhd/transport/udp_simple.hpp>
uhd::wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors);
uhd_error try_usrp_x300_reset()
{
uhd::transport::udp_simple::sptr udp_simple = uhd::transport::udp_simple::make_connected(\"\", \"49152\");
uhd::wb_iface::sptr x300_ctrl = x300_make_ctrl_iface_enet(udp_simple, true);
x300_ctrl->poke32(0x100058, 1);
return UHD_ERROR_NONE;
}
int main(int argc, char** argv)
{
try_usrp_x300_reset();
return 0;
}" UHD_ENABLE_X300_FW_RESET)
set(CMAKE_REQUIRED_FLAGS ${_CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_LIBRARIES ${_CMAKE_REQUIRED_LIBRARIES})
ENDIF(UHD_FOUND)
ENDIF(NOT UHD_FOUND) ENDIF(NOT UHD_FOUND)

@ -29,7 +29,12 @@ if(RF_FOUND)
if (UHD_FOUND) if (UHD_FOUND)
add_definitions(-DENABLE_UHD) add_definitions(-DENABLE_UHD)
list(APPEND SOURCES_RF rf_uhd_imp.c uhd_c_api.cpp) list(APPEND SOURCES_RF rf_uhd_imp.cc)
# If found, add a macro to inform the UHD driver about the available feature
if (UHD_ENABLE_X300_FW_RESET)
add_definitions(-DENABLE_UHD_X300_FW_RESET)
endif(UHD_ENABLE_X300_FW_RESET)
endif (UHD_FOUND) endif (UHD_FOUND)
if (BLADERF_FOUND) if (BLADERF_FOUND)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -24,6 +24,10 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "srslte/config.h" #include "srslte/config.h"
#include "srslte/phy/common/phy_common.h" #include "srslte/phy/common/phy_common.h"
#include "srslte/phy/rf/rf.h" #include "srslte/phy/rf/rf.h"
@ -32,6 +36,7 @@
#define DEVNAME_X300 "uhd_x300" #define DEVNAME_X300 "uhd_x300"
#define DEVNAME_N300 "uhd_n300" #define DEVNAME_N300 "uhd_n300"
#define DEVNAME_E3X0 "uhd_e3x0" #define DEVNAME_E3X0 "uhd_e3x0"
#define DEVNAME_UNKNOWN "uhd_unknown"
SRSLTE_API int rf_uhd_open(char* args, void** handler); SRSLTE_API int rf_uhd_open(char* args, void** handler);
@ -43,8 +48,6 @@ SRSLTE_API int rf_uhd_close(void* h);
SRSLTE_API int rf_uhd_start_rx_stream(void* h, bool now); SRSLTE_API int rf_uhd_start_rx_stream(void* h, bool now);
SRSLTE_API int rf_uhd_start_rx_stream_nsamples(void* h, uint32_t nsamples);
SRSLTE_API int rf_uhd_stop_rx_stream(void* h); SRSLTE_API int rf_uhd_stop_rx_stream(void* h);
SRSLTE_API void rf_uhd_flush_buffer(void* h); SRSLTE_API void rf_uhd_flush_buffer(void* h);
@ -105,4 +108,8 @@ SRSLTE_API int rf_uhd_send_timed_multi(void* h,
bool is_start_of_burst, bool is_start_of_burst,
bool is_end_of_burst); bool is_end_of_burst);
#ifdef __cplusplus
}
#endif
#endif /* SRSLTE_RF_UHD_IMP_H_ */ #endif /* SRSLTE_RF_UHD_IMP_H_ */

@ -0,0 +1,235 @@
/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSLTE_RF_UHD_SAFE_H
#define SRSLTE_RF_UHD_SAFE_H
#ifdef ENABLE_UHD_X300_FW_RESET
#include <uhd/transport/udp_simple.hpp>
uhd::wb_iface::sptr x300_make_ctrl_iface_enet(uhd::transport::udp_simple::sptr udp, bool enable_errors);
#endif /* ENABLE_UHD_X300_FW_RESET */
class rf_uhd_safe
{
private:
// List of errors that can happen in the USRP make that need to restart the device
const std::set<uhd_error> USRP_MAKE_RESET_ERR = {UHD_ERROR_IO};
// UHD pointers
uhd::usrp::multi_usrp::sptr usrp = nullptr;
uhd::rx_streamer::sptr rx_stream = nullptr;
uhd::tx_streamer::sptr tx_stream = nullptr;
uhd_error usrp_make_internal(const uhd::device_addr_t& dev_addr)
{
// Destroy any previous USRP instance
usrp.reset();
UHD_SAFE_C_SAVE_ERROR(this, usrp = uhd::usrp::multi_usrp::make(dev_addr);)
}
#ifdef ENABLE_UHD_X300_FW_RESET
uhd_error try_usrp_x300_reset(const uhd::device_addr_t& dev_addr)
{
UHD_SAFE_C_SAVE_ERROR(
this,
if (not dev_addr.has_key("addr")) { return UHD_ERROR_NONE; }
printf("Reseting X300 in address %s\n", dev_addr["addr"].c_str());
{ // Reset Scope
// Create UDP connection
uhd::transport::udp_simple::sptr udp_simple =
uhd::transport::udp_simple::make_connected(dev_addr["addr"], "49152");
// Create X300 control
uhd::wb_iface::sptr x300_ctrl = x300_make_ctrl_iface_enet(udp_simple, true);
// Reset FPGA firmware
x300_ctrl->poke32(0x100058, 1);
printf("Reset Done!\n");
}
return UHD_ERROR_NONE;)
}
#endif /* ENABLE_UHD_X300_FW_RESET */
public:
std::string last_error;
inline uhd_error usrp_make(const uhd::device_addr_t& dev_addr)
{
uhd_error err = usrp_make_internal(dev_addr);
#ifdef ENABLE_UHD_X300_FW_RESET
// Looks up error in reset table
if (USRP_MAKE_RESET_ERR.count(err) == 0 or not dev_addr.has_key("addr")) {
// If no error in table or not specified type, returns
return err;
}
// Reset device
err = try_usrp_x300_reset(dev_addr);
if (err != UHD_ERROR_NONE) {
return err;
}
// Try opening the device one more time
return usrp_make_internal(dev_addr);
#else /* ENABLE_UHD_X300_FW_RESET */
return err;
#endif /* ENABLE_UHD_X300_FW_RESET */
}
inline uhd_error set_tx_subdev(const std::string& string)
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_tx_subdev_spec(string);)
}
inline uhd_error set_rx_subdev(const std::string& string)
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_rx_subdev_spec(string);)
}
inline uhd_error get_mboard_name(std::string& mboard_name)
{
UHD_SAFE_C_SAVE_ERROR(this, mboard_name = usrp->get_mboard_name();)
}
inline uhd_error get_mboard_sensor_names(std::vector<std::string>& sensors)
{
UHD_SAFE_C_SAVE_ERROR(this, sensors = usrp->get_mboard_sensor_names();)
}
inline uhd_error get_rx_sensor_names(std::vector<std::string>& sensors)
{
UHD_SAFE_C_SAVE_ERROR(this, sensors = usrp->get_rx_sensor_names();)
}
inline uhd_error get_sensor(const std::string& sensor_name, uhd::sensor_value_t& sensor_value)
{
UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_mboard_sensor(sensor_name);)
}
inline uhd_error get_rx_sensor(const std::string& sensor_name, uhd::sensor_value_t& sensor_value)
{
UHD_SAFE_C_SAVE_ERROR(this, sensor_value = usrp->get_rx_sensor(sensor_name);)
}
inline uhd_error set_time_unknown_pps(const uhd::time_spec_t& timespec)
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_time_unknown_pps(timespec);)
}
inline uhd_error set_time_now(const uhd::time_spec_t& timespec)
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_time_now(timespec);)
}
inline uhd_error get_time_now(uhd::time_spec_t& timespec)
{
UHD_SAFE_C_SAVE_ERROR(this, timespec = usrp->get_time_now();)
}
inline uhd_error start_rx_stream(double delay)
{
UHD_SAFE_C_SAVE_ERROR(this, uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
stream_cmd.time_spec = usrp->get_time_now();
stream_cmd.time_spec += 0.1;
stream_cmd.stream_now = false;
rx_stream->issue_stream_cmd(stream_cmd);)
}
inline uhd_error stop_rx_stream()
{
UHD_SAFE_C_SAVE_ERROR(this, uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
rx_stream->issue_stream_cmd(stream_cmd);)
}
inline uhd_error set_sync_source(const std::string& source)
{
#if UHD_VERSION < 3140099
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_clock_source(source); usrp->set_time_source(source);)
#else
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_sync_source(source, source);)
#endif
}
inline uhd_error get_gain_range(uhd::gain_range_t& tx_gain_range, uhd::gain_range_t& rx_gain_range)
{
UHD_SAFE_C_SAVE_ERROR(this, tx_gain_range = usrp->get_tx_gain_range(); rx_gain_range = usrp->get_rx_gain_range();)
}
inline uhd_error set_master_clock_rate(double rate)
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_master_clock_rate(rate);)
}
inline uhd_error set_rx_rate(double rate) { UHD_SAFE_C_SAVE_ERROR(this, usrp->set_rx_rate(rate);) }
inline uhd_error set_tx_rate(double rate) { UHD_SAFE_C_SAVE_ERROR(this, usrp->set_tx_rate(rate);) }
inline uhd_error set_command_time(const uhd::time_spec_t& timespec)
{
UHD_SAFE_C_SAVE_ERROR(this, usrp->set_command_time(timespec);)
}
inline uhd_error destroy_rx_stream() { UHD_SAFE_C_SAVE_ERROR(this, rx_stream = nullptr;) }
inline uhd_error get_rx_stream(const uhd::stream_args_t& args, size_t& max_num_samps)
{
UHD_SAFE_C_SAVE_ERROR(this, rx_stream = nullptr; rx_stream = usrp->get_rx_stream(args);
max_num_samps = rx_stream->get_max_num_samps();)
}
inline uhd_error destroy_tx_stream() { UHD_SAFE_C_SAVE_ERROR(this, rx_stream = nullptr;) }
inline uhd_error get_tx_stream(const uhd::stream_args_t& args, size_t& max_num_samps)
{
UHD_SAFE_C_SAVE_ERROR(this, tx_stream = nullptr; tx_stream = usrp->get_tx_stream(args);
max_num_samps = tx_stream->get_max_num_samps();)
}
inline uhd_error set_tx_gain(size_t ch, double gain) { UHD_SAFE_C_SAVE_ERROR(this, usrp->set_tx_gain(gain, ch);) }
inline uhd_error set_rx_gain(size_t ch, double gain) { UHD_SAFE_C_SAVE_ERROR(this, usrp->set_rx_gain(gain, ch);) }
inline uhd_error get_rx_gain(double& gain) { UHD_SAFE_C_SAVE_ERROR(this, gain = usrp->get_rx_gain();) }
inline uhd_error get_tx_gain(double& gain) { UHD_SAFE_C_SAVE_ERROR(this, gain = usrp->get_tx_gain();) }
inline uhd_error set_tx_freq(uint32_t ch, double target_freq, double& actual_freq)
{
UHD_SAFE_C_SAVE_ERROR(this, uhd::tune_request_t tune_request(target_freq);
uhd::tune_result_t tune_result = usrp->set_tx_freq(tune_request, ch);
actual_freq = tune_result.target_rf_freq;)
}
inline uhd_error set_rx_freq(uint32_t ch, double target_freq, double& actual_freq)
{
UHD_SAFE_C_SAVE_ERROR(this, uhd::tune_request_t tune_request(target_freq);
uhd::tune_result_t tune_result = usrp->set_rx_freq(tune_request, ch);
actual_freq = tune_result.target_rf_freq;)
}
inline uhd_error receive(void** buffs,
const size_t nsamps_per_buff,
uhd::rx_metadata_t& metadata,
const double timeout,
const bool one_packet,
size_t& nof_rxd_samples)
{
UHD_SAFE_C_SAVE_ERROR(this, uhd::rx_streamer::buffs_type buffs_cpp(buffs, rx_stream->get_num_channels());
nof_rxd_samples = rx_stream->recv(buffs_cpp, nsamps_per_buff, metadata, timeout, one_packet);)
}
inline uhd_error recv_async_msg(uhd::async_metadata_t& async_metadata, double timeout, bool& valid)
{
UHD_SAFE_C_SAVE_ERROR(this, valid = tx_stream->recv_async_msg(async_metadata, timeout); if (valid) {
return UHD_ERROR_NONE;
} valid = usrp.get()->get_device()->recv_async_msg(async_metadata);)
}
inline uhd_error send(void** buffs,
const size_t nsamps_per_buff,
const uhd::tx_metadata_t& metadata,
const double timeout,
size_t& nof_txd_samples)
{
UHD_SAFE_C_SAVE_ERROR(this, uhd::tx_streamer::buffs_type buffs_cpp(buffs, tx_stream->get_num_channels());
nof_txd_samples = tx_stream->send(buffs_cpp, nsamps_per_buff, metadata, timeout);)
}
inline bool is_rx_ready() { return rx_stream != nullptr; }
inline bool is_tx_ready() { return tx_stream != nullptr; }
};
#endif // SRSLTE_RF_UHD_SAFE_H

@ -1,75 +0,0 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/* This file implements a few features not currently provided by the UHD C-API */
#include <uhd.h>
#include <uhd/usrp/multi_usrp.hpp>
extern "C" {
#include "srslte/phy/rf/rf.h"
#include "uhd_c_api.h"
}
#if UHD_VERSION < 31100
static void (*handler)(const char*);
void translate_handler(uhd::msg::type_t type, const std::string & msg)
{
if(handler)
handler(msg.c_str());
}
#endif
void rf_uhd_register_msg_handler_c(void (*new_handler)(const char*))
{
#if UHD_VERSION < 31100
handler = new_handler;
uhd::msg::register_handler(translate_handler);
#endif
}
void uhd_tx_metadata_set_time_spec(uhd_tx_metadata_handle *md, time_t secs, double frac_secs)
{
(*md)->tx_metadata_cpp.time_spec = uhd::time_spec_t(secs, frac_secs);
(*md)->tx_metadata_cpp.has_time_spec = true;
}
void uhd_tx_metadata_set_start(uhd_tx_metadata_handle *md, bool is_start_of_burst)
{
(*md)->tx_metadata_cpp.start_of_burst = is_start_of_burst;
}
void uhd_tx_metadata_set_has_time_spec(uhd_tx_metadata_handle *md, bool has_time_spec)
{
(*md)->tx_metadata_cpp.has_time_spec = has_time_spec;
}
void uhd_tx_metadata_set_end(uhd_tx_metadata_handle *md, bool is_end_of_burst)
{
(*md)->tx_metadata_cpp.end_of_burst = is_end_of_burst;
}
void uhd_tx_metadata_add_time_spec(uhd_tx_metadata_handle *md, double frac_secs)
{
(*md)->tx_metadata_cpp.time_spec += frac_secs;
}

@ -1,36 +0,0 @@
/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSLTE_UHD_C_API_C_
#define SRSLTE_UHD_C_API_C_
#include "srslte/config.h"
#include "srslte/phy/rf/rf.h"
#include <uhd.h>
/* Declare functions not currently provided by the C-API */
SRSLTE_API void rf_uhd_register_msg_handler_c(void (*new_handler)(const char*));
SRSLTE_API void uhd_tx_metadata_set_time_spec(uhd_tx_metadata_handle* md, time_t secs, double frac_secs);
SRSLTE_API void uhd_tx_metadata_set_start(uhd_tx_metadata_handle* md, bool is_start_of_burst);
SRSLTE_API void uhd_tx_metadata_set_has_time_spec(uhd_tx_metadata_handle* md, bool has_time_spec);
SRSLTE_API void uhd_tx_metadata_set_end(uhd_tx_metadata_handle* md, bool is_end_of_burst);
SRSLTE_API void uhd_tx_metadata_add_time_spec(uhd_tx_metadata_handle* md, double frac_secs);
#endif /* SRSLTE_UHD_C_API_C_ */

@ -339,6 +339,7 @@ bool radio::tx(rf_buffer_interface& buffer, const uint32_t& nof_samples_, const
return false; return false;
} }
log_h->debug("radio_tx: time=%ld:%f, is_start=%d\n", tx_time.full_secs, tx_time.frac_secs, is_start_of_burst);
int ret = srslte_rf_send_timed_multi( int ret = srslte_rf_send_timed_multi(
&rf_device, radio_buffers, nof_samples, tx_time.full_secs, tx_time.frac_secs, true, is_start_of_burst, false); &rf_device, radio_buffers, nof_samples, tx_time.full_secs, tx_time.frac_secs, true, is_start_of_burst, false);
is_start_of_burst = false; is_start_of_burst = false;
@ -351,6 +352,7 @@ void radio::tx_end()
return; return;
} }
if (!is_start_of_burst) { if (!is_start_of_burst) {
log_h->debug("radio_tx_end: time=%ld:%f\n", end_of_burst_time.full_secs, end_of_burst_time.frac_secs);
srslte_rf_send_timed2(&rf_device, zeros, 0, end_of_burst_time.full_secs, end_of_burst_time.frac_secs, false, true); srslte_rf_send_timed2(&rf_device, zeros, 0, end_of_burst_time.full_secs, end_of_burst_time.frac_secs, false, true);
is_start_of_burst = true; is_start_of_burst = true;
} }
@ -424,6 +426,7 @@ void radio::set_rx_srate(const double& srate)
if (!is_initialized) { if (!is_initialized) {
return; return;
} }
log_h->debug("Setting RX sample rate=%f\n", srate);
srslte_rf_set_rx_srate(&rf_device, srate); srslte_rf_set_rx_srate(&rf_device, srate);
} }
@ -489,6 +492,7 @@ void radio::set_tx_srate(const double& srate)
if (!is_initialized) { if (!is_initialized) {
return; return;
} }
log_h->debug("Setting TX sample rate=%f\n", srate);
cur_tx_srate = srslte_rf_set_tx_srate(&rf_device, srate); cur_tx_srate = srslte_rf_set_tx_srate(&rf_device, srate);
int nsamples = 0; int nsamples = 0;

@ -483,7 +483,14 @@ void sync::run_camping_state()
break; break;
case 0: case 0:
Warning("SYNC: Out-of-sync detected in PSS/SSS\n"); Warning("SYNC: Out-of-sync detected in PSS/SSS\n");
// End transmission burst, avoid Tx Underflow
radio_h->tx_end();
// Inform about the out-of-synch to upper layer
out_of_sync(); out_of_sync();
// Releases assigned worker
worker->release(); worker->release();
// Force decoding MIB, for making sure that the TTI will be right // Force decoding MIB, for making sure that the TTI will be right
@ -784,7 +791,6 @@ void sync::set_sampling_rate()
srate_mode = SRATE_CAMP; srate_mode = SRATE_CAMP;
radio_h->set_rx_srate(current_srate); radio_h->set_rx_srate(current_srate);
radio_h->set_tx_srate(current_srate);
} else { } else {
Error("Error setting sampling rate for cell with %d PRBs\n", cell.nof_prb); Error("Error setting sampling rate for cell with %d PRBs\n", cell.nof_prb);
} }

Loading…
Cancel
Save