Change default bandwidth to 25 MHz to match maximum USRP2 bandwidth
[debian/gnuradio] / usrp2 / firmware / lib / db_bitshark_rx.c
1 /*
2  * Copyright 2010 Free Software Foundation, Inc.
3  *
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.
8  *
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.
13  *
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/>.
16  *
17  */
18
19 #include "db_bitshark_rx.h"
20 #include <memory_map.h>
21 #include <db_base.h>
22 #include <hal_io.h>
23 #include <mdelay.h>
24 #include <lsdac.h>
25 #include <clocks.h>
26 #include <stdio.h>
27 #include <stdint.h>
28 #include <string.h>
29 #include <i2c.h>
30
31 /* Note: Thie general structure of this file is based on the db_wbxng.c 
32    codebase for the wbx daughterboard. */
33
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
43
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 |
48        |4-bytes 0x00|
49        |4-byte unsigned RF center freq (in KHz)|
50    |RegAddr: 0x01-RF channel filter bandwidth register |
51        |4-bytes 0x00|
52        |4-byte unsigned RF channel filter bw (in KHz)|
53    |RegAddr: 0x02-RF gain register |
54        |7-bytes 0x00|
55        |1-byte signed RF gain (in dB)|
56    |RegAddr: 0x03-Baseband gain register |
57        |4-bytes 0x00|
58        |4-byte signed baseband filter gain (in dB)|
59    |RegAddr: 0x10-ADF4350 register |
60        |4-bytes 0x00|
61        |4-byte ADF4350 register value (actual ADF4350 reg addr embedded 
62         within 4-byte value)|
63    |RegAddr: 0x11-SKY73202 register |
64        |5-bytes 0x00|
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 |
69        |3-bytes 0x00|
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) |
76        
77   ---------------------------------------------------------------------------
78    
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)
86    byte 6: 0x0F
87    byte 7: 0x42
88    byte 8: 0x40 (LSB of the 1000000 KHz value, in hex)
89    
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)
99    byte 6: 0x8C
100    byte 7: 0xBA
101    byte 8: 0x80 (LSB of the BURX ref clk freq)
102
103    Note: The endian-ness of 4-byte values used in I2C cmds is different on 
104    USRP2 compared to USRP1.
105    
106 */
107
108 #define NUM_BYTES_IN_I2C_CMD 9
109 #define I2C_ADDR 0x47
110
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);
115
116 static bool set_clock_scheme(uint8_t clock_scheme, uint32_t ref_clk_freq);
117
118 /*
119  * The class instances
120  */
121 struct db_bitshark_rx db_bitshark_rx = {
122     .base.dbid = 0x0070,
123     .base.is_tx = false,
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,
140     .base.atr_txval = 0,
141     .base.atr_rxval = 0,
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
146 };
147
148 bool
149 bitshark_rx_init(struct db_base *dbb)
150 {
151     struct db_bitshark_rx_dummy *db = (struct db_bitshark_rx_dummy *) dbb;    
152
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 */
156     
157     /* setup the clock scheme to accept the USRP2's 100 MHz ref clk */
158     set_clock_scheme(0,100000000);
159
160     /* initial setting of gain */
161     dbb->set_gain(dbb,U2_DOUBLE_TO_FXPT_GAIN(20.0));
162     
163     /* Set the freq now to get the one time 10ms delay out of the way. */
164     u2_fxpt_freq_t      dc;
165     dbb->set_freq(dbb, dbb->freq_min, &dc);
166
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
172        application. */
173     db->extra.set_bw(dbb, 25000);  /* 25 MHz channel bw */
174     
175     return true;
176 }
177
178 bool
179 bitshark_rx_set_freq(struct db_base *dbb, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc)
180 {
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_to_double(freq)/1000.0);
185     
186     if(!(freq>=db->base.freq_min && freq<=db->base.freq_max)) 
187     {
188         return false;
189     }
190     
191     memset(args,0x00,NUM_BYTES_IN_I2C_CMD);
192     memcpy(val,&freq_in_khz,4);
193     args[0] = RF_CENTER_FREQ_REG;
194     args[5] = val[3];
195     args[6] = val[2];
196     args[7] = val[1];
197     args[8] = val[0];
198     
199     i2c_write(I2C_ADDR, args, NUM_BYTES_IN_I2C_CMD);
200     *dc = freq;
201     return true;
202 }
203
204 bool
205 bitshark_rx_set_gain(struct db_base *dbb, u2_fxpt_gain_t gain)
206 {
207     struct db_bitshark_rx_dummy *db = (struct db_bitshark_rx_dummy *) dbb;
208     
209     unsigned char args[NUM_BYTES_IN_I2C_CMD];
210     uint8_t final_gain = (uint8_t)(u2_fxpt_gain_round_to_int(gain));
211     
212     if(!(gain >= db->base.gain_min && gain <= db->base.gain_max)) 
213     {
214         return false;
215     }
216     
217     memset(args,0x00,NUM_BYTES_IN_I2C_CMD);
218     args[0] = RF_GAIN_REG;
219     args[5] = final_gain;
220
221     i2c_write(I2C_ADDR, args, NUM_BYTES_IN_I2C_CMD);
222
223     return true;
224 }
225
226 bool
227 bitshark_rx_set_bw(struct db_base *dbb, uint16_t bw_in_khz)
228 {
229     struct db_bitshark_rx_dummy *db = (struct db_bitshark_rx_dummy *) dbb;
230     unsigned char val[4];
231     unsigned char args[NUM_BYTES_IN_I2C_CMD];
232     
233     if(!(bw_in_khz >= db->extra.bw_min && bw_in_khz <= db->extra.bw_max)) 
234     {
235         return false;
236     }
237     
238     memset(args,0x00,NUM_BYTES_IN_I2C_CMD);
239     memcpy(val,&bw_in_khz,4);
240     args[0] = RF_CENTER_FREQ_REG;
241     args[5] = val[3];
242     args[6] = val[2];
243     args[7] = val[1];
244     args[8] = val[0];
245
246     i2c_write(I2C_ADDR, args, NUM_BYTES_IN_I2C_CMD);
247
248     return true;
249 }
250
251 static bool
252 set_clock_scheme(uint8_t clock_scheme, uint32_t ref_clk_freq)
253 {
254     /* Set the clock scheme for determining how the BURX
255        dboard receives its clock.  For the USRP2, there is really only
256        one way of doing this, which is to use the 100 MHz ref clk
257        on the USRP2 as its reference.  However, it is possible to
258        use the BURX's 26 MHz TCXO as the external reference input to
259        the USRP, which would provide phase lock between our oscillator
260        and the USRP's 100 MHz oscillator.  And since the BURX board
261        provides the ability to warp the oscillator, this may be
262        useful to some folks.  Otherwise, the BURX board will always
263        just take the 100 MHz reference from the USRP2 as its reference.
264     */
265     
266     unsigned char args[NUM_BYTES_IN_I2C_CMD];
267     char val[4];
268
269     if (clock_scheme > 1) 
270     {
271         return false;
272     }
273
274     memcpy(val,&ref_clk_freq,4);
275     args[0] = CLOCK_SCHEME_REG;
276     args[4] = clock_scheme;
277     args[5] = val[3];
278     args[6] = val[2];
279     args[7] = val[1];
280     args[8] = val[0];
281
282     i2c_write(I2C_ADDR, args, NUM_BYTES_IN_I2C_CMD);
283
284     return true;
285 }
286