25 Commits

Author SHA1 Message Date
Kirill Zakharenko
20ab77fe91 release 1.0.19 2020-05-26 07:55:28 +03:00
Kirill Zakharenko
e597866c9d python: install umtrx property tree lib for python 3 as well 2020-05-26 05:51:02 +03:00
Clément BRUGUERA
9f0bf718e2 Fix compilation error against libboost 1.67 2019-11-01 00:23:23 +03:00
Alexander Chemeris
9797c410e3 Do not rely on N200 EEPROM code.
New UHD versions removed device-specific code from public headers, so
we've copied relevant code into our own codebase.

Also renamed N100 to N200 to follow the main UHD codebase naming.
2019-10-31 19:22:50 +03:00
Alexander Chemeris
c87ac1ba32 Detect uhd/utils/thread_priority.hpp deprecation 2019-10-31 19:22:50 +03:00
Alexander Chemeris
48ad4cd890 Don't include uhd/utils/atomic.hpp - we disabled threading here long time ago 2019-10-31 19:22:50 +03:00
Alexander Chemeris
828c811f79 Fix uhd/utils/msg.hpp missing in newer UHD 2019-10-31 19:22:50 +03:00
Kirill Zakharenko
6c9567c46f bump version to 1.0.18 2019-07-15 18:03:30 +03:00
Kirill Zakharenko
2fa07d28d6 umtrx_monitor: bind to localhost instead of 0.0.0.0 2019-07-15 18:03:13 +03:00
Kirill Zakharenko
e4dff6e07c bumped version to 1.0.17 2019-07-08 21:48:01 +03:00
Kirill Zakharenko
fab18d97a2 umtrx_auto_calibration: save result files to /var/lib/umtrx by default 2019-07-05 15:13:26 +03:00
Kirill Zakharenko
c9304575bf bumped version to 1.0.16 2019-07-03 21:17:31 +03:00
Kirill Zakharenko
61ac2ee278 umtrx_cal_*: fix for abrupt termination
tx_thread creates a child thread, which it join()s on, when terminating
calling interrupt() on tx_thread interferes with the join()
so we replace interrupt() with an atomic flag

(not sure how this worked before)
2019-07-03 21:17:31 +03:00
Kirill Zakharenko
7199b8667f boost: use minimally required build Boost dependencies
speeds up clean builds
2019-07-03 21:17:31 +03:00
Kirill Zakharenko
91185de06a util: install python utils directly into /usr/bin 2019-07-03 21:17:30 +03:00
Kirill Zakharenko
99d1b8adf3 utils: move umtrx python libraries to PYTHONPATH 2019-07-03 21:17:30 +03:00
Kirill Zakharenko
b81240db26 utils: remove collectd integration, it belongs in another package 2019-07-03 21:17:30 +03:00
Kirill Zakharenko
0d0f0c710c debian: Update deb deps to bionic 2019-07-03 21:17:30 +03:00
sergforce
f528fa442f Merge pull request #23 from pespin/pespin/fix-build
umtrx_monitor.cpp: Fix compilation against newer boost
2018-04-22 18:41:38 +03:00
Pau Espin Pedrol
132f8995ec umtrx_monitor.cpp: Fix compilation against newer boost
Related: github issue #22
2018-04-21 15:23:42 +02:00
satunnainen
93d4343d85 bump version to 1.0.15 2017-08-15 03:04:15 +03:00
Alexander Chemeris
1421327cfe host: Python 2 compatibility for umtrx_property_tree.py
bytes(u'something', 'utf-8') is only available in Python 3. A backwards
compatible version of it is u'something'.encode('utf-8').
2017-08-14 23:46:06 +03:00
Alexander Chemeris
1e0c879f53 utils: s/USRP/UmTRX/g in console output of umtrx_net_burner.py 2017-08-08 21:34:51 +03:00
satunnainen
479d6e9cf6 bump version to 1.0.14 2017-08-07 10:35:28 +03:00
Alexander Chemeris
4bba18b1cf host: Fix build. 2017-08-04 18:44:55 +03:00
38 changed files with 338 additions and 171 deletions

42
debian/changelog vendored
View File

@@ -1,3 +1,45 @@
umtrx (1.0.19) bionic; urgency=medium
* library now supports python3
* updated for latest UHD/libboost
-- Kirill Zakharenko <kirill.zakharenko@fairwaves.co> Tue, 26 May 2020 07:48:32 +0300
umtrx (1.0.18) bionic; urgency=medium
* umtrx status monitor now binds to localhost instead of 0.0.0.0
-- Kirill Zakharenko <earwin@gmail.com> Fri, 12 Jul 2019 13:39:48 +0300
umtrx (1.0.17) bionic; urgency=medium
* umtrx_auto_calibration: save result files to /var/lib/umtrx by default
-- Kirill Zakharenko <earwin@gmail.com> Wed, 20 Jun 2019 13:39:48 +0300
umtrx (1.0.16) bionic; urgency=medium
* first bionic build
* python libraries are now in PYTHONPATH and reusable
* minimized Boost build deps for faster builds
* dropped collectd integration
* fixed abrupt termination of umtrx_cal_*
-- Kirill Zakharenko <earwin@gmail.com> Wed, 19 Jun 2019 13:39:48 +0300
umtrx (1.0.15) trusty; urgency=medium
* host: Python 2 compatibility for umtrx_property_tree.py
* utils: s/USRP/UmTRX/g in console output of umtrx_net_burner.py
-- Rauf Gyulaliev <rauf.gyulaliev@fairwaves.co> Tue, 15 Aug 2017 03:03:23 +0300
umtrx (1.0.14) trusty; urgency=medium
* Quick build fix.
-- Rauf Gyulaliev <rauf.gyulaliev@fairwaves.co> Mon, 07 Aug 2017 09:15:31 +0300
umtrx (1.0.13) trusty; urgency=low
* [ZPU/host] Read TCXO DAC calibration from EEPROM once on UmTRX boot instead

2
debian/compat vendored
View File

@@ -1 +1 @@
9
11

8
debian/control vendored
View File

@@ -3,9 +3,13 @@ Section: libs
Priority: optional
Maintainer: Josh Blum <josh@pothosware.com>
Build-Depends:
debhelper (>= 9.0.0),
debhelper (>= 11.0.0),
cmake (>= 2.8),
libboost-all-dev,
libboost-date-time-dev,
libboost-filesystem-dev,
libboost-system-dev,
libboost-thread-dev,
libboost-program-options-dev,
libuhd-dev (>= 3.7)
Standards-Version: 3.9.5
Homepage: http://umtrx.org/

View File

@@ -1,8 +1,4 @@
usr/bin
images/u2plus_umtrx_v2.bin images/umtrx_txrx_uhd.bin usr/share/umtrx/firmware
host/utils/umtrx_property_tree.py host/utils/umtrx_vswr.py usr/share/umtrx
host/utils/umtrx_query_sensors.py host/utils/umtrx_query_versions.py host/utils/umtrx_net_burner.py usr/share/umtrx
host/utils/collectd/umtrx.types.db usr/share/collectd
host/utils/collectd/umtrx2collectd.py usr/share/umtrx
host/utils/collectd/umtrx.conf etc/collectd/collectd.conf.d
host/utils/umtrx_property_tree.py host/utils/umtrx_vswr.py usr/lib/python2.7/dist-packages
host/utils/umtrx_property_tree.py host/utils/umtrx_vswr.py usr/lib/python3/dist-packages

3
debian/umtrx.links vendored
View File

@@ -1,3 +0,0 @@
/usr/share/umtrx/umtrx_net_burner.py /usr/bin/umtrx_net_burner
/usr/share/umtrx/umtrx_query_sensors.py /usr/bin/umtrx_query_sensors
/usr/share/umtrx/umtrx_query_versions.py /usr/bin/umtrx_query_versions

View File

@@ -77,6 +77,20 @@ list(APPEND UMTRX_LIBRARIES ${UHD_LIBRARIES})
MESSAGE(STATUS "UHD include directories: ${UHD_INCLUDE_DIRS}")
MESSAGE(STATUS "UHD libraries: ${UHD_LIBRARIES}")
if (EXISTS "${UHD_INCLUDE_DIRS}/uhd/utils/msg.hpp")
add_definitions(-DUHD_HAS_MSG_HPP)
message(STATUS " use msg.hpp for logging")
else()
message(STATUS " use log.hpp for logging")
endif()
if (EXISTS "${UHD_INCLUDE_DIRS}/uhd/utils/thread.hpp")
add_definitions(-DTHREAD_PRIORITY_HPP_DEPRECATED)
message(STATUS " use thread.hpp (new interface)")
else()
message(STATUS " use thread_priority.hpp (old interface)")
endif()
########################################################################
# Setup Boost
########################################################################

View File

@@ -18,7 +18,7 @@
#include "apply_corrections.hpp"
#include <uhd/usrp/dboard_eeprom.hpp>
#include <uhd/utils/paths.hpp>
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/utils/csv.hpp>
#include <uhd/types/dict.hpp>
#include <boost/filesystem.hpp>

View File

@@ -22,7 +22,7 @@
#include <uhd/transport/vrt_if_packet.hpp>
#include <uhd/types/metadata.hpp>
#include <uhd/utils/byteswap.hpp>
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
namespace uhd{ namespace usrp{
@@ -55,14 +55,14 @@ namespace uhd{ namespace usrp{
if (metadata.event_code &
( async_metadata_t::EVENT_CODE_UNDERFLOW
| async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET)
) UHD_MSG(fastpath) << "U";
) {UHD_LOG_FASTPATH("U");}
else if (metadata.event_code &
( async_metadata_t::EVENT_CODE_SEQ_ERROR
| async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST)
) UHD_MSG(fastpath) << "S";
) {UHD_LOG_FASTPATH("S");}
else if (metadata.event_code &
async_metadata_t::EVENT_CODE_TIME_ERROR
) UHD_MSG(fastpath) << "L";
) {UHD_LOG_FASTPATH("L");}
}

View File

@@ -18,7 +18,7 @@
#include "rx_dsp_core_200.hpp"
#include <uhd/types/dict.hpp>
#include <uhd/exception.hpp>
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/utils/safe_call.hpp>
#include <uhd/utils/algorithm.hpp>
#include <boost/assign/list_of.hpp>

View File

@@ -22,9 +22,8 @@
#include <uhd/exception.hpp>
#include <uhd/convert.hpp>
#include <uhd/stream.hpp>
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/utils/tasks.hpp>
#include <uhd/utils/atomic.hpp>
#include <uhd/utils/byteswap.hpp>
#include <uhd/types/metadata.hpp>
#include <uhd/transport/vrt_if_packet.hpp>
@@ -92,22 +91,14 @@ public:
}
~recv_packet_handler(void){
_task_barrier.interrupt();
_task_handlers.clear();
}
//! Resize the number of transport channels
void resize(const size_t size){
if (this->size() == size) return;
_task_handlers.clear();
_props.resize(size);
//re-initialize all buffers infos by re-creating the vector
_buffers_infos = std::vector<buffers_info_type>(4, buffers_info_type(size));
_task_barrier.resize(size);
_task_handlers.resize(size);
for (size_t i = 1/*skip 0*/; i < size; i++){
//_task_handlers[i] = task::make(boost::bind(&recv_packet_handler::converter_thread_task, this, i));
};
}
//! Get the channel width of this handler
@@ -559,7 +550,7 @@ private:
rx_metadata_t metadata = curr_info.metadata;
_props[index].handle_overflow();
curr_info.metadata = metadata;
UHD_MSG(fastpath) << "O";
UHD_LOG_FASTPATH("O");
}
return;
@@ -576,7 +567,7 @@ private:
prev_info[index].ifpi.num_payload_words32*sizeof(boost::uint32_t)/_bytes_per_otw_item, _samp_rate);
curr_info.metadata.out_of_sequence = true;
curr_info.metadata.error_code = rx_metadata_t::ERROR_CODE_OVERFLOW;
UHD_MSG(fastpath) << "D";
UHD_LOG_FASTPATH("D");
return;
}
@@ -666,8 +657,6 @@ private:
******************************************************************/
UHD_INLINE void converter_thread_task(const size_t index)
{
//_task_barrier.wait();
//shortcut references to local data structures
buffers_info_type &buff_info = get_curr_buffer_info();
per_buffer_info_type &info = buff_info[index];
@@ -691,13 +680,9 @@ private:
if (buff_info.data_bytes_to_copy == _convert_bytes_to_copy){
info.buff.reset(); //effectively a release
}
//if (index == 0) _task_barrier.wait_others();
}
//! Shared variables for the worker threads
reusable_barrier _task_barrier;
std::vector<task::sptr> _task_handlers;
size_t _convert_nsamps;
const rx_streamer::buffs_type *_convert_buffs;
size_t _convert_buffer_offset_bytes;

View File

@@ -22,9 +22,8 @@
#include <uhd/exception.hpp>
#include <uhd/convert.hpp>
#include <uhd/stream.hpp>
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/utils/tasks.hpp>
#include <uhd/utils/atomic.hpp>
#include <uhd/utils/byteswap.hpp>
#include <uhd/types/metadata.hpp>
#include <uhd/transport/vrt_if_packet.hpp>
@@ -74,22 +73,14 @@ public:
}
~send_packet_handler(void){
_task_barrier.interrupt();
_task_handlers.clear();
}
//! Resize the number of transport channels
void resize(const size_t size){
if (this->size() == size) return;
_task_handlers.clear();
_props.resize(size);
static const boost::uint64_t zero = 0;
_zero_buffs.resize(size, &zero);
_task_barrier.resize(size);
_task_handlers.resize(size);
for (size_t i = 1/*skip 0*/; i < size; i++){
//_task_handlers[i] = task::make(boost::bind(&send_packet_handler::converter_thread_task, this, i));
};
}
//! Get the channel width of this handler
@@ -390,8 +381,6 @@ private:
******************************************************************/
UHD_INLINE void converter_thread_task(const size_t index)
{
//_task_barrier.wait();
//shortcut references to local data structures
managed_send_buffer::sptr &buff = _props[index].buff;
vrt::if_packet_info_t if_packet_info = *_convert_if_packet_info;
@@ -419,13 +408,9 @@ private:
const size_t num_vita_words32 = _header_offset_words32+if_packet_info.num_packet_words32;
buff->commit(num_vita_words32*sizeof(boost::uint32_t));
buff.reset(); //effectively a release
//if (index == 0) _task_barrier.wait_others();
}
//! Shared variables for the worker threads
reusable_barrier _task_barrier;
std::vector<task::sptr> _task_handlers;
size_t _convert_nsamps;
const tx_streamer::buffs_type *_convert_buffs;
size_t _convert_buffer_offset_bytes;

View File

@@ -18,7 +18,7 @@
#include "tx_dsp_core_200.hpp"
#include <uhd/types/dict.hpp>
#include <uhd/exception.hpp>
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/utils/algorithm.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/math/special_functions/round.hpp>

View File

@@ -118,7 +118,7 @@ double lms6002d_dev::txrx_pll_tune(uint8_t reg, double ref_clock, double out_fre
for (int i = 0; i < 64; i++) {
// Update VCOCAP
lms_write_bits(reg + 0x9, 0x3f, i);
usleep(50);
usleep(long(50));
int comp = read_reg(reg + 0x0a);
switch (comp >> 6) {
@@ -360,7 +360,7 @@ int lms6002d_dev::general_dc_calibration_loop(uint8_t dc_addr, uint8_t calibrati
if (verbosity > 1) printf("cnt=%d\n", try_cnt_limit);
// Wait for 6.4(1.6) us
usleep(6.4);
usleep(long(6.4));
// Read DC_CLBR_DONE
reg_val = read_reg(calibration_reg_base+0x01);

View File

@@ -10,7 +10,7 @@
#include <uhd/utils/static.hpp>
#include <uhd/utils/assert_has.hpp>
#include <uhd/utils/algorithm.hpp>
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/types/ranges.hpp>
#include <uhd/types/sensors.hpp>
#include <uhd/types/dict.hpp>

View File

@@ -1,5 +1,5 @@
#include "power_amp.hpp"
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/exception.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>

View File

@@ -17,6 +17,7 @@
#include <uhd/usrp/mboard_eeprom.hpp>
#include <uhd/types/mac_addr.hpp>
#include <uhd/types/byte_vector.hpp>
#include <uhd/utils/byteswap.hpp>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/assign/list_of.hpp>
@@ -29,7 +30,9 @@
using namespace uhd;
using namespace uhd::usrp;
static const boost::uint8_t N100_EEPROM_ADDR = 0x50;
static const boost::uint8_t N200_EEPROM_ADDR = 0x50;
static const size_t SERIAL_LEN = 9;
static const size_t NAME_MAX_LEN = 32 - SERIAL_LEN;
//! convert a string to a byte vector to write to eeprom
static byte_vector_t string_to_uint16_bytes(const std::string &num_str){
@@ -45,6 +48,28 @@ static std::string uint16_bytes_to_string(const byte_vector_t &bytes){
return (num == 0 or num == 0xffff)? "" : boost::lexical_cast<std::string>(num);
}
struct n200_eeprom_map{
uint16_t hardware;
uint8_t mac_addr[6];
uint32_t subnet;
uint32_t ip_addr;
uint16_t _pad0;
uint16_t revision;
uint16_t product;
unsigned char _pad1;
unsigned char gpsdo;
unsigned char serial[SERIAL_LEN];
unsigned char name[NAME_MAX_LEN];
uint32_t gateway;
};
enum n200_gpsdo_type{
N200_GPSDO_NONE = 0,
N200_GPSDO_INTERNAL = 1,
N200_GPSDO_ONBOARD = 2
};
/***********************************************************************
* Implementation of UmTRX load/store - an extension for N100
**********************************************************************/
@@ -66,94 +91,228 @@ static const uhd::dict<std::string, boost::uint8_t> UMTRX_OFFSETS = boost::assig
#endif
void load_umtrx_eeprom(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
//load all the N100 stuf first
mb_eeprom = mboard_eeprom_t(iface, "N100");
//clear the EEPROM dict
mb_eeprom = mboard_eeprom_t();
///////////////////////////////////////////////////////
// EEPROM values common between USRP N200 and UmTRX
///////////////////////////////////////////////////////
//extract the hardware number
mb_eeprom["hardware"] = uint16_bytes_to_string(
iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, hardware), 2)
);
//extract the revision number
mb_eeprom["revision"] = uint16_bytes_to_string(
iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, revision), 2)
);
//extract the product code
mb_eeprom["product"] = uint16_bytes_to_string(
iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, product), 2)
);
//extract the addresses
mb_eeprom["mac-addr"] = mac_addr_t::from_bytes(iface.read_eeprom(
N200_EEPROM_ADDR, offsetof(n200_eeprom_map, mac_addr), 6
)).to_string();
boost::asio::ip::address_v4::bytes_type ip_addr_bytes;
byte_copy(iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, ip_addr), 4), ip_addr_bytes);
mb_eeprom["ip-addr"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
byte_copy(iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, subnet), 4), ip_addr_bytes);
mb_eeprom["subnet"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
byte_copy(iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gateway), 4), ip_addr_bytes);
mb_eeprom["gateway"] = boost::asio::ip::address_v4(ip_addr_bytes).to_string();
//gpsdo capabilities
uint8_t gpsdo_byte = iface.read_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gpsdo), 1).at(0);
switch(n200_gpsdo_type(gpsdo_byte)){
case N200_GPSDO_INTERNAL: mb_eeprom["gpsdo"] = "internal"; break;
case N200_GPSDO_ONBOARD: mb_eeprom["gpsdo"] = "onboard"; break;
default: mb_eeprom["gpsdo"] = "none";
}
//extract the serial
mb_eeprom["serial"] = bytes_to_string(iface.read_eeprom(
N200_EEPROM_ADDR, offsetof(n200_eeprom_map, serial), SERIAL_LEN
));
//extract the name
mb_eeprom["name"] = bytes_to_string(iface.read_eeprom(
N200_EEPROM_ADDR, offsetof(n200_eeprom_map, name), NAME_MAX_LEN
));
//Empty serial correction: use the mac address to determine serial.
//Older usrp2 models don't have a serial burned into EEPROM.
//The lower mac address bits will function as the serial number.
if (mb_eeprom["serial"].empty()){
byte_vector_t mac_addr_bytes = mac_addr_t::from_string(mb_eeprom["mac-addr"]).to_bytes();
unsigned serial = mac_addr_bytes.at(5) | (unsigned(mac_addr_bytes.at(4) & 0x0f) << 8);
mb_eeprom["serial"] = std::to_string(serial);
}
/////////////////////////////////////////////
// UmTRX specific EEPROM values
/////////////////////////////////////////////
//extract the Tx VGA1 DC I/Q offset values
{
uint8_t val = int(iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["tx1-vga1-dc-i"], 1).at(0));
uint8_t val = int(iface.read_eeprom(N200_EEPROM_ADDR, UMTRX_OFFSETS["tx1-vga1-dc-i"], 1).at(0));
mb_eeprom["tx1-vga1-dc-i"] = (val==255)?"":boost::lexical_cast<std::string>(int(val));
}
{
uint8_t val = int(iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["tx1-vga1-dc-q"], 1).at(0));
uint8_t val = int(iface.read_eeprom(N200_EEPROM_ADDR, UMTRX_OFFSETS["tx1-vga1-dc-q"], 1).at(0));
mb_eeprom["tx1-vga1-dc-q"] = (val==255)?"":boost::lexical_cast<std::string>(int(val));
}
{
uint8_t val = int(iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["tx2-vga1-dc-i"], 1).at(0));
uint8_t val = int(iface.read_eeprom(N200_EEPROM_ADDR, UMTRX_OFFSETS["tx2-vga1-dc-i"], 1).at(0));
mb_eeprom["tx2-vga1-dc-i"] = (val==255)?"":boost::lexical_cast<std::string>(int(val));
}
{
uint8_t val = int(iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["tx2-vga1-dc-q"], 1).at(0));
uint8_t val = int(iface.read_eeprom(N200_EEPROM_ADDR, UMTRX_OFFSETS["tx2-vga1-dc-q"], 1).at(0));
mb_eeprom["tx2-vga1-dc-q"] = (val==255)?"":boost::lexical_cast<std::string>(int(val));
}
//extract the TCXO DAC calibration value
mb_eeprom["tcxo-dac"] = uint16_bytes_to_string(
iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["tcxo-dac"], 2)
iface.read_eeprom(N200_EEPROM_ADDR, UMTRX_OFFSETS["tcxo-dac"], 2)
);
mb_eeprom["pa_dcdc_r"] =
boost::lexical_cast<std::string>(unsigned(iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_dcdc_r"], 1).at(0)));
boost::lexical_cast<std::string>(unsigned(iface.read_eeprom(N200_EEPROM_ADDR, UMTRX_OFFSETS["pa_dcdc_r"], 1).at(0)));
{
uint8_t val = int(iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_low"], 1).at(0));
uint8_t val = int(iface.read_eeprom(N200_EEPROM_ADDR, UMTRX_OFFSETS["pa_low"], 1).at(0));
mb_eeprom["pa_low"] = (val==255)?"":boost::lexical_cast<std::string>(int(val));
}
{
uint8_t val = int(iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_en1"], 1).at(0));
uint8_t val = int(iface.read_eeprom(N200_EEPROM_ADDR, UMTRX_OFFSETS["pa_en1"], 1).at(0));
mb_eeprom["pa_en1"] = (val != 0) ?"1":"0";
}
{
uint8_t val = int(iface.read_eeprom(N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_en2"], 1).at(0));
uint8_t val = int(iface.read_eeprom(N200_EEPROM_ADDR, UMTRX_OFFSETS["pa_en2"], 1).at(0));
mb_eeprom["pa_en2"] = (val != 0) ?"1":"0";
}
}
void store_umtrx_eeprom(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface){
mb_eeprom.commit(iface, "N100");
void store_umtrx_eeprom(const mboard_eeprom_t &mb_eeprom, i2c_iface &iface)
{
///////////////////////////////////////////////////////
// EEPROM values common between USRP N200 and UmTRX
///////////////////////////////////////////////////////
//parse the revision number
if (mb_eeprom.has_key("hardware")) iface.write_eeprom(
N200_EEPROM_ADDR, offsetof(n200_eeprom_map, hardware),
string_to_uint16_bytes(mb_eeprom["hardware"])
);
//parse the revision number
if (mb_eeprom.has_key("revision")) iface.write_eeprom(
N200_EEPROM_ADDR, offsetof(n200_eeprom_map, revision),
string_to_uint16_bytes(mb_eeprom["revision"])
);
//parse the product code
if (mb_eeprom.has_key("product")) iface.write_eeprom(
N200_EEPROM_ADDR, offsetof(n200_eeprom_map, product),
string_to_uint16_bytes(mb_eeprom["product"])
);
//store the addresses
if (mb_eeprom.has_key("mac-addr")) iface.write_eeprom(
N200_EEPROM_ADDR, offsetof(n200_eeprom_map, mac_addr),
mac_addr_t::from_string(mb_eeprom["mac-addr"]).to_bytes()
);
if (mb_eeprom.has_key("ip-addr")){
byte_vector_t ip_addr_bytes(4);
byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["ip-addr"]).to_bytes(), ip_addr_bytes);
iface.write_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, ip_addr), ip_addr_bytes);
}
if (mb_eeprom.has_key("subnet")){
byte_vector_t ip_addr_bytes(4);
byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["subnet"]).to_bytes(), ip_addr_bytes);
iface.write_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, subnet), ip_addr_bytes);
}
if (mb_eeprom.has_key("gateway")){
byte_vector_t ip_addr_bytes(4);
byte_copy(boost::asio::ip::address_v4::from_string(mb_eeprom["gateway"]).to_bytes(), ip_addr_bytes);
iface.write_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gateway), ip_addr_bytes);
}
//gpsdo capabilities
if (mb_eeprom.has_key("gpsdo")){
uint8_t gpsdo_byte = N200_GPSDO_NONE;
if (mb_eeprom["gpsdo"] == "internal") gpsdo_byte = N200_GPSDO_INTERNAL;
if (mb_eeprom["gpsdo"] == "onboard") gpsdo_byte = N200_GPSDO_ONBOARD;
iface.write_eeprom(N200_EEPROM_ADDR, offsetof(n200_eeprom_map, gpsdo), byte_vector_t(1, gpsdo_byte));
}
//store the serial
if (mb_eeprom.has_key("serial")) iface.write_eeprom(
N200_EEPROM_ADDR, offsetof(n200_eeprom_map, serial),
string_to_bytes(mb_eeprom["serial"], SERIAL_LEN)
);
//store the name
if (mb_eeprom.has_key("name")) iface.write_eeprom(
N200_EEPROM_ADDR, offsetof(n200_eeprom_map, name),
string_to_bytes(mb_eeprom["name"], NAME_MAX_LEN)
);
/////////////////////////////////////////////
// UmTRX specific EEPROM values
/////////////////////////////////////////////
//store the Tx VGA1 DC I/Q offset values
if (mb_eeprom.has_key("tx1-vga1-dc-i")) iface.write_eeprom(
N100_EEPROM_ADDR, UMTRX_OFFSETS["tx1-vga1-dc-i"],
N200_EEPROM_ADDR, UMTRX_OFFSETS["tx1-vga1-dc-i"],
byte_vector_t(1, boost::lexical_cast<int>(mb_eeprom["tx1-vga1-dc-i"]))
);
if (mb_eeprom.has_key("tx1-vga1-dc-q")) iface.write_eeprom(
N100_EEPROM_ADDR, UMTRX_OFFSETS["tx1-vga1-dc-q"],
N200_EEPROM_ADDR, UMTRX_OFFSETS["tx1-vga1-dc-q"],
byte_vector_t(1, boost::lexical_cast<int>(mb_eeprom["tx1-vga1-dc-q"]))
);
if (mb_eeprom.has_key("tx2-vga1-dc-i")) iface.write_eeprom(
N100_EEPROM_ADDR, UMTRX_OFFSETS["tx2-vga1-dc-i"],
N200_EEPROM_ADDR, UMTRX_OFFSETS["tx2-vga1-dc-i"],
byte_vector_t(1, boost::lexical_cast<int>(mb_eeprom["tx2-vga1-dc-i"]))
);
if (mb_eeprom.has_key("tx2-vga1-dc-q")) iface.write_eeprom(
N100_EEPROM_ADDR, UMTRX_OFFSETS["tx2-vga1-dc-q"],
N200_EEPROM_ADDR, UMTRX_OFFSETS["tx2-vga1-dc-q"],
byte_vector_t(1, boost::lexical_cast<int>(mb_eeprom["tx2-vga1-dc-q"]))
);
//extract the TCXO DAC calibration value
if (mb_eeprom.has_key("tcxo-dac")) iface.write_eeprom(
N100_EEPROM_ADDR, UMTRX_OFFSETS["tcxo-dac"],
N200_EEPROM_ADDR, UMTRX_OFFSETS["tcxo-dac"],
string_to_uint16_bytes(mb_eeprom["tcxo-dac"])
);
if (mb_eeprom.has_key("pa_dcdc_r")) iface.write_eeprom(
N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_dcdc_r"],
N200_EEPROM_ADDR, UMTRX_OFFSETS["pa_dcdc_r"],
byte_vector_t(1, boost::lexical_cast<unsigned>(mb_eeprom["pa_dcdc_r"]))
);
if (mb_eeprom.has_key("pa_low")) iface.write_eeprom(
N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_low"],
N200_EEPROM_ADDR, UMTRX_OFFSETS["pa_low"],
byte_vector_t(1, boost::lexical_cast<int>(mb_eeprom["pa_low"]))
);
if (mb_eeprom.has_key("pa_en1")) iface.write_eeprom(
N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_en1"],
N200_EEPROM_ADDR, UMTRX_OFFSETS["pa_en1"],
byte_vector_t(1, boost::lexical_cast<int>(mb_eeprom["pa_en1"]))
);
if (mb_eeprom.has_key("pa_en2")) iface.write_eeprom(
N100_EEPROM_ADDR, UMTRX_OFFSETS["pa_en2"],
N200_EEPROM_ADDR, UMTRX_OFFSETS["pa_en2"],
byte_vector_t(1, boost::lexical_cast<int>(mb_eeprom["pa_en2"]))
);
}

View File

@@ -17,7 +17,7 @@
#include "umtrx_regs.hpp"
#include <uhd/exception.hpp>
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/utils/safe_call.hpp>
#include <uhd/transport/vrt_if_packet.hpp>
#include "umtrx_fifo_ctrl.hpp"

View File

@@ -17,7 +17,7 @@
#include "usrp2/fw_common.h"
#include "umtrx_iface.hpp"
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/utils/log.hpp>
#include <uhd/utils/byteswap.hpp>
#include <uhd/types/device_addr.hpp>

View File

@@ -20,7 +20,7 @@
#include "umtrx_impl.hpp"
#include "umtrx_iface.hpp"
#include <uhd/exception.hpp>
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include "missing/platform.hpp"
#include <uhd/utils/tasks.hpp>
#include <uhd/utils/safe_call.hpp>

View File

@@ -18,9 +18,9 @@
#include "umtrx_impl.hpp"
#include "umtrx_regs.hpp"
#include "umtrx_version.hpp"
#include "umtrx_log_adapter.hpp"
#include "cores/apply_corrections.hpp"
#include <uhd/utils/log.hpp>
#include <uhd/utils/msg.hpp>
#include <boost/bind.hpp>
#include <boost/thread.hpp> //sleep
#include <boost/assign/list_of.hpp>
@@ -741,7 +741,7 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
}
//TCXO DAC calibration control
if (not tcxo_dac.empty()) _tree->create<uint16_t>(mb_path / "tcxo_dac" / "value")
_tree->create<uint16_t>(mb_path / "tcxo_dac" / "value")
.subscribe(boost::bind(&umtrx_impl::set_tcxo_dac, this, _iface, _1));
////////////////////////////////////////////////////////////////////

View File

@@ -27,7 +27,11 @@
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#ifdef THREAD_PRIORITY_HPP_DEPRECATED
# include <uhd/utils/thread.hpp>
#else // THREAD_PRIORITY_HPP_DEPRECATED
# include <uhd/utils/thread_priority.hpp>
#endif // THREAD_PRIORITY_HPP_DEPRECATED
//A reasonable number of frames for send/recv and async/sync
static const size_t DEFAULT_NUM_FRAMES = 32;

View File

@@ -0,0 +1,24 @@
#ifndef UMTRX_LOG_ADAPTER_HPP
#define UMTRX_LOG_ADAPTER_HPP
#ifdef UHD_HAS_MSG_HPP
#include <uhd/utils/msg.hpp>
#define UHD_LOG_FASTPATH(message) UHD_MSG(fastpath) << (message)
#else // UHD_HAS_MSG_HPP
#include <uhd/utils/log.hpp>
enum {
_uhd_log_level_status,
_uhd_log_level_warning,
_uhd_log_level_error
};
#define UHD_MSG(severity) ((_uhd_log_level_##severity==_uhd_log_level_status)?UHD_LOGGER_INFO("UmTRX"): \
(_uhd_log_level_##severity==_uhd_log_level_warning)?UHD_LOGGER_WARNING("UmTRX"): \
UHD_LOGGER_ERROR("UmTRX"))
#endif // UHD_HAS_MSG_HPP
#endif // UMTRX_LOG_ADAPTER_HPP

View File

@@ -16,7 +16,7 @@
//
#include "umtrx_impl.hpp"
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/types/sensors.hpp>
#include <uhd/types/ranges.hpp>
#include <boost/asio.hpp>
@@ -71,7 +71,7 @@ void umtrx_impl::status_monitor_start(const uhd::device_addr_t &device_addr)
{
UHD_MSG(status) << "Creating TCP monitor on port " << device_addr.get("status_port") << std::endl;
_server_query_tcp_acceptor.reset(new asio::ip::tcp::acceptor(
_server_query_io_service, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), device_addr.cast<int>("status_port", 0))));
_server_query_io_service, asio::ip::tcp::endpoint(asio::ip::address::from_string("127.0.0.1"), device_addr.cast<int>("status_port", 0))));
_server_query_task = task::make(boost::bind(&umtrx_impl::server_query_handler, this));
}
_status_monitor_task = task::make(boost::bind(&umtrx_impl::status_monitor_handler, this));
@@ -118,7 +118,7 @@ void umtrx_impl::status_monitor_handler(void)
void umtrx_impl::server_query_handler(void)
{
//accept the client socket (timeout is 100 ms, task is called again)
if (not wait_read_sockfd(_server_query_tcp_acceptor->native(), 100)) return;
if (not wait_read_sockfd(_server_query_tcp_acceptor->native_handle(), 100)) return;
boost::shared_ptr<asio::ip::tcp::socket> socket(new asio::ip::tcp::socket(_server_query_io_service));
_server_query_tcp_acceptor->accept(*socket);

View File

@@ -6,6 +6,9 @@ INSTALL(PROGRAMS
umtrx_gps_coord
umtrx_auto_calibration
umtrx_firmware
umtrx_net_burner
umtrx_query_sensors
umtrx_query_versions
DESTINATION bin
)

View File

@@ -1,6 +0,0 @@
TypesDB "/usr/share/collectd/umtrx.types.db"
LoadPlugin exec
<Plugin exec>
Exec "fairwaves-monitoring" "/usr/share/umtrx/umtrx2collectd.py"
</Plugin>

View File

@@ -1 +0,0 @@
sensor value:GAUGE:U:U

View File

@@ -1,54 +0,0 @@
#!/usr/bin/python -u
# -*- coding: utf-8 -*-
import os
import sched, time
from umtrx_property_tree import umtrx_property_tree
from umtrx_vswr import umtrx_vswr
BOARD_ID = "0"
SENSORS_PATH = "/mboards/{id}/sensors".format(id=BOARD_ID)
VSWR_CALIBRATION = 0 # = TM10_VSWR_cal
HOSTNAME = os.environ['COLLECTD_HOSTNAME'] if 'COLLECTD_HOSTNAME' in os.environ else 'localhost'
INTERVAL = os.environ['COLLECTD_INTERVAL'] if 'COLLECTD_INTERVAL' in os.environ else '60'
umtrx = umtrx_property_tree()
umtrx.connect()
# typically this yields: ['tempA', 'tempB', 'voltagePR1', 'voltagePF1', 'voltagePR2', 'voltagePF2', 'voltagezero', 'voltageVin', 'voltageVinPA', 'voltageDCOUT']
sensors_list = umtrx.list_path_raw(SENSORS_PATH).get("result", [])
def publish():
now = time.time()
current_sensors = {sensor: umtrx.query_sensor_value(SENSORS_PATH + "/" + sensor) for sensor in sensors_list}
for channel in ["1", "2"]:
vpf_name = "voltagePF" + channel
vpr_name = "voltagePR" + channel
if vpf_name in current_sensors and vpr_name in current_sensors:
vswr = umtrx_vswr(float(current_sensors[vpf_name]), float(current_sensors[vpr_name]), VSWR_CALIBRATION)
current_sensors["VSWR" + channel] = vswr.vswr()
current_sensors["ReturnLoss" + channel] = vswr.return_loss()
for name, value in current_sensors.items():
print "PUTVAL {host}/umtrx-{id}/sensor-{name} interval={interval} {now}:{value}".format(
host=HOSTNAME, id=BOARD_ID, name=name.lower(), interval=INTERVAL, now=now, value=value)
s = sched.scheduler(time.time, time.sleep)
def timer_loop():
s.enter(float(INTERVAL), 1, timer_loop, ())
publish()
timer_loop()
s.run()
umtrx.close()

View File

@@ -12,16 +12,22 @@ if [ "$#" -lt "1" ] ; then
echo " - Tx DC offset calibration"
echo " - Tx IQ balance calibration"
echo
echo "The result of the calibration is stored in the DIR/.uhd/cal/ directory. DIR is one of the \$APPDATA, \$HOME and /tmp,"
echo "whichever is defined. Make sure you run calibration from the same user as the one who runs applications or define"
echo "\$APPDATA or \$HOME appropriately. Calibration files will be loaded by the application automatically on startup."
echo "Old calibration files are renamed when you run a calibration to avoid overwriting."
echo "The result of the calibration is stored in the \$UHD_CONFIG_DIR/.uhd/cal/ directory."
echo "If \$UHD_CONFIG_DIR is undefined, /var/lib/umtrx is used instead."
echo "When running UHD applications, make sure you set one of \$UHD_CONFIG_DIR, \$APPDATA or \$HOME to the same directory,"
echo "so the calibration files could be found and autoloaded by the application on startup."
echo "Existing calibration files are renamed when you run a calibration to avoid overwriting."
echo
echo "Calibration is permanent and only depends on temperature. If the temperature of the system is stable, you need to"
echo "run the calibration only once."
exit 1
fi
if [ -z "$UHD_CONFIG_DIR" ]; then
export UHD_CONFIG_DIR=/var/lib/umtrx
fi
mkdir -p $UHD_CONFIG_DIR
presets=$*
sides="A B"

View File

@@ -18,6 +18,7 @@
#include "usrp_cal_utils.hpp"
#include <uhd/utils/safe_main.hpp>
#include <boost/ref.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <boost/math/special_functions/round.hpp>
@@ -342,8 +343,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
//create a transmitter thread
std::atomic<bool> interrupted(false);
boost::thread_group threads;
threads.create_thread(boost::bind(&tx_thread, usrp, tx_wave_freq, tx_wave_ampl));
threads.create_thread(boost::bind(&tx_thread, usrp, tx_wave_freq, tx_wave_ampl, boost::ref(interrupted)));
//store the results here
std::vector<result_t> results;
@@ -403,7 +405,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << std::endl;
//stop the transmitter
threads.interrupt_all();
interrupted = true;
threads.join_all();
if (not vm.count("single_test"))

View File

@@ -18,6 +18,7 @@
#include "usrp_cal_utils.hpp"
#include <uhd/utils/safe_main.hpp>
#include <boost/ref.hpp>
#include <boost/program_options.hpp>
#include <boost/math/special_functions/round.hpp>
#include <iostream>
@@ -83,8 +84,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
//create a transmitter thread
std::atomic<bool> interrupted(false);
boost::thread_group threads;
threads.create_thread(boost::bind(&tx_thread, usrp, tx_wave_freq, tx_wave_ampl));
threads.create_thread(boost::bind(&tx_thread, usrp, tx_wave_freq, tx_wave_ampl, boost::ref(interrupted)));
//re-usable buffer for samples
std::vector<samp_type> buff;
@@ -177,7 +179,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::cout << std::endl;
//stop the transmitter
threads.interrupt_all();
interrupted = true;
threads.join_all();
store_results(usrp, results, "tx", "iq", vm.count("append"));

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python
#
# Copyright 2010-2011 Ettus Research LLC
# Copyright 2013-2017 Fairwaves, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -16,10 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# TODO: make it autodetect UHD devices
import optparse
import math
import os
import re
import struct
@@ -495,7 +493,7 @@ class burner_socket(object):
########################################################################
def get_options():
parser = optparse.OptionParser()
parser.add_option("--addr", type="string", help="USRP-N2XX device address", default='')
parser.add_option("--addr", type="string", help="UmTRX device address", default='')
parser.add_option("--fw", type="string", help="firmware image path (optional)", default='')
parser.add_option("--fpga", type="string", help="fpga image path (optional)", default='')
parser.add_option("--reset", action="store_true", help="reset the device after writing", default=False)
@@ -527,7 +525,7 @@ if __name__=='__main__':
if options.overwrite_safe and not options.read:
print("Are you REALLY, REALLY sure you want to overwrite the safe image? This is ALMOST ALWAYS a terrible idea.")
print("If your image is faulty, your USRP2+ will become a brick until reprogrammed via JTAG.")
print("If your image is faulty, your UmTRX will become a brick until reprogrammed via JTAG.")
response = raw_input("""Type "yes" to continue, or anything else to quit: """)
if response != "yes": sys.exit(0)

View File

@@ -15,7 +15,6 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <uhd/utils/thread_priority.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/utils/paths.hpp>
#include <uhd/utils/algorithm.hpp>

View File

@@ -26,7 +26,7 @@ class umtrx_property_tree:
d = dict(action=action, path=path)
if value_type is not None: d['type'] = value_type
if value is not None: d['value'] = value
return self.s.send(bytes(json.dumps(d)+'\n', 'UTF-8'))
return self.s.send((json.dumps(d)+'\n').encode('UTF-8'))
def _recv_response(self):
resp = self.f.readline().strip()

View File

@@ -15,7 +15,11 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifdef THREAD_PRIORITY_HPP_DEPRECATED
# include <uhd/utils/thread.hpp>
#else // THREAD_PRIORITY_HPP_DEPRECATED
# include <uhd/utils/thread_priority.hpp>
#endif // THREAD_PRIORITY_HPP_DEPRECATED
#include <uhd/utils/safe_main.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <boost/program_options.hpp>

View File

@@ -15,7 +15,6 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <uhd/utils/thread_priority.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/utils/paths.hpp>
#include <uhd/utils/algorithm.hpp>

View File

@@ -16,9 +16,13 @@
//
#include <uhd/utils/paths.hpp>
#ifdef THREAD_PRIORITY_HPP_DEPRECATED
# include <uhd/utils/thread.hpp>
#else // THREAD_PRIORITY_HPP_DEPRECATED
# include <uhd/utils/thread_priority.hpp>
#endif // THREAD_PRIORITY_HPP_DEPRECATED
#include <uhd/utils/algorithm.hpp>
#include <uhd/utils/msg.hpp>
#include "umtrx_log_adapter.hpp"
#include <uhd/property_tree.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <uhd/usrp/dboard_eeprom.hpp>
@@ -31,6 +35,7 @@
#include <complex>
#include <cmath>
#include <fstream>
#include <atomic>
namespace fs = boost::filesystem;
@@ -227,7 +232,7 @@ static void capture_samples(
/***********************************************************************
* Transmit thread
**********************************************************************/
static void tx_thread(uhd::usrp::multi_usrp::sptr usrp, const double tx_wave_freq, const double tx_wave_ampl){
static void tx_thread(uhd::usrp::multi_usrp::sptr usrp, const double tx_wave_freq, const double tx_wave_ampl, std::atomic<bool> &interrupted){
uhd::set_thread_priority_safe();
//create a transmit streamer
@@ -246,7 +251,7 @@ static void tx_thread(uhd::usrp::multi_usrp::sptr usrp, const double tx_wave_fre
wave_table table(tx_wave_ampl);
//fill buff and send until interrupted
while (not boost::this_thread::interruption_requested()){
while (not interrupted){
for (size_t i = 0; i < buff.size(); i++){
buff[i] = table(index += step);
}