Cleanup in preparation for merge
[debian/gnuradio] / usrp / host / lib / db_dtt768.cc
1 /* -*- c++ -*- */
2 //
3 // Copyright 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 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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <usrp/db_dtt768.h>
27 #include <db_base_impl.h>
28
29 int
30 control_byte_4()
31 {
32   int C = 0;   // Charge Pump Current, no info on how to choose
33   int R = 4;   // 125 kHz fref
34   
35   // int ATP = 7; // Disable internal AGC
36   return (0x80 | C<<5 | R);
37 }
38
39 int
40 control_byte_5(float freq, int agcmode = 1)
41 {
42   if(agcmode) {
43     if(freq < 150e6) {
44       return 0x3B;
45     }
46     else if(freq < 420e6) {
47       return 0x7E;
48     }
49     else {
50       return 0xB7;
51     }
52   }
53   else {
54     if(freq < 150e6) {
55       return 0x39;
56     }
57     else if(freq < 420e6) {
58       return 0x7C;
59     }
60     else {
61       return 0xB5;
62     }
63   }
64 }
65         
66 int
67 control_byte_6()
68 {
69   int ATC = 0;   // AGC time constant = 100ms, 1 = 3S
70   int IFE = 1;   // IF AGC amplifier enable
71   int AT = 0;    // AGC control, ???
72   
73   return (ATC << 5 | IFE << 4 | AT);
74 }
75
76 int
77 control_byte_7()
78 {
79   int SAS = 1;  // SAW Digital mode
80   int AGD = 1;  // AGC disable
81   int ADS = 0;  // AGC detector into ADC converter
82   int T = 0;    // Test mode, undocumented
83   return (SAS << 7 | AGD << 5 | ADS << 4 | T);
84 }
85
86 db_dtt768::db_dtt768(usrp_basic_sptr _usrp, int which)
87   : db_base(_usrp, which)
88 {
89   /*
90    * Control custom DTT76803-based daughterboard.
91    * 
92    * @param usrp: instance of usrp.source_c
93    * @param which: which side: 0 or 1 corresponding to RX_A or RX_B respectively
94    * @type which: int
95    */
96   
97   if(d_which == 0) {
98     d_i2c_addr = 0x60;
99   }
100   else {
101     d_i2c_addr = 0x62;
102   }
103
104   d_IF = 44e6;
105         
106   d_f_ref = 125e3;
107   d_inverted = false;
108
109   set_gain((gain_min() + gain_max()) / 2.0);
110
111   bypass_adc_buffers(false);
112 }
113
114 db_dtt768::~db_dtt768()
115 {
116 }
117   
118 float
119 db_dtt768::gain_min()
120 {
121   return 0;
122 }
123
124 float
125 db_dtt768::gain_max()
126 {
127   return 115;
128 }
129
130 float
131 db_dtt768::gain_db_per_step()
132 {
133   return 1;
134 }
135
136 bool
137 db_dtt768::set_gain(float gain)
138 {
139   assert(gain>=0 && gain<=115);
140
141   float rfgain, ifgain, pgagain;
142   if(gain > 60) {
143     rfgain = 60;
144     gain = gain - 60;
145   }
146   else {
147     rfgain = gain;
148     gain = 0;
149   }
150   
151   if(gain > 35) {
152     ifgain = 35;
153     gain = gain - 35;
154   }
155   else {
156     ifgain = gain;
157     gain = 0;
158   }
159   pgagain = gain;
160   
161   _set_rfagc(rfgain);
162   _set_ifagc(ifgain);
163   _set_pga(pgagain);
164
165   return true;
166 }
167
168 double
169 db_dtt768::freq_min()
170 {
171   return 44e6;
172 }
173
174 double
175 db_dtt768::freq_max()
176 {
177   return 900e6;
178 }
179
180 struct freq_result_t
181 db_dtt768::set_freq(double target_freq)
182 {
183   /*
184    * @returns (ok, actual_baseband_freq) where:
185    * ok is True or False and indicates success or failure,
186    * actual_baseband_freq is the RF frequency that corresponds to DC in the IF.
187    */
188   
189   freq_result_t ret = {false, 0.0};
190
191   if(target_freq < freq_min() || target_freq > freq_max()) {
192     return ret;
193   }
194         
195   double target_lo_freq = target_freq + d_IF;  // High side mixing
196
197   int divisor = (int)(0.5+(target_lo_freq / d_f_ref));
198   double actual_lo_freq = d_f_ref*divisor;
199   
200   if((divisor & ~0x7fff) != 0) {                // must be 15-bits or less
201     return ret;
202   }
203   
204   // build i2c command string
205   std::vector<int> buf(6);
206   buf[0] = (divisor >> 8) & 0xff;          // DB1
207   buf[1] = divisor & 0xff;                 // DB2
208   buf[2] = control_byte_4();
209   buf[3] = control_byte_5(target_freq);
210   buf[4] = control_byte_6();
211   buf[5] = control_byte_7();
212
213   bool ok = usrp()->write_i2c(d_i2c_addr, int_seq_to_str (buf));
214
215   d_freq = actual_lo_freq - d_IF;
216   
217   ret.ok = ok;
218   ret.baseband_freq = actual_lo_freq;
219
220   return ret;
221
222 }
223   
224 bool
225 db_dtt768::is_quadrature()
226 {
227   /*
228    * Return True if this board requires both I & Q analog channels.
229    * 
230    * This bit of info is useful when setting up the USRP Rx mux register.
231    */
232      
233   return false;
234 }
235
236 bool
237 db_dtt768::spectrum_inverted()
238 {
239   /*
240    * The 43.75 MHz version is inverted
241    */
242   
243   return d_inverted;
244 }
245
246 bool
247 db_dtt768::set_bw(float bw)
248 {
249   /*
250    * Choose the SAW filter bandwidth, either 7MHz or 8MHz)
251    */
252
253   d_bw = bw;
254   set_freq(d_freq);
255
256   return true; // FIXME: propagate set_freq result
257 }
258
259 void
260 db_dtt768::_set_rfagc(float gain)
261 {
262   assert(gain <= 60 && gain >= 0);
263   // FIXME this has a 0.5V step between gain = 60 and gain = 59.
264   // Why are there two cases instead of a single linear case?
265   float voltage;
266   if(gain == 60) {
267     voltage = 4;
268   }
269   else {
270     voltage = gain/60.0 * 2.25 + 1.25;
271   }
272   
273   int dacword = (int)(4096*voltage/1.22/3.3);    // 1.22 = opamp gain
274     
275   assert(dacword>=0 && dacword<4096);
276   usrp()->write_aux_dac(d_which, 1, dacword);
277 }
278
279 void
280 db_dtt768::_set_ifagc(float gain)
281 {
282   assert(gain <= 35 && gain >= 0);
283   float voltage = gain/35.0 * 2.1 + 1.4;
284   int dacword = (int)(4096*voltage/1.22/3.3);    // 1.22 = opamp gain
285
286   assert(dacword>=0 && dacword<4096);
287   usrp()->write_aux_dac(d_which, 0, dacword);
288 }
289
290 void
291 db_dtt768::_set_pga(float pga_gain)
292 {
293   assert(pga_gain >=0 && pga_gain <=20);
294   if(d_which == 0) {
295     usrp()->set_pga (0, pga_gain);
296   }
297   else {
298     usrp()->set_pga (2, pga_gain);
299   }
300 }