GNU Radio's SOAPY Package
source_impl.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * gr-soapy: Soapy SDR Radio Out-Of-Tree Module
4  *
5  * Copyright (C) 2018, 2019, 2020
6  * Libre Space Foundation <http://libre.space>
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 /// \file source_impl.h
22 
23 #ifndef INCLUDED_SOAPY_SOURCE_IMPL_H
24 #define INCLUDED_SOAPY_SOURCE_IMPL_H
25 
26 #include <soapy/source.h>
27 #include <boost/bind.hpp>
28 #include <boost/thread/mutex.hpp>
29 
30 #include <SoapySDR/Version.hpp>
31 #include <SoapySDR/Modules.hpp>
32 #include <SoapySDR/Registry.hpp>
33 #include <SoapySDR/Device.hpp>
34 
35 typedef boost::function<void(pmt::pmt_t, size_t)> cmd_handler_t;
36 
37 namespace gr {
38 namespace soapy {
39 
40 /*!
41  * \brief Source block implementation for SDR devices.
42  */
43 
44 class source_impl : public source {
45 private:
46  const std::string d_dev_str;
47  const std::string d_args;
48 
49  SoapySDR::Device *d_device;
50  SoapySDR::Stream *d_stream;
51 
52  bool d_stopped;
53  size_t d_mtu;
54 
55  double d_frequency;
56  float d_gain;
57  double d_sampling_rate;
58  double d_bandwidth;
59  std::string d_antenna;
60  size_t d_nchan;
61  gr_complexd d_dc_offset;
62  bool d_dc_offset_auto_mode;
63  bool d_gain_auto_mode;
64  double d_frequency_correction;
65  gr_complexd d_iq_balance;
66  double d_clock_rate;
67  std::string d_clock_source;
68 
69  void register_msg_cmd_handler(const pmt::pmt_t &cmd, cmd_handler_t handler);
70  std::map<pmt::pmt_t, cmd_handler_t> d_cmd_handlers;
71 
72  inline io_signature::sptr
73  args_to_io_sig(const std::string type, size_t nchan)
74  {
75  size_t size = 0;
76  if (type == "fc32") {
77  size = 8;
78  }
79  else if (type == "sc16") {
80  size = 4;
81  }
82  else if (type == "sc8") {
83  size = 2;
84  }
85  else if (type == "s16") {
86  size = 2;
87  }
88  else if (type == "s8") {
89  size = 1;
90  }
91  return io_signature::make(nchan, nchan, size);
92  }
93 
94  /*!
95  * Create and store a new Device object using the make function of SoapySDR
96  * API.
97  * For every makeDevice call an unmakeDevice call is also made.
98  *
99  * \param argStr device construction key/value argument string
100  */
101  void
102  makeDevice(const std::string &argStr);
103 
104  /*!
105  * Destroy a Device object created by makeDevice call.
106  * Called for every makeDevice call.
107  * \param dev a pointer to a Device object
108  */
109  void
110  unmakeDevice(SoapySDR::Device *dev);
111 
112 public:
113  source_impl(size_t nchan, const std::string device,
114  const std::string args, double sampling_rate,
115  const std::string type);
116  ~source_impl();
117 
118  virtual bool start();
119  virtual bool stop();
120 
121  // Where all the action really happens
122  int work(int noutput_items,
123  gr_vector_const_void_star &input_items,
124  gr_vector_void_star &output_items);
125 
126  virtual std::vector<std::string> listAntennas(int channel);
127 
128  /*!
129  * Set the center frequency for the specified RX chain.
130  * Default implementation tunes RF component frequency as close as
131  * possible to the requested frequency. See specific device module
132  * for more information.
133  * \param channel an available channel on the device
134  * \param frequency center frequency in Hz
135  */
136  void set_frequency(size_t channel, double frequency);
137 
138  /*!
139  * Set the center frequency for the specified RX chain of the element.
140  * Default implementation tunes RF component frequency as close as
141  * possible to the requested frequency. See specific device module
142  * for more information
143  * \param channel an available channel on the device
144  * \param name an available element name
145  * \param frequency center frequency in Hz
146  */
147  void set_frequency(size_t channel, const std::string &name, double frequency);
148 
149  virtual void set_overall_gain(size_t channel, float gain, bool manual_mode);
150 
151  virtual bool hasDCOffset(int channel);
152  virtual bool hasIQBalance(int channel);
153  virtual bool hasFrequencyCorrection(int channel);
154 
155  /*!
156  * Set the overall gain for the specified RX chain.
157  * The gain will be distributed automatically across available
158  * elements according to Soapy API.
159  * \param channel an available channel on the device
160  * \param gain the new amplification value in dB
161  */
162  void set_gain(size_t channel, float gain);
163 
164  /*!
165  * Set the value for the specified gain for the specified TX chain.
166  * \param channel an available channel on the device
167  * \param name an available gain on the device
168  * \param gain gain the new amplification value in dB
169  */
170  void set_gain(size_t channel, const std::string name, float gain,
171  bool manual_mode);
172 
173 
174  /**
175  * Checks if the specified gain type for the given channel is
176  * available
177  * @param channel an available channel on the device
178  * @param nane an available gain on the device
179  * @return true if the gain setting exists, false otherwise
180  */
181  bool gain_available(size_t channel, const std::string &name);
182 
183  /*!
184  * Set the automatic gain mode for the specified chain if supported.
185  * If not supported set gain value manually.
186  * \param channel an available channel on the device
187  * \param gain_auto_mode true for automatic gain mode
188  */
189  void set_gain_mode(size_t channel, bool gain_auto_mode);
190 
191  /*!
192  * Set the baseband sample rate for the RX chain.
193  * \param channel an available channel on the device
194  * \param sample_rate the sample rate samples per second
195  */
196  void set_sample_rate(size_t channel, double sample_rate);
197 
198  /*!
199  * Set the baseband filter width of the RX chain
200  * \param channel an available channel on the device
201  * \param bandwidth the baseband filter width in Hz
202  */
203  void set_bandwidth(size_t channel, double bandwidth);
204 
205  /*!
206  * Set the antenna element for the RX chain.
207  * \param channel an available channel on the device
208  * \param name the name of an available antenna
209  */
210  void set_antenna(size_t channel, const std::string &name);
211 
212  /*!
213  * Set the dc offset correction for the RX chain.
214  * If the dc offset correction automatic mode is on
215  * the value is omitted and the device sets the dc offset
216  * correction automatically.
217  * \param channel an available channel on the device
218  * \param dc_offset the relative correction (1.0 max)
219  * \param dc_offset_auto_mode true for automatic dc offset correction
220  */
221  void set_dc_offset(size_t channel, gr_complexd dc_offset,
222  bool dc_offset_auto_mode);
223 
224  /*!
225  * Set automatic dc offset correction to the RX chain
226  * if supported by the device.
227  * \param channel an available channel on the device
228  * \param dc_offset_auto_mode true for automatic dc offset correction
229  */
230  void set_dc_offset_mode(size_t channel, bool dc_offset_auto_mode);
231 
232  /*!
233  * Set the frequency correction to the RX chain.
234  * @param channel an available channel on the device
235  * @param freq_correction the correction value in PPM
236  */
237  void set_frequency_correction(size_t channel, double freq_correction);
238 
239  /*!
240  * Set iq balance correction to the RX chain
241  * \param channel an available channel on the device
242  * \param iq_balance the relative correction (1.0 max)
243  */
244  void set_iq_balance(size_t channel, gr_complexd iq_balance);
245 
246  /*!
247  * Set the master clock rate of the device
248  * \param clock_rate the clock rate in Hz
249  */
250  void set_master_clock_rate(double clock_rate);
251 
252  /*!
253  * Set the clock source of the device
254  * \param clock_source the name of clock source
255  */
256  void set_clock_source(const std::string &clock_source);
257 
258  /*!
259  * Set the frontend mapping of available DSP units to RF frontends.
260  * This mapping controls channel mapping and channel availability.
261  * \param frontend_mapping a vendor-specific mapping string
262  */
263  void set_frontend_mapping(const std::string &frontend_mapping);
264 
265  /*!
266  * Get the down conversion frequency of the chain.
267  * \param channel an available channel on the device
268  * \return the center frequency in Hz
269  */
270  double get_frequency(size_t channel);
271 
272  /*!
273  * Get the overall value of the gain elements in a chain
274  * \param channel an available channel on the device
275  * \return the value of the gain in dB
276  */
277  double get_gain(size_t channel);
278 
279  /*!
280  * Get the automatic gain mode on the RX chain.
281  * \param channel an available channel on the device
282  * \return true for automatic gain setting
283  */
284  bool get_gain_mode(size_t channel);
285 
286  /*!
287  * Get the baseband sample rate of the RX chain.
288  * \param channel an available channel on the device
289  * \return the sample rate in samples per second
290  */
291  double get_sampling_rate(size_t channel);
292 
293  /*!
294  * Get baseband filter width of the RX chain.
295  * \param channel an available channel on the device
296  * \return the baseband filter width in Hz
297  */
298  double get_bandwidth(size_t channel);
299 
300  /*!
301  * Get the selected antenna on RX chain.
302  * \param channel an available channel on the device
303  * \return the name of the selected antenna
304  */
305  std::string get_antenna(size_t channel);
306 
307  /*!
308  * Get the DC offset correction.
309  * \param channel an available channel on the device
310  * \return the relative correction (1.0 max)
311  */
312  std::complex<double> get_dc_offset(size_t channel);
313 
314  /*!
315  * Get the automatic DC offset correction mode.
316  * \param channel an available channel on the device
317  * \return true for automatic offset correction
318  */
319  bool get_dc_offset_mode(size_t channel);
320 
321  /*!
322  * Get the frequency correction value.
323  * \param channel an available channel on the device
324  * \return the correction value in PPM
325  */
326  double get_frequency_correction(size_t channel);
327 
328  /*!
329  * Get the IQ balance correction.
330  * \param channel an available channel on the device
331  * \return the relative correction (1.0 max)
332  */
333  std::complex<double> get_iq_balance(size_t channel);
334 
335  /*!
336  * Get the master clock rate of the device.
337  * \return the clock rate in Hz
338  */
339  double get_master_clock_rate();
340 
341  /*!
342  * Get the clock source of the device
343  * \return the name of the clock source
344  */
345  std::string get_clock_source();
346 
347  /*!
348  * Calls the correct message handler according to the received message symbol.
349  * A dictionary with key the handler name is used in order to call the
350  * corresponding handler.
351  * \param msg a PMT dictionary
352  */
353  void msg_handler_command(pmt::pmt_t msg);
354 
355  /*!
356  * Set the center frequency of the RX chain.
357  * @param val center frequency in Hz
358  * @param chann an available channel on the device
359  */
360  void cmd_handler_frequency(pmt::pmt_t val, size_t chann);
361 
362  /*!
363  * Set the overall gain for the specified chain.
364  * The gain will be distributed automatically across available
365  * elements according to Soapy API.
366  * @param val the new amplification value in dB
367  * @param chann an avalaible channel on the device
368  */
369  void cmd_handler_gain(pmt::pmt_t val, size_t chann);
370 
371  /*!
372  * Set the baseband sample rate for the RX chain.
373  * @param val the sample rate samples per second
374  * @param chann an available channel on the device
375  */
376  void cmd_handler_samp_rate(pmt::pmt_t val, size_t chann);
377 
378  /*!
379  * Set the baseband filter width for the RX chain.
380  * @param val baseband filter width in Hz
381  * @param chann an available channel on the device
382  */
383  void cmd_handler_bw(pmt::pmt_t val, size_t chann);
384 
385  /*!
386  * Set the anntena element for the RX chain.
387  * @param val name of the anntena
388  * @param chann an available channel on the device
389  */
390  void cmd_handler_antenna(pmt::pmt_t val, size_t chann);
391 };
392 } // namespace soapy
393 } // namespace gr
394 
395 #endif /* INCLUDED_SOAPY_SOURCE_IMPL_H */
396 
gr::soapy::source_impl::stop
virtual bool stop()
gr::soapy::source_impl::set_clock_source
void set_clock_source(const std::string &clock_source)
gr::soapy::source_impl::get_gain
double get_gain(size_t channel)
gr::soapy::source_impl::set_iq_balance
void set_iq_balance(size_t channel, gr_complexd iq_balance)
gr::soapy::source_impl::~source_impl
~source_impl()
cmd_handler_t
boost::function< void(pmt::pmt_t, size_t)> cmd_handler_t
Definition: sink_impl.h:34
gr::soapy::source_impl::set_frontend_mapping
void set_frontend_mapping(const std::string &frontend_mapping)
gr::soapy::source_impl::set_gain_mode
void set_gain_mode(size_t channel, bool gain_auto_mode)
gr::soapy::source_impl::cmd_handler_bw
void cmd_handler_bw(pmt::pmt_t val, size_t chann)
gr::soapy::source_impl::hasIQBalance
virtual bool hasIQBalance(int channel)
gr::soapy::source_impl::get_dc_offset
std::complex< double > get_dc_offset(size_t channel)
gr::soapy::source_impl::hasFrequencyCorrection
virtual bool hasFrequencyCorrection(int channel)
gr::soapy::source_impl::set_frequency
void set_frequency(size_t channel, double frequency)
gr::soapy::source_impl::set_master_clock_rate
void set_master_clock_rate(double clock_rate)
gr::soapy::source_impl::set_dc_offset
void set_dc_offset(size_t channel, gr_complexd dc_offset, bool dc_offset_auto_mode)
gr::soapy::source_impl::work
int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
gr::soapy::source_impl::get_sampling_rate
double get_sampling_rate(size_t channel)
gr::soapy::source
Definition: source.h:54
gr::soapy::source_impl::set_gain
void set_gain(size_t channel, float gain)
gr::soapy::source_impl::set_overall_gain
virtual void set_overall_gain(size_t channel, float gain, bool manual_mode)
gr::soapy::source_impl::cmd_handler_antenna
void cmd_handler_antenna(pmt::pmt_t val, size_t chann)
gr::soapy::source_impl::cmd_handler_gain
void cmd_handler_gain(pmt::pmt_t val, size_t chann)
gr::soapy::source_impl::msg_handler_command
void msg_handler_command(pmt::pmt_t msg)
source.h
gr::soapy::source_impl::start
virtual bool start()
gr::soapy::source_impl::get_master_clock_rate
double get_master_clock_rate()
gr::soapy::source_impl::cmd_handler_samp_rate
void cmd_handler_samp_rate(pmt::pmt_t val, size_t chann)
gr::soapy::source_impl
Source block implementation for SDR devices.
Definition: source_impl.h:44
gr::soapy::source_impl::get_frequency_correction
double get_frequency_correction(size_t channel)
cmd_handler_t
boost::function< void(pmt::pmt_t, size_t)> cmd_handler_t
Definition: source_impl.h:35
gr::soapy::source_impl::get_antenna
std::string get_antenna(size_t channel)
gr::soapy::source_impl::listAntennas
virtual std::vector< std::string > listAntennas(int channel)
gr::soapy::source_impl::cmd_handler_frequency
void cmd_handler_frequency(pmt::pmt_t val, size_t chann)
gr::soapy::source_impl::get_frequency
double get_frequency(size_t channel)
gr::soapy::source_impl::hasDCOffset
virtual bool hasDCOffset(int channel)
gr::soapy::source_impl::get_iq_balance
std::complex< double > get_iq_balance(size_t channel)
gr::soapy::source_impl::get_dc_offset_mode
bool get_dc_offset_mode(size_t channel)
gr::soapy::source_impl::set_bandwidth
void set_bandwidth(size_t channel, double bandwidth)
gr::soapy::source_impl::get_bandwidth
double get_bandwidth(size_t channel)
gr::soapy::source_impl::set_dc_offset_mode
void set_dc_offset_mode(size_t channel, bool dc_offset_auto_mode)
gr::soapy::source_impl::set_sample_rate
void set_sample_rate(size_t channel, double sample_rate)
gr::soapy::source_impl::gain_available
bool gain_available(size_t channel, const std::string &name)
gr
Definition: sink.h:29
gr::soapy::source_impl::set_frequency_correction
void set_frequency_correction(size_t channel, double freq_correction)
gr::soapy::source_impl::source_impl
source_impl(size_t nchan, const std::string device, const std::string args, double sampling_rate, const std::string type)
gr::soapy::source_impl::get_clock_source
std::string get_clock_source()
gr::soapy::source_impl::set_antenna
void set_antenna(size_t channel, const std::string &name)
gr::soapy::source_impl::get_gain_mode
bool get_gain_mode(size_t channel)