diff options
Diffstat (limited to 'gr-iio/lib/fmcomms2_source_impl.cc')
-rw-r--r-- | gr-iio/lib/fmcomms2_source_impl.cc | 207 |
1 files changed, 177 insertions, 30 deletions
diff --git a/gr-iio/lib/fmcomms2_source_impl.cc b/gr-iio/lib/fmcomms2_source_impl.cc index e102e99247..e6651e49bc 100644 --- a/gr-iio/lib/fmcomms2_source_impl.cc +++ b/gr-iio/lib/fmcomms2_source_impl.cc @@ -19,6 +19,8 @@ #include <thread> #include <vector> +#include <volk/volk.h> + #define MIN_RATE 520333 #define DECINT_RATIO 8 #define OVERFLOW_CHECK_PERIOD_MS 1000 @@ -26,18 +28,20 @@ namespace gr { namespace iio { -fmcomms2_source::sptr fmcomms2_source::make(const std::string& uri, - const std::vector<bool>& ch_en, - unsigned long buffer_size) +template <typename T> +typename fmcomms2_source<T>::sptr fmcomms2_source<T>::make(const std::string& uri, + const std::vector<bool>& ch_en, + unsigned long buffer_size) { - return gnuradio::make_block_sptr<fmcomms2_source_impl>( + return gnuradio::make_block_sptr<fmcomms2_source_impl<T>>( device_source_impl::get_context(uri), ch_en, buffer_size); } -std::vector<std::string> fmcomms2_source_impl::get_channels_vector(bool ch1_en, - bool ch2_en, - bool ch3_en, - bool ch4_en) +template <typename T> +std::vector<std::string> fmcomms2_source_impl<T>::get_channels_vector(bool ch1_en, + bool ch2_en, + bool ch3_en, + bool ch4_en) { std::vector<std::string> channels; if (ch1_en) @@ -51,8 +55,9 @@ std::vector<std::string> fmcomms2_source_impl::get_channels_vector(bool ch1_en, return channels; } +template <typename T> std::vector<std::string> -fmcomms2_source_impl::get_channels_vector(const std::vector<bool>& ch_en) +fmcomms2_source_impl<T>::get_channels_vector(const std::vector<bool>& ch_en) { std::vector<std::string> channels; int idx = 0; @@ -66,13 +71,32 @@ fmcomms2_source_impl::get_channels_vector(const std::vector<bool>& ch_en) return channels; } +template <> +fmcomms2_source_impl<int16_t>::fmcomms2_source_impl(iio_context* ctx, + const std::vector<bool>& ch_en, + unsigned long buffer_size) + : gr::sync_block("fmcomms2_source", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(1, -1, sizeof(int16_t))), + device_source_impl(ctx, + true, + "cf-ad9361-lpc", + get_channels_vector(ch_en), + "ad9361-phy", + std::vector<std::string>(), + buffer_size, + 0) +{ + overflow_thd = std::thread(&fmcomms2_source_impl<int16_t>::check_overflow, this); +} -fmcomms2_source_impl::fmcomms2_source_impl(iio_context* ctx, - const std::vector<bool>& ch_en, - unsigned long buffer_size) +template <typename T> +fmcomms2_source_impl<T>::fmcomms2_source_impl(iio_context* ctx, + const std::vector<bool>& ch_en, + unsigned long buffer_size) : gr::sync_block("fmcomms2_source", gr::io_signature::make(0, 0, 0), - gr::io_signature::make(1, -1, sizeof(short))), + gr::io_signature::make(1, -1, sizeof(T))), device_source_impl(ctx, true, "cf-ad9361-lpc", @@ -82,12 +106,25 @@ fmcomms2_source_impl::fmcomms2_source_impl(iio_context* ctx, buffer_size, 0) { - overflow_thd = std::thread(&fmcomms2_source_impl::check_overflow, this); + overflow_thd = std::thread(&fmcomms2_source_impl<T>::check_overflow, this); + + // Device Buffers are always presented as short from device_sink + d_device_bufs.resize(get_channels_vector(ch_en).size()); + for (size_t i = 0; i < d_device_bufs.size(); i++) { + d_device_bufs[i].resize(s_initial_device_buf_size); + } + d_float_ivec.resize(s_initial_device_buf_size); + d_float_rvec.resize(s_initial_device_buf_size); } -fmcomms2_source_impl::~fmcomms2_source_impl() { overflow_thd.join(); } +template <typename T> +fmcomms2_source_impl<T>::~fmcomms2_source_impl() +{ + overflow_thd.join(); +} -void fmcomms2_source_impl::check_overflow(void) +template <typename T> +void fmcomms2_source_impl<T>::check_overflow(void) { uint32_t status; int ret; @@ -126,7 +163,103 @@ void fmcomms2_source_impl::check_overflow(void) } } -void fmcomms2_source_impl::update_dependent_params() + +template <> +int fmcomms2_source_impl<std::int16_t>::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + if (2 * output_items.size() > d_device_item_ptrs.size()) { + d_device_item_ptrs.resize(2 * output_items.size()); + } + + for (size_t i = 0; i < 2 * output_items.size(); i += 2) { + if (noutput_items > (int)d_device_bufs[i].size()) { + d_device_bufs[i].resize(noutput_items); + d_device_bufs[i + 1].resize(noutput_items); + } + d_device_item_ptrs[i] = static_cast<void*>(d_device_bufs[i].data()); + d_device_item_ptrs[i + 1] = static_cast<void*>(d_device_bufs[i + 1].data()); + } + + + // Since device_source returns shorts, we can just pass off the work + int ret = device_source_impl::work(noutput_items, input_items, d_device_item_ptrs); + if (ret <= 0) { + return ret; + } + + // Do the conversion from shorts to interleaved shorts + for (size_t i = 0; i < output_items.size(); i += 2) { + auto out = static_cast<short*>(output_items[i]); + + for (int j = 0; j < noutput_items; j++) { + out[2 * j] = d_device_bufs[i][j]; + out[2 * j + 1] = d_device_bufs[i + 1][j]; + } + } + + return ret; +} + + +template <> +int fmcomms2_source_impl<gr_complex>::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + if (2 * output_items.size() > d_device_item_ptrs.size()) { + d_device_item_ptrs.resize(2 * output_items.size()); + } + if (noutput_items > (int)d_float_rvec.size()) { + d_float_rvec.resize(noutput_items); + d_float_ivec.resize(noutput_items); + } + for (size_t i = 0; i < 2 * output_items.size(); i += 2) { + if (noutput_items > (int)d_device_bufs[i].size()) { + d_device_bufs[i].resize(noutput_items); + d_device_bufs[i + 1].resize(noutput_items); + } + d_device_item_ptrs[i] = static_cast<void*>(d_device_bufs[i].data()); + d_device_item_ptrs[i + 1] = static_cast<void*>(d_device_bufs[i + 1].data()); + } + + int ret = device_source_impl::work(noutput_items, input_items, d_device_item_ptrs); + if (ret <= 0) { + return ret; + } + + // Do the conversion from shorts to gr_complex + for (size_t i = 0; i < output_items.size(); i++) { + auto out = static_cast<gr_complex*>(output_items[i]); + + // for (int n = 0; n < noutput_items; n++) { + // out[n] = gr_complex(float(d_device_bufs[i][n]) / 2048.0, + // float(d_device_bufs[i+1][n]) / 2048.0); + // } + + volk_16i_s32f_convert_32f( + d_float_rvec.data(), d_device_bufs[i].data(), 2048.0, noutput_items); + volk_16i_s32f_convert_32f( + d_float_ivec.data(), d_device_bufs[i + 1].data(), 2048.0, noutput_items); + + volk_32f_x2_interleave_32fc( + out, d_float_rvec.data(), d_float_ivec.data(), noutput_items); + } + + return ret; +} + +template <typename T> +int fmcomms2_source_impl<T>::work(int noutput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + return device_source_impl::work(noutput_items, input_items, output_items); +} + +template <typename T> +void fmcomms2_source_impl<T>::update_dependent_params() { std::vector<std::string> params; // Set rate configuration @@ -162,19 +295,22 @@ void fmcomms2_source_impl::update_dependent_params() } } -void fmcomms2_source_impl::set_len_tag_key(const std::string& len_tag_key) +template <typename T> +void fmcomms2_source_impl<T>::set_len_tag_key(const std::string& len_tag_key) { device_source_impl::set_len_tag_key(len_tag_key); } -void fmcomms2_source_impl::set_frequency(unsigned long long frequency) +template <typename T> +void fmcomms2_source_impl<T>::set_frequency(unsigned long long frequency) { std::vector<std::string> params; params.push_back("out_altvoltage0_RX_LO_frequency=" + std::to_string(frequency)); device_source_impl::set_params(params); } -void fmcomms2_source_impl::set_samplerate(unsigned long samplerate) +template <typename T> +void fmcomms2_source_impl<T>::set_samplerate(unsigned long samplerate) { std::vector<std::string> params; if (samplerate < MIN_RATE) { @@ -195,7 +331,8 @@ void fmcomms2_source_impl::set_samplerate(unsigned long samplerate) update_dependent_params(); } -void fmcomms2_source_impl::set_gain_mode(size_t chan, const std::string& mode) +template <typename T> +void fmcomms2_source_impl<T>::set_gain_mode(size_t chan, const std::string& mode) { bool is_fmcomms4 = !iio_device_find_channel(phy, "voltage1", false); if ((!is_fmcomms4 && chan > 0) || chan > 1) { @@ -210,8 +347,8 @@ void fmcomms2_source_impl::set_gain_mode(size_t chan, const std::string& mode) d_gain_mode[chan] = mode; } - -void fmcomms2_source_impl::set_gain(size_t chan, double gain_value) +template <typename T> +void fmcomms2_source_impl<T>::set_gain(size_t chan, double gain_value) { bool is_fmcomms4 = !iio_device_find_channel(phy, "voltage1", false); if ((!is_fmcomms4 && chan > 0) || chan > 1) { @@ -231,21 +368,26 @@ void fmcomms2_source_impl::set_gain(size_t chan, double gain_value) d_gain_value[chan] = gain_value; } -void fmcomms2_source_impl::set_quadrature(bool quadrature) +template <typename T> +void fmcomms2_source_impl<T>::set_quadrature(bool quadrature) { std::vector<std::string> params; params.push_back("in_voltage_quadrature_tracking_en=" + std::to_string(quadrature)); device_source_impl::set_params(params); d_quadrature = quadrature; } -void fmcomms2_source_impl::set_rfdc(bool rfdc) + +template <typename T> +void fmcomms2_source_impl<T>::set_rfdc(bool rfdc) { std::vector<std::string> params; params.push_back("in_voltage_rf_dc_offset_tracking_en=" + std::to_string(rfdc)); device_source_impl::set_params(params); d_rfdc = rfdc; } -void fmcomms2_source_impl::set_bbdc(bool bbdc) + +template <typename T> +void fmcomms2_source_impl<T>::set_bbdc(bool bbdc) { std::vector<std::string> params; params.push_back("in_voltage_bb_dc_offset_tracking_en=" + std::to_string(bbdc)); @@ -253,10 +395,11 @@ void fmcomms2_source_impl::set_bbdc(bool bbdc) d_bbdc = bbdc; } -void fmcomms2_source_impl::set_filter_params(const std::string& filter_source, - const std::string& filter_filename, - float fpass, - float fstop) +template <typename T> +void fmcomms2_source_impl<T>::set_filter_params(const std::string& filter_source, + const std::string& filter_filename, + float fpass, + float fstop) { d_filter_source = filter_source; d_filter_filename = filter_filename; @@ -266,5 +409,9 @@ void fmcomms2_source_impl::set_filter_params(const std::string& filter_source, update_dependent_params(); } +template class fmcomms2_source<int16_t>; +template class fmcomms2_source<std::complex<int16_t>>; +template class fmcomms2_source<gr_complex>; + } /* namespace iio */ } /* namespace gr */ |