2 // Copyright 2010 Free Software Foundation, Inc.
4 // This file is part of GNU Radio
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)
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.
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.
25 #include <usrp/db_bitshark_rx.h>
26 #include <db_base_impl.h>
32 /* Note: Thie general structure of this file is based on the db_dbsrx.cc
33 codebase for the dbsrx daughterboard. */
35 /* The following defines specify the address map provided by the
36 Bitshark card. These registers are all accessed over I2C. */
37 #define RF_CENTER_FREQ_REG 0x00
38 #define RF_CHAN_FILTER_BW_REG 0x01
39 #define RF_GAIN_REG 0x02
40 #define BB_GAIN_REG 0x03
41 #define ADF4350_REG 0x10
42 #define SKY73202_REG 0x11
43 #define CLOCK_SCHEME_REG 0x20
45 /* The following table lists the registers provided by the BURX board that
46 are accessible over I2C:
47 --------------------------------------------------------
48 |RegAddr: 0x00-RF Center Freq register |
50 |4-byte unsigned RF center freq (in KHz)|
51 |RegAddr: 0x01-RF channel filter bandwidth register |
53 |4-byte unsigned RF channel filter bw (in KHz)|
54 |RegAddr: 0x02-RF gain register |
56 |1-byte signed RF gain (in dB)|
57 |RegAddr: 0x03-Baseband gain register |
59 |4-byte signed baseband filter gain (in dB)|
60 |RegAddr: 0x10-ADF4350 register |
62 |4-byte ADF4350 register value (actual ADF4350 reg addr embedded
64 |RegAddr: 0x11-SKY73202 register |
66 |1-byte reg 0 of SKY73202 |
67 |1-byte reg 1 of SKY73202 |
68 |1-byte reg 2 of SKY73202 |
69 |RegAddr: 0x20-Clock Scheme |
71 |1-byte indicating clocking scheme:
72 -0x00 -> BURX local TCXO off, BURX accepts ref clock from
73 USRP (freq of USRP's ref clock specified in bytes 2-5)
74 -0x01 -> BURX local TCXO on, BURX uses its local TCXO as its ref
75 clock, TCXO signal output for use by USRP |
76 |4-byte USRP ref clock freq in hz (only needed if byte 1 set to 0x00) |
78 ---------------------------------------------------------------------------
80 As an example, lets say the client wants to set an RF center freq of
81 1000 MHz. In KHz, this translates to 1000000 (resolution is only down to
82 steps of 1 KHz), which is 0x000F4240 in hex. So the complete 9-byte I2C
83 sequence that the client should send is as follows:
84 byte 0: 0x00-register 0x00 is the target of the write operation
85 bytes 1-4: 0x00 (padding)
86 byte 5: 0x40 (LSB of the 1000000 KHz value, in hex)
89 byte 8: 0x00 (MSB of the 1000000 KHz value, in hex)
91 If using the usrper cmd-line application on a PC, this sequence would
92 be sent as follows (assuming that the BURX is in slot A):
94 # usrper i2c_write 0x47 000000000040420F00
96 How about another example...lets say the client wants to setup the clock
97 scheme to use scheme #1 where the 26 MHz TCXO on the BURX board is enabled,
98 and is provided to the USRP. 26 MHz (i.e. 26 million), in hex, is 0x18CBA80.
99 So the complete 9-byte I2C sequence that the client should send is as follows:
100 byte 0: 0x20-register 0x20 is the target of the write operation
101 bytes 1-3: 0x00 (padding)
102 byte 4: 0x01 (indicating that clock scheme #1 is wanted)
103 byte 5: 0x80 (LSB of the BURX ref clk freq)
106 byte 8: 0x01 (MSB of the BURX ref clk freq)
108 To enable the BURX local ref clk, which will also make it available on the
109 on-board U.FL connector as a source for the USRP, a user can also use
110 the usrper cmd-line application on a PC. The following sequence would
111 be sent (assuming that the BURX is in slot A):
113 # usrper i2c_write 0x47 200000000180BA8C01
117 #define NUM_BYTES_IN_I2C_CMD 9
119 /*****************************************************************************/
121 db_bitshark_rx::db_bitshark_rx(usrp_basic_sptr _usrp, int which)
122 : db_base(_usrp, which)
124 // Control Bitshark receiver USRP daughterboard.
126 // @param usrp: instance of usrp.source_c
127 // @param which: which side: 0, 1 corresponding to RX_A or RX_B respectively
129 // turn off all outputs
130 usrp()->_write_oe(d_which, 0, 0xffff);
142 set_gain((gain_min() + gain_max()) / 2.0);
144 // by default, assume we're using the USRPs clock as the ref clk,
145 // so setup the clock scheme and frequency. If the user wants
146 // to use the Bitshark's TCXO, the clock scheme should be set
147 // to 1, the freq should be set to 26000000, and a top-level
148 // 'make' and 'make install' needs to be executed. In addition,
149 // a U.FL to SMA cable needs to connect J6 on the Bitshark to
150 // the external clk input on the USRP
151 set_clock_scheme(0,64000000);
153 set_bw(8e6); // Default IF bandwidth to match USRP1 max host bandwidth
155 bypass_adc_buffers(true);
158 db_bitshark_rx::~db_bitshark_rx()
163 /************ Private Functions **********************/
166 db_bitshark_rx::_set_pga(int pga_gain)
168 assert(pga_gain>=0 && pga_gain<=20);
171 usrp()->set_pga (0, pga_gain);
172 usrp()->set_pga (1, pga_gain);
176 usrp()->set_pga (2, pga_gain);
177 usrp()->set_pga (3, pga_gain);
181 /************ Public Functions **********************/
183 db_bitshark_rx::shutdown()
187 d_is_shutdown = true;
192 db_bitshark_rx::set_bw (float bw)
194 std::vector<int> args(NUM_BYTES_IN_I2C_CMD,0);
195 uint16_t rf_bw_in_khz = (uint16_t)(bw/1000.0);
198 uint8_t try_count = 0;
201 if (rf_bw_in_khz < 660 || rf_bw_in_khz > 56000)
203 fprintf(stderr, "db_bitshark_rx::set_bw: bw (=%d) must be between 660 KHz and 56 MHz inclusive\n", rf_bw_in_khz);
206 //fprintf(stdout,"Setting bw: requested bw in khz is %d\r\n",rf_bw_in_khz);
207 memcpy(val,&rf_bw_in_khz,4);
208 args[0] = RF_CHAN_FILTER_BW_REG;
213 while ((result != true) && (try_count < 3))
215 result=usrp()->write_i2c (d_i2c_addr, int_seq_to_str (args));
221 fprintf(stderr, "db_bitshark_rx:set_bw: giving up after 3 tries without success\n");
227 /* The gain referenced below is RF gain only. There are two independent
228 gain settings at RF: a digital step attenuator (providing 0, -6, -12, and
229 -18 dB of attenuation), and a second LNA (LNA2) that provides ~25 dB of
230 gain (roughly...it actually depends on the RF freq). So combining these
231 two stages can provide an overall gain range from 0 (which is mapped
232 to -18 dB on the step attenuator + LNA2 turned off) to 42 (which is
233 mapped to 0 dB on the step attenuator + LNA2 turned on).
235 There could be better ways to map these, but this is sufficient for
238 db_bitshark_rx::gain_min()
244 db_bitshark_rx::gain_max()
250 db_bitshark_rx::gain_db_per_step()
256 db_bitshark_rx::set_gain(float gain)
260 // @param gain: RF gain in decibels, range of 0-42
261 // @returns True/False
263 std::vector<int> args(NUM_BYTES_IN_I2C_CMD,0);
265 uint8_t try_count = 0;
267 if (gain < gain_min() || gain > gain_max())
269 fprintf(stderr,"db_bitshark_rx::set_gain: gain (=%f) must be between %f and %f inclusive\n", gain,gain_min(),gain_max());
272 //fprintf(stdout,"db_bitshark_rx::set_gain: requested gain of %f\r\n",gain);
273 args[0] = RF_GAIN_REG;
276 while ((result != true) && (try_count < 3))
278 result=usrp()->write_i2c (d_i2c_addr, int_seq_to_str (args));
284 fprintf(stderr, "db_bitshark_rx:set_gain: giving up after 3 tries without success\n");
292 db_bitshark_rx::set_clock_scheme(uint8_t clock_scheme, uint32_t ref_clk_freq)
294 // Set the clock scheme for determining how the BURX
295 // dboard receives its clock. Note: Ideally, the constructor for the
296 // BURX board could simply call this method to set how it wants the
297 // clock scheme configured. However, depending on the application
298 // using the daughterboard, the constructor may run _after_ some
299 // other portion of the application needs the FPGA. And if the
300 // the clock source for the FPGA was the BURX's 26 MHz TCXO, we're in
301 // a chicken-before-the-egg dilemna. So the solution is to leave
302 // this function here for reference in case an app wants to use it,
303 // and also give the user the ability to set the clock scheme through
304 // the usrper cmd-line application (see example at the top of this
307 // @param clock_scheme
308 // @param ref_clk_freq in Hz
309 // @returns True/False
311 std::vector<int> args(NUM_BYTES_IN_I2C_CMD,0);
313 uint8_t try_count = 0;
316 if (clock_scheme > 1)
318 fprintf(stderr,"db_bitshark_rx::set_clock_scheme: invalid scheme %d\n",clock_scheme);
321 //fprintf(stdout,"db_bitshark_rx::set_clock_scheme: requested clock schem of %d with freq %d Hz \n",clock_scheme,ref_clk_freq);
322 memcpy(val,&ref_clk_freq,4);
323 args[0] = CLOCK_SCHEME_REG;
324 args[4] = (int)clock_scheme;
330 while ((result != true) && (try_count < 3))
332 result=usrp()->write_i2c (d_i2c_addr, int_seq_to_str (args));
338 fprintf(stderr, "db_bitshark_rx:set_clock_scheme: giving up after 3 tries without success\n");
344 db_bitshark_rx::freq_min()
350 db_bitshark_rx::freq_max()
356 db_bitshark_rx::set_freq(double freq)
358 // Set the frequency.
360 // @param freq: target RF frequency in Hz
361 // @type freq: double
363 // @returns (ok, actual_baseband_freq) where:
364 // ok is True or False and indicates success or failure,
365 // actual_baseband_freq is RF frequency that corresponds to DC in the IF.
367 std::vector<int> args(NUM_BYTES_IN_I2C_CMD,0);
368 std::vector<int> bytes(2);
370 freq_result_t act_freq = {false, 0};
371 uint32_t freq_in_khz = (uint32_t)(freq/1000.0);
373 uint8_t try_count = 0;
376 if(!(freq>=freq_min() && freq<=freq_max()))
381 //fprintf(stdout,"db_bitshark_rx::set_freq: requested freq is %d KHz\n",freq_in_khz);
382 memcpy(val,&freq_in_khz,4);
383 args[0] = RF_CENTER_FREQ_REG;
389 while ((result != true) && (try_count < 3))
391 result=usrp()->write_i2c (d_i2c_addr, int_seq_to_str (args));
397 fprintf(stderr, "db_bitshark_rx:set_freq: giving up after 3 tries without success\n");
400 act_freq.ok = result;
401 act_freq.baseband_freq = (double)freq;
406 db_bitshark_rx::is_quadrature()
408 // Return True if this board requires both I & Q analog channels.
413 db_bitshark_rx::i_and_q_swapped()
415 // Returns True since our I and Q channels are swapped