1 /* -*- c++ -*- */
2 /*
3  * Copyright 2013-2017 Nuand LLC
4  * Copyright 2013 Dimitri Stolnikov <horiz0n@gmx.net>
5  *
6  * GNU Radio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3, or (at your option)
9  * any later version.
10  *
11  * GNU Radio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GNU Radio; see the file COPYING.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street,
19  * Boston, MA 02110-1301, USA.
20  */
21 #ifndef INCLUDED_BLADERF_COMMON_H
22 #define INCLUDED_BLADERF_COMMON_H
23 
24 #include <list>
25 #include <map>
26 #include <memory>
27 #include <mutex>
28 #include <string>
29 #include <vector>
30 
31 #include <libbladeRF.h>
32 
33 #include "osmosdr/ranges.h"
34 #include "arg_helpers.h"
35 
36 #include "bladerf_compat.h"
37 
38 #ifdef _MSC_VER
39 #include <cstddef>
40 typedef ptrdiff_t ssize_t;
41 #endif //_MSC_VER
42 
43 #define BLADERF_DEBUG_ENABLE
44 
45 typedef std::shared_ptr<struct bladerf> bladerf_sptr;
46 
47 /* Identification of the bladeRF hardware in use */
48 typedef enum {
49   BOARD_TYPE_UNKNOWN,   /**< Board type is unknown */
50   BOARD_TYPE_NONE,      /**< Uninitialized or no board present */
51   BOARD_TYPE_BLADERF_1, /**< bladeRF 1 (LMS6002D-based, 1RX/1TX) */
52   BOARD_TYPE_BLADERF_2, /**< bladeRF 2 (AD9361-based, 2RX/2TX) */
53 } bladerf_board_type;
54 
55 /* Mapping of bladerf_channel to bool */
56 typedef std::map<bladerf_channel, bool> bladerf_channel_enable_map;
57 
58 /* Mapping of bladerf_channel to gnuradio port/chan */
59 typedef std::map<bladerf_channel, int> bladerf_channel_map;
60 
61 /* Convenience macros for throwing a runtime error */
62 #define BLADERF_THROW(message)                                              \
63   {                                                                         \
64     throw std::runtime_error(std::string(__FUNCTION__) + ": " + message);   \
65   }
66 
67 #define BLADERF_THROW_STATUS(status, message)                               \
68   {                                                                         \
69     BLADERF_THROW(boost::str(boost::format("%s: %s (%d)") % message         \
70       % bladerf_strerror(status) % status));                                \
71   }
72 
73 /* Convenience macros for printing a warning message to stderr */
74 #define BLADERF_WARNING(message)                                            \
75   {                                                                         \
76     std::cerr << _pfx << __FUNCTION__ << ": " << message << std::endl;      \
77   }
78 
79 #define BLADERF_WARN_STATUS(status, message)                                \
80   {                                                                         \
81     BLADERF_WARNING(message << ": " << bladerf_strerror(status));           \
82   }                                                                         \
83 
84 /* Convenience macro for printing an informational message to stdout */
85 #define BLADERF_INFO(message)                                               \
86   {                                                                         \
87     std::cout << _pfx << __FUNCTION__ << ": " << message << std::endl;      \
88   }
89 
90 /* Convenience macro for printing a debug message to stdout */
91 #ifdef BLADERF_DEBUG_ENABLE
92 #define BLADERF_DEBUG(message) BLADERF_INFO("DEBUG: " << message)
93 #else
94 #define BLADERF_DEBUG(message)
95 #endif // BLADERF_DEBUG_ENABLE
96 
97 /* Given a bladerf_channel_layout, calculate the number of streams */
98 size_t num_streams(bladerf_channel_layout layout);
99 
100 /**
101  * Common class for bladeRF interaction
102  */
103 class bladerf_common
104 {
105 public:
106   /*****************************************************************************
107    * Public methods
108    ****************************************************************************/
109   bladerf_common();
110 
111 protected:
112   /*****************************************************************************
113    * Protected methods
114    ****************************************************************************/
115 
116   /**
117    * Handle initialization and parameters common to both source & sink
118    *
119    * Specify arguments in key=value,key=value format, e.g.
120    *    bladerf=0,buffers=512
121    *
122    * Recognized arguments:
123    *  Key             Allowed values
124    * ---------------------------------------------------------------------------
125    * REQUIRED:
126    *  bladerf         a valid instance or serial number
127    * USB INTERFACE CONTROL:
128    *  buffers         (default: NUM_BUFFERS)
129    *  buflen          (default: NUM_SAMPLES_PER_BUFFER)
130    *  stream_timeout  valid time in milliseconds (default: 3000)
131    *  transfers       (default: NUM_TRANSFERS)
132    * FPGA CONTROL:
133    *  enable_metadata 1 to enable metadata
134    *  fpga            a path to a valid .rbf file
135    *  fpga-reload     1 to force reloading the FPGA unconditionally
136    * RF CONTROL:
137    *  agc             1 to enable, 0 to disable (default: hardware-dependent)
138    *  agc_mode        default, manual, fast, slow, hybrid (default: default)
139    *  loopback        bb_txlpf_rxvga2, bb_txlpf_rxlpf, bb_txvga1_rxvga2,
140    *                  bb_txvga1_rxlpf, rf_lna1, rf_lna2, rf_lna3, firmware,
141    *                  ad9361_bist, none (default: none)
142    *                    ** Note: valid on receive channels only
143    *  rxmux           baseband, 12bit, 32bit, digital (default: baseband)
144    *                    ** Note: valid on receive channels only
145    *  smb             a valid frequency
146    *  tamer           internal, external_1pps, external (default: internal)
147    *  xb200           auto, auto3db, 50M, 144M, 222M, custom (default: auto)
148    * MISC:
149    *  verbosity       verbose, debug, info, warning, error, critical, silent
150    *                    (default: info)
151    *                    ** Note: applies only to libbladeRF logging
152    */
153   void init(dict_t const &dict, bladerf_direction direction);
154 
155   /* Get a vector of available devices */
156   static std::vector<std::string> devices();
157   /* Get the type of the open bladeRF board */
158   bladerf_board_type get_board_type();
159   /* Get the maximum number of channels supported in a given direction */
160   size_t get_max_channels(bladerf_direction direction);
161 
162   void set_channel_enable(bladerf_channel ch, bool enable);
163   bool get_channel_enable(bladerf_channel ch);
164 
165   /* Set libbladeRF verbosity */
166   void set_verbosity(std::string const &verbosity);
167 
168   /* Convert an antenna/channel name (e.g. "RX2") to a bladerf_channel */
169   bladerf_channel str2channel(std::string const &ch);
170   /* Convert a bladerf_channel to an antenna/channel name (e.g. "RX2") */
171   std::string channel2str(bladerf_channel ch);
172   /* Convert a bladerf_channel to a hardware port identifier */
173   int channel2rfport(bladerf_channel ch);
174 
175   /* Using the channel map, get the bladerf_channel for a gnuradio chan */
176   bladerf_channel chan2channel(bladerf_direction direction, size_t chan = 0);
177 
178   /* Get range of supported sampling rates for channel ch */
179   osmosdr::meta_range_t sample_rates(bladerf_channel ch);
180   /* Set sampling rate on channel ch to rate */
181   double set_sample_rate(double rate, bladerf_channel ch);
182   /* Get the current sampling rate on channel ch */
183   double get_sample_rate(bladerf_channel ch);
184 
185   /* Get range of supported RF frequencies for channel ch */
186   osmosdr::freq_range_t freq_range(bladerf_channel ch);
187   /* Set center RF frequency of channel ch to freq */
188   double set_center_freq(double freq, bladerf_channel ch);
189   /* Get the center RF frequency of channel ch */
190   double get_center_freq(bladerf_channel ch);
191 
192   /* Get range of supported bandwidths for channel ch */
193   osmosdr::freq_range_t filter_bandwidths(bladerf_channel ch);
194   /* Set the bandwidth on channel ch to bandwidth */
195   double set_bandwidth(double bandwidth, bladerf_channel ch);
196   /* Get the current bandwidth of channel ch */
197   double get_bandwidth(bladerf_channel ch);
198 
199   /* Get the names of gain stages on channel ch */
200   std::vector<std::string> get_gain_names(bladerf_channel ch);
201   /* Get range of supported overall gain values on channel ch */
202   osmosdr::gain_range_t get_gain_range(bladerf_channel ch);
203   /* Get range of supported gain values for gain stage 'name' on channel ch */
204   osmosdr::gain_range_t get_gain_range(std::string const &name,
205                                        bladerf_channel ch);
206 
207   /* Enable or disable the automatic gain control on channel ch */
208   bool set_gain_mode(bool automatic, bladerf_channel ch,
209                      bladerf_gain_mode agc_mode = BLADERF_GAIN_DEFAULT);
210   /* Get the current automatic gain control status on channel ch */
211   bool get_gain_mode(bladerf_channel ch);
212 
213   /* Set the overall gain value on channel ch */
214   double set_gain(double gain, bladerf_channel ch);
215   /* Set the gain of stage 'name' on channel ch */
216   double set_gain(double gain, std::string const &name, bladerf_channel ch);
217   /* Get the overall gain value on channel ch */
218   double get_gain(bladerf_channel ch);
219   /* Get the gain of stage 'name' on channel ch */
220   double get_gain(std::string const &name, bladerf_channel ch);
221 
222   /* Get the list of antennas supported by a channel */
223   std::vector<std::string> get_antennas(bladerf_direction dir);
224   bool set_antenna(bladerf_direction dir, size_t chan, const std::string &antenna);
225 
226   /* Set the DC offset on channel ch */
227   int set_dc_offset(std::complex<double> const &offset, bladerf_channel ch);
228   /* Set the IQ balance on channel ch */
229   int set_iq_balance(std::complex<double> const &balance, bladerf_channel ch);
230 
231   /* Get the list of supported clock sources */
232   std::vector<std::string> get_clock_sources(size_t mboard = 0);
233   /* Set the clock source to */
234   void set_clock_source(std::string const &source, size_t mboard = 0);
235   /* Get the name of the current clock source */
236   std::string get_clock_source(size_t mboard = 0);
237 
238   /* Set the SMB frequency */
239   void set_smb_frequency(double frequency);
240   /* Get the current SMB frequency */
241   double get_smb_frequency();
242 
243   /*****************************************************************************
244    * Protected members
245    ****************************************************************************/
246   bladerf_sptr _dev;            /**< shared pointer for the active device */
247   std::string _pfx;             /**< prefix for console messages */
248   unsigned int _failures;       /**< counter for consecutive rx/tx failures */
249 
250   size_t _num_buffers;          /**< number of buffers to allocate */
251   size_t _samples_per_buffer;   /**< how many samples per buffer */
252   size_t _num_transfers;        /**< number of active backend transfers */
253   unsigned int _stream_timeout; /**< timeout for backend transfers */
254 
255   bladerf_format _format;       /**< sample format to use */
256 
257   bladerf_channel_map _chanmap; /**< map of antennas to channels */
258   bladerf_channel_enable_map _enables;  /**< enabled channels */
259 
260   /*****************************************************************************
261    * Protected constants
262    ****************************************************************************/
263   /* Maximum bladerf_sync_{rx,tx} failures to allow before giving up */
264   static const unsigned int MAX_CONSECUTIVE_FAILURES = 3;
265 
266   /* BladeRF IQ correction parameters */
267   static const int16_t DCOFF_SCALE = 2048;
268   static const int16_t GAIN_SCALE = 4096;
269   static const int16_t PHASE_SCALE = 4096;
270 
271 private:
272   /*****************************************************************************
273    * Private methods
274    ****************************************************************************/
275   /* Open the bladeRF described by device_name. Returns a sptr if successful */
276   bladerf_sptr open(const std::string &device_name);
277   /* Called by shared_ptr when a bladerf_sptr hits a refcount of 0 */
278   static void close(void *dev);
279   /* If a device described by devinfo is open, this returns a sptr to it */
280   static bladerf_sptr get_cached_device(struct bladerf_devinfo devinfo);
281   /* Prints a summary of device information */
282   void print_device_info();
283 
284   bool is_antenna_valid(bladerf_direction dir, const std::string &antenna);
285 
286   /*****************************************************************************
287    * Private members
288    ****************************************************************************/
289   static std::mutex _devs_mutex;  /**< mutex for access to _devs */
290   static std::list<std::weak_ptr<struct bladerf>> _devs;  /**< dev cache */
291 };
292 
293 #endif
294