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