Cleanup in preparation for merge
[debian/gnuradio] / usrp / host / lib / db_dbs_rx.cc
1 //
2 // Copyright 2008,2009 Free Software Foundation, Inc.
3 // 
4 // This file is part of GNU Radio
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 asversion 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 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <usrp/db_dbs_rx.h>
26 #include <db_base_impl.h>
27 #include <cmath>
28 #include <cstdio>
29
30
31 /*****************************************************************************/
32
33
34 db_dbs_rx::db_dbs_rx(usrp_basic_sptr _usrp, int which)
35   : db_base(_usrp, which)
36 {
37   // Control DBS receiver based USRP daughterboard.
38   // 
39   // @param usrp: instance of usrp.source_c
40   // @param which: which side: 0, 1 corresponding to RX_A or RX_B respectively
41
42   usrp()->_write_oe(d_which, 0x0001, 0x0001);
43   if(which == 0) {
44     d_i2c_addr = 0x67;
45   }
46   else {
47     d_i2c_addr = 0x65;
48   }
49
50   d_n = 950;
51   d_div2 = 0;
52   d_osc = 5;
53   d_cp = 3;
54   d_r = 4;
55   d_r_int = 1;
56   d_fdac = 127;
57   d_m = 2;
58   d_dl = 0;
59   d_ade = 0;
60   d_adl = 0;
61   d_gc1 = 0;
62   d_gc2 = 31;
63   d_diag = 0;
64   
65   _enable_refclk(true);
66   
67   set_gain((gain_min() + gain_max()) / 2.0);       // initialize gain
68
69   bypass_adc_buffers(true);
70 }
71
72 db_dbs_rx::~db_dbs_rx()
73 {
74   shutdown();
75 }
76
77 void
78 db_dbs_rx::shutdown()
79 {
80   if (!d_is_shutdown){
81     d_is_shutdown = true;
82     // do whatever there is to do to shutdown orderly
83     _enable_refclk(false);
84   }
85 }
86
87 void
88 db_dbs_rx::_write_reg (int regno, int v)
89 {
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);
93   args[0] = regno;
94   args[1] = v;
95   usrp()->write_i2c (d_i2c_addr, int_seq_to_str (args));
96 }
97
98 void
99 db_dbs_rx::_write_regs (int starting_regno, const std::vector<int> &vals)
100 {
101   // starting_regno is in [0,5],
102   // vals is a seq of integers to write to consecutive registers"""
103
104   //FIXME
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));
109 }
110         
111 std::vector<int>
112 db_dbs_rx::_read_status ()
113 {
114   //If successful, return list of two ints: [status_info, filter_DAC]"""
115   std::string s = usrp()->read_i2c (d_i2c_addr, 2);
116   if(s.size() != 2) {
117     std::vector<int> ret(0);
118     return ret;
119   }
120   return str_to_int_seq (s);
121 }
122
123 void
124 db_dbs_rx::_send_reg(int regno)
125 {
126   assert(0 <= regno && regno <= 5);
127   if(regno == 0)
128     _write_reg(0,(d_div2<<7) + (d_n>>8));
129   if(regno == 1)
130     _write_reg(1,d_n & 255);
131   if(regno == 2)
132     _write_reg(2,d_osc + (d_cp<<3) + (d_r_int<<5));
133   if(regno == 3)
134     _write_reg(3,d_fdac);
135   if(regno == 4)
136     _write_reg(4,d_m + (d_dl<<5) + (d_ade<<6) + (d_adl<<7));
137   if(regno == 5)
138     _write_reg(5,d_gc2 + (d_diag<<5));
139 }
140
141 // BW setting
142 void
143 db_dbs_rx::_set_m(int m)
144 {
145   assert(m>0 && m<32);
146   d_m = m;
147   _send_reg(4);
148 }
149   
150 void
151 db_dbs_rx::_set_fdac(int fdac)
152 {
153   assert(fdac>=0 && fdac<128);
154   d_fdac = fdac;
155   _send_reg(3);
156 }
157
158 bool
159 db_dbs_rx::set_bw (float bw)
160 {
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);
163     return false;
164   }
165
166   // struct bw_t ret = {0, 0, 0};
167   int m_max, m_min, m_test, fdac_test;
168   if(bw >= 4e6)
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)));
174   
175   m_min = int(ceil(_refclk_freq()/2.5e6));
176   m_test = m_max;
177   while(m_test >= m_min) {
178     fdac_test = static_cast<int>(round(((bw * m_test / _refclk_freq())-4)/.145));
179     if(fdac_test > 127)
180       m_test = m_test - 1;
181     else
182       break;
183   }
184
185   if(m_test>=m_min && fdac_test>=0) {
186     _set_m(m_test);
187     _set_fdac(fdac_test);
188
189     //ret.m = d_m;
190     //ret.fdac = d_fdac;
191     //ret.div = _refclk_freq()/d_m*(4+0.145*d_fdac);
192   }
193   else {
194     fprintf(stderr, "db_dbs_rx::set_bw: failed\n");
195     return false;
196   }
197
198   return true;
199 }
200
201 // Gain setting
202 void
203 db_dbs_rx::_set_dl(int dl)
204 {
205   assert(dl == 0 || dl == 1);
206   d_dl = dl;
207   _send_reg(4);
208 }
209
210 void
211 db_dbs_rx::_set_gc2(int gc2)
212 {
213   assert(gc2<32 && gc2>=0);
214   d_gc2 = gc2;
215   _send_reg(5);
216 }
217
218 void
219 db_dbs_rx::_set_gc1(int gc1)
220 {
221   assert(gc1>=0 && gc1<4096);
222   d_gc1 = gc1;
223   usrp()->write_aux_dac(d_which, 0, gc1);
224 }
225
226 void
227 db_dbs_rx::_set_pga(int pga_gain)
228 {
229   assert(pga_gain>=0 && pga_gain<=20);
230   if(d_which == 0) {
231     usrp()->set_pga (0, pga_gain);
232     usrp()->set_pga (1, pga_gain);
233   }
234   else {
235     usrp()->set_pga (2, pga_gain);
236     usrp()->set_pga (3, pga_gain);
237   }
238 }
239
240 float
241 db_dbs_rx::gain_min()
242 {
243   return 0;
244 }
245
246 float
247 db_dbs_rx::gain_max()
248 {
249   return 104;
250 }
251
252 float
253 db_dbs_rx::gain_db_per_step()
254 {
255   return 1;
256 }
257
258 bool 
259 db_dbs_rx::set_gain(float gain)
260 {
261   // Set the gain.
262   // 
263   // @param gain:  gain in decibels
264   // @returns True/False
265
266   if(!(gain>=0 && gain<105)) {
267     throw std::runtime_error("gain out of range\n");
268   }
269
270   int gc1=0, gc2=0, dl=0, pga=0;
271
272   if(gain < 56) {
273     gc1 = int((-gain*1.85/56.0 + 2.6)*4096.0/3.3);
274     gain = 0;
275   }
276   else {
277     gc1 = 0;
278     gain -= 56;
279   }
280    
281   if(gain < 24) {
282     gc2 = static_cast<int>(round(31.0 * (1-gain/24.0)));
283     gain = 0;
284   }
285   else {
286     gc2 = 0;
287     gain -=24;
288   }
289   
290   if(gain >= 4.58) {
291     dl = 1;
292     gain -= 4.58;
293   }
294
295   pga = gain;
296   _set_gc1(gc1);
297   _set_gc2(gc2);
298   _set_dl(dl);
299   _set_pga(pga);
300
301   return true;
302 }
303
304 // Frequency setting
305 void
306 db_dbs_rx::_set_osc(int osc)
307 {
308   assert(osc>=0 && osc<8);
309   d_osc = osc;
310   _send_reg(2);
311 }
312
313 void
314 db_dbs_rx::_set_cp(int cp)
315 {
316   assert(cp>=0 && cp<4);
317   d_cp = cp;
318   _send_reg(2);
319 }
320
321 void
322 db_dbs_rx::_set_n(int n)
323 {
324   assert(n>256 && n<32768);
325   d_n = n;
326   _send_reg(0);
327   _send_reg(1);
328 }
329
330 void
331 db_dbs_rx::_set_div2(int div2)
332 {
333   assert(div2 == 0 || div2 == 1);
334   d_div2 = div2;
335   _send_reg(0);
336 }
337
338 void
339 db_dbs_rx::_set_r(int r)
340 {
341   assert(r>=0 && r<128);
342   d_r = r;
343   d_r_int = static_cast<int>(round(log10(r)/log10(2)) - 1);
344   _send_reg(2);
345 }
346
347 // FIXME  How do we handle ADE and ADL properly?
348 void
349 db_dbs_rx::_set_ade(int ade)
350 {
351   assert(ade == 0 || ade == 1);
352   d_ade = ade;
353   _send_reg(4);
354 }
355
356 double
357 db_dbs_rx::freq_min()
358 {
359   return 500e6;
360 }
361
362 double
363 db_dbs_rx::freq_max()
364 {
365   return 2.6e9;
366 }
367
368 struct freq_result_t
369 db_dbs_rx::set_freq(double freq)
370 {
371   // Set the frequency.
372   // 
373   // @param freq:  target RF frequency in Hz
374   // @type freq:   double
375   // 
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.
379   
380   freq_result_t args = {false, 0};
381   
382   if(!(freq>=freq_min() && freq<=freq_max())) {
383     return args;
384   }
385   
386   double vcofreq;
387   if(freq<1150e6) {
388     _set_div2(0);
389     vcofreq = 4 * freq;
390   }
391   else {
392     _set_div2(1);
393     vcofreq = 2 * freq;
394   }
395   
396   _set_ade(1);
397   int rmin = std::max(2, (int)(_refclk_freq()/2e6));
398   int rmax = std::min(128, (int)(_refclk_freq()/500e3));
399   int r = 2;
400   int n = 0;
401   int best_r = 2;
402   int best_n = 0;
403   int best_delta = 10e6;
404   int delta;
405   
406   while(r <= rmax) {
407     n = static_cast<int>(round(freq/(_refclk_freq()/r)));
408     if(r<rmin || n<256) {
409       r = r * 2;
410       continue;
411     }
412     delta = (int)fabs(n*_refclk_freq()/r - freq);
413     if(delta < 75e3) {
414       best_r = r;
415       best_n = n;
416       break;
417     }
418     if(delta < best_delta*0.9) {
419       best_r = r;
420       best_n = n;
421       best_delta = delta;
422     }
423     r = r * 2;
424   }
425   _set_r(best_r);
426
427   _set_n(static_cast<int>(round(best_n)));
428  
429   int vco;
430   if(vcofreq < 2433e6)
431     vco = 0;
432   else if(vcofreq < 2711e6)
433     vco=1;
434   else if(vcofreq < 3025e6)
435     vco=2;
436   else if(vcofreq < 3341e6)
437     vco=3;
438   else if(vcofreq < 3727e6)
439     vco=4;
440   else if(vcofreq < 4143e6)
441     vco=5;
442   else if(vcofreq < 4493e6)
443     vco=6;
444   else
445     vco=7;
446   
447   _set_osc(vco);
448   
449   // Set CP current
450   int adc_val = 0;
451   std::vector<int> bytes(2);
452   while(adc_val == 0 || adc_val == 7) {
453     bytes = _read_status();
454     adc_val = bytes[0] >> 2;
455     if(adc_val == 0) {
456       if(vco <= 0) {
457         return args;
458       }
459       else {
460         vco = vco - 1;
461       }
462     }
463     else if(adc_val == 7) {
464       if(vco >= 7) {
465         return args;
466       }
467       else {
468         vco = vco + 1;
469       }
470     }
471     _set_osc(vco);
472   }
473   
474   if(adc_val == 1 || adc_val == 2) {
475     _set_cp(1);
476   }
477   else if(adc_val == 3 || adc_val == 4) {
478     _set_cp(2);
479   }
480   else {
481     _set_cp(3);
482   }
483   
484   args.ok = true;
485   args.baseband_freq = d_n * _refclk_freq() / d_r;
486   return args;
487 }
488
489 int
490 db_dbs_rx::_refclk_divisor()
491 {
492   //Return value to stick in REFCLK_DIVISOR register
493   return 16;
494 }
495
496 bool 
497 db_dbs_rx::is_quadrature()
498 {
499   // Return True if this board requires both I & Q analog channels.  
500   return true;
501 }