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