Imported Upstream version 3.2.2
[debian/gnuradio] / usrp / host / lib / legacy / db_tv_rx.cc
1 //
2 // Copyright 2008 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 #include <db_tv_rx.h>
22 #include <db_base_impl.h>
23
24 /*****************************************************************************/
25
26 int
27 control_byte_1(bool fast_tuning_p, int reference_divisor)
28 {
29   int c = 0x88;
30   if(fast_tuning_p) {
31     c |= 0x40;
32   }
33
34   if(reference_divisor == 512) {
35     c |= 0x3 << 1;
36   }
37   else if(reference_divisor == 640) {
38     c |= 0x0 << 1;
39   }
40   else if(reference_divisor == 1024) {
41     c |= 0x1 << 1;
42   }
43   else {
44     assert(0);
45   }
46
47   return c;
48 }
49
50 int
51 control_byte_2(double target_freq, bool shutdown_tx_PGA)
52 {
53   int c;
54   if(target_freq < 158e6) {        // VHF low
55     c = 0xa0;
56   }
57   else if(target_freq < 464e6) {   // VHF high
58     c = 0x90;
59   }
60   else {                           // UHF
61     c = 0x30;
62   }
63
64   if(shutdown_tx_PGA) {
65     c |= 0x08;
66   }
67
68   return c;
69 }
70
71
72 /*****************************************************************************/
73
74
75 db_tv_rx::db_tv_rx(usrp_basic_sptr usrp, int which,
76                    double first_IF, double second_IF)
77   : db_base(usrp, which)
78 {
79   // Handler for Tv Rx daughterboards.
80   // 
81   // @param usrp: instance of usrp.source_c
82   // @param which: which side: 0, 1 corresponding to RX_A or RX_B respectively
83
84   if(which == 0) {
85     d_i2c_addr = 0x60;
86   }
87   else {
88     d_i2c_addr = 0x61;
89   }
90
91   d_first_IF = first_IF;
92   d_second_IF = second_IF;
93   d_reference_divisor = 640;
94   d_fast_tuning = false;
95   d_inverted = false;                     // FIXME get rid of this
96   
97   set_gain((gain_min() + gain_max()) / 2.0);       // initialize gain
98
99   bypass_adc_buffers(false);
100 }
101
102 db_tv_rx::~db_tv_rx()
103 {
104 }
105
106 // Gain setting
107 void
108 db_tv_rx::_set_rfagc(float gain)
109 {
110   float voltage;
111
112   assert(gain <= 60 && gain >= 0);
113   // FIXME this has a 0.5V step between gain = 60 and gain = 59.
114   // Why are there two cases instead of a single linear case?
115   if(gain == 60) {
116     voltage = 4;
117   }
118   else {
119     voltage = gain/60.0 * 2.25 + 1.25;
120   }
121   int dacword = int(4096*voltage/1.22/3.3);    // 1.22 = opamp gain
122
123   assert(dacword>=0 && dacword<4096);
124   usrp()->write_aux_dac(d_which, 1, dacword);
125 }
126
127 void
128 db_tv_rx::_set_ifagc(float gain)
129 {
130   float voltage;
131
132   assert(gain <= 35 && gain >= 0);
133   voltage = gain/35.0 * 2.1 + 1.4;
134   int dacword = int(4096*voltage/1.22/3.3);    // 1.22 = opamp gain
135   
136   assert(dacword>=0 && dacword<4096);
137   usrp()->write_aux_dac(d_which, 0, dacword);
138 }
139
140 void
141 db_tv_rx::_set_pga(float pga_gain)
142 {
143   assert(pga_gain >=0 && pga_gain <=20);
144   if(d_which == 0) {
145     usrp()->set_pga(0, pga_gain);
146   }
147   else {
148     usrp()->set_pga (2, pga_gain);
149   }
150 }           
151
152 double
153 db_tv_rx::freq_min()
154 {
155   return 50e6;
156 }
157
158 double
159 db_tv_rx::freq_max()
160 {
161   return 860e6;
162 }
163
164 struct freq_result_t
165 db_tv_rx::set_freq(double target_freq)
166 {
167   // Set the frequency.
168   // 
169   // @param freq:  target RF frequency in Hz
170   // @type freq:   double
171   // 
172   // @returns (ok, actual_baseband_freq) where:
173   //   ok is True or False and indicates success or failure,
174   //   actual_baseband_freq is RF frequency that corresponds to DC in the IF.
175   
176   freq_result_t args = {false, 0};
177
178   double fmin = freq_min();
179   double fmax = freq_max();
180   if((target_freq < fmin) || (target_freq > fmax)) {
181     return args;
182   }
183   
184   double target_lo_freq = target_freq + d_first_IF;    // High side mixing
185   double f_ref = 4.0e6 / (double)(d_reference_divisor); // frequency steps
186
187   int divisor = int((target_lo_freq + (f_ref * 4)) / (f_ref * 8));  
188   double actual_lo_freq = (f_ref * 8 * divisor);
189   double actual_freq = actual_lo_freq - d_first_IF;
190
191   if((divisor & ~0x7fff) != 0) {                // must be 15-bits or less
192     return args;
193   }
194
195   // build i2c command string
196   std::vector<int> buf(4);
197   buf[0] = (divisor >> 8) & 0xff;         // DB1
198   buf[1] = divisor & 0xff;                // DB2
199   buf[2] = control_byte_1(d_fast_tuning, d_reference_divisor);
200   buf[3] = control_byte_2(actual_freq, true);
201
202   args.ok = usrp()->write_i2c(d_i2c_addr, int_seq_to_str (buf));
203   args.baseband_freq = actual_freq - d_second_IF;
204   return args;
205 }
206
207 float
208 db_tv_rx::gain_min()
209 {
210   return 0;
211 }
212
213 float
214 db_tv_rx::gain_max()
215 {
216   return 115;
217 }
218
219 float
220 db_tv_rx::gain_db_per_step()
221 {
222   return 1;
223 }
224
225 bool 
226 db_tv_rx::set_gain(float gain)
227 {
228   // Set the gain.
229   // 
230   // @param gain:  gain in decibels
231   // @returns True/False
232
233   float rfgain, ifgain, pgagain;
234
235   assert(gain>=0 && gain<=115);
236   if(gain>60) {
237     rfgain = 60;
238     gain = gain - 60;
239   }
240   else {
241     rfgain = gain;
242     gain = 0;
243   }
244    
245   if(gain > 35) {
246     ifgain = 35;
247     gain = gain - 35;
248   }
249   else {
250     ifgain = gain;
251     gain = 0;
252   }
253
254   pgagain = gain;
255   _set_rfagc(rfgain);
256   _set_ifagc(ifgain);
257   _set_pga(pgagain);
258
259   return true;
260 }
261
262 bool 
263 db_tv_rx::is_quadrature()
264 {
265   // Return True if this board requires both I & Q analog channels.  
266   return false;
267 }
268
269 bool
270 db_tv_rx::spectrum_inverted() 
271 {
272   // The 43.75 MHz version is inverted
273   return d_inverted;
274 }