3 * Copyright 2004,2008 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
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)
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.
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.
23 #include <usrp_standard.h>
25 #include "usrp_prims.h"
26 #include "fpga_regs_common.h"
27 #include "fpga_regs_standard.h"
34 static const int OLD_CAPS_VAL = 0xaa55ff77;
35 static const int DEFAULT_CAPS_VAL = ((2 << bmFR_RB_CAPS_NDUC_SHIFT)
36 | (2 << bmFR_RB_CAPS_NDDC_SHIFT)
37 | bmFR_RB_CAPS_RX_HAS_HALFBAND);
39 // #define USE_FPGA_TX_CORDIC
42 using namespace ad9862;
44 #define NELEM(x) (sizeof (x) / sizeof (x[0]))
48 usrp_standard_common::calc_dxc_freq(double target_freq, double baseband_freq, double fs,
49 double *dxc_freq, bool *inverted)
52 Calculate the frequency to use for setting the digital up or down converter.
54 @param target_freq: desired RF frequency (Hz)
55 @param baseband_freq: the RF frequency that corresponds to DC in the IF.
56 @param fs: converter sample rate
58 @returns: 2-tuple (ddc_freq, inverted) where ddc_freq is the value
59 for the ddc and inverted is True if we're operating in an inverted
64 printf("calc_dxc_freq:\n");
65 printf(" target = %f\n", target_freq);
66 printf(" baseband = %f\n", baseband_freq);
67 printf(" fs = %f\n", fs);
70 double delta = target_freq - baseband_freq;
76 if(delta <= fs/2) { // non-inverted region
80 else { // inverted region
81 *dxc_freq = delta - fs;
90 *dxc_freq = -delta; // non-inverted region
93 else { // inverted region
94 *dxc_freq = delta + fs;
100 printf(" dxc_freq = %f\n", *dxc_freq);
101 printf(" inverted = %s\n", *inverted ? "true" : "false");
107 * Real lambda expressions would be _so_ much easier...
111 virtual bool is_tx() = 0;
112 virtual bool set_dxc_freq(double dxc_freq) = 0;
113 virtual double dxc_freq() = 0;
116 class ddc_control : public dxc_control {
117 usrp_standard_rx *d_u;
121 ddc_control(usrp_standard_rx *u, int chan)
122 : d_u(u), d_chan(chan) {}
124 bool is_tx(){ return false; }
125 bool set_dxc_freq(double dxc_freq){ return d_u->set_rx_freq(d_chan, dxc_freq); }
126 double dxc_freq(){ return d_u->rx_freq(d_chan); }
129 class duc_control : public dxc_control {
130 usrp_standard_tx *d_u;
134 duc_control(usrp_standard_tx *u, int chan)
135 : d_u(u), d_chan(chan) {}
137 bool is_tx(){ return true; }
138 bool set_dxc_freq(double dxc_freq){ return d_u->set_tx_freq(d_chan, dxc_freq); }
139 double dxc_freq() { return d_u->tx_freq(d_chan); }
144 * \brief Tune such that target_frequency ends up at DC in the complex baseband
146 * \param db the daughterboard to use
147 * \param target_freq the center frequency we want at baseband (DC)
148 * \param fs the sample rate
149 * \param dxc DDC or DUC access and control object
150 * \param[out] result details of what we did
152 * \returns true iff operation was successful
154 * Tuning is a two step process. First we ask the front-end to
155 * tune as close to the desired frequency as it can. Then we use
156 * the result of that operation and our target_frequency to
157 * determine the value for the digital down converter.
160 tune_a_helper(db_base_sptr db, double target_freq, double fs,
161 dxc_control &dxc, usrp_tune_result *result)
163 bool inverted = false;
165 double actual_dxc_freq;
167 // Ask the d'board to tune as closely as it can to target_freq
169 bool ok = db->set_freq(target_freq, &result->baseband_freq);
173 freq_result_t fr = db->set_freq(target_freq);
175 result->baseband_freq = fr.baseband_freq;
179 // Calculate the DDC setting that will downconvert the baseband from the
180 // daughterboard to our target frequency.
181 usrp_standard_common::calc_dxc_freq(target_freq, result->baseband_freq, fs,
182 &dxc_freq, &inverted);
184 // If the spectrum is inverted, and the daughterboard doesn't do
185 // quadrature downconversion, we can fix the inversion by flipping the
186 // sign of the dxc_freq... (This only happens using the basic_rx board)
188 if(db->spectrum_inverted())
189 inverted = !inverted;
191 if(inverted && !db->is_quadrature()){
192 dxc_freq = -dxc_freq;
193 inverted = !inverted;
196 if (dxc.is_tx()) // down conversion versus up conversion
197 dxc_freq = -dxc_freq;
199 ok &= dxc.set_dxc_freq(dxc_freq);
200 actual_dxc_freq = dxc.dxc_freq();
202 result->dxc_freq = dxc_freq;
203 result->residual_freq = dxc_freq - actual_dxc_freq;
204 result->inverted = inverted;
210 compute_freq_control_word_fpga (double master_freq, double target_freq,
211 double *actual_freq, bool verbose)
213 static const int NBITS = 14;
215 int v = (int) rint (target_freq / master_freq * pow (2.0, 32.0));
218 v = (v >> (32 - NBITS)) << (32 - NBITS); // keep only top NBITS
220 *actual_freq = v * master_freq / pow (2.0, 32.0);
224 "compute_freq_control_word_fpga: target = %g actual = %g delta = %g\n",
225 target_freq, *actual_freq, *actual_freq - target_freq);
227 return (unsigned int) v;
230 // The 9862 uses an unsigned 24-bit frequency tuning word and
231 // a separate register to control the sign.
234 compute_freq_control_word_9862 (double master_freq, double target_freq,
235 double *actual_freq, bool verbose)
242 int v = (int) rint (fabs (target_freq) / master_freq * pow (2.0, 24.0));
243 *actual_freq = v * master_freq / pow (2.0, 24.0) * sign;
247 "compute_freq_control_word_9862: target = %g actual = %g delta = %g v = %8d\n",
248 target_freq, *actual_freq, *actual_freq - target_freq, v);
250 return (unsigned int) v;
253 // ----------------------------------------------------------------
255 usrp_standard_common::usrp_standard_common(usrp_basic *parent)
257 // read new FPGA capability register
258 if (!parent->_read_fpga_reg(FR_RB_CAPS, &d_fpga_caps)){
259 fprintf (stderr, "usrp_standard_common: failed to read FPGA cap register.\n");
260 throw std::runtime_error ("usrp_standard_common::ctor");
262 // If we don't have the cap register, set the value to what it would
263 // have had if we did have one ;)
264 if (d_fpga_caps == OLD_CAPS_VAL)
265 d_fpga_caps = DEFAULT_CAPS_VAL;
268 fprintf(stdout, "has_rx_halfband = %d\n", has_rx_halfband());
269 fprintf(stdout, "nddcs = %d\n", nddcs());
270 fprintf(stdout, "has_tx_halfband = %d\n", has_tx_halfband());
271 fprintf(stdout, "nducs = %d\n", nducs());
276 usrp_standard_common::has_rx_halfband() const
278 return (d_fpga_caps & bmFR_RB_CAPS_RX_HAS_HALFBAND) ? true : false;
282 usrp_standard_common::nddcs() const
284 return (d_fpga_caps & bmFR_RB_CAPS_NDDC_MASK) >> bmFR_RB_CAPS_NDDC_SHIFT;
288 usrp_standard_common::has_tx_halfband() const
290 return (d_fpga_caps & bmFR_RB_CAPS_TX_HAS_HALFBAND) ? true : false;
294 usrp_standard_common::nducs() const
296 return (d_fpga_caps & bmFR_RB_CAPS_NDUC_MASK) >> bmFR_RB_CAPS_NDUC_SHIFT;
299 // ----------------------------------------------------------------
302 real_rx_mux_value (int mux, int nchan)
310 usrp_standard_rx::usrp_standard_rx (int which_board,
311 unsigned int decim_rate,
312 int nchan, int mux, int mode,
313 int fusb_block_size, int fusb_nblocks,
314 const std::string fpga_filename,
315 const std::string firmware_filename
317 : usrp_basic_rx (which_board, fusb_block_size, fusb_nblocks,
318 fpga_filename, firmware_filename),
319 usrp_standard_common(this),
320 d_nchan (1), d_sw_mux (0x0), d_hw_mux (0x0)
322 if (!set_format(make_format())){
323 fprintf (stderr, "usrp_standard_rx: set_format failed\n");
324 throw std::runtime_error ("usrp_standard_rx::ctor");
326 if (!set_nchannels (nchan)){
327 fprintf (stderr, "usrp_standard_rx: set_nchannels failed\n");
328 throw std::runtime_error ("usrp_standard_rx::ctor");
330 if (!set_decim_rate (decim_rate)){
331 fprintf (stderr, "usrp_standard_rx: set_decim_rate failed\n");
332 throw std::runtime_error ("usrp_standard_rx::ctor");
334 if (!set_mux (real_rx_mux_value (mux, nchan))){
335 fprintf (stderr, "usrp_standard_rx: set_mux failed\n");
336 throw std::runtime_error ("usrp_standard_rx::ctor");
338 if (!set_fpga_mode (mode)){
339 fprintf (stderr, "usrp_standard_rx: set_fpga_mode failed\n");
340 throw std::runtime_error ("usrp_standard_rx::ctor");
343 for (int i = 0; i < MAX_CHAN; i++){
349 usrp_standard_rx::~usrp_standard_rx ()
351 // fprintf(stderr, "\nusrp_standard_rx: dtor\n");
355 usrp_standard_rx::start ()
357 if (!usrp_basic_rx::start ())
366 usrp_standard_rx::stop ()
368 bool ok = usrp_basic_rx::stop ();
375 usrp_standard_rx_sptr
376 usrp_standard_rx::make (int which_board,
377 unsigned int decim_rate,
378 int nchan, int mux, int mode,
379 int fusb_block_size, int fusb_nblocks,
380 const std::string fpga_filename,
381 const std::string firmware_filename
385 usrp_standard_rx_sptr u =
386 usrp_standard_rx_sptr(new usrp_standard_rx(which_board, decim_rate,
388 fusb_block_size, fusb_nblocks,
389 fpga_filename, firmware_filename));
394 return usrp_standard_rx_sptr();
399 usrp_standard_rx::set_decim_rate(unsigned int rate)
401 if (has_rx_halfband()){
402 if ((rate & 0x1) || rate < 4 || rate > 256){
403 fprintf (stderr, "usrp_standard_rx::set_decim_rate: rate must be EVEN and in [4, 256]\n");
408 if (rate < 4 || rate > 128){
409 fprintf (stderr, "usrp_standard_rx::set_decim_rate: rate must be in [4, 128]\n");
415 set_usb_data_rate ((adc_rate () / rate * nchannels ())
416 * (2 * sizeof (short)));
418 bool s = disable_rx ();
419 int v = has_rx_halfband() ? d_decim_rate/2 - 1 : d_decim_rate - 1;
420 bool ok = _write_fpga_reg (FR_DECIM_RATE, v);
425 bool usrp_standard_rx::set_nchannels (int nchan)
427 if (!(nchan == 1 || nchan == 2 || nchan == 4))
435 return write_hw_mux_reg ();
439 // map software mux value to hw mux value
441 // Software mux value:
444 // 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
445 // +-------+-------+-------+-------+-------+-------+-------+-------+
446 // | Q3 | I3 | Q2 | I2 | Q1 | I1 | Q0 | I0 |
447 // +-------+-------+-------+-------+-------+-------+-------+-------+
449 // Each 4-bit I field is either 0,1,2,3
450 // Each 4-bit Q field is either 0,1,2,3 or 0xf (input is const zero)
451 // All Q's must be 0xf or none of them may be 0xf
454 // Hardware mux value:
457 // 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
458 // +-----------------------+-------+-------+-------+-------+-+-----+
459 // | must be zero | Q3| I3| Q2| I2| Q1| I1| Q0| I0|Z| NCH |
460 // +-----------------------+-------+-------+-------+-------+-+-----+
464 map_sw_mux_to_hw_mux (int sw_mux, int *hw_mux_ptr)
466 // confirm that all I's are either 0,1,2,3
468 for (int i = 0; i < 8; i += 2){
469 int t = (sw_mux >> (4 * i)) & 0xf;
470 if (!(0 <= t && t <= 3))
474 // confirm that all Q's are either 0,1,2,3 or 0xf
476 for (int i = 1; i < 8; i += 2){
477 int t = (sw_mux >> (4 * i)) & 0xf;
478 if (!(t == 0xf || (0 <= t && t <= 3)))
482 // confirm that all Q inputs are 0xf (const zero input),
483 // or none of them are 0xf
488 for (int i = 0; i < 4; i++){
489 int qx_is_0xf = ((sw_mux >> (8 * i + 4)) & 0xf) == 0xf;
494 if (q_and || !q_or){ // OK
495 int hw_mux_value = 0;
497 for (int i = 0; i < 8; i++){
498 int t = (sw_mux >> (4 * i)) & 0x3;
499 hw_mux_value |= t << (2 * i + 4);
503 hw_mux_value |= 0x8; // all Q's zero
505 *hw_mux_ptr = hw_mux_value;
513 usrp_standard_rx::set_mux (int mux)
515 if (!map_sw_mux_to_hw_mux (mux, &d_hw_mux))
518 // fprintf (stderr, "sw_mux = 0x%08x hw_mux = 0x%08x\n", mux, d_hw_mux);
521 return write_hw_mux_reg ();
525 usrp_standard_rx::write_hw_mux_reg ()
527 bool s = disable_rx ();
528 bool ok = _write_fpga_reg (FR_RX_MUX, d_hw_mux | d_nchan);
534 usrp_standard_rx::determine_rx_mux_value(const usrp_subdev_spec &ss)
537 Determine appropriate Rx mux value as a function of the subdevice choosen and the
538 characteristics of the respective daughterboard.
540 @param u: instance of USRP source
541 @param subdev_spec: return value from subdev option parser.
542 @type subdev_spec: (side, subdev), where side is 0 or 1 and subdev is 0 or 1
543 @returns: the Rx mux value
545 Figure out which A/D's to connect to the DDC.
547 Each daughterboard consists of 1 or 2 subdevices. (At this time,
548 all but the Basic Rx have a single subdevice. The Basic Rx
549 has two independent channels, treated as separate subdevices).
550 subdevice 0 of a daughterboard may use 1 or 2 A/D's. We determine this
551 by checking the is_quadrature() method. If subdevice 0 uses only a single
552 A/D, it's possible that the daughterboard has a second subdevice, subdevice 1,
553 and it uses the second A/D.
555 If the card uses only a single A/D, we wire a zero into the DDC Q input.
557 (side, 0) says connect only the A/D's used by subdevice 0 to the DDC.
558 (side, 1) says connect only the A/D's used by subdevice 1 to the DDC.
561 struct truth_table_element
566 unsigned int d_mux_val;
568 truth_table_element(int side, unsigned int uses, bool swap_iq, unsigned int mux_val=0)
569 : d_side(side), d_uses(uses), d_swap_iq(swap_iq), d_mux_val(mux_val){}
571 bool operator==(const truth_table_element &in)
573 return (d_side == in.d_side && d_uses == in.d_uses && d_swap_iq == in.d_swap_iq);
576 unsigned int mux_val() { return d_mux_val; }
581 throw std::invalid_argument("subdev_spec");
584 // This is a tuple of length 1 or 2 containing the subdevice
585 // classes for the selected side.
586 std::vector<db_base_sptr> db = this->db(ss.side);
588 unsigned int subdev0_uses, subdev1_uses, uses;
590 // compute bitmasks of used A/D's
592 if(db[0]->is_quadrature())
593 subdev0_uses = 0x3; // uses A/D 0 and 1
595 subdev0_uses = 0x1; // uses A/D 0 only
597 if(db.size() > 1) // more than 1 subdevice?
598 subdev1_uses = 0x2; // uses A/D 1 only
600 subdev1_uses = 0x0; // uses no A/D (doesn't exist)
604 else if(ss.subdev == 1)
607 throw std::invalid_argument("subdev_spec");
610 throw std::runtime_error("Daughterboard doesn't have a subdevice 1");
613 bool swap_iq = db[0]->i_and_q_swapped();
615 truth_table_element truth_table[8] = {
616 // (side, uses, swap_iq) : mux_val
617 truth_table_element(0, 0x1, false, 0xf0f0f0f0),
618 truth_table_element(0, 0x2, false, 0xf0f0f0f1),
619 truth_table_element(0, 0x3, false, 0x00000010),
620 truth_table_element(0, 0x3, true, 0x00000001),
621 truth_table_element(1, 0x1, false, 0xf0f0f0f2),
622 truth_table_element(1, 0x2, false, 0xf0f0f0f3),
623 truth_table_element(1, 0x3, false, 0x00000032),
624 truth_table_element(1, 0x3, true, 0x00000023)
626 size_t nelements = sizeof(truth_table)/sizeof(truth_table[0]);
628 truth_table_element target(ss.side, uses, swap_iq, 0);
631 for(i = 0; i < nelements; i++){
632 if (truth_table[i] == target)
633 return truth_table[i].mux_val();
635 throw std::runtime_error("internal error");
641 usrp_standard_rx::set_rx_freq (int channel, double freq)
643 if (channel < 0 || channel > MAX_CHAN)
647 compute_freq_control_word_fpga (adc_rate(),
648 freq, &d_rx_freq[channel],
651 return _write_fpga_reg (FR_RX_FREQ_0 + channel, v);
655 usrp_standard_rx::decim_rate () const { return d_decim_rate; }
658 usrp_standard_rx::nchannels () const { return d_nchan; }
661 usrp_standard_rx::mux () const { return d_sw_mux; }
664 usrp_standard_rx::rx_freq (int channel) const
666 if (channel < 0 || channel >= MAX_CHAN)
669 return d_rx_freq[channel];
673 usrp_standard_rx::set_fpga_mode (int mode)
675 return _write_fpga_reg (FR_MODE, mode);
679 usrp_standard_rx::set_ddc_phase(int channel, int phase)
681 if (channel < 0 || channel >= MAX_CHAN)
684 return _write_fpga_reg(FR_RX_PHASE_0 + channel, phase);
688 // To avoid quiet failures, check for things that our code cares about.
691 rx_format_is_valid(unsigned int format)
693 int width = usrp_standard_rx::format_width(format);
694 int want_q = usrp_standard_rx::format_want_q(format);
696 if (!(width == 8 || width == 16)) // FIXME add other widths when valid
699 if (!want_q) // FIXME remove check when the rest of the code can handle I only
706 usrp_standard_rx::set_format(unsigned int format)
708 if (!rx_format_is_valid(format))
711 return _write_fpga_reg(FR_RX_FORMAT, format);
715 usrp_standard_rx::format() const
717 return d_fpga_shadows[FR_RX_FORMAT];
720 // ----------------------------------------------------------------
723 usrp_standard_rx::make_format(int width, int shift, bool want_q, bool bypass_halfband)
725 unsigned int format =
726 (((width << bmFR_RX_FORMAT_WIDTH_SHIFT) & bmFR_RX_FORMAT_WIDTH_MASK)
727 | ((shift << bmFR_RX_FORMAT_SHIFT_SHIFT) & bmFR_RX_FORMAT_SHIFT_MASK));
730 format |= bmFR_RX_FORMAT_WANT_Q;
732 format |= bmFR_RX_FORMAT_BYPASS_HB;
738 usrp_standard_rx::format_width(unsigned int format)
740 return (format & bmFR_RX_FORMAT_WIDTH_MASK) >> bmFR_RX_FORMAT_WIDTH_SHIFT;
744 usrp_standard_rx::format_shift(unsigned int format)
746 return (format & bmFR_RX_FORMAT_SHIFT_MASK) >> bmFR_RX_FORMAT_SHIFT_SHIFT;
750 usrp_standard_rx::format_want_q(unsigned int format)
752 return (format & bmFR_RX_FORMAT_WANT_Q) != 0;
756 usrp_standard_rx::format_bypass_halfband(unsigned int format)
758 return (format & bmFR_RX_FORMAT_BYPASS_HB) != 0;
762 usrp_standard_rx::tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result)
764 ddc_control dxc(this, chan);
765 return tune_a_helper(db, target_freq, converter_rate(), dxc, result);
769 //////////////////////////////////////////////////////////////////
772 // tx data is timed to CLKOUT1 (64 MHz)
774 // fine modulator enabled
777 static unsigned char tx_regs_use_nco[] = {
778 REG_TX_IF, (TX_IF_USE_CLKOUT1
781 | TX_IF_INTERLEAVED),
782 REG_TX_DIGITAL, (TX_DIGITAL_2_DATA_PATHS
783 | TX_DIGITAL_INTERPOLATE_4X)
788 real_tx_mux_value (int mux, int nchan)
803 usrp_standard_tx::usrp_standard_tx (int which_board,
804 unsigned int interp_rate,
806 int fusb_block_size, int fusb_nblocks,
807 const std::string fpga_filename,
808 const std::string firmware_filename
810 : usrp_basic_tx (which_board, fusb_block_size, fusb_nblocks, fpga_filename, firmware_filename),
811 usrp_standard_common(this),
812 d_sw_mux (0x8), d_hw_mux (0x81)
814 if (!usrp_9862_write_many_all (d_udh, tx_regs_use_nco, sizeof (tx_regs_use_nco))){
815 fprintf (stderr, "usrp_standard_tx: failed to init AD9862 TX regs\n");
816 throw std::runtime_error ("usrp_standard_tx::ctor");
818 if (!set_nchannels (nchan)){
819 fprintf (stderr, "usrp_standard_tx: set_nchannels failed\n");
820 throw std::runtime_error ("usrp_standard_tx::ctor");
822 if (!set_interp_rate (interp_rate)){
823 fprintf (stderr, "usrp_standard_tx: set_interp_rate failed\n");
824 throw std::runtime_error ("usrp_standard_tx::ctor");
826 if (!set_mux (real_tx_mux_value (mux, nchan))){
827 fprintf (stderr, "usrp_standard_tx: set_mux failed\n");
828 throw std::runtime_error ("usrp_standard_tx::ctor");
831 for (int i = 0; i < MAX_CHAN; i++){
832 d_tx_modulator_shadow[i] = (TX_MODULATOR_DISABLE_NCO
833 | TX_MODULATOR_COARSE_MODULATION_NONE);
834 d_coarse_mod[i] = CM_OFF;
839 usrp_standard_tx::~usrp_standard_tx ()
841 // fprintf(stderr, "\nusrp_standard_tx: dtor\n");
845 usrp_standard_tx::start ()
847 if (!usrp_basic_tx::start ())
856 usrp_standard_tx::stop ()
858 bool ok = usrp_basic_tx::stop ();
865 usrp_standard_tx_sptr
866 usrp_standard_tx::make (int which_board,
867 unsigned int interp_rate,
869 int fusb_block_size, int fusb_nblocks,
870 const std::string fpga_filename,
871 const std::string firmware_filename
875 usrp_standard_tx_sptr u =
876 usrp_standard_tx_sptr(new usrp_standard_tx(which_board, interp_rate, nchan, mux,
877 fusb_block_size, fusb_nblocks,
878 fpga_filename, firmware_filename));
883 return usrp_standard_tx_sptr();
888 usrp_standard_tx::set_interp_rate (unsigned int rate)
890 // fprintf (stderr, "usrp_standard_tx::set_interp_rate\n");
892 if ((rate & 0x3) || rate < 4 || rate > 512){
893 fprintf (stderr, "usrp_standard_tx::set_interp_rate: rate must be in [4, 512] and a multiple of 4.\n");
897 d_interp_rate = rate;
898 set_usb_data_rate ((dac_rate () / rate * nchannels ())
899 * (2 * sizeof (short)));
901 // We're using the interp by 4 feature of the 9862 so that we can
902 // use its fine modulator. Thus, we reduce the FPGA's interpolation rate
905 bool s = disable_tx ();
906 bool ok = _write_fpga_reg (FR_INTERP_RATE, d_interp_rate/4 - 1);
912 usrp_standard_tx::set_nchannels (int nchan)
914 if (!(nchan == 1 || nchan == 2))
921 return write_hw_mux_reg ();
925 usrp_standard_tx::set_mux (int mux)
929 return write_hw_mux_reg ();
933 usrp_standard_tx::write_hw_mux_reg ()
935 bool s = disable_tx ();
936 bool ok = _write_fpga_reg (FR_TX_MUX, d_hw_mux | d_nchan);
942 usrp_standard_tx::determine_tx_mux_value(const usrp_subdev_spec &ss)
945 Determine appropriate Tx mux value as a function of the subdevice choosen.
947 @param u: instance of USRP source
948 @param subdev_spec: return value from subdev option parser.
949 @type subdev_spec: (side, subdev), where side is 0 or 1 and subdev is 0
950 @returns: the Rx mux value
952 This is simpler than the rx case. Either you want to talk
953 to side A or side B. If you want to talk to both sides at once,
954 determine the value manually.
958 throw std::invalid_argument("subdev_spec");
960 std::vector<db_base_sptr> db = this->db(ss.side);
962 if(db[0]->i_and_q_swapped()) {
963 unsigned int mask[2] = {0x0089, 0x8900};
964 return mask[ss.side];
967 unsigned int mask[2] = {0x0098, 0x9800};
968 return mask[ss.side];
974 #ifdef USE_FPGA_TX_CORDIC
977 usrp_standard_tx::set_tx_freq (int channel, double freq)
979 if (channel < 0 || channel >= MAX_CHAN)
982 // This assumes we're running the 4x on-chip interpolator.
985 compute_freq_control_word_fpga (dac_rate () / 4,
986 freq, &d_tx_freq[channel],
989 return _write_fpga_reg (FR_TX_FREQ_0 + channel, v);
996 usrp_standard_tx::set_tx_freq (int channel, double freq)
998 if (channel < 0 || channel >= MAX_CHAN)
1001 // split freq into fine and coarse components
1006 assert (dac_rate () == 128000000);
1008 if (freq < -44e6) // too low
1010 else if (freq < -24e6){ // [-44, -24)
1011 cm = CM_NEG_FDAC_OVER_4;
1012 coarse = -dac_rate () / 4;
1014 else if (freq < -8e6){ // [-24, -8)
1015 cm = CM_NEG_FDAC_OVER_8;
1016 coarse = -dac_rate () / 8;
1018 else if (freq < 8e6){ // [-8, 8)
1022 else if (freq < 24e6){ // [8, 24)
1023 cm = CM_POS_FDAC_OVER_8;
1024 coarse = dac_rate () / 8;
1026 else if (freq <= 44e6){ // [24, 44]
1027 cm = CM_POS_FDAC_OVER_4;
1028 coarse = dac_rate () / 4;
1034 set_coarse_modulator (channel, cm); // set bits in d_tx_modulator_shadow
1036 double fine = freq - coarse;
1039 // Compute fine tuning word...
1040 // This assumes we're running the 4x on-chip interpolator.
1041 // (This is required to use the fine modulator.)
1044 compute_freq_control_word_9862 (dac_rate () / 4,
1045 fine, &d_tx_freq[channel], d_verbose);
1047 d_tx_freq[channel] += coarse; // adjust actual
1049 unsigned char high, mid, low;
1051 high = (v >> 16) & 0xff;
1052 mid = (v >> 8) & 0xff;
1053 low = (v >> 0) & 0xff;
1057 // write the fine tuning word
1058 ok &= _write_9862 (channel, REG_TX_NCO_FTW_23_16, high);
1059 ok &= _write_9862 (channel, REG_TX_NCO_FTW_15_8, mid);
1060 ok &= _write_9862 (channel, REG_TX_NCO_FTW_7_0, low);
1063 d_tx_modulator_shadow[channel] |= TX_MODULATOR_ENABLE_NCO;
1066 d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_FINE_TUNE;
1068 d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_NEG_FINE_TUNE;
1070 ok &=_write_9862 (channel, REG_TX_MODULATOR, d_tx_modulator_shadow[channel]);
1077 usrp_standard_tx::set_coarse_modulator (int channel, coarse_mod_t cm)
1079 if (channel < 0 || channel >= MAX_CHAN)
1083 case CM_NEG_FDAC_OVER_4:
1084 d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
1085 d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_4;
1086 d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_COARSE_TUNE;
1089 case CM_NEG_FDAC_OVER_8:
1090 d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
1091 d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_8;
1092 d_tx_modulator_shadow[channel] |= TX_MODULATOR_NEG_COARSE_TUNE;
1096 d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
1099 case CM_POS_FDAC_OVER_8:
1100 d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
1101 d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_8;
1104 case CM_POS_FDAC_OVER_4:
1105 d_tx_modulator_shadow[channel] &= ~TX_MODULATOR_CM_MASK;
1106 d_tx_modulator_shadow[channel] |= TX_MODULATOR_COARSE_MODULATION_F_OVER_4;
1113 d_coarse_mod[channel] = cm;
1118 usrp_standard_tx::interp_rate () const { return d_interp_rate; }
1121 usrp_standard_tx::nchannels () const { return d_nchan; }
1124 usrp_standard_tx::mux () const { return d_sw_mux; }
1127 usrp_standard_tx::tx_freq (int channel) const
1129 if (channel < 0 || channel >= MAX_CHAN)
1132 return d_tx_freq[channel];
1135 usrp_standard_tx::coarse_mod_t
1136 usrp_standard_tx::coarse_modulator (int channel) const
1138 if (channel < 0 || channel >= MAX_CHAN)
1141 return d_coarse_mod[channel];
1145 usrp_standard_tx::tune(int chan, db_base_sptr db, double target_freq, usrp_tune_result *result)
1147 duc_control dxc(this, chan);
1148 return tune_a_helper(db, target_freq, converter_rate(), dxc, result);