mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
docs: Amended docs for conversion routines
This commit is contained in:
parent
ec11128445
commit
b60704d8b7
85
host/docs/converters.dox
Normal file
85
host/docs/converters.dox
Normal file
@ -0,0 +1,85 @@
|
||||
/*! \page page_converters Converters
|
||||
|
||||
\section converters_overview Overview
|
||||
|
||||
When streaming from device to host, the converter has a central role: It converts
|
||||
the sample (or streaming) data from a format the device understands to a format
|
||||
the user can deal with. During conversion, data is copied from the transport buffer
|
||||
to the buffer provided by the user (or vice versa). For zero-copy architectures,
|
||||
this means there are the fewest possible copies between the device transport and
|
||||
the user application.
|
||||
|
||||
The conversion encompasses several elements. The most obvious is that of the data type:
|
||||
Most FPGAs use integer data types, the most common being complex 16-bit integers (16 bit
|
||||
for I and Q, respectively). If the user wants his data in float, the converter casts
|
||||
the data type, and also scales the data, typically such that the full dynamic range
|
||||
of the 16-Bit integers is mapped onto the float range of -1 to 1.
|
||||
The converter also handles the endianness: On the network, data is usually stored as
|
||||
big-endian, whereas most platforms store data internally as little-endian.
|
||||
|
||||
The format used by the user application is coined the 'CPU Format', whereas the format
|
||||
used between the device and UHD is called the 'OTW Format' (*Over-the-wire* format).
|
||||
|
||||
The most common combinations of OTW and CPU formats are shipped with UHD. If your
|
||||
application requires a more exotic CPU format, there is an API to register your own
|
||||
converters.
|
||||
|
||||
\section converters_formats Formats and Converter Choice
|
||||
|
||||
To obtain a list of names of data formats, see uhd::stream_args_t. This also provides
|
||||
an example for how to instantiate a streamer that uses `sc16` over the wire, and `fc32`
|
||||
as CPU format.
|
||||
|
||||
Any pair of OTW and CPU formats can only be used if a converter was registered
|
||||
for that specific pair.
|
||||
|
||||
\subsection converters_formats_internal Internal format strings
|
||||
|
||||
The CPU format is always as defined by the host system, so for example `fc32` is always
|
||||
a `std::complex<float>`, whatever that is.
|
||||
|
||||
For the OTW format, there are more subtleties to observe: On top of the actual
|
||||
data format, there are device-specific components to the OTW format, such as
|
||||
the endianness and the data encapsulation. Internally, the OTW format strings
|
||||
are thus more descriptive than the formats listed at uhd::stream_args_t::otw_format
|
||||
(i.e., the format types you can specify in the stream args).
|
||||
|
||||
As an example, the N2x0 series encapsulates all data in 32-bit chunks, and
|
||||
always uses big-endian transport type. When using `sc16` over the wire, the
|
||||
internal format description would be `sc16_item32_be`, which describes all
|
||||
those elements. During a receive operation, UHD would instantiate a converter
|
||||
from `sc16_item32_be` to `fc32`. The same converter could not be used for the
|
||||
B2x0 series, for example, which uses little-endian transport format and would
|
||||
require a `sc16_item32_le` converter.
|
||||
|
||||
\section converters_accel Hardware-specific Converters
|
||||
|
||||
Given enough knowledge about the platform architecture, it is possible to
|
||||
have converters that use mechanisms to accelerate the conversion (e.g. chipset
|
||||
intrinsics). It is possible to register multiple converters for the same
|
||||
OTW/CPU format pair, and have UHD choose one depending on the current platform.
|
||||
|
||||
\section converters_register Registering converters
|
||||
|
||||
The converter architecture was designed to be dynamically extendable. If your
|
||||
application requires converters not shipped with UHD, they can be added from
|
||||
your application without having to modify UHD.
|
||||
Modifying UHD may be required, e.g. when adding new devices or functionality
|
||||
to UHD.
|
||||
|
||||
\subsection converters_register_extra Outside of UHD
|
||||
|
||||
Registering a converter from your application requires deriving
|
||||
from uhd::convert::converter and overriding all the pure virtual functions.
|
||||
|
||||
Before any UHD operations are performed, this converter class needs to be
|
||||
registered by calling uhd::convert::converter::register_converter.
|
||||
|
||||
\subsection converters_register_internal Inside UHD
|
||||
|
||||
If the converters shipped with UHD need to be amended, new converter classes
|
||||
should be added to `lib/convert`. Use the DECLARE_CONVERTER convenience macro
|
||||
where possible. See this directory for examples.
|
||||
|
||||
*/
|
||||
// vim:ft=doxygen:
|
||||
@ -49,8 +49,7 @@ at the expense of precision, **complex-int8** may be used.
|
||||
The user may request arbitrary combinations of host and link data types;
|
||||
however, not all combinations are supported. The user may register
|
||||
custom data type formats and conversion routines. See
|
||||
convert.hpp for further documentation.
|
||||
convert.hpp and \ref page_converters for further documentation.
|
||||
|
||||
TODO: provide example of convert API
|
||||
*/
|
||||
// vim:ft=doxygen:
|
||||
|
||||
@ -10,6 +10,7 @@ publically available symbol in the UHD namespace.
|
||||
Some additional pages on developing UHD are also available here:
|
||||
|
||||
\li \subpage page_coding
|
||||
\li \subpage page_converters
|
||||
\li \subpage page_stream
|
||||
|
||||
*/
|
||||
|
||||
@ -46,7 +46,14 @@ namespace uhd{ namespace convert{
|
||||
|
||||
private:
|
||||
//! Callable method: input vectors, output vectors, num samples
|
||||
virtual void operator()(const input_type&, const output_type&, const size_t) = 0;
|
||||
//
|
||||
// This is the guts of the converter. When deriving new converter types,
|
||||
// this is where the actual conversion routines go.
|
||||
//
|
||||
// \param in Pointers to the input buffers
|
||||
// \param out Pointers to the output buffers
|
||||
// \param num Number of items in the input buffers to convert
|
||||
virtual void operator()(const input_type& in, const output_type& out, const size_t num) = 0;
|
||||
};
|
||||
|
||||
//! Conversion factory function typedef
|
||||
@ -69,6 +76,9 @@ namespace uhd{ namespace convert{
|
||||
|
||||
/*!
|
||||
* Register a converter function.
|
||||
*
|
||||
* Converters with higher priority are given preference.
|
||||
*
|
||||
* \param id identify the conversion
|
||||
* \param fcn makes a new converter
|
||||
* \param prio the function priority
|
||||
|
||||
@ -22,10 +22,10 @@
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
/*! \file byteswap.hpp
|
||||
*
|
||||
* Provide fast byteswaping routines for 16, 32, and 64 bit integers,
|
||||
* by using the system's native routines/intrinsics when available.
|
||||
*/
|
||||
|
||||
namespace uhd{
|
||||
|
||||
//! perform a byteswap on a 16 bit integer
|
||||
@ -44,9 +44,15 @@ namespace uhd{
|
||||
template<typename T> T htonx(T);
|
||||
|
||||
//! worknet to host: short, long, or long-long
|
||||
//
|
||||
// The argument is assumed to be little-endian (i.e, the inverse
|
||||
// of typical network endianness).
|
||||
template<typename T> T wtohx(T);
|
||||
|
||||
//! host to worknet: short, long, or long-long
|
||||
//
|
||||
// The return value is little-endian (i.e, the inverse
|
||||
// of typical network endianness).
|
||||
template<typename T> T htowx(T);
|
||||
|
||||
} //namespace uhd
|
||||
|
||||
@ -42,6 +42,19 @@
|
||||
const input_type &inputs, const output_type &outputs, const size_t nsamps \
|
||||
)
|
||||
|
||||
/*! Convenience macro to declare a single-function converter
|
||||
*
|
||||
* Most converters consist of a single for loop, and can make use of
|
||||
* this macro for declaration and registering.
|
||||
*
|
||||
* Following this macro should be a function block in curly braces
|
||||
* which runs the conversion. Available parameters in this function block
|
||||
* are:
|
||||
* - `inputs`: Vector of pointers to the input data. Size of the vector == `num_in`
|
||||
* - `outputs`: Vector of pointers to where the output data goes. Size of the vector == `num_out`
|
||||
* - `nsamps`: Number of items per input buffer to convert
|
||||
* - `scale_factor`: Scaling factor for float conversions
|
||||
*/
|
||||
#define DECLARE_CONVERTER(in_form, num_in, out_form, num_out, prio) \
|
||||
_DECLARE_CONVERTER(__convert_##in_form##_##num_in##_##out_form##_##num_out##_##prio, in_form, num_in, out_form, num_out, prio)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user