2 // Copyright 2008,2009 Free Software Foundation, Inc.
4 // This file is part of GNU Radio
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 asversion 3, or (at your option)
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.
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.
25 #include <usrp/db_dbs_rx.h>
26 #include <db_base_impl.h>
31 /*****************************************************************************/
34 db_dbs_rx::db_dbs_rx(usrp_basic_sptr _usrp, int which)
35 : db_base(_usrp, which)
37 // Control DBS receiver based USRP daughterboard.
39 // @param usrp: instance of usrp.source_c
40 // @param which: which side: 0, 1 corresponding to RX_A or RX_B respectively
42 usrp()->_write_oe(d_which, 0x0001, 0x0001);
67 set_gain((gain_min() + gain_max()) / 2.0); // initialize gain
69 bypass_adc_buffers(true);
72 db_dbs_rx::~db_dbs_rx()
82 // do whatever there is to do to shutdown orderly
83 _enable_refclk(false);
88 db_dbs_rx::_write_reg (int regno, int v)
90 //regno is in [0,5], v is value to write to register"""
91 assert (0 <= regno && regno <= 5);
92 std::vector<int> args(2);
95 usrp()->write_i2c (d_i2c_addr, int_seq_to_str (args));
99 db_dbs_rx::_write_regs (int starting_regno, const std::vector<int> &vals)
101 // starting_regno is in [0,5],
102 // vals is a seq of integers to write to consecutive registers"""
105 std::vector<int> args;
106 args.push_back(starting_regno);
107 args.insert(args.end(), vals.begin(), vals.end());
108 usrp()->write_i2c (d_i2c_addr, int_seq_to_str (args));
112 db_dbs_rx::_read_status ()
114 //If successful, return list of two ints: [status_info, filter_DAC]"""
115 std::string s = usrp()->read_i2c (d_i2c_addr, 2);
117 std::vector<int> ret(0);
120 return str_to_int_seq (s);
124 db_dbs_rx::_send_reg(int regno)
126 assert(0 <= regno && regno <= 5);
128 _write_reg(0,(d_div2<<7) + (d_n>>8));
130 _write_reg(1,d_n & 255);
132 _write_reg(2,d_osc + (d_cp<<3) + (d_r_int<<5));
134 _write_reg(3,d_fdac);
136 _write_reg(4,d_m + (d_dl<<5) + (d_ade<<6) + (d_adl<<7));
138 _write_reg(5,d_gc2 + (d_diag<<5));
143 db_dbs_rx::_set_m(int m)
151 db_dbs_rx::_set_fdac(int fdac)
153 assert(fdac>=0 && fdac<128);
159 db_dbs_rx::set_bw (float bw)
161 if (bw < 1e6 || bw > 33e6) {
162 fprintf(stderr, "db_dbs_rx::set_bw: bw (=%f) must be between 1e6 and 33e6 inclusive\n", bw);
166 // struct bw_t ret = {0, 0, 0};
167 int m_max, m_min, m_test, fdac_test;
169 m_max = int(std::min(31, (int)floor(_refclk_freq()/1e6)));
170 else if(bw >= 2e6) // Outside of Specs!
171 m_max = int(std::min(31, (int)floor(_refclk_freq()/.5e6)));
172 else // Way outside of Specs!
173 m_max = int(std::min(31, (int)floor(_refclk_freq()/.25e6)));
175 m_min = int(ceil(_refclk_freq()/2.5e6));
177 while(m_test >= m_min) {
178 fdac_test = static_cast<int>(round(((bw * m_test / _refclk_freq())-4)/.145));
185 if(m_test>=m_min && fdac_test>=0) {
187 _set_fdac(fdac_test);
191 //ret.div = _refclk_freq()/d_m*(4+0.145*d_fdac);
194 fprintf(stderr, "db_dbs_rx::set_bw: failed\n");
203 db_dbs_rx::_set_dl(int dl)
205 assert(dl == 0 || dl == 1);
211 db_dbs_rx::_set_gc2(int gc2)
213 assert(gc2<32 && gc2>=0);
219 db_dbs_rx::_set_gc1(int gc1)
221 assert(gc1>=0 && gc1<4096);
223 usrp()->write_aux_dac(d_which, 0, gc1);
227 db_dbs_rx::_set_pga(int pga_gain)
229 assert(pga_gain>=0 && pga_gain<=20);
231 usrp()->set_pga (0, pga_gain);
232 usrp()->set_pga (1, pga_gain);
235 usrp()->set_pga (2, pga_gain);
236 usrp()->set_pga (3, pga_gain);
241 db_dbs_rx::gain_min()
247 db_dbs_rx::gain_max()
253 db_dbs_rx::gain_db_per_step()
259 db_dbs_rx::set_gain(float gain)
263 // @param gain: gain in decibels
264 // @returns True/False
266 if(!(gain>=0 && gain<105)) {
267 throw std::runtime_error("gain out of range\n");
270 int gc1=0, gc2=0, dl=0, pga=0;
273 gc1 = int((-gain*1.85/56.0 + 2.6)*4096.0/3.3);
282 gc2 = static_cast<int>(round(31.0 * (1-gain/24.0)));
306 db_dbs_rx::_set_osc(int osc)
308 assert(osc>=0 && osc<8);
314 db_dbs_rx::_set_cp(int cp)
316 assert(cp>=0 && cp<4);
322 db_dbs_rx::_set_n(int n)
324 assert(n>256 && n<32768);
331 db_dbs_rx::_set_div2(int div2)
333 assert(div2 == 0 || div2 == 1);
339 db_dbs_rx::_set_r(int r)
341 assert(r>=0 && r<128);
343 d_r_int = static_cast<int>(round(log10(r)/log10(2)) - 1);
347 // FIXME How do we handle ADE and ADL properly?
349 db_dbs_rx::_set_ade(int ade)
351 assert(ade == 0 || ade == 1);
357 db_dbs_rx::freq_min()
363 db_dbs_rx::freq_max()
369 db_dbs_rx::set_freq(double freq)
371 // Set the frequency.
373 // @param freq: target RF frequency in Hz
374 // @type freq: double
376 // @returns (ok, actual_baseband_freq) where:
377 // ok is True or False and indicates success or failure,
378 // actual_baseband_freq is RF frequency that corresponds to DC in the IF.
380 freq_result_t args = {false, 0};
382 if(!(freq>=freq_min() && freq<=freq_max())) {
397 int rmin = std::max(2, (int)(_refclk_freq()/2e6));
398 int rmax = std::min(128, (int)(_refclk_freq()/500e3));
403 int best_delta = 10e6;
407 n = static_cast<int>(round(freq/(_refclk_freq()/r)));
408 if(r<rmin || n<256) {
412 delta = (int)fabs(n*_refclk_freq()/r - freq);
418 if(delta < best_delta*0.9) {
427 _set_n(static_cast<int>(round(best_n)));
432 else if(vcofreq < 2711e6)
434 else if(vcofreq < 3025e6)
436 else if(vcofreq < 3341e6)
438 else if(vcofreq < 3727e6)
440 else if(vcofreq < 4143e6)
442 else if(vcofreq < 4493e6)
451 std::vector<int> bytes(2);
452 while(adc_val == 0 || adc_val == 7) {
453 bytes = _read_status();
454 adc_val = bytes[0] >> 2;
463 else if(adc_val == 7) {
474 if(adc_val == 1 || adc_val == 2) {
477 else if(adc_val == 3 || adc_val == 4) {
485 args.baseband_freq = d_n * _refclk_freq() / d_r;
490 db_dbs_rx::_refclk_divisor()
492 //Return value to stick in REFCLK_DIVISOR register
497 db_dbs_rx::is_quadrature()
499 // Return True if this board requires both I & Q analog channels.