The example refactoring required usage of the get/set source API, which
isn't available on B2xx series. This patch tests for the existence of
said API, and disables its usage if appropriate.
The refactoring changed the behaviour of --bitbang: before, it would
terminate after one readback unless --repeat was specified, in which
case it would require a Ctrl-C (SIGINT). After the refactoring, it
always required a SIGINT. This changes the behaviour back to prior to
727141d, and will now only read back once, unless --repeat is provided.
This also fixes the bitbang devtest, which would go on indefinitely.
The example had organically grown and was getting hard to read, and also
had some known issues. Summary of fixes:
- Default GPIO bank and connector are now derived from the device. This
allows this example to pass without throwing an exception on E3xx and
X4xx series when using default arguments.
- The bitbang test is moved into its own code section, to make the rest
more readable.
- We move all the streamer-related code into a helper struct
- Some repetitive parts of the code are moved into their own functions
- The argument --require-loopback is added, which will fail tests if
GPIO pins are not correctly looped back externally
- --list-banks is renamed to --list_banks for consistency
This causes the latest RFNoC protocol version to be used by default
and avoids the need to update YAML files every time the RFNoC
protocol version gets bumped.
Add support for reading the number of supported SPI slaves from
the device. This has become necessary because we may have bitfiles
with different capabilities and we want to report this back correctly.
- rfnoc_replay_samples_from_file still had UHD3-vestiges for selecting
block port and ID
- The documentation for stream_args_t also included block port and ID
examples
The counters that keep track of overruns, underruns, number of samples
transferred, etc., were not atomic. Thus, running benchmark_rate with
multiple threads would result in inaccurate statistics being reported at
the end of the run. This commit makes those counters atomic variables so
that they are updated properly.
- Use connect_through_blocks() to create connections
- Remove check for spp being an integer multiple of the word size, the
atomic item size feature will do that for us now
- When using --nsamps, automatically terminate application after samples
have been tx'd.
- Added sleep statements to throttle empty while loops
- Minor formatting changes
This example would not specify a channel when querying the actual
frequency/bandwidth/gain after setting it. When using the --channels
options like this:
tx_bursts --channels 1 --freq 1e9 [...]
...it would request the frequency of 1 GHz on channel 1, then query the
frequency on channel 0 when reporting the "actual" frequency.
Also removes some boost::format().
Some comments describing data flow direction were wrong. This commit
updates the Mako files and updates the noc_shell modules with newly
generated versions.
This example had some major issues since UHD 4, which are now fixed.
Mainly, the option to include a custom RFNoC block was not working.
The example was rehauled severely:
- Custom blocks are now usable again.
- UHD/RFNoC code is used for the connections, rather than a custom
kludge.
- Sample rate is set via property propagation
- boost::format() was not helpful in this example, and was removed.
- A list of active connections is now printed
- The --block-args argument is dropped in favour of --block-props. The
former never did anything useful, and "block args" are a UHD 3 thing.
"bank" refers to what the radio control sees, and "port" refers to what
the user looking at the physical device sees. For example, on X410 each
radio control only has a single (24-bit) output, which can be routed
to either of two ports.
This removes some constants from UHD that were left over from RFNoC/UHD
3.x. They are unused.
rfnoc_rx_to_file had a commented-out section that was also UHD-3 only.
Note that rfnoc/constants.hpp is pretty bare now, and could be removed.
However, it is in the public header section, so we shall leave the used
constants where they are.
This requires fixing includes in mgmt_portal.cpp.
This is a very mechanical task that could almost have been done with
sed. Boost versions of mutexes and locks were removed, and replaced with
std:: versions. The replacement tables are as follows:
== Mutexes ==
- boost::mutex -> std::mutex
- boost::recursive_mutex -> std::recursive_mutex
Mutexes behave identically between Boost and std:: and have the same
API.
== Locks ==
C++11 has only two types of lock that we use/need in UHD:
- std::lock_guard: Identical to boost::lock_guard
- std::unique_lock: Identical to boost::unique_lock
Boost also has boost::mutex::scoped_lock, which is a typedef for
boost::unique_lock<>. However, we often have used scoped_lock where we
meant to use lock_guard<>. The name is a bit misleading, "scoped lock"
sounding a bit like an RAII mechanism. Therefore, some previous
boost::mutex::scoped_lock are now std::lock_guard<>.
std::unique_lock is required when doing more than RAII locking (i.e.,
unlocking, relocking, usage with condition variables, etc.).
== Condition Variables ==
Condition variables were out of the scope of this lock/mutex change, but
in UHD, we inconsistently use boost::condition vs.
boost::condition_variable. The former is a templated version of the
latter, and thus works fine with std::mutex'es. Therefore, some
boost::condition_variable where changed to boost::condition.
All locks and mutexes use `#include <mutex>`. The corresponding Boost
includes were removed. In some cases, this exposed issues with implicit
Boost includes elsewhere. The missing explicit includes were added.
the USRP power meter will only receive from a single channel which
is configured by the argument parameter. The streamer receive
data will therefor alwalys have a single channel. So do not index
with chan when passing the streamer to uhd.dsp.signals.get_usrp_power.
- Like with RX, this now allows passing in stream time and existing
streamer
- There was no EOB being sent at the end (now there is)
- Fixed some linter issues
This fixes a subtle bug, where a variable to cache the timestamp of an
error gets bound to the metadata instead of creating a copy thereof.
Without this fix, the calculation of dropped samples would always be 0,
because the difference in timestamps would incorrectly be always zero.
This fix will now make a copy of the timestamp.
Shoutout to GitHub user bhorsfield for finding this issue.
- Fixes a bug where the RX stream command set set independent of the
device time. Now, we read back get_time_now() to calculate the command
time.
- When using multiple RX USRPs, sync their times. Before, they were left
untouched, causing possible timing mismatches.
- Increase the initial timeout value. The previous value had only been
tested with N2x0.
- Replace the boost::thread_group with a std::thread.
- Remove some boost::format where it didn't add value.
See the CMake 3.8 documentation on these two variables:
https://cmake.org/cmake/help/v3.8/variable/PROJECT-NAME_SOURCE_DIR.htmlhttps://cmake.org/cmake/help/v3.8/variable/CMAKE_SOURCE_DIR.html
Under normal circumstances, these two are identical. For sub-projects
(i.e., when building UHD as part of something else that is also a CMake
project), only the former is useful. There is no discernible downside of
using UHD_SOURCE_DIR over CMAKE_SOURCE_DIR.
This was changed using sed:
$ sed -i "s/CMAKE_SOURCE_DIR/UHD_SOURCE_DIR/g" \
`ag -l CMAKE_SOURCE_DIR **/{CMakeLists.txt,*.cmake}`
$ sed -i "s/CMAKE_BINARY_DIR/UHD_BINARY_DIR/g" \
`ag -l CMAKE_BINARY_DIR **/{CMakeLists.txt,*.cmake}`
At the same time, we also replace the CMake variable UHD_HOST_ROOT (used
in MPM) with UHD_SOURCE_DIR. There's no reason to have two variables
with the same meaning and different names, but more importantly, this
means that UHD_SOURCE_DIR is defined even in those cases where MPM calls
into CMake files from UHD without any additional patches.
Shoutout to GitHub user marcobergamin for bringing this up.
Its behaviour is almost identical to std::lround, which we use instead.
The only downside of std::lround is that it always returns a long, which
we don't always need. We thus add some casts for those cases to make the
compiler happy.
The checks from the new clang-tidy file are applied to the source tree
using:
$ find . -name "*.cpp" | sort -u | xargs \
--max-procs 8 --max-args 1 clang-tidy --format-style=file \
--fix -p /path/to/compile_commands.json
The implementation was not properly configuring the stream command if
the --random flag was used. It was especially bad when multiple
channels were specified.
Signed-off-by: michael-west <michael.west@ettus.com>
- Add missing "uhd/" subdirectory.
- Update install path for YAML file.
- Fix include directories and link libraries for init_gain_block.
Signed-off-by: michael-west <michael.west@ettus.com>
This example exercises the Replay Block RFNoC API. The Replay records
IQ data from a file and plays it back into a Radio for transmitting.
Signed-off-by: mattprost <matt.prost@ni.com>
I was using this example for testing with the simulator. If there is a
flow control failure, the original example would just silently finish,
outputing the message "Done!" (Not even printing a timeout message).
This commit asserts that the number of samples sent is equal to the
number of samples provided.
Signed-off-by: Samuel O'Brien <sam.obrien@ni.com>
This PR applies antenna channel settings before available calibration
data, and moves initialization code to setup_device, returning necessary
settings in a tuple.
Refresh screen after printing the DFT data.
Use C++14 std::this_thread::sleep_for to control the refresh rate.
Signed-off-by: Etienne Wodey <wodey@iqo.uni-hannover.de>
This is a utility that can be used to measure received power, assuming
a calibrated device.
For example, it can be called like this:
usrp_power_meter.py -a type=x300 -f 1e9 --mode continuous
To continuously measure input power at 1 GHz.
This changes two things in all applicable files:
- Remove imports from __future__
- Change default shebangs from /usr/bin/env python to /usr/bin/env
python3
The example assumed that there was always at least one TX and on RX
channel. Since that is not always true, this change checks for TX
and RX channels and only exucutes tests for what exists on the device.
Signed-off-by: Michael West <michael.west@ettus.com>
The example assumed that there was always at least one TX and on RX
channel. Since that is not always true, this change checks for TX
and RX channels and only exucutes tests for what exists on the device.
Applied clang format.
Signed-off-by: Michael West <michael.west@ettus.com>
If you run
tx_waveforms --power -20 [other args]
it will try to set the out power to -20 dBm. The signal amplitude is
factored in, so changing --ampl will not change the actual TX power
unless it causes clipping, or becomes too low.
If the USRP does not support setting a power, the program will terminate
early. If it does support setting a power, but can't reach the requested
power, it will coerce, and print the actual, available power.
The existing implementation would create a real signal for any type of
signal (CONST, RAMP, SQUARE, and SINE), and then create the complex
signal by simply delaying the Q value by a 90 degree phase. This had
surprising results for all waveforms:
- CONST waveforms would have a baseband value of ampl + j ampl, thus
increasing the output power by 3 dB vs. what one would expect when
setting an amplitude. It is now ampl + j * 0, and the power is
ampl**2. This now makes the power consistent with SINE, which it was
not, even though a const signal is a sine signal with a frequency of
zero.
- SQUARE waveforms would phase-delay the Q part, thus resulting in three
power output levels (when both phases are zero, when both phases are
ampl, and when one of them is zero and other is ampl). However, the
square signal is useful for watching it in the scope, and there, it
helps if the power is predictably either high or low within the
selected frequency. The Q value is now always zero.
- RAMP waveforms had the same issue and were also resolved by setting
Q to zero.
- SINE signals were fine, although the implementation used sin + j cos
to calculate a complex sine, not cos + j sin according to Euler's
formula.
To make this wavetable more useful with absolute power settings, the
changes mentioned above were implemented. The dBFs power of CONST and
SINE can now be calculated by using ampl**2, SQUARE by using
(ampl**2)/2, and RAMP by solving the integral over a ramp from -1 to 1.
This commit modifies the benchmark_rate example to use the operating
system's default thread priority, instead of real-time thread priority,
by default. UHD 4.0 includes a number of significant improvements to
the streaming architecture that allow for best performance to be
achieved without having to resort to elevating the process thread
priority to real-time. Internal testing shows degraded streaming
performance in common use cases (i.e. non-DPDK) when the process thread
priority is set to real-time.
It should be noted that applications which use DPDK may still experience
better performance when the process thread priority is set to real-time.
Users may continue to manually override the process thread priority
in benchmark_rate using the --priority=high command-line option. The
need to elevate the process thread priority will be application- and
deployment-dependent.
This replaces chdr_word_t, which was a statically defined 64-bit data
type, with a paramaterizable data type that matches the defined CHDR_W.
Code that formerly referenced the chdr_word_t data type can now define
the data type for their desired CHDR_W and ITEM_W as follows:
// Define the CHDR word and item/sample data types
typedef ChdrData #(CHDR_W, ITEM_W)::chdr_word_t chdr_word_t;
typedef ChdrData #(CHDR_W, ITEM_W)::item_t item_t;
ITEM_W is optional when defining chdr_word_t if items are not
needed. Static methods in the ChdrData class also provide the ability to
convert between CHDR words and data items. For example:
// Convert CHDR data buffer to a buffer of samples
samples = ChdrData#(CHDR_W, ITEM_W)::chdr_to_item(data);
Adds a ZPU register to control the FP GPIO source. These are 2bits
per GPIO pin, totalling 24 bits. 0 corresponds to RF-A, 1 corresponds
to RF-B. The following Python code will control the upper 6 bits of the
front-panel GPIO from the B-side radio on an X300:
>>> import uhd
>>> U = uhd.usrp.MultiUSRP("type=x300")
>>> U.get_gpio_src_banks()
['FP0']
>>> U.get_gpio_src("FP0")
['RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA',
'RFA', 'RFA']
>>> U.set_gpio_src("FP0", ['RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA',
'RFB', 'RFB', 'RFB', 'RFB', 'RFB', 'RFB'])
>>> U.get_gpio_src("FP0")
['RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFA', 'RFB', 'RFB', 'RFB', 'RFB',
'RFB', 'RFB']
>>> # Make all GPIOs outputs:
>>> U.set_gpio_attr("FP0A", "DDR", 0xFFF)
>>> U.set_gpio_attr("FP0B", "DDR", 0xFFF)
>>> # Control all GPIOs from software (not ATR):
>>> U.set_gpio_attr("FP0A", "CTRL", 0x000)
>>> U.set_gpio_attr("FP0B", "CTRL", 0x000)
>>> # Bottom 3 pins go high from radio A
>>> U.set_gpio_attr("FP0A", "OUT", 0x007)
>>> # Top 3 pins go high from radio B
>>> U.set_gpio_attr("FP0B", "OUT", 0xE00)
Amends the gpio.cpp example to allow switching the source.
Co-authored-by: Brent Stapleton <brent.stapleton@ettus.com>
Cleans up the print out for the benchmark rate example. Removes
race condition that would cause send and receive initialization
messages to interleave to stdout.
Using default values, the initial delay for tx is larger than the
default timeout of tx_streamer::send. Changing the example to always
specify a timeout in send.
Small changes to remove various compiler warnings found in MSVC
- Adding uhd::narrow_cast to verious spots
- wavetable.hpp: all floats literals in the wavetable.
- paths_test: unnecessary character escape
- replay example: remove unreferenced noc_id
- adfXXXX: Fixing qualifiers to match between parent and derived
classes
- rpc, block_id: Removing unused name in try...catch
- Add option for high or normal thread priority with default set to high
- Add rx_delay and tx_delay options to dynamically set start delays
(default of 0.25 seconds for TX and 0.05 seconds for RX)
Signed-off-by: Michael West <michael.west@ettus.com>
Improves dpdk streaming performance for benchmark_rate by elevating
thread priority of the send and recv threads. It does this
conditionally, if use_dpdk=1 was passed in through the command line
args. Admittedly, this is not a perfect solution, as it does not
account for the case when a dpdk user is utilizing a config file to
pass in that information. The scope of this fix does seem
appropriate for an example.
The gpio example would continously call get_time_now() to time a loop.
There is no need to query a device here, so we query the system timer
instead.
This fixes an issue where the large amounts of control traffic could
slow down TX, causing the TX and FDX tests to fail. This was only ever
seen on the X300_HG over 1GigE.
This allows adding stream args to the Python version of benchmark_rate
in the same way as for the C++ version, e.g.:
python3 ./benchmark_rate.py \
--args addr=192.168.40.2,num_poll_offload_threads=4 \
--rx_stream_args \
recv_offload=1,num_recv_frames=32,recv_offload_wait_mode=poll \
--tx_stream_args \
send_offload=1,num_send_frames=32,send_offload_wait_mode=poll \
[... other arguments ...]
For the burst ACK test, test_messages would send 3 packets. However,
that assumes that the underlying link is fast enough to send three
packets in time, and some devices are hard to operate without underruns
without also specifying a start-of burst timestamp. Often, test_messages
would report that no ACK was received, but instead, an underrun was
received.
test_messages also doesn't need to send three packets. The three packets
came from the "start of burst" flag, which no device in UHD supports.
The change is thus to send a single packet with an EOB marker for the
burst ACK test. This will work regardless of the link speed and CPU
power.
This subdirectory is its own, self-contained project. It is supposed to
work against the UHD version it is shipped with.
Co-Authored-By: Martin Braun <martin.braun@ettus.com>
Co-Authored-By: Wade Fife <wade.fife@ni.com>
Note: Replacing everything with a lambda would be even better, but that
can't be easily scripted so we'll do this as a first step to reduce the
Boost footprint.
This also removes occurences of #include <boost/bind.hpp>, and makes
sure all usages of std::bind have an #include <functional>. clang-format
wasn't always applied to minimize the changeset in this commit, however,
it was applied to the blocks of #includes.
Due to conflicts with other Boost libraries, the placeholders _1, _2,
etc. could not be directly used, but had to be explicitly called out
(as std::placeholders::_1, etc.). This makes the use of std::bind even
uglier, which serves as another reminder that using std::bind (and even
more so, boost::bind) should be avoided.
nirio/rpc/rpc_client.cpp still contains a reference to boost::bind. It
was not possible to remove it by simply doing a search and replace, so
it will be removed in a separate commit.
This is mostly a search-and-replace operation, with few exceptions:
- boost::function has a clear() method. In C++11, this is achieved by
assigning nullptr to the std::function object.
- The empty() method is replaced by std::function's bool() operator
This removes the following Boost constructs:
- boost::shared_ptr, boost::weak_ptr
- boost::enable_shared_from_this
- boost::static_pointer_cast, boost::dynamic_pointer_cast
The appropriate includes were also removed. All C++11 versions of these
require #include <memory>.
Note that the stdlib and Boost versions have the exact same syntax, they
only differ in the namespace (boost vs. std). The modifications were all
done using sed, with the exception of boost::scoped_ptr, which was
replaced by std::unique_ptr.
References to boost::smart_ptr were also removed.
boost::intrusive_ptr is not removed in this commit, since it does not
have a 1:1 mapping to a C++11 construct.
rfnoc_nullsource_ce_rx, rfnoc_rx_to_file:
These examples are modified so they can be run with the new RFNoC API.
test_messages:
Fixes failures in the time test when it is executed immediately after an
underrun test. The DUC considers time specs on a per burst basis, so
when the underrun test leaves a burst unfinished, a time spec on the
next burst is ignored.
This removes the following symbols:
- otw_type_t
- clock_config_t
- Any functions that use those symbols
- Non-standard args from examples (e.g., --total-time is deprecated in
favour of --duration)
- Boost >= 1.58
- CMake >= 3.5.1
- gcc >= 5.4.0
- Clang >= 3.8, AppleClang >= 600
- Python >= 3.5 (Py2k no longer supported)
- Numpy >= 1.11
- C++14 for lib, include may now use C++11 constructs.
- Because there is no more code requiring C++03 syntax, we remove the
include-specific clang-format file
The E31x will always have a valid PPS, because it is generated
internally. The external PPS however is used to drive the ppsloop, which
means the ref_locked sensor can be a substitute for the PPS, but only on
in this case.
This commit also removes some superfluous includes from this example.
Remove UHD call to elevate thread priority to realtime. Setting all
threads to the same realtime priority can cause the threads to not share
access to the network interface fairly, which adversely affects
operation of the worker threads in UHD.
The timestamp from the streamer corresponds to the first sample, but
a better indicator of transport latency will use the time of the last
RX sample. Otherwise, nsamps will reduce the timing budget to send the
TX samples. Include this mode to allow latency_test to have a version
where there is largely no dependence amongst the variables.
- When printing statistics, the number of TX and RX timeouts were mixed
up.
- Fixing main() docstring
Fixes e735a63ff9 ("python: Adding Python API benchmark rate")
Fix memory leak: 'buff' was never freed.
While we're at it replace the kludgy malloc(n*y*sizeof(float))
by calloc(sizeof(float), n*y).
Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
Remove dead store to is_locked. The variable isn't read before
being overwritten, so the extra store is useless.
Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
There was a corner case where the data could be such that the FFT plot
symbol selection would cause an out-of-bounds access on the symbols
table, and abort the example with an uncaught exception.
Turning off clang formatting around the program option declarations.
clang-format makes them looks bad an unreadable because it thinks the
options are function calls or something.
- examples affected: rfnoc_rx_to_file
- fixes UHD build error with Boost 1.67: boost::posix_time::seconds no
longer supports double argument as of version 1.67
Move filling the TX buffer outside the critical path. Now, we pre-fill
the TX buffer before entering the send loop (and before setting the
TX stream time), and fill the TX buffer after calling send() (for the
next iteration).
Move the setting of the streaming start times back as late as possible.
Currently, there are memory allocations in between setting the
time_spec in the TX metadata and actually starting streaming. This will
lessen the need for an INIT_DELAY and decrease the probability of late
packets.
Add support for benchmarking multi-channel streamers. This also
simplifies the way the test parameters are specified to avoid confusion
due to the additional dimension. For rx, multi-channel streamer
configurations require split_stream noc blocks so that timestamps of
packets in the same streamer align. Add support for loopback FIFOs.
- Add keyboard controls for sample rate, gain, analog bandwidth,
frequency, as well as the display's dynamic range, reference level,
and frame rate.
- The current values for these properties, as well as the keys to
control them, are displayed in a small window at the top of the
display. This control window can be toggled by pressing 'c'
- Remove unnecessary Boostisms
- Remove unecessary thread priority (this example doesn't actually do
anything that requires high thread priority)
- Used auto in some places to increase readability
- Fixed some compiler warnings
No functional changes.
This makes the noc traffic counter register actually reflect the
registers in the FPGA. The FPGA register names were changed prior to
merging to master, and the ready count registers were removed.
Fix USRP2 MIMO synchronization in benchmark_rate.
When synchronizing N2XXs connected with a MIMO cable, only the master's
time needs to be set; the slave will be synchronized automatically.
Currently, calling set_time_unknown_pps will attempt to synchronize the
slave on the next PPS, which can cause problems since the MIMO cable
doesn't propogate a PPS signal.
Duration of multichannel benchmark was 50 seconds longer than
intended- a 50ms initialization delay was mistakenly multiplied by
1000.
Fixes e735a63ff9 ("python: Adding Python API benchmark rate")
The C/C++ standards don't define what time_t is, only that it is
arithmetic (and real for C11, and integral for C++). It should not be
used in portable software and is only used as the return value for some
libc calls.
A common definition for time_t is int64_t, so we'll switch to that
permanently in our own APIs. System APIs will of course stick with
time_t.
- Separating exposed Python data structures into logical sections
- Exposes all of the multi_usrp API
- Adds a layer of Python for documentation and adding helper methods
- Adds improvements and fixes to the MultiUSRP object
- Includes additional exposed data structures (like time_spec_t, etc.)
- Add code to release the Python GIL during long C++ calls
Initial commit of the Python API using Boost.Python. Bind the
MultiUSRP API for use in Python. Bindings intended to provide as
complete coverage as possible.
- Wrap most multi_usrp calls
- Adding multi channel send/recv examples in examples/python
- Adding setuptools support
- Initial attempt at binding the UHD types and filters
There are cases when the first sample after an overrun has an earlier
timestamp than the timestamp of the error package. In this case,
benchmark_rate would incorrectly determine the number of dropped
samples, causing it to display a very large number.
This is not a fix of the negative offset issue, but will avoid
displaying overly pessimistic numbers dropped samples.
An error message is still displayed when this happens, which aids in
debugging this situation.
When too many overruns, underruns, or dropped packets are detected,
benchmark_rate will now return EXIT_FAILURE. This allows to use it for
automated tests.
The thresholds are set very high by default, but can be manually tuned
by using new command line arguments:
$ benchmark_rate --overrun-threshold 0 # Fail on any number of Os
- Messages are all timestamped, enables better understanding of the
output log
- Less usage of Boost
- More stats (differentiate between RX and TX timeouts and sequence
errors)
uhd::get_system_time() is an abstracted way of reading back a time, and
is not UHD-specific. As such, there's no reason to keep it in the public
part of the API where we're contractually obligated not to touch it.
Instead, moving it to the internal API space.
The former compiles to evaluating `a`, then throwing away the result,
evaluating `b`, then using that to fill in the first placeholder in
`format`. And that is wrong.
Pointed to this by Clang++'s "unused result" warning.
- Also removes all references to boost/cstdint.hpp and replaces it with
stdint.h (The 'correct' replacement would be <cstdint>, but not all of our
compilers support that).
time_t is not guaranteed to be printable as in int type. Use
difftime to portably convert time_t to float and print result.
Signed-off-by: Philip Balister <philip@opensdr.com>
Function needs pointer to size_t type. I suspect using uint64_t could
lead to trouble on a 32 bit machine.
Signed-off-by: Philip Balister <philip@opensdr.com>
- Wait for ACKs for all channels
- Put EOB on last data packet instead of empty packet
- Exit with failure when send times out and SIGINT has been received