2 * Copyright 2010 Free Software Foundation, Inc.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "db_bitshark_rx.h"
20 #include <memory_map.h>
31 /* Note: Thie general structure of this file is based on the db_wbxng.c
32 codebase for the wbx daughterboard. */
34 /* The following defines specify the address map provided by the
35 Bitshark USRP Rx (BURX) board. These registers are all accessed over I2C. */
36 #define RF_CENTER_FREQ_REG 0x00
37 #define RF_CHAN_FILTER_BW_REG 0x01
38 #define RF_GAIN_REG 0x02
39 #define BB_GAIN_REG 0x03
40 #define ADF4350_REG 0x10
41 #define SKY73202_REG 0x11
42 #define CLOCK_SCHEME_REG 0x20
44 /* The following table lists the registers provided by the Bitshark board
45 that are accessible over I2C:
46 --------------------------------------------------------
47 |RegAddr: 0x00-RF Center Freq register |
49 |4-byte unsigned RF center freq (in KHz)|
50 |RegAddr: 0x01-RF channel filter bandwidth register |
52 |4-byte unsigned RF channel filter bw (in KHz)|
53 |RegAddr: 0x02-RF gain register |
55 |1-byte signed RF gain (in dB)|
56 |RegAddr: 0x03-Baseband gain register |
58 |4-byte signed baseband filter gain (in dB)|
59 |RegAddr: 0x10-ADF4350 register |
61 |4-byte ADF4350 register value (actual ADF4350 reg addr embedded
63 |RegAddr: 0x11-SKY73202 register |
65 |1-byte reg 0 of SKY73202 |
66 |1-byte reg 1 of SKY73202 |
67 |1-byte reg 2 of SKY73202 |
68 |RegAddr: 0x20-Clock Scheme |
70 |1-byte indicating clocking scheme:
71 -0x00 -> BURX local TCXO off, BURX accepts ref clock from
72 USRP2 (freq of USRP2's ref clock specified in bytes 2-5)
73 -0x01 -> BURX local TCXO on, BURX uses its local TCXO as its ref
74 clock, TCXO signal output for use as phase lock for USRP2 |
75 |4-byte USRP2 ref clock freq in hz (only needed if byte 1 set to 0x00) |
77 ---------------------------------------------------------------------------
79 As an example, lets say the client wants to set an RF center freq of
80 1000 MHz. In KHz, this translates to 1000000 (resolution is only down to
81 steps of 1 KHz), which is 0x000F4240 in hex. So the complete 9-byte I2C
82 sequence that the client should send is as follows:
83 byte 0: 0x00-register 0x00 is the target of the write operation
84 bytes 1-4: 0x00 (padding)
85 byte 5: 0x00 (MSB of the 1000000 KHz value, in hex)
88 byte 8: 0x40 (LSB of the 1000000 KHz value, in hex)
90 How about another example...lets say the client wants to setup the clock
91 scheme to use scheme #1 where the 26 MHz TCXO on the BURX board is enabled,
92 and is provided to the USRP2 for it to phase lock to it as an external ref.
93 26 MHz (i.e. 26 million), in hex, is 0x18CBA80.
94 So the complete 9-byte I2C sequence that the client should send is as follows:
95 byte 0: 0x20-register 0x20 is the target of the write operation
96 bytes 1-3: 0x00 (padding)
97 byte 4: 0x01 (indicating that clock scheme #1 is wanted)
98 byte 5: 0x01 (MSB of the BURX ref clk freq)
101 byte 8: 0x80 (LSB of the BURX ref clk freq)
103 Note: The endian-ness of 4-byte values used in I2C cmds is different on
104 USRP2 compared to USRP1.
108 #define NUM_BYTES_IN_I2C_CMD 9
109 #define I2C_ADDR 0x47
111 bool bitshark_rx_init(struct db_base *dbb);
112 bool bitshark_rx_set_freq(struct db_base *dbb, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc);
113 bool bitshark_rx_set_gain(struct db_base *dbb, u2_fxpt_gain_t gain);
114 bool bitshark_rx_set_bw(struct db_base *dbb, uint16_t bw);
116 static bool set_clock_scheme(uint8_t clock_scheme, uint32_t ref_clk_freq);
119 * The class instances
121 struct db_bitshark_rx db_bitshark_rx = {
124 .base.output_enables = 0x0000,
125 .base.used_pins = 0x0000,
126 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(300e6),
127 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(4000e6),
128 .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
129 .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(42),
130 .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(6),
131 .base.is_quadrature = true,
132 .base.i_and_q_swapped = true,
133 .base.spectrum_inverted = false,
134 .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
135 .base.init = bitshark_rx_init,
136 .base.set_freq = bitshark_rx_set_freq,
137 .base.set_gain = bitshark_rx_set_gain,
138 .base.set_tx_enable = 0,
139 .base.atr_mask = 0x0000,
142 .base.set_antenna = 0,
143 .extra.bw_min = 660, /* in KHz, so 660 KHz */
144 .extra.bw_max = 56000, /* in KHz, so 56 MHz */
145 .extra.set_bw = bitshark_rx_set_bw
149 bitshark_rx_init(struct db_base *dbb)
151 struct db_bitshark_rx_dummy *db = (struct db_bitshark_rx_dummy *) dbb;
153 clocks_enable_rx_dboard(true, 0);
154 /* hal_gpio_write( GPIO_RX_BANK, ENABLE_5|ENABLE_33, ENABLE_5|ENABLE_33 ); */
155 /* above isn't needed, since we don't have any GPIO from the FPGA */
157 /* setup the clock scheme to accept the USRP2's 100 MHz ref clk */
158 set_clock_scheme(0,100000000);
160 /* initial setting of gain */
161 dbb->set_gain(dbb,U2_DOUBLE_TO_FXPT_GAIN(20.0));
163 /* Set the freq now to get the one time 10ms delay out of the way. */
165 dbb->set_freq(dbb, dbb->freq_min, &dc);
167 /* set up the RF bandwidth of the signal of interest...Note: there
168 doesn't appear to be a standard way of setting this bandwidth
169 in USRP2-land (compared to USRP1-land, where we have the
170 straight-forward set_bw() method). Not sure why this is, but
171 for now, simply set the bandwidth once for the intended
173 db->extra.set_bw(dbb, 25000); /* 25 MHz channel bw */
179 bitshark_rx_set_freq(struct db_base *dbb, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc)
181 struct db_bitshark_rx_dummy *db = (struct db_bitshark_rx_dummy *) dbb;
182 unsigned char args[NUM_BYTES_IN_I2C_CMD];
183 unsigned char val[4];
184 uint32_t freq_in_khz = (uint32_t)(u2_fxpt_freq_round_to_uint(freq)/1000);
186 if(!(freq>=db->base.freq_min && freq<=db->base.freq_max))
191 memset(args,0x00,NUM_BYTES_IN_I2C_CMD);
192 memcpy(val,&freq_in_khz,4);
193 args[0] = RF_CENTER_FREQ_REG;
199 i2c_write(I2C_ADDR, args, NUM_BYTES_IN_I2C_CMD);
200 /* Add a brief delay after each command. This only seems to be
201 necessary when sending a sequence of commands one after the other.
202 This issue appears to be specific to the USRP2, since it isn't
203 necessary on the USRP1. The 5 mS delay is a bit of
204 an emperical compromise: too short (say, 1 mS), and every once
205 in a great while a command will still be magically dropped on its
206 way out...too long (say, 500 mS) and higher-level apps such as
207 usrp2_fft.py seem to choke because the init sequence is taking
208 too long. So 5 mS was tested repeatedly without error, and deemed
209 reasonable. Not sure if this is an issue with the I2C master
210 code in the microblaze or some place else, and I hate magic
211 delays too, but this seems to be stable. */
219 bitshark_rx_set_gain(struct db_base *dbb, u2_fxpt_gain_t gain)
221 struct db_bitshark_rx_dummy *db = (struct db_bitshark_rx_dummy *) dbb;
223 unsigned char args[NUM_BYTES_IN_I2C_CMD];
224 uint8_t final_gain = (uint8_t)(u2_fxpt_gain_round_to_int(gain));
226 if(!(gain >= db->base.gain_min && gain <= db->base.gain_max))
231 memset(args,0x00,NUM_BYTES_IN_I2C_CMD);
232 args[0] = RF_GAIN_REG;
233 args[5] = final_gain;
235 i2c_write(I2C_ADDR, args, NUM_BYTES_IN_I2C_CMD);
236 /* Add a brief delay after each command. This only seems to be
237 necessary when sending a sequence of commands one after the other.
238 This issue appears to be specific to the USRP2, since it isn't
239 necessary on the USRP1. The 5 mS delay is a bit of
240 an emperical compromise: too short (say, 1 mS), and every once
241 in a great while a command will still be magically dropped on its
242 way out...too long (say, 500 mS) and higher-level apps such as
243 usrp2_fft.py seem to choke because the init sequence is taking
244 too long. So 5 mS was tested repeatedly without error, and deemed
245 reasonable. Not sure if this is an issue with the I2C master
246 code in the microblaze or some place else, and I hate magic
247 delays too, but this seems to be stable. */
254 bitshark_rx_set_bw(struct db_base *dbb, uint16_t bw_in_khz)
256 struct db_bitshark_rx_dummy *db = (struct db_bitshark_rx_dummy *) dbb;
257 unsigned char val[2];
258 unsigned char args[NUM_BYTES_IN_I2C_CMD];
260 if(!(bw_in_khz >= db->extra.bw_min && bw_in_khz <= db->extra.bw_max))
265 memset(args,0x00,NUM_BYTES_IN_I2C_CMD);
266 memcpy(val,&bw_in_khz,2);
267 args[0] = RF_CHAN_FILTER_BW_REG;
271 i2c_write(I2C_ADDR, args, NUM_BYTES_IN_I2C_CMD);
272 /* Add a brief delay after each command. This only seems to be
273 necessary when sending a sequence of commands one after the other.
274 This issue appears to be specific to the USRP2, since it isn't
275 necessary on the USRP1. The 5 mS delay is a bit of
276 an emperical compromise: too short (say, 1 mS), and every once
277 in a great while a command will still be magically dropped on its
278 way out...too long (say, 500 mS) and higher-level apps such as
279 usrp2_fft.py seem to choke because the init sequence is taking
280 too long. So 5 mS was tested repeatedly without error, and deemed
281 reasonable. Not sure if this is an issue with the I2C master
282 code in the microblaze or some place else, and I hate magic
283 delays too, but this seems to be stable. */
290 set_clock_scheme(uint8_t clock_scheme, uint32_t ref_clk_freq)
292 /* Set the clock scheme for determining how the BURX
293 dboard receives its clock. For the USRP2, there is really only
294 one way of doing this, which is to use the 100 MHz ref clk
295 on the USRP2 as its reference. However, it is possible to
296 use the BURX's 26 MHz TCXO as the external reference input to
297 the USRP, which would provide phase lock between our oscillator
298 and the USRP's 100 MHz oscillator. And since the BURX board
299 provides the ability to warp the oscillator, this may be
300 useful to some folks. Otherwise, the BURX board will always
301 just take the 100 MHz reference from the USRP2 as its reference.
304 unsigned char args[NUM_BYTES_IN_I2C_CMD];
307 if (clock_scheme > 1)
312 memcpy(val,&ref_clk_freq,4);
313 args[0] = CLOCK_SCHEME_REG;
314 args[4] = clock_scheme;
320 i2c_write(I2C_ADDR, args, NUM_BYTES_IN_I2C_CMD);
321 /* Add a brief delay after each command. This only seems to be
322 necessary when sending a sequence of commands one after the other.
323 This issue appears to be specific to the USRP2, since it isn't
324 necessary on the USRP1. The 5 mS delay is a bit of
325 an emperical compromise: too short (say, 1 mS), and every once
326 in a great while a command will still be magically dropped on its
327 way out...too long (say, 500 mS) and higher-level apps such as
328 usrp2_fft.py seem to choke because the init sequence is taking
329 too long. So 5 mS was tested repeatedly without error, and deemed
330 reasonable. Not sure if this is an issue with the I2C master
331 code in the microblaze or some place else, and I hate magic
332 delays too, but this seems to be stable. */