Project

General

Profile

Bug #5425 » bladerf_source_c_fix.cc

aoweis, 01/29/2022 04:20 AM

 
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

    
22
/*
23
 * config.h is generated by configure.  It contains the results
24
 * of probing for features, options etc.  It should be the first
25
 * file included in your .cc file.
26
 */
27
#ifdef HAVE_CONFIG_H
28
#include "config.h"
29
#endif
30

    
31
#include <iostream>
32

    
33
#include <boost/assign.hpp>
34
#include <boost/format.hpp>
35
#include <boost/lexical_cast.hpp>
36

    
37
#include <gnuradio/io_signature.h>
38

    
39
#include <volk/volk.h>
40

    
41
#include "arg_helpers.h"
42
#include "bladerf_source_c.h"
43
#include "osmosdr/source.h"
44

    
45
using namespace boost::assign;
46

    
47
/******************************************************************************
48
 * Functions
49
 ******************************************************************************/
50

    
51
/*
52
 * Create a new instance of bladerf_source_c and return
53
 * a boost shared_ptr.  This is effectively the public constructor.
54
 */
55
bladerf_source_c_sptr make_bladerf_source_c(const std::string &args)
56
{
57
  return gnuradio::get_initial_sptr(new bladerf_source_c(args));
58
}
59

    
60
/******************************************************************************
61
 * Private methods
62
 ******************************************************************************/
63

    
64
/*
65
 * The private constructor
66
 */
67
bladerf_source_c::bladerf_source_c(const std::string &args) :
68
  gr::sync_block( "bladerf_source_c",
69
                  gr::io_signature::make(0, 0, 0),
70
                  args_to_io_signature(args)),
71
  _16icbuf(NULL),
72
  _32fcbuf(NULL),
73
  _running(false),
74
  _agcmode(BLADERF_GAIN_DEFAULT)
75
{
76
  int status;
77

    
78
  dict_t dict = params_to_dict(args);
79

    
80
  /* Perform src/sink agnostic initializations */
81
  init(dict, BLADERF_RX);
82

    
83
  /* Handle setting of sampling mode */
84
  if (dict.count("sampling")) {
85
    bladerf_sampling sampling = BLADERF_SAMPLING_UNKNOWN;
86

    
87
    if (dict["sampling"] == "internal") {
88
      sampling = BLADERF_SAMPLING_INTERNAL;
89
    } else if (dict["sampling"] == "external") {
90
      sampling = BLADERF_SAMPLING_EXTERNAL;
91
    } else {
92
      BLADERF_WARNING("Invalid sampling mode: " + dict["sampling"]);
93
    }
94

    
95
    if (sampling != BLADERF_SAMPLING_UNKNOWN) {
96
      status = bladerf_set_sampling(_dev.get(), sampling);
97
      if (status != 0) {
98
        BLADERF_WARNING("Problem while setting sampling mode: " <<
99
                        bladerf_strerror(status));
100
      }
101
    }
102
  }
103

    
104
  /* Bias tee */
105
  if (dict.count("biastee")) {
106
    set_biastee_mode(dict["biastee"]);
107
  }
108

    
109
  /* Loopback */
110
  set_loopback_mode(dict.count("loopback") ? dict["loopback"] : "none");
111

    
112
  /* RX Mux */
113
  set_rx_mux_mode(dict.count("rxmux") ? dict["rxmux"] : "baseband");
114

    
115
  /* AGC mode */
116
  if (dict.count("agc_mode")) {
117
    set_agc_mode(dict["agc_mode"]);
118
  }
119

    
120
  /* Specify initial gain mode */
121
  if (dict.count("agc")) {
122
    for (size_t i = 0; i < get_max_channels(); ++i) {
123
      set_gain_mode(boost::lexical_cast<bool>(dict["agc"]), BLADERF_CHANNEL_RX(i));
124
      BLADERF_INFO(boost::str(boost::format("%s gain mode set to '%s'")
125
                    % channel2str(BLADERF_CHANNEL_RX(i))
126
                    % get_gain_mode(BLADERF_CHANNEL_RX(i))));
127
    }
128
  }
129

    
130
  /* Warn user about using an old FPGA version, as we no longer strip off the
131
   * markers that were pressent in the pre-v0.0.1 FPGA */
132
  {
133
    struct bladerf_version fpga_version;
134

    
135
    if (bladerf_fpga_version(_dev.get(), &fpga_version) != 0) {
136
      BLADERF_WARNING("Failed to get FPGA version");
137
    } else if (fpga_version.major <= 0 &&
138
               fpga_version.minor <= 0 &&
139
               fpga_version.patch < 1) {
140
      BLADERF_WARNING("Warning: FPGA version v0.0.1 or later is required. "
141
                      "Using an earlier FPGA version will result in "
142
                      "misinterpeted samples.");
143
    }
144
  }
145

    
146
  /* Initialize channel <-> antenna map */
147
  for (std::string ant : get_antennas()) {
148
    _chanmap[str2channel(ant)] = -1;
149
  }
150

    
151
  /* Bounds-checking output signature depending on our underlying hardware */
152
  if (get_num_channels() > get_max_channels()) {
153
    BLADERF_WARNING("Warning: number of channels specified on command line ("
154
                    << get_num_channels() << ") is greater than the maximum "
155
                    "number supported by this device (" << get_max_channels()
156
                    << "). Resetting to " << get_max_channels() << ".");
157

    
158
    set_output_signature(gr::io_signature::make(get_max_channels(),
159
                                                get_max_channels(),
160
                                                sizeof(gr_complex)));
161
  }
162

    
163
  /* Set up constraints */
164
  int const alignment_multiple = volk_get_alignment() / sizeof(gr_complex);
165
  set_alignment(std::max(1,alignment_multiple));
166
  set_max_noutput_items(_samples_per_buffer);
167
  set_output_multiple(get_num_channels());
168

    
169
  /* Set channel layout */
170
  _layout = (get_num_channels() > 1) ? BLADERF_RX_X2 : BLADERF_RX_X1;
171

    
172
  /* Initial wiring of antennas to channels */
173
  for (size_t ch = 0; ch < get_num_channels(); ++ch) {
174
    set_channel_enable(BLADERF_CHANNEL_RX(ch), true);
175
    _chanmap[BLADERF_CHANNEL_RX(ch)] = ch;
176
  }
177

    
178
  BLADERF_DEBUG("initialization complete");
179
}
180

    
181
bool bladerf_source_c::is_antenna_valid(const std::string &antenna)
182
{
183
  for (std::string ant : get_antennas()) {
184
    if (antenna == ant) {
185
      return true;
186
    }
187
  }
188

    
189
  return false;
190
}
191

    
192
/******************************************************************************
193
 * Public methods
194
 ******************************************************************************/
195

    
196
std::string bladerf_source_c::name()
197
{
198
  return "bladeRF receiver";
199
}
200

    
201
std::vector<std::string> bladerf_source_c::get_devices()
202
{
203
  return bladerf_common::devices();
204
}
205

    
206
size_t bladerf_source_c::get_max_channels()
207
{
208
  return bladerf_common::get_max_channels(BLADERF_RX);
209
}
210

    
211
size_t bladerf_source_c::get_num_channels()
212
{
213
  return output_signature()->max_streams();
214
}
215

    
216
bool bladerf_source_c::start()
217
{
218
  int status;
219

    
220
  BLADERF_DEBUG("starting source");
221

    
222
  gr::thread::scoped_lock guard(d_mutex);
223

    
224
  status = bladerf_sync_config(_dev.get(), _layout, _format, _num_buffers,
225
                               _samples_per_buffer, _num_transfers,
226
                               _stream_timeout);
227
  if (status != 0) {
228
    BLADERF_THROW_STATUS(status, "bladerf_sync_config failed");
229
  }
230

    
231
  for (size_t ch = 0; ch < get_max_channels(); ++ch) {
232
    bladerf_channel brfch = BLADERF_CHANNEL_RX(ch);
233
    if (get_channel_enable(brfch)) {
234
      status = bladerf_enable_module(_dev.get(), brfch, true);
235
      if (status != 0) {
236
        BLADERF_THROW_STATUS(status, "bladerf_enable_module failed");
237
      }
238
    }
239
  }
240

    
241
  /* Allocate memory for conversions in work() */
242
  size_t alignment = volk_get_alignment();
243

    
244
  _16icbuf = reinterpret_cast<int16_t *>(volk_malloc(4*_samples_per_buffer*sizeof(int16_t), alignment));
245
  _32fcbuf = reinterpret_cast<gr_complex *>(volk_malloc(2*_samples_per_buffer*sizeof(gr_complex), alignment));
246

    
247
  _running = true;
248

    
249
  return true;
250
}
251

    
252
bool bladerf_source_c::stop()
253
{
254
  int status;
255

    
256
  BLADERF_DEBUG("stopping source");
257

    
258
  gr::thread::scoped_lock guard(d_mutex);
259

    
260
  if (!_running) {
261
    BLADERF_WARNING("source already stopped, nothing to do here");
262
    return true;
263
  }
264

    
265
  _running = false;
266

    
267
  for (size_t ch = 0; ch < get_max_channels(); ++ch) {
268
    bladerf_channel brfch = BLADERF_CHANNEL_RX(ch);
269
    if (get_channel_enable(brfch)) {
270
      status = bladerf_enable_module(_dev.get(), brfch, false);
271
      if (status != 0) {
272
        BLADERF_THROW_STATUS(status, "bladerf_enable_module failed");
273
      }
274
    }
275
  }
276

    
277
  /* Deallocate conversion memory */
278
  volk_free(_16icbuf);
279
  volk_free(_32fcbuf);
280
  _16icbuf = NULL;
281
  _32fcbuf = NULL;
282

    
283
  return true;
284
}
285

    
286
int bladerf_source_c::work(int noutput_items,
287
                          gr_vector_const_void_star &input_items,
288
                          gr_vector_void_star &output_items)
289
{
290
  int status;
291
  struct bladerf_metadata meta;
292
  struct bladerf_metadata *meta_ptr = NULL;
293
  size_t nstreams = num_streams(_layout);
294

    
295
  gr::thread::scoped_lock guard(d_mutex);
296

    
297
  // if we aren't running, nothing to do here
298
  if (!_running) {
299
    return 0;
300
  }
301

    
302
  // set up metadata
303
  if (BLADERF_FORMAT_SC16_Q11_META == _format) {
304
    memset(&meta, 0, sizeof(meta));
305
    meta.flags = BLADERF_META_FLAG_RX_NOW;
306
    meta_ptr = &meta;
307
  }
308

    
309
  // grab samples into temp buffer
310
    if(nstreams > 1)
311
    status = bladerf_sync_rx(_dev.get(), static_cast<void *>(_16icbuf), 2 * noutput_items, meta_ptr, _stream_timeout);
312
  else
313
    status = bladerf_sync_rx(_dev.get(), static_cast<void *>(_16icbuf), noutput_items, meta_ptr, _stream_timeout);
314

    
315
  if (status != 0) {
316
    BLADERF_WARNING(boost::str(boost::format("bladerf_sync_rx error: %s")
317
                    % bladerf_strerror(status)));
318
    ++_failures;
319

    
320
    if (_failures >= MAX_CONSECUTIVE_FAILURES) {
321
      BLADERF_WARNING("Consecutive error limit hit. Shutting down.");
322
      return WORK_DONE;
323
    }
324
  } else {
325
    _failures = 0;
326
  }
327

    
328
  // convert from int16_t to float
329
  // output_items is gr_complex (2x float), so num_points is 2*noutput_items
330
  volk_16i_s32f_convert_32f(reinterpret_cast<float *>(_32fcbuf), _16icbuf,
331
                            SCALING_FACTOR, 4*noutput_items);
332

    
333
  // copy the samples into output_items
334
  gr_complex **out = reinterpret_cast<gr_complex **>(&output_items[0]);
335

    
336
  if (nstreams > 1) {
337
    // we need to deinterleave the multiplex as we copy
338
    gr_complex const *deint_in = _32fcbuf;
339

    
340
    for (size_t i = 0; i < noutput_items; ++i) {
341
      for (size_t n = 0; n < nstreams; ++n) {
342
        memcpy(out[n]++, deint_in++, sizeof(gr_complex));
343
      }
344
    }
345
  } else {
346
    // no deinterleaving to do: simply copy everything
347
    memcpy(out[0], _32fcbuf, sizeof(gr_complex) * noutput_items);
348
  }
349

    
350
  return noutput_items;
351
}
352

    
353
osmosdr::meta_range_t bladerf_source_c::get_sample_rates()
354
{
355
  return sample_rates(chan2channel(BLADERF_RX, 0));
356
}
357

    
358
double bladerf_source_c::set_sample_rate(double rate)
359
{
360
  return bladerf_common::set_sample_rate(rate, chan2channel(BLADERF_RX, 0));
361
}
362

    
363
double bladerf_source_c::get_sample_rate()
364
{
365
  return bladerf_common::get_sample_rate(chan2channel(BLADERF_RX, 0));
366
}
367

    
368
osmosdr::freq_range_t bladerf_source_c::get_freq_range(size_t chan)
369
{
370
  return bladerf_common::freq_range(chan2channel(BLADERF_RX, chan));
371
}
372

    
373
double bladerf_source_c::set_center_freq(double freq, size_t chan)
374
{
375
  return bladerf_common::set_center_freq(freq, chan2channel(BLADERF_RX, chan));
376
}
377

    
378
double bladerf_source_c::get_center_freq(size_t chan)
379
{
380
  return bladerf_common::get_center_freq(chan2channel(BLADERF_RX, chan));
381
}
382

    
383
double bladerf_source_c::set_freq_corr(double ppm, size_t chan)
384
{
385
  /* TODO: Write the VCTCXO with a correction value (also changes TX ppm value!) */
386
  BLADERF_WARNING("Frequency correction is not implemented.");
387
  return get_freq_corr(chan2channel(BLADERF_RX, chan));
388
}
389

    
390
double bladerf_source_c::get_freq_corr(size_t chan)
391
{
392
  /* TODO: Return back the frequency correction in ppm */
393
  return 0;
394
}
395

    
396
std::vector<std::string> bladerf_source_c::get_gain_names(size_t chan)
397
{
398
  return bladerf_common::get_gain_names(chan2channel(BLADERF_RX, chan));
399
}
400

    
401
osmosdr::gain_range_t bladerf_source_c::get_gain_range(size_t chan)
402
{
403
  return bladerf_common::get_gain_range(chan2channel(BLADERF_RX, chan));
404
}
405

    
406
osmosdr::gain_range_t bladerf_source_c::get_gain_range(const std::string &name,
407
                                                       size_t chan)
408
{
409
  return bladerf_common::get_gain_range(name, chan2channel(BLADERF_RX, chan));
410
}
411

    
412
bool bladerf_source_c::set_gain_mode(bool automatic, size_t chan)
413
{
414
  return bladerf_common::set_gain_mode(automatic,
415
                                       chan2channel(BLADERF_RX, chan),
416
                                       _agcmode);
417
}
418

    
419
bool bladerf_source_c::get_gain_mode(size_t chan)
420
{
421
  return bladerf_common::get_gain_mode(chan2channel(BLADERF_RX, chan));
422
}
423

    
424
double bladerf_source_c::set_gain(double gain, size_t chan)
425
{
426
  return bladerf_common::set_gain(gain, chan2channel(BLADERF_RX, chan));
427
}
428

    
429
double bladerf_source_c::set_gain(double gain, const std::string &name,
430
                                  size_t chan)
431
{
432
  return bladerf_common::set_gain(gain, name, chan2channel(BLADERF_RX, chan));
433
}
434

    
435
double bladerf_source_c::get_gain(size_t chan)
436
{
437
  return bladerf_common::get_gain(chan2channel(BLADERF_RX, chan));
438
}
439

    
440
double bladerf_source_c::get_gain(const std::string &name, size_t chan)
441
{
442
  return bladerf_common::get_gain(name, chan2channel(BLADERF_RX, chan));
443
}
444

    
445
std::vector<std::string> bladerf_source_c::get_antennas(size_t chan)
446
{
447
  return bladerf_common::get_antennas(BLADERF_RX);
448
}
449

    
450
std::string bladerf_source_c::set_antenna(const std::string &antenna,
451
                                          size_t chan)
452
{
453
  bool _was_running = _running;
454

    
455
  if (_was_running) {
456
    stop();
457
  }
458

    
459
  bladerf_common::set_antenna(BLADERF_RX, chan, antenna);
460

    
461
  if (_was_running) {
462
    start();
463
  }
464

    
465
  return get_antenna(chan);
466
}
467

    
468
std::string bladerf_source_c::get_antenna(size_t chan)
469
{
470
  return channel2str(chan2channel(BLADERF_RX, chan));
471
}
472

    
473
void bladerf_source_c::set_dc_offset_mode(int mode, size_t chan)
474
{
475
  if (osmosdr::source::DCOffsetOff == mode) {
476
    //_src->set_auto_dc_offset( false, chan );
477
    /* reset to default for off-state */
478
    set_dc_offset(std::complex<double>(0.0, 0.0), chan);
479
  } else if (osmosdr::source::DCOffsetManual == mode) {
480
    /* disable auto mode, but keep correcting with last known values */
481
    //_src->set_auto_dc_offset( false, chan );
482
  } else if (osmosdr::source::DCOffsetAutomatic == mode) {
483
    //_src->set_auto_dc_offset( true, chan );
484
    BLADERF_WARNING("Automatic DC correction mode is not implemented.");
485
  }
486
}
487

    
488
void bladerf_source_c::set_dc_offset(const std::complex<double> &offset,
489
                                     size_t chan)
490
{
491
  int status;
492

    
493
  status = bladerf_common::set_dc_offset(offset, chan2channel(BLADERF_RX, chan));
494

    
495
  if (status != 0) {
496
    BLADERF_THROW_STATUS(status, "could not set dc offset");
497
  }
498
}
499

    
500
void bladerf_source_c::set_iq_balance_mode(int mode, size_t chan)
501
{
502
  if (osmosdr::source::IQBalanceOff == mode) {
503
    //_src->set_auto_iq_balance( false, chan );
504
    /* reset to default for off-state */
505
    set_iq_balance(std::complex<double>(0.0, 0.0), chan);
506
  } else if (osmosdr::source::IQBalanceManual == mode) {
507
    /* disable auto mode, but keep correcting with last known values */
508
    //_src->set_auto_iq_balance( false, chan );
509
  } else if (osmosdr::source::IQBalanceAutomatic == mode) {
510
    //_src->set_auto_iq_balance( true, chan );
511
    BLADERF_WARNING("Automatic IQ correction mode is not implemented.");
512
  }
513
}
514

    
515
void bladerf_source_c::set_iq_balance(const std::complex<double> &balance,
516
                                      size_t chan)
517
{
518
  int status;
519

    
520
  status = bladerf_common::set_iq_balance(balance, chan2channel(BLADERF_RX, chan));
521

    
522
  if (status != 0) {
523
    BLADERF_THROW_STATUS(status, "could not set iq balance");
524
  }
525
}
526

    
527
osmosdr::freq_range_t bladerf_source_c::get_bandwidth_range(size_t chan)
528
{
529
  return filter_bandwidths(chan2channel(BLADERF_RX, chan));
530
}
531

    
532
double bladerf_source_c::set_bandwidth(double bandwidth, size_t chan)
533
{
534
  return bladerf_common::set_bandwidth(bandwidth,
535
                                       chan2channel(BLADERF_RX, chan));
536
}
537

    
538
double bladerf_source_c::get_bandwidth(size_t chan)
539
{
540
  return bladerf_common::get_bandwidth(chan2channel(BLADERF_RX, chan));
541
}
542

    
543
std::vector<std::string> bladerf_source_c::get_clock_sources(size_t mboard)
544
{
545
  return bladerf_common::get_clock_sources(mboard);
546
}
547

    
548
void bladerf_source_c::set_clock_source(const std::string &source,
549
                                        size_t mboard)
550
{
551
  bladerf_common::set_clock_source(source, mboard);
552
}
553

    
554
std::string bladerf_source_c::get_clock_source(size_t mboard)
555
{
556
  return bladerf_common::get_clock_source(mboard);
557
}
558

    
559
void bladerf_source_c::set_biastee_mode(const std::string &mode)
560
{
561
  int status;
562
  bool enable;
563

    
564
  if (mode == "on" || mode == "1" || mode == "rx") {
565
    enable = true;
566
  } else {
567
    enable = false;
568
  }
569

    
570
  status = bladerf_set_bias_tee(_dev.get(), BLADERF_CHANNEL_RX(0), enable);
571
  if (BLADERF_ERR_UNSUPPORTED == status) {
572
    // unsupported, but not worth crashing out
573
    BLADERF_WARNING("Bias-tee not supported by device");
574
  } else if (status != 0) {
575
    BLADERF_THROW_STATUS(status, "Failed to set bias-tee");
576
  }
577
}
578

    
579
void bladerf_source_c::set_loopback_mode(const std::string &loopback)
580
{
581
  int status;
582
  bladerf_loopback mode;
583

    
584
  if (loopback == "bb_txlpf_rxvga2") {
585
    mode = BLADERF_LB_BB_TXLPF_RXVGA2;
586
  } else if (loopback == "bb_txlpf_rxlpf") {
587
    mode = BLADERF_LB_BB_TXLPF_RXLPF;
588
  } else if (loopback == "bb_txvga1_rxvga2") {
589
    mode = BLADERF_LB_BB_TXVGA1_RXVGA2;
590
  } else if (loopback == "bb_txvga1_rxlpf") {
591
    mode = BLADERF_LB_BB_TXVGA1_RXLPF;
592
  } else if (loopback == "rf_lna1") {
593
    mode = BLADERF_LB_RF_LNA1;
594
  } else if (loopback == "rf_lna2") {
595
    mode = BLADERF_LB_RF_LNA2;
596
  } else if (loopback == "rf_lna3") {
597
    mode = BLADERF_LB_RF_LNA3;
598
  } else if (loopback == "firmware") {
599
    mode = BLADERF_LB_FIRMWARE;
600
  } else if (loopback == "rfic_bist") {
601
    mode = BLADERF_LB_RFIC_BIST;
602
  } else if (loopback == "none") {
603
    mode = BLADERF_LB_NONE;
604
  } else {
605
    BLADERF_THROW("Unknown loopback mode: " + loopback);
606
  }
607

    
608
  status = bladerf_set_loopback(_dev.get(), mode);
609
  if (BLADERF_ERR_UNSUPPORTED == status) {
610
    // unsupported, but not worth crashing out
611
    BLADERF_WARNING("Loopback mode not supported by device: " + loopback);
612
  } else if (status != 0) {
613
    BLADERF_THROW_STATUS(status, "Failed to set loopback mode");
614
  }
615
}
616

    
617
void bladerf_source_c::set_rx_mux_mode(const std::string &rxmux)
618
{
619
  int status;
620
  bladerf_rx_mux mode;
621

    
622
  if (rxmux == "baseband") {
623
    mode = BLADERF_RX_MUX_BASEBAND;
624
  } else if (rxmux == "12bit") {
625
    mode = BLADERF_RX_MUX_12BIT_COUNTER;
626
  } else if (rxmux == "32bit") {
627
    mode = BLADERF_RX_MUX_32BIT_COUNTER;
628
  } else if (rxmux == "digital") {
629
    mode = BLADERF_RX_MUX_DIGITAL_LOOPBACK;
630
  } else {
631
    BLADERF_THROW("Unknown RX mux mode: " + rxmux);
632
  }
633

    
634
  status = bladerf_set_rx_mux(_dev.get(), mode);
635
  if (BLADERF_ERR_UNSUPPORTED == status) {
636
    // unsupported, but not worth crashing out
637
    BLADERF_WARNING("RX mux mode not supported by device: " + rxmux);
638
  } else if (status != 0) {
639
    BLADERF_THROW_STATUS(status, "Failed to set RX mux mode");
640
  }
641
}
642

    
643
void bladerf_source_c::set_agc_mode(const std::string &agcmode)
644
{
645
#ifndef BLADERF_COMPATIBILITY
646
  int status;
647
  bladerf_gain_mode mode;
648
  bool ok = false;
649
  struct bladerf_gain_modes const *modes = NULL;
650

    
651
  /* Get the list of AGC modes */
652
  status = bladerf_get_gain_modes(_dev.get(), BLADERF_CHANNEL_RX(0), &modes);
653
  if (status < 0) {
654
    BLADERF_THROW_STATUS(status, "failed to get gain modes");
655
  }
656

    
657
  size_t count = status;
658

    
659
  /* Compare... */
660
  for (size_t i = 0; i < count; ++i) {
661
    if (agcmode == std::string(modes[i].name)) {
662
      mode = modes[i].mode;
663
      ok = true;
664
      BLADERF_DEBUG("Setting gain mode to " << mode << " (" << agcmode << ")");
665
      break;
666
    }
667
  }
668

    
669
  if (!ok) {
670
    BLADERF_WARNING("Unknown gain mode \"" << agcmode << "\"");
671
    return;
672
  }
673

    
674
  _agcmode = mode;
675

    
676
  for (size_t i = 0; i < get_num_channels(); ++i) {
677
    if (bladerf_common::get_gain_mode(BLADERF_CHANNEL_RX(i))) {
678
      /* Refresh this */
679
      bladerf_common::set_gain_mode(true, BLADERF_CHANNEL_RX(i), _agcmode);
680
    }
681
  }
682
#endif
683
}
(2-2/2)
Add picture from clipboard (Maximum size: 48.8 MB)