Statistics
| Branch: | Tag: | Revision:

root / usrp / host / lib / usrp_standard.cc @ 8d3550d3

History | View | Annotate | Download (29.7 kB)

1
/* -*- c++ -*- */
2
/*
3
 * Copyright 2004,2008,2009 Free Software Foundation, Inc.
4
 * 
5
 * This file is part of GNU Radio
6
 * 
7
 * GNU Radio is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3, or (at your option)
10
 * any later version.
11
 * 
12
 * GNU Radio is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 * 
17
 * You should have received a copy of the GNU General Public License
18
 * along with GNU Radio; see the file COPYING.  If not, write to
19
 * the Free Software Foundation, Inc., 51 Franklin Street,
20
 * Boston, MA 02110-1301, USA.
21
 */
22
23
#include <usrp/usrp_standard.h>
24
25
#include "usrp/usrp_prims.h"
26
#include "fpga_regs_common.h"
27
#include "fpga_regs_standard.h"
28
#include <stdexcept>
29
#include <assert.h>
30
#include <math.h>
31
#include <ad9862.h>
32
#include <cstdio>
33
34
35
static const int OLD_CAPS_VAL = 0xaa55ff77;
36
static const int DEFAULT_CAPS_VAL = ((2 << bmFR_RB_CAPS_NDUC_SHIFT)
37
                                     | (2 << bmFR_RB_CAPS_NDDC_SHIFT)
38
                                     | bmFR_RB_CAPS_RX_HAS_HALFBAND);
39
40
// #define USE_FPGA_TX_CORDIC
41
42
43
using namespace ad9862;
44
45
#define NELEM(x) (sizeof (x) / sizeof (x[0]))
46
47
48
void
49
usrp_standard_common::calc_dxc_freq(double target_freq, double baseband_freq, double fs,
50
                                    double *dxc_freq, bool *inverted)
51
{
52
  /*
53
    Calculate the frequency to use for setting the digital up or down converter.
54
    
55
    @param target_freq: desired RF frequency (Hz)
56
    @param baseband_freq: the RF frequency that corresponds to DC in the IF.
57
    @param fs: converter sample rate
58
    
59
    @returns: 2-tuple (ddc_freq, inverted) where ddc_freq is the value
60
      for the ddc and inverted is True if we're operating in an inverted
61
      Nyquist zone.
62
  */
63
64
#if 0
65
    printf("calc_dxc_freq:\n");
66
    printf("  target   = %f\n", target_freq);
67
    printf("  baseband = %f\n", baseband_freq);
68
    printf("  fs       = %f\n", fs);
69
#endif
70
71
  double delta = target_freq - baseband_freq;
72
    
73
  if(delta >= 0) {
74
    while(delta > fs) {
75
      delta -= fs;
76
    }
77
    if(delta <= fs/2) {                // non-inverted region
78
      *dxc_freq = -delta;        
79
      *inverted = false;
80
    }
81
    else {                             // inverted region
82
      *dxc_freq = delta - fs;
83
      *inverted = true;
84
    }
85
  }
86
  else {
87
    while(delta < -fs) {
88
      delta += fs;
89
    }
90
    if(delta >= -fs/2) {
91
      *dxc_freq = -delta;        // non-inverted region
92
      *inverted = false;
93
    }
94
    else {                        // inverted region
95
      *dxc_freq = delta + fs;
96
      *inverted = true;
97
    }
98
  }
99
100
#if 0
101
    printf("  dxc_freq  = %f\n", *dxc_freq);
102
    printf("  inverted  = %s\n", *inverted ? "true" : "false");
103
#endif
104
}
105
106
107
/* 
108
 * Real lambda expressions would be _so_ much easier...
109
 */
110
class dxc_control {
111
public:
112
  virtual bool is_tx() = 0;
113
  virtual bool set_dxc_freq(double dxc_freq) = 0;
114
  virtual double dxc_freq() = 0;
115
};
116
117
class ddc_control : public dxc_control {
118
  usrp_standard_rx     *d_u;
119
  int                        d_chan;
120
121
public:
122
  ddc_control(usrp_standard_rx *u, int chan)
123
    : d_u(u), d_chan(chan) {}
124
  
125
  bool is_tx(){ return false; }
126
  bool set_dxc_freq(double dxc_freq){ return d_u->set_rx_freq(d_chan, dxc_freq); }
127
  double dxc_freq(){ return d_u->rx_freq(d_chan); }
128
};
129
130
class duc_control : public dxc_control {
131
  usrp_standard_tx     *d_u;
132
  int                        d_chan;
133
134
public:
135
  duc_control(usrp_standard_tx *u, int chan)
136
    : d_u(u), d_chan(chan) {}
137
  
138
  bool is_tx(){ return true; }
139
  bool set_dxc_freq(double dxc_freq){ return d_u->set_tx_freq(d_chan, dxc_freq); }
140
  double dxc_freq() { return d_u->tx_freq(d_chan); }
141
};
142
143
144
/*!
145
 * \brief Tune such that target_frequency ends up at DC in the complex baseband
146
 *
147
 * \param db                the daughterboard to use
148
 * \param target_freq        the center frequency we want at baseband (DC)
149
 * \param fs                 the sample rate
150
 * \param dxc                DDC or DUC access and control object
151
 * \param[out] result        details of what we did
152
 *
153
 * \returns true iff operation was successful
154
 *
155
 * Tuning is a two step process.  First we ask the front-end to
156
 * tune as close to the desired frequency as it can.  Then we use
157
 * the result of that operation and our target_frequency to
158
 * determine the value for the digital down converter.
159
 */
160
static bool
161
tune_a_helper(db_base_sptr db, double target_freq, double fs,
162
              dxc_control &dxc, usrp_tune_result *result)
163
{
164
  bool inverted = false;
165
  double dxc_freq;
166
  double actual_dxc_freq;
167
168
  // Ask the d'board to tune as closely as it can to target_freq
169
#if 0
170
  bool ok = db->set_freq(target_freq, &result->baseband_freq);
171
#else
172
  bool ok;
173
  {
174
    freq_result_t fr = db->set_freq(target_freq);
175
    ok = fr.ok;
176
    result->baseband_freq = fr.baseband_freq;
177
  }
178
#endif
179
180
  // Calculate the DDC setting that will downconvert the baseband from the
181
  // daughterboard to our target frequency.
182
  usrp_standard_common::calc_dxc_freq(target_freq, result->baseband_freq, fs,
183
                                      &dxc_freq, &inverted);
184
185
  // If the spectrum is inverted, and the daughterboard doesn't do
186
  // quadrature downconversion, we can fix the inversion by flipping the
187
  // sign of the dxc_freq...  (This only happens using the basic_rx board)
188
  
189
  if(db->spectrum_inverted())
190
    inverted = !inverted;
191
  
192
  if(inverted && !db->is_quadrature()){
193
    dxc_freq = -dxc_freq;
194
    inverted = !inverted;
195
  }
196
  
197
  if (dxc.is_tx() && !db->i_and_q_swapped())                // down conversion versus up conversion
198
    dxc_freq = -dxc_freq;
199
200
  ok &= dxc.set_dxc_freq(dxc_freq);
201
  actual_dxc_freq = dxc.dxc_freq();
202
  
203
  result->dxc_freq = dxc_freq;
204
  result->residual_freq = dxc_freq - actual_dxc_freq;
205
  result->inverted = inverted;
206
  return ok;
207
}
208
209
210
static unsigned int
211
compute_freq_control_word_fpga (double master_freq, double target_freq,
212
                                double *actual_freq, bool verbose)
213
{
214
  static const int NBITS = 14;
215
  
216
  int        v = (int) rint (target_freq / master_freq * pow (2.0, 32.0));
217
218
  if (0)
219
    v = (v >> (32 - NBITS)) << (32 - NBITS);        // keep only top NBITS
220
221
  *actual_freq = v * master_freq / pow (2.0, 32.0);
222
223
  if (verbose)
224
    fprintf (stderr,
225
             "compute_freq_control_word_fpga: target = %g  actual = %g  delta = %g\n",
226
             target_freq, *actual_freq, *actual_freq - target_freq);
227
228
  return (unsigned int) v;
229
}
230
231
// The 9862 uses an unsigned 24-bit frequency tuning word and 
232
// a separate register to control the sign.
233
234
static unsigned int
235
compute_freq_control_word_9862 (double master_freq, double target_freq,
236
                                double *actual_freq, bool verbose)
237
{
238
  double sign = 1.0;
239
240
  if (target_freq < 0)
241
    sign = -1.0;
242
243
  int        v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0));
244
  *actual_freq = v * master_freq / pow (2.0, 24.0) * sign;
245
246
  if (verbose)
247
    fprintf (stderr,
248
     "compute_freq_control_word_9862: target = %g  actual = %g  delta = %g  v = %8d\n",
249
     target_freq, *actual_freq, *actual_freq - target_freq, v);
250
251
  return (unsigned int) v;
252
}
253
254
// ----------------------------------------------------------------
255
256
usrp_standard_common::usrp_standard_common(usrp_basic *parent)
257
{
258
  // read new FPGA capability register
259
  if (!parent->_read_fpga_reg(FR_RB_CAPS, &d_fpga_caps)){
260
    fprintf (stderr, "usrp_standard_common: failed to read FPGA cap register.\n");
261
    throw std::runtime_error ("usrp_standard_common::ctor");
262
  }
263
  // If we don't have the cap register, set the value to what it would
264
  // have had if we did have one ;)
265
  if (d_fpga_caps == OLD_CAPS_VAL)
266
    d_fpga_caps = DEFAULT_CAPS_VAL;
267
268
  if (0){
269
    fprintf(stdout, "has_rx_halfband = %d\n", has_rx_halfband());
270
    fprintf(stdout, "nddcs           = %d\n", nddcs());
271
    fprintf(stdout, "has_tx_halfband = %d\n", has_tx_halfband());
272
    fprintf(stdout, "nducs           = %d\n", nducs());
273
  }
274
}
275
276
bool
277
usrp_standard_common::has_rx_halfband() const
278
{
279
  return (d_fpga_caps & bmFR_RB_CAPS_RX_HAS_HALFBAND) ? true : false;
280
}
281
282
int
283
usrp_standard_common::nddcs() const
284
{
285
  return (d_fpga_caps & bmFR_RB_CAPS_NDDC_MASK) >> bmFR_RB_CAPS_NDDC_SHIFT;
286
}
287
288
bool
289
usrp_standard_common::has_tx_halfband() const
290
{
291
  return (d_fpga_caps & bmFR_RB_CAPS_TX_HAS_HALFBAND) ? true : false;
292
}
293
294
int
295
usrp_standard_common::nducs() const
296
{
297
  return (d_fpga_caps & bmFR_RB_CAPS_NDUC_MASK) >> bmFR_RB_CAPS_NDUC_SHIFT;
298
}
299
300
// ----------------------------------------------------------------
301
302
static int 
303
real_rx_mux_value (int mux, int nchan)
304
{
305
  if (mux != -1)
306
    return mux;
307
308
  return 0x32103210;
309
}
310
311
usrp_standard_rx::usrp_standard_rx (int which_board,
312
                                    unsigned int decim_rate,
313
                                    int nchan, int mux, int mode,
314
                                    int fusb_block_size, int fusb_nblocks,
315
                                    const std::string fpga_filename,
316
                                    const std::string firmware_filename
317
                                    )
318
  : usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks,
319
                   fpga_filename, firmware_filename),
320
    usrp_standard_common(this),
321
    d_nchan (1), d_sw_mux (0x0), d_hw_mux (0x0)
322
{
323
  if (!set_format(make_format())){
324
    fprintf (stderr, "usrp_standard_rx: set_format failed\n");
325
    throw std::runtime_error ("usrp_standard_rx::ctor");
326
  }
327
  if (!set_nchannels (nchan)){
328
    fprintf (stderr, "usrp_standard_rx: set_nchannels failed\n");
329
    throw std::runtime_error ("usrp_standard_rx::ctor");
330
  }
331
  if (!set_decim_rate (decim_rate)){
332
    fprintf (stderr, "usrp_standard_rx: set_decim_rate failed\n");
333
    throw std::runtime_error ("usrp_standard_rx::ctor");
334
  }
335
  if (!set_mux (real_rx_mux_value (mux, nchan))){
336
    fprintf (stderr, "usrp_standard_rx: set_mux failed\n");
337
    throw std::runtime_error ("usrp_standard_rx::ctor");
338
  }
339
  if (!set_fpga_mode (mode)){
340
    fprintf (stderr, "usrp_standard_rx: set_fpga_mode failed\n");
341
    throw std::runtime_error ("usrp_standard_rx::ctor");
342
  }
343
344
  for (int i = 0; i < MAX_CHAN; i++){
345
    set_rx_freq(i, 0);
346
    set_ddc_phase(i, 0);
347
  }
348
}
349
350
usrp_standard_rx::~usrp_standard_rx ()
351
{
352
  // fprintf(stderr, "\nusrp_standard_rx: dtor\n");
353
}
354
355
bool
356
usrp_standard_rx::start ()
357
{
358
  if (!usrp_basic_rx::start ())
359
    return false;
360
361
  // add our code here
362
363
  return true;
364
}
365
366
bool
367
usrp_standard_rx::stop ()
368
{
369
  bool ok = usrp_basic_rx::stop ();
370
371
  // add our code here
372
373
  return ok;
374
}
375
376
usrp_standard_rx_sptr
377
usrp_standard_rx::make (int which_board,
378
                        unsigned int decim_rate,
379
                        int nchan, int mux, int mode,
380
                        int fusb_block_size, int fusb_nblocks,
381
                        const std::string fpga_filename,
382
                        const std::string firmware_filename
383
                        )
384
{
385
  try {
386
    usrp_standard_rx_sptr u = 
387
      usrp_standard_rx_sptr(new usrp_standard_rx(which_board, decim_rate,
388
                                                 nchan, mux, mode,
389
                                                 fusb_block_size, fusb_nblocks,
390
                                                 fpga_filename, firmware_filename));
391
    u->init_db(u);
392
    return u;
393
  }
394
  catch (...){
395
    return usrp_standard_rx_sptr();
396
  }
397
}
398
399
bool
400
usrp_standard_rx::set_decim_rate(unsigned int rate)
401
{
402
  if (has_rx_halfband()){
403
    if ((rate & 0x1) || rate < 4 || rate > 256){
404
      fprintf (stderr, "usrp_standard_rx::set_decim_rate: rate must be EVEN and in [4, 256]\n");
405
      return false;
406
    }
407
  }
408
  else {
409
    if (rate < 4 || rate > 128){
410
      fprintf (stderr, "usrp_standard_rx::set_decim_rate: rate must be in [4, 128]\n");
411
      return false;
412
    }
413
  }
414
415
  d_decim_rate = rate;
416
  set_usb_data_rate ((adc_rate () / rate * nchannels ())
417
                     * (2 * sizeof (short)));
418
419
  bool s = disable_rx ();
420
  int v = has_rx_halfband() ? d_decim_rate/2 - 1 : d_decim_rate - 1;
421
  bool ok = _write_fpga_reg (FR_DECIM_RATE, v);
422
  restore_rx (s);
423
  return ok;
424
}
425
426
bool usrp_standard_rx::set_nchannels (int nchan)
427
{
428
  if (!(nchan == 1 || nchan == 2 || nchan == 4))
429
    return false;
430
431
  if (nchan > nddcs())
432
    return false;
433
434
  d_nchan = nchan;
435
436
  return write_hw_mux_reg ();
437
}
438
439
440
// map software mux value to hw mux value
441
//
442
// Software mux value:
443
//
444
//    3                   2                   1                       
445
//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
446
// +-------+-------+-------+-------+-------+-------+-------+-------+
447
// |   Q3  |   I3  |   Q2  |   I2  |   Q1  |   I1  |   Q0  |   I0  |
448
// +-------+-------+-------+-------+-------+-------+-------+-------+
449
//
450
// Each 4-bit I field is either 0,1,2,3
451
// Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero)
452
// All Q's must be 0xf or none of them may be 0xf
453
//
454
//
455
// Hardware mux value:
456
//
457
//    3                   2                   1                       
458
//  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
459
// +-----------------------+-------+-------+-------+-------+-+-----+
460
// |      must be zero     | Q3| I3| Q2| I2| Q1| I1| Q0| I0|Z| NCH |
461
// +-----------------------+-------+-------+-------+-------+-+-----+
462
463
464
static bool
465
map_sw_mux_to_hw_mux (int sw_mux, int *hw_mux_ptr)
466
{
467
  // confirm that all I's are either 0,1,2,3 
468
469
  for (int i = 0; i < 8; i += 2){
470
    int t = (sw_mux >> (4 * i)) & 0xf;
471
    if (!(0 <= t && t <= 3))
472
      return false;
473
  }
474
475
  // confirm that all Q's are either 0,1,2,3 or 0xf
476
477
  for (int i = 1; i < 8; i += 2){
478
    int t = (sw_mux >> (4 * i)) & 0xf;
479
    if (!(t == 0xf || (0 <= t && t <= 3)))
480
      return false;
481
  }
482
483
  // confirm that all Q inputs are 0xf (const zero input),
484
  // or none of them are 0xf
485
486
  int q_and = 1;
487
  int q_or =  0;
488
489
  for (int i = 0; i < 4; i++){
490
    int qx_is_0xf = ((sw_mux >> (8 * i + 4)) & 0xf) == 0xf;
491
    q_and &= qx_is_0xf;
492
    q_or  |= qx_is_0xf;
493
  }
494
495
  if (q_and || !q_or){                // OK
496
    int hw_mux_value = 0;
497
498
    for (int i = 0; i < 8; i++){
499
      int t = (sw_mux >> (4 * i)) & 0x3;
500
      hw_mux_value |= t << (2 * i + 4);
501
    }
502
503
    if (q_and)
504
      hw_mux_value |= 0x8;        // all Q's zero
505
506
    *hw_mux_ptr = hw_mux_value;
507
    return true;
508
  }
509
  else
510
    return false;
511
}
512
513
bool
514
usrp_standard_rx::set_mux (int mux)
515
{
516
  if (!map_sw_mux_to_hw_mux (mux, &d_hw_mux))
517
    return false;
518
519
  // fprintf (stderr, "sw_mux = 0x%08x  hw_mux = 0x%08x\n", mux, d_hw_mux);
520
521
  d_sw_mux = mux;
522
  return write_hw_mux_reg ();
523
}
524
525
bool
526
usrp_standard_rx::write_hw_mux_reg ()
527
{
528
  bool s = disable_rx ();
529
  bool ok = _write_fpga_reg (FR_RX_MUX, d_hw_mux | d_nchan);
530
  restore_rx (s);
531
  return ok;
532
}
533
534
int
535
usrp_standard_rx::determine_rx_mux_value(const usrp_subdev_spec &ss)
536
{
537
  /*
538
    Determine appropriate Rx mux value as a function of the subdevice choosen and the
539
    characteristics of the respective daughterboard.
540
    
541
    @param u:           instance of USRP source
542
    @param subdev_spec: return value from subdev option parser.  
543
    @type  subdev_spec: (side, subdev), where side is 0 or 1 and subdev is 0 or 1
544
    @returns:           the Rx mux value
545
  
546
    Figure out which A/D's to connect to the DDC.
547
    
548
    Each daughterboard consists of 1 or 2 subdevices.  (At this time,
549
    all but the Basic Rx have a single subdevice.  The Basic Rx
550
    has two independent channels, treated as separate subdevices).
551
    subdevice 0 of a daughterboard may use 1 or 2 A/D's.  We determine this
552
    by checking the is_quadrature() method.  If subdevice 0 uses only a single
553
    A/D, it's possible that the daughterboard has a second subdevice, subdevice 1,
554
    and it uses the second A/D.
555
    
556
    If the card uses only a single A/D, we wire a zero into the DDC Q input.
557
    
558
    (side, 0) says connect only the A/D's used by subdevice 0 to the DDC.
559
    (side, 1) says connect only the A/D's used by subdevice 1 to the DDC.
560
  */
561
562
  struct truth_table_element
563
  {
564
    int          d_side;
565
    int          d_uses;
566
    bool         d_swap_iq;
567
    unsigned int d_mux_val;
568
569
    truth_table_element(int side, unsigned int uses, bool swap_iq, unsigned int mux_val=0)
570
      : d_side(side), d_uses(uses), d_swap_iq(swap_iq), d_mux_val(mux_val){}
571
      
572
    bool operator==(const truth_table_element &in)
573
    {
574
      return (d_side == in.d_side && d_uses == in.d_uses && d_swap_iq == in.d_swap_iq);
575
    }
576
577
    unsigned int mux_val() { return d_mux_val; }
578
  };
579
580
581
  if (!is_valid(ss))
582
    throw std::invalid_argument("subdev_spec");
583
584
585
  // This is a tuple of length 1 or 2 containing the subdevice
586
  // classes for the selected side.
587
  std::vector<db_base_sptr> db = this->db(ss.side);
588
  
589
  unsigned int uses;
590
591
  // compute bitmasks of used A/D's
592
  
593
  if(db[ss.subdev]->is_quadrature())
594
    uses = 0x3;               // uses A/D 0 and 1
595
  else if (ss.subdev == 0)
596
    uses = 0x1;               // uses A/D 0 only
597
  else if(ss.subdev == 1)
598
    uses = 0x2;               // uses A/D 1 only
599
  else
600
    uses = 0x0;               // uses no A/D (doesn't exist)
601
  
602
  if(uses == 0){
603
    throw std::runtime_error("Determine RX Mux Error");
604
  }
605
  
606
  bool swap_iq = db[ss.subdev]->i_and_q_swapped();
607
  
608
  truth_table_element truth_table[8] = {
609
    // (side, uses, swap_iq) : mux_val
610
    truth_table_element(0, 0x1, false, 0xf0f0f0f0),
611
    truth_table_element(0, 0x2, false, 0xf0f0f0f1),
612
    truth_table_element(0, 0x3, false, 0x00000010),
613
    truth_table_element(0, 0x3, true,  0x00000001),
614
    truth_table_element(1, 0x1, false, 0xf0f0f0f2),
615
    truth_table_element(1, 0x2, false, 0xf0f0f0f3),
616
    truth_table_element(1, 0x3, false, 0x00000032),
617
    truth_table_element(1, 0x3, true,  0x00000023)
618
  };
619
  size_t nelements = sizeof(truth_table)/sizeof(truth_table[0]);
620
  
621
  truth_table_element target(ss.side, uses, swap_iq, 0);
622
  
623
  size_t i;
624
  for(i = 0; i < nelements; i++){
625
    if (truth_table[i] == target)
626
      return truth_table[i].mux_val();
627
  }
628
  throw std::runtime_error("internal error");
629
}
630
631
int
632
usrp_standard_rx::determine_rx_mux_value(const usrp_subdev_spec &ss_a, const usrp_subdev_spec &ss_b)
633
{
634
  std::vector<db_base_sptr> db_a = this->db(ss_a.side);
635
  std::vector<db_base_sptr> db_b = this->db(ss_b.side);
636
  if (db_a[ss_a.subdev]->is_quadrature() != db_b[ss_b.subdev]->is_quadrature()){
637
    throw std::runtime_error("Cannot compute dual mux when mixing quadrature and non-quadrature subdevices");
638
  }
639
  int mux_a = determine_rx_mux_value(ss_a);
640
  int mux_b = determine_rx_mux_value(ss_b);
641
  //move the lower byte of the mux b into the second byte of the mux a
642
  return ((mux_b & 0xff) << 8) | (mux_a & 0xffff00ff);
643
}
644
645
bool
646
usrp_standard_rx::set_rx_freq (int channel, double freq)
647
{
648
  if (channel < 0 || channel > MAX_CHAN)
649
    return false;
650
651
  unsigned int v =
652
    compute_freq_control_word_fpga (adc_rate(),
653
                                    freq, &d_rx_freq[channel],
654
                                    d_verbose);
655
656
  return _write_fpga_reg (FR_RX_FREQ_0 + channel, v);
657
}
658
659
unsigned int
660
usrp_standard_rx::decim_rate () const { return d_decim_rate; }
661
662
int
663
usrp_standard_rx::nchannels () const { return d_nchan; }
664
665
int
666
usrp_standard_rx::mux () const { return d_sw_mux; }
667
668
double 
669
usrp_standard_rx::rx_freq (int channel) const
670
{
671
  if (channel < 0 || channel >= MAX_CHAN)
672
    return 0;
673
674
  return d_rx_freq[channel];
675
}
676
677
bool
678
usrp_standard_rx::set_fpga_mode (int mode)
679
{
680
  return _write_fpga_reg (FR_MODE, mode);
681
}
682
683
bool
684
usrp_standard_rx::set_ddc_phase(int channel, int phase)
685
{
686
  if (channel < 0 || channel >= MAX_CHAN)
687
    return false;
688
689
  return _write_fpga_reg(FR_RX_PHASE_0 + channel, phase);
690
}
691
692
693
// To avoid quiet failures, check for things that our code cares about.
694
695
static bool
696
rx_format_is_valid(unsigned int format)
697
{
698
  int width =  usrp_standard_rx::format_width(format);
699
  int want_q = usrp_standard_rx::format_want_q(format);
700
701
  if (!(width == 8 || width == 16))        // FIXME add other widths when valid
702
    return false;
703
704
  if (!want_q)                // FIXME remove check when the rest of the code can handle I only
705
    return false;
706
707
  return true;
708
}
709
710
bool
711
usrp_standard_rx::set_format(unsigned int format)
712
{
713
  if (!rx_format_is_valid(format))
714
    return false;
715
716
  return _write_fpga_reg(FR_RX_FORMAT, format);
717
}
718
719
unsigned int
720
usrp_standard_rx::format() const
721
{
722
  return d_fpga_shadows[FR_RX_FORMAT];
723
}
724
725
// ----------------------------------------------------------------
726
727
unsigned int 
728
usrp_standard_rx::make_format(int width, int shift, bool want_q, bool bypass_halfband)
729
{
730
  unsigned int format = 
731
    (((width << bmFR_RX_FORMAT_WIDTH_SHIFT) & bmFR_RX_FORMAT_WIDTH_MASK)
732
     | ((shift << bmFR_RX_FORMAT_SHIFT_SHIFT) & bmFR_RX_FORMAT_SHIFT_MASK));
733
734
  if (want_q)
735
    format |= bmFR_RX_FORMAT_WANT_Q;
736
  if (bypass_halfband)
737
    format |= bmFR_RX_FORMAT_BYPASS_HB;
738
739
  return format;
740
}
741
742
int
743
usrp_standard_rx::format_width(unsigned int format)
744
{
745
  return (format & bmFR_RX_FORMAT_WIDTH_MASK) >> bmFR_RX_FORMAT_WIDTH_SHIFT;
746
}
747
748
int
749
usrp_standard_rx::format_shift(unsigned int format)
750
{
751
  return (format & bmFR_RX_FORMAT_SHIFT_MASK) >> bmFR_RX_FORMAT_SHIFT_SHIFT;
752
}
753
754
bool
755
usrp_standard_rx::format_want_q(unsigned int format)
756
{
757
  return (format & bmFR_RX_FORMAT_WANT_Q) != 0;
758
}
759
760
bool
761
usrp_standard_rx::format_bypass_halfband(unsigned int format)
762
{
763
  return (format & bmFR_RX_FORMAT_BYPASS_HB) != 0;
764
}
765
766
bool
767
usrp_standard_rx::tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result)
768
{
769
  ddc_control dxc(this, chan);
770
  return tune_a_helper(db, target_freq, converter_rate(), dxc, result);
771
}
772
773
774
//////////////////////////////////////////////////////////////////
775
776
777
// tx data is timed to CLKOUT1 (64 MHz)
778
// interpolate 4x
779
// fine modulator enabled
780
781
782
static unsigned char tx_regs_use_nco[] = {
783
  REG_TX_IF,                (TX_IF_USE_CLKOUT1
784
                         | TX_IF_I_FIRST
785
                         | TX_IF_2S_COMP
786
                         | TX_IF_INTERLEAVED),
787
  REG_TX_DIGITAL,        (TX_DIGITAL_2_DATA_PATHS
788
                         | TX_DIGITAL_INTERPOLATE_4X)
789
};
790
791
792
static int
793
real_tx_mux_value (int mux, int nchan)
794
{
795
  if (mux != -1)
796
    return mux;
797
798
  switch (nchan){
799
  case 1:
800
    return 0x0098;
801
  case 2:
802
    return 0xba98;
803
  default:
804
    assert (0);
805
  }
806
}
807
808
usrp_standard_tx::usrp_standard_tx (int which_board,
809
                                    unsigned int interp_rate,
810
                                    int nchan, int mux,
811
                                    int fusb_block_size, int fusb_nblocks,
812
                                    const std::string fpga_filename,
813
                                    const std::string firmware_filename
814
                                    )
815
  : usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks, fpga_filename, firmware_filename),
816
    usrp_standard_common(this),
817
    d_sw_mux (0x8), d_hw_mux (0x81)
818
{
819
  if (!usrp_9862_write_many_all (d_udh, tx_regs_use_nco, sizeof (tx_regs_use_nco))){
820
    fprintf (stderr, "usrp_standard_tx: failed to init AD9862 TX regs\n");
821
    throw std::runtime_error ("usrp_standard_tx::ctor");
822
  }
823
  if (!set_nchannels (nchan)){
824
    fprintf (stderr, "usrp_standard_tx: set_nchannels failed\n");
825
    throw std::runtime_error ("usrp_standard_tx::ctor");
826
  }
827
  if (!set_interp_rate (interp_rate)){
828
    fprintf (stderr, "usrp_standard_tx: set_interp_rate failed\n");
829
    throw std::runtime_error ("usrp_standard_tx::ctor");
830
  }
831
  if (!set_mux (real_tx_mux_value (mux, nchan))){
832
    fprintf (stderr, "usrp_standard_tx: set_mux failed\n");
833
    throw std::runtime_error ("usrp_standard_tx::ctor");
834
  }
835
836
  for (int i = 0; i < MAX_CHAN; i++){
837
    d_tx_modulator_shadow[i] = (TX_MODULATOR_DISABLE_NCO
838
                                | TX_MODULATOR_COARSE_MODULATION_NONE);
839
    d_coarse_mod[i] = CM_OFF;
840
    set_tx_freq (i, 0);
841
  }
842
}
843
844
usrp_standard_tx::~usrp_standard_tx ()
845
{
846
  // fprintf(stderr, "\nusrp_standard_tx: dtor\n");
847
}
848
849
bool
850
usrp_standard_tx::start ()
851
{
852
  if (!usrp_basic_tx::start ())
853
    return false;
854
855
  // add our code here
856
857
  return true;
858
}
859
860
bool
861
usrp_standard_tx::stop ()
862
{
863
  bool ok = usrp_basic_tx::stop ();
864
865
  // add our code here
866
867
  return ok;
868
}
869
870
usrp_standard_tx_sptr
871
usrp_standard_tx::make (int which_board,
872
                        unsigned int interp_rate,
873
                        int nchan, int mux,
874
                        int fusb_block_size, int fusb_nblocks,
875
                        const std::string fpga_filename,
876
                        const std::string firmware_filename
877
                        )
878
{
879
  try {
880
    usrp_standard_tx_sptr u  = 
881
      usrp_standard_tx_sptr(new usrp_standard_tx(which_board, interp_rate, nchan, mux,
882
                                                 fusb_block_size, fusb_nblocks,
883
                                                 fpga_filename, firmware_filename));
884
    u->init_db(u);
885
    return u;
886
  }
887
  catch (...){
888
    return usrp_standard_tx_sptr();
889
  }
890
}
891
892
bool
893
usrp_standard_tx::set_interp_rate (unsigned int rate)
894
{
895
  // fprintf (stderr, "usrp_standard_tx::set_interp_rate\n");
896
897
  if ((rate & 0x3) || rate < 4 || rate > 512){
898
    fprintf (stderr, "usrp_standard_tx::set_interp_rate: rate must be in [4, 512] and a multiple of 4.\n");
899
    return false;
900
  }
901
902
  d_interp_rate = rate;
903
  set_usb_data_rate ((dac_rate () / rate * nchannels ())
904
                     * (2 * sizeof (short)));
905
906
  // We're using the interp by 4 feature of the 9862 so that we can
907
  // use its fine modulator.  Thus, we reduce the FPGA's interpolation rate
908
  // by a factor of 4.
909
910
  bool s = disable_tx ();
911
  bool ok = _write_fpga_reg (FR_INTERP_RATE, d_interp_rate/4 - 1);
912
  restore_tx (s);
913
  return ok;
914
}
915
916
bool
917
usrp_standard_tx::set_nchannels (int nchan)
918
{
919
  if (!(nchan == 1 || nchan == 2))
920
    return false;
921
922
  if (nchan > nducs())
923
    return false;
924
925
  d_nchan = nchan;
926
  return write_hw_mux_reg ();
927
}
928
929
bool
930
usrp_standard_tx::set_mux (int mux)
931
{
932
  d_sw_mux = mux;
933
  d_hw_mux = mux << 4;
934
  return write_hw_mux_reg ();
935
}
936
937
bool
938
usrp_standard_tx::write_hw_mux_reg ()
939
{
940
  bool s = disable_tx ();
941
  bool ok = _write_fpga_reg (FR_TX_MUX, d_hw_mux | d_nchan);
942
  restore_tx (s);
943
  return ok;
944
}
945
946
int
947
usrp_standard_tx::determine_tx_mux_value(const usrp_subdev_spec &ss)
948
{
949
  /*
950
    Determine appropriate Tx mux value as a function of the subdevice choosen.
951
952
    @param u:           instance of USRP source
953
    @param subdev_spec: return value from subdev option parser.  
954
    @type  subdev_spec: (side, subdev), where side is 0 or 1 and subdev is 0
955
    @returns:           the Rx mux value
956
  
957
    This is simpler than the rx case.  Either you want to talk
958
    to side A or side B.  If you want to talk to both sides at once,
959
    determine the value manually.
960
  */
961
962
  if (!is_valid(ss))
963
    throw std::invalid_argument("subdev_spec");
964
965
  std::vector<db_base_sptr> db = this->db(ss.side);
966
  
967
  if(db[ss.subdev]->i_and_q_swapped()) {
968
    unsigned int mask[2] = {0x0089, 0x8900};
969
    return mask[ss.side];
970
  }
971
  else {
972
    unsigned int mask[2] = {0x0098, 0x9800};
973
    return mask[ss.side];
974
  }
975
}
976
977
int
978
usrp_standard_tx::determine_tx_mux_value(const usrp_subdev_spec &ss_a, const usrp_subdev_spec &ss_b)
979
{
980
  if (ss_a.side == ss_b.side && ss_a.subdev == ss_b.subdev){
981
    throw std::runtime_error("Cannot compute dual mux, repeated subdevice");
982
  }
983
  int mux_a = determine_tx_mux_value(ss_a);
984
  //Get the mux b:
985
  //        DAC0 becomes DAC2
986
  //        DAC1 becomes DAC3
987
  unsigned int mask[2] = {0x0022, 0x2200};
988
  int mux_b = determine_tx_mux_value(ss_b) + mask[ss_b.side];
989
  return mux_b | mux_a;
990
}
991
992
#ifdef USE_FPGA_TX_CORDIC
993
994
bool
995
usrp_standard_tx::set_tx_freq (int channel, double freq)
996
{
997
  if (channel < 0 || channel >= MAX_CHAN)
998
    return false;
999
1000
  // This assumes we're running the 4x on-chip interpolator.
1001
1002
  unsigned int v =
1003
    compute_freq_control_word_fpga (dac_rate () / 4,
1004
                                    freq, &d_tx_freq[channel],
1005
                                    d_verbose);
1006
1007
  return _write_fpga_reg (FR_TX_FREQ_0 + channel, v);
1008
}
1009
1010
1011
#else
1012
1013
bool
1014
usrp_standard_tx::set_tx_freq (int channel, double freq)
1015
{
1016
  if (channel < 0 || channel >= MAX_CHAN)
1017
    return false;
1018
1019
  // split freq into fine and coarse components
1020
1021
  coarse_mod_t        cm;
1022
  double        coarse;
1023
1024
  assert (dac_rate () == 128000000);
1025
1026
  if (freq < -44e6)                // too low
1027
    return false;
1028
  else if (freq < -24e6){        // [-44, -24)
1029
    cm = CM_NEG_FDAC_OVER_4;
1030
    coarse = -dac_rate () / 4;
1031
  }
1032
  else if (freq < -8e6){        // [-24, -8)
1033
    cm = CM_NEG_FDAC_OVER_8;
1034
    coarse = -dac_rate () / 8;
1035
  }
1036
  else if (freq < 8e6){                // [-8, 8)
1037
    cm = CM_OFF;
1038
    coarse = 0;
1039
  }
1040
  else if (freq < 24e6){        // [8, 24)
1041
    cm = CM_POS_FDAC_OVER_8;
1042
    coarse = dac_rate () / 8;
1043
  }
1044
  else if (freq <= 44e6){        // [24, 44]
1045
    cm = CM_POS_FDAC_OVER_4;
1046
    coarse = dac_rate () / 4;
1047
  }
1048
  else                                // too high
1049
    return false;
1050
1051
1052
  set_coarse_modulator (channel, cm);        // set bits in d_tx_modulator_shadow
1053
1054
  double fine = freq - coarse;
1055
1056
1057
  // Compute fine tuning word...
1058
  // This assumes we're running the 4x on-chip interpolator.
1059
  // (This is required to use the fine modulator.)
1060
1061
  unsigned int v =
1062
    compute_freq_control_word_9862 (dac_rate () / 4,
1063
                                    fine, &d_tx_freq[channel], d_verbose);
1064
1065
  d_tx_freq[channel] += coarse;                // adjust actual
1066
  
1067
  unsigned char high, mid, low;
1068
1069
  high = (v >> 16) & 0xff;
1070
  mid =  (v >>  8) & 0xff;
1071
  low =  (v >>  0) & 0xff;
1072
1073
  bool ok = true;
1074
1075
  // write the fine tuning word
1076
  ok &= _write_9862 (channel, REG_TX_NCO_FTW_23_16, high);
1077
  ok &= _write_9862 (channel, REG_TX_NCO_FTW_15_8,  mid);
1078
  ok &= _write_9862 (channel, REG_TX_NCO_FTW_7_0,   low);
1079
1080
1081
  d_tx_modulator_shadow[channel] |= TX_MODULATOR_ENABLE_NCO;
1082
1083
  if (fine < 0)
1084
    d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_FINE_TUNE;
1085
  else
1086
    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_NEG_FINE_TUNE;
1087
1088
  ok &=_write_9862 (channel, REG_TX_MODULATOR, d_tx_modulator_shadow[channel]);
1089
1090
  return ok;
1091
}
1092
#endif
1093
1094
bool
1095
usrp_standard_tx::set_coarse_modulator (int channel, coarse_mod_t cm)
1096
{
1097
  if (channel < 0 || channel >= MAX_CHAN)
1098
    return false;
1099
1100
  switch (cm){
1101
  case CM_NEG_FDAC_OVER_4:
1102
    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
1103
    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_4;
1104
    d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_COARSE_TUNE;
1105
    break;
1106
1107
  case CM_NEG_FDAC_OVER_8:
1108
    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
1109
    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_8;
1110
    d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_COARSE_TUNE;
1111
    break;
1112
1113
  case CM_OFF:
1114
    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
1115
    break;
1116
1117
  case CM_POS_FDAC_OVER_8:
1118
    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
1119
    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_8;
1120
    break;
1121
1122
  case CM_POS_FDAC_OVER_4:
1123
    d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
1124
    d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_4;
1125
    break;
1126
1127
  default:
1128
    return false;
1129
  }
1130
1131
  d_coarse_mod[channel] = cm;
1132
  return true;
1133
}
1134
1135
unsigned int
1136
usrp_standard_tx::interp_rate () const { return d_interp_rate; }
1137
1138
int
1139
usrp_standard_tx::nchannels () const { return d_nchan; }
1140
1141
int
1142
usrp_standard_tx::mux () const { return d_sw_mux; }
1143
1144
double
1145
usrp_standard_tx::tx_freq (int channel) const
1146
{
1147
  if (channel < 0 || channel >= MAX_CHAN)
1148
    return 0;
1149
1150
  return d_tx_freq[channel];
1151
}
1152
1153
usrp_standard_tx::coarse_mod_t
1154
usrp_standard_tx::coarse_modulator (int channel) const
1155
{
1156
  if (channel < 0 || channel >= MAX_CHAN)
1157
    return CM_OFF;
1158
1159
  return d_coarse_mod[channel];
1160
}
1161
1162
bool
1163
usrp_standard_tx::tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result)
1164
{
1165
  duc_control dxc(this, chan);
1166
  return tune_a_helper(db, target_freq, converter_rate(), dxc, result);
1167
}