Imported Upstream version 3.2.2
[debian/gnuradio] / usrp / host / lib / legacy / db_dtt754.cc
1 /* -*- c++ -*- */
2 //
3 // Copyright 2008 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 asversion 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 #include <db_dtt754.h>
23 #include <db_base_impl.h>
24
25 int
26 control_byte_1()
27 {
28   int RS = 0;  // 0 = 166.66kHz reference
29   int ATP = 7; // Disable internal AGC
30   return (0x80 | ATP<<3 | RS);
31 }
32
33 int
34 control_byte_2()
35 {
36   int STBY = 0;  // powered on
37   int XTO = 1;   // turn off xtal out, which we don't have
38   int ATC = 0;   // not clear exactly, possibly speeds up or slows down AGC, which we are not using
39   
40   int c = 0xc2 | ATC<<5 | STBY<<4 | XTO;
41   return c;
42 }
43
44 int
45 bandswitch_byte(float freq, float bw)
46 {
47   int P5, CP, BS;
48
49   if(bw>7.5e6) {
50     P5 = 1;
51   }
52   else {
53     P5 = 0;
54   }
55
56   if(freq < 121e6) {
57     CP = 0;
58     BS = 1;
59   }
60   else if(freq < 141e6) {
61     CP = 1;
62     BS = 1;
63   }
64   else if(freq < 166e6) {
65     CP = 2;
66     BS = 1;
67   }
68   else if(freq < 182e6) {
69     CP = 3;
70     BS = 1;
71   }
72   else if(freq < 286e6) {
73     CP = 0;
74     BS = 2;
75   }
76   else if(freq < 386e6) {
77     CP = 1;
78     BS = 2;
79   }
80   else if(freq < 446e6) {
81     CP = 2;
82     BS = 2;
83   }
84   else if(freq < 466e6) {
85     CP = 3;
86     BS = 2;
87   }
88   else if(freq < 506e6) {
89     CP = 0;
90     BS = 8;
91   }
92   else if(freq < 761e6) {
93     CP = 1;
94     BS = 8;
95   }
96   else if(freq < 846e6) {
97     CP = 2;
98     BS = 8;
99   }
100   else { // limit is ~905 MHz
101     CP = 3;
102     BS = 8;
103   }
104   return (CP<<6 | P5 << 4 | BS);
105 }
106
107 db_dtt754::db_dtt754(usrp_basic_sptr _usrp, int which)
108   : db_base(_usrp, which)
109 {
110   /*
111    * Control custom DTT75403-based daughterboard.
112    * 
113    * @param usrp: instance of usrp.source_c
114    * @param which: which side: 0 or 1 corresponding to RX_A or RX_B respectively
115    * @type which: int
116    */
117
118   // FIXME: DTT754 and DTT768 can probably inherit from a DTT class
119   
120   if(d_which == 0) {
121     d_i2c_addr = 0x60;
122   }
123   else {
124     d_i2c_addr = 0x62;
125   }
126
127   d_bw = 7e6;
128   d_IF = 36e6;
129         
130   d_f_ref = 166.6666e3;
131   d_inverted = false;
132
133   set_gain((gain_min() + gain_max()) / 2.0);
134
135   bypass_adc_buffers(false);
136 }
137
138 db_dtt754::~db_dtt754()
139 {
140 }
141   
142 float
143 db_dtt754::gain_min()
144 {
145   return 0;
146 }
147
148 float
149 db_dtt754::gain_max()
150 {
151   return 115;
152 }
153
154 float
155 db_dtt754::gain_db_per_step()
156 {
157   return 1;
158 }
159
160 bool
161 db_dtt754::set_gain(float gain)
162 {
163   assert(gain>=0 && gain<=115);
164
165   float rfgain, ifgain, pgagain;
166   if(gain > 60) {
167     rfgain = 60;
168     gain = gain - 60;
169   }
170   else {
171     rfgain = gain;
172     gain = 0;
173   }
174   
175   if(gain > 35) {
176     ifgain = 35;
177     gain = gain - 35;
178   }
179   else {
180     ifgain = gain;
181     gain = 0;
182   }
183   pgagain = gain;
184   
185   _set_rfagc(rfgain);
186   _set_ifagc(ifgain);
187   _set_pga(pgagain);
188
189   return true; // can't fail with the assert in place
190 }
191
192 double
193 db_dtt754::freq_min()
194 {
195   return 44e6;
196 }
197
198 double
199 db_dtt754::freq_max()
200 {
201   return 900e6;
202 }
203
204 struct freq_result_t
205 db_dtt754::set_freq(double target_freq)
206 {
207   /*
208    * @returns (ok, actual_baseband_freq) where:
209    * ok is True or False and indicates success or failure,
210    * actual_baseband_freq is the RF frequency that corresponds to DC in the IF.
211    */
212   
213   freq_result_t ret = {false, 0.0};
214
215   if(target_freq < freq_min() || target_freq > freq_max()) {
216     return ret;
217   }
218         
219   double target_lo_freq = target_freq + d_IF;  // High side mixing
220
221   int divisor = (int)(0.5+(target_lo_freq / d_f_ref));
222   double actual_lo_freq = d_f_ref*divisor;
223   
224   if((divisor & ~0x7fff) != 0) {                // must be 15-bits or less
225     return ret;
226   }
227   
228   // build i2c command string
229   std::vector<int> buf(5);
230   buf[0] = (divisor >> 8) & 0xff;          // DB1
231   buf[1] = divisor & 0xff;                 // DB2
232   buf[2] = control_byte_1();
233   buf[3] = bandswitch_byte(actual_lo_freq, d_bw);
234   buf[4] = control_byte_2();
235
236   bool ok = usrp()->write_i2c(d_i2c_addr, int_seq_to_str (buf));
237
238   d_freq = actual_lo_freq - d_IF;
239         
240   ret.ok = ok;
241   ret.baseband_freq = actual_lo_freq;
242
243   return ret;
244
245 }
246   
247 bool
248 db_dtt754::is_quadrature()
249 {
250   /*
251    * Return True if this board requires both I & Q analog channels.
252    * 
253    * This bit of info is useful when setting up the USRP Rx mux register.
254    */
255      
256   return false;
257 }
258
259 bool
260 db_dtt754::spectrum_inverted()
261 {
262   /*
263    * The 43.75 MHz version is inverted
264    */
265   
266   return d_inverted;
267 }
268
269 bool
270 db_dtt754::set_bw(float bw)
271 {
272   /*
273    * Choose the SAW filter bandwidth, either 7MHz or 8MHz)
274    */
275
276   d_bw = bw;
277   set_freq(d_freq);
278
279   return true; // FIXME: propagate set_freq result
280 }
281
282 void
283 db_dtt754::_set_rfagc(float gain)
284 {
285   assert(gain <= 60 && gain >= 0);
286   // FIXME this has a 0.5V step between gain = 60 and gain = 59.
287   // Why are there two cases instead of a single linear case?
288   float voltage;
289   if(gain == 60) {
290     voltage = 4;
291   }
292   else {
293     voltage = gain/60.0 * 2.25 + 1.25;
294   }
295   
296   int dacword = (int)(4096*voltage/1.22/3.3);    // 1.22 = opamp gain
297     
298   assert(dacword>=0 && dacword<4096);
299   usrp()->write_aux_dac(d_which, 1, dacword);
300 }
301
302 void
303 db_dtt754::_set_ifagc(float gain)
304 {
305   assert(gain <= 35 && gain >= 0);
306   float voltage = gain/35.0 * 2.1 + 1.4;
307   int dacword = (int)(4096*voltage/1.22/3.3);    // 1.22 = opamp gain
308
309   assert(dacword>=0 && dacword<4096);
310   usrp()->write_aux_dac(d_which, 0, dacword);
311 }
312
313 void
314 db_dtt754::_set_pga(float pga_gain)
315 {
316   assert(pga_gain >=0 && pga_gain <=20);
317   if(d_which == 0) {
318     usrp()->set_pga (0, pga_gain);
319   }
320   else {
321     usrp()->set_pga (2, pga_gain);
322   }
323 }