Merged r10383:10390 from jcorgan/u2-wip into trunk.
[debian/gnuradio] / usrp2 / firmware / lib / db_rfx.c
1 /*
2  * Copyright 2008,2009 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 #include <spi.h>
19 #include <memory_map.h>
20 #include <db_base.h>
21 #include <hal_io.h>
22 #include <ad9510.h>
23 #include <stdio.h>
24 #include <mdelay.h>
25 #include <lsdac.h>
26 #include <clocks.h>
27
28
29 bool rfx_init_rx(struct db_base *db);
30 bool rfx_init_tx(struct db_base *db);
31 bool rfx_set_freq(struct db_base *db, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc);
32 bool rfx_set_gain_rx(struct db_base *db, u2_fxpt_gain_t gain);
33 bool rfx_set_gain_tx(struct db_base *db, u2_fxpt_gain_t gain);
34 bool rfx_set_tx_enable(struct db_base *, bool on);
35
36 // Control Latch Defines
37 #define P 0  // Prescalar value for setting in regs, must match the next line...
38 #define PRESCALER 8  // Presacalar value for computations
39 #define PD 0  // Power down, 0 = normal operation
40 #define PL 0 // PLL power output
41 #define MTLD 1 // Mute till lock detect
42 #define CPGAIN 0 // Charge pump gain, use setting 1, also in N-reg
43 #define CP3S 0 // Charge pump tri-state, 0 = normal operation
44 #define PDP 1 // Phase detector polarity
45 #define MUXOUT 1 // Digital lock detect, active high
46 #define CR 0 // normal operation
47 #define PC 1 // core power
48
49 // N Latch Defines
50 #define DIVSEL 0 // N Counter always operates on full rate
51 #define N_RSV 0
52
53 // R Latch Defines
54 #define R_RSV 0
55 #define R_BSC 3
56 #define R_TMB 0
57 #define R_LDP 1
58 #define R_ABP 0
59 #define R_DIV 16
60
61 #define phdet_freq (U2_DOUBLE_TO_FXPT_FREQ(100e6/R_DIV))
62
63 // IO Pin functions
64 #define POWER_UP  (1 << 7)  //  Low enables power supply
65 #define ANT_SW  (1 << 6)   // On TX DB, 0 = TX, 1 = RX, on RX DB 0 = main ant, 1 = RX2
66 #define MIX_EN  (1 << 5)   // Enable appropriate mixer
67 #define LOCKDET_MASK (1 << 2)   // Input pin
68
69 struct db_rfx_common {
70   // RFX common stuff
71   unsigned char DIV2;
72   unsigned char CP1;
73   unsigned char CP2;
74   int freq_mult;
75   int spi_mask;  
76 };
77
78 struct db_rfx_dummy {
79   struct db_base        base;
80   struct db_rfx_common  common;
81 };
82
83
84 struct db_rfx_400_rx {
85   struct db_base        base;
86   struct db_rfx_common  common;
87 };
88
89 struct db_rfx_400_tx {
90   struct db_base        base;
91   struct db_rfx_common  common;
92 };
93
94 struct db_rfx_900_rx {
95   struct db_base        base;
96   struct db_rfx_common  common;
97 };
98
99 struct db_rfx_900_tx {
100   struct db_base        base;
101   struct db_rfx_common  common;
102 };
103
104 struct db_rfx_1200_rx {
105   struct db_base        base;
106   struct db_rfx_common  common;
107 };
108
109 struct db_rfx_1200_tx {
110   struct db_base        base;
111   struct db_rfx_common  common;
112 };
113
114 struct db_rfx_1800_rx {
115   struct db_base        base;
116   struct db_rfx_common  common;
117 };
118
119 struct db_rfx_1800_tx {
120   struct db_base        base;
121   struct db_rfx_common  common;
122 };
123
124 struct db_rfx_2400_rx {
125   struct db_base        base;
126   struct db_rfx_common  common;
127 };
128
129 struct db_rfx_2400_tx {
130   struct db_base        base;
131   struct db_rfx_common  common;
132 };
133
134
135 /*
136  * The class instances
137  */
138 struct db_rfx_400_rx db_rfx_400_rx = {
139   .base.dbid = 0x0024,
140   .base.is_tx = false,
141   .base.output_enables = 0x00E0,
142   .base.used_pins = 0x00FF,
143   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(400e6),
144   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(500e6),
145   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
146   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(45),
147   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.022),
148   .base.is_quadrature = true,
149   .base.i_and_q_swapped = true,
150   .base.spectrum_inverted = false,
151   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
152   .base.init = rfx_init_rx,
153   .base.set_freq = rfx_set_freq,
154   .base.set_gain = rfx_set_gain_rx,
155   .base.set_tx_enable = 0,
156   .base.atr_mask = 0x00E0,
157   .base.atr_txval = POWER_UP,
158   .base.atr_rxval = POWER_UP|MIX_EN,
159   // .base.atr_tx_delay =
160   // .base.atr_rx_delay =
161   .common.DIV2 = 0,
162   .common.CP1 = 7,
163   .common.CP2 = 7,
164   .common.spi_mask = SPI_SS_RX_DB,
165   .common.freq_mult = 2
166 };
167
168
169 struct db_rfx_400_tx db_rfx_400_tx = {
170   .base.dbid = 0x0028,
171   .base.is_tx = true,
172   .base.output_enables = 0x00E0,
173   .base.used_pins = 0x00FF,
174   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(400e6),
175   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(500e6),
176   //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
177   //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
178   //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
179   .base.is_quadrature = true,
180   .base.i_and_q_swapped = true,
181   .base.spectrum_inverted = false,
182   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(12.5e6),
183   .base.init = rfx_init_tx,
184   .base.set_freq = rfx_set_freq,
185   .base.set_gain = rfx_set_gain_tx,
186   .base.set_tx_enable = rfx_set_tx_enable,
187   .base.atr_mask = 0x00E0,
188   .base.atr_txval = POWER_UP|MIX_EN, 
189   .base.atr_rxval = POWER_UP|ANT_SW,
190   // .base.atr_tx_delay =
191   // .base.atr_rx_delay =
192   .common.DIV2 = 1,
193   .common.CP1 = 7,
194   .common.CP2 = 7,
195   .common.spi_mask = SPI_SS_TX_DB,
196   .common.freq_mult = 2
197 };
198
199 struct db_rfx_900_rx db_rfx_900_rx = {
200   .base.dbid = 0x0025,
201   .base.is_tx = false,
202   .base.output_enables = 0x00E0,
203   .base.used_pins = 0x00FF,
204   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(800e6),
205   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1000e6),
206   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
207   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
208   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
209   .base.is_quadrature = true,
210   .base.i_and_q_swapped = true,
211   .base.spectrum_inverted = false,
212   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
213   .base.init = rfx_init_rx,
214   .base.set_freq = rfx_set_freq,
215   .base.set_gain = rfx_set_gain_rx,
216   .base.set_tx_enable = 0,
217   .base.atr_mask = 0x00E0,
218   .base.atr_txval = 0,
219   .base.atr_rxval = MIX_EN,
220   // .base.atr_tx_delay =
221   // .base.atr_rx_delay =
222   .common.DIV2 = 1,
223   .common.CP1 = 7,
224   .common.CP2 = 7,
225   .common.spi_mask = SPI_SS_RX_DB,
226   .common.freq_mult = 2
227 };
228
229
230 struct db_rfx_900_tx db_rfx_900_tx = {
231   .base.dbid = 0x0029,
232   .base.is_tx = true,
233   .base.output_enables = 0x00E0,
234   .base.used_pins = 0x00FF,
235   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(800e6),
236   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1000e6),
237   //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
238   //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
239   //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
240   .base.is_quadrature = true,
241   .base.i_and_q_swapped = true,
242   .base.spectrum_inverted = false,
243   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(12.5e6),
244   .base.init = rfx_init_tx,
245   .base.set_freq = rfx_set_freq,
246   .base.set_gain = rfx_set_gain_tx,
247   .base.set_tx_enable = rfx_set_tx_enable,
248   .base.atr_mask = 0x00E0,
249   .base.atr_txval = MIX_EN, 
250   .base.atr_rxval = ANT_SW,
251   // .base.atr_tx_delay =
252   // .base.atr_rx_delay =
253   .common.DIV2 = 1,
254   .common.CP1 = 7,
255   .common.CP2 = 7,
256   .common.spi_mask = SPI_SS_TX_DB,
257   .common.freq_mult = 2
258 };
259
260 struct db_rfx_1200_rx db_rfx_1200_rx = {
261   .base.dbid = 0x0026,
262   .base.is_tx = false,
263   .base.output_enables = 0x00E0,
264   .base.used_pins = 0x00FF,
265   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1150e6),
266   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1350e6),
267   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
268   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
269   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
270   .base.is_quadrature = true,
271   .base.i_and_q_swapped = true,
272   .base.spectrum_inverted = false,
273   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
274   .base.init = rfx_init_rx,
275   .base.set_freq = rfx_set_freq,
276   .base.set_gain = rfx_set_gain_rx,
277   .base.set_tx_enable = 0,
278   .base.atr_mask = 0x00E0,
279   .base.atr_txval = 0,
280   .base.atr_rxval = MIX_EN,
281   // .base.atr_tx_delay =
282   // .base.atr_rx_delay =
283   .common.DIV2 = 1,
284   .common.CP1 = 7,
285   .common.CP2 = 7,
286   .common.spi_mask = SPI_SS_RX_DB,
287   .common.freq_mult = 2
288 };
289
290
291 struct db_rfx_1200_tx db_rfx_1200_tx = {
292   .base.dbid = 0x002a,
293   .base.is_tx = true,
294   .base.output_enables = 0x00E0,
295   .base.used_pins = 0x00FF,
296   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1150e6),
297   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1350e6),
298   //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
299   //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
300   //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
301   .base.is_quadrature = true,
302   .base.i_and_q_swapped = true,
303   .base.spectrum_inverted = false,
304   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(12.5e6),
305   .base.init = rfx_init_tx,
306   .base.set_freq = rfx_set_freq,
307   .base.set_gain = rfx_set_gain_tx,
308   .base.set_tx_enable = rfx_set_tx_enable,
309   .base.atr_mask = 0x00E0,
310   .base.atr_txval = MIX_EN, 
311   .base.atr_rxval = ANT_SW,
312   // .base.atr_tx_delay =
313   // .base.atr_rx_delay =
314   .common.DIV2 = 1,
315   .common.CP1 = 7,
316   .common.CP2 = 7,
317   .common.spi_mask = SPI_SS_TX_DB,
318   .common.freq_mult = 2
319 };
320
321 struct db_rfx_1800_rx db_rfx_1800_rx = {
322   .base.dbid = 0x0034,
323   .base.is_tx = false,
324   .base.output_enables = 0x00E0,
325   .base.used_pins = 0x00FF,
326   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1600e6),
327   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2000e6),
328   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
329   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
330   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
331   .base.is_quadrature = true,
332   .base.i_and_q_swapped = true,
333   .base.spectrum_inverted = false,
334   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
335   .base.init = rfx_init_rx,
336   .base.set_freq = rfx_set_freq,
337   .base.set_gain = rfx_set_gain_rx,
338   .base.set_tx_enable = 0,
339   .base.atr_mask = 0x00E0,
340   .base.atr_txval = 0,
341   .base.atr_rxval = MIX_EN,
342   // .base.atr_tx_delay =
343   // .base.atr_rx_delay =
344   .common.DIV2 = 0,
345   .common.CP1 = 7,
346   .common.CP2 = 7,
347   .common.spi_mask = SPI_SS_RX_DB,
348   .common.freq_mult = 1
349 };
350
351
352 struct db_rfx_1800_tx db_rfx_1800_tx = {
353   .base.dbid = 0x0035,
354   .base.is_tx = true,
355   .base.output_enables = 0x00E0,
356   .base.used_pins = 0x00FF,
357   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1600e6),
358   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2000e6),
359   //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
360   //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
361   //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
362   .base.is_quadrature = true,
363   .base.i_and_q_swapped = true,
364   .base.spectrum_inverted = false,
365   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(12.5e6),
366   .base.init = rfx_init_tx,
367   .base.set_freq = rfx_set_freq,
368   .base.set_gain = rfx_set_gain_tx,
369   .base.set_tx_enable = rfx_set_tx_enable,
370   .base.atr_mask = 0x00E0,
371   .base.atr_txval = MIX_EN, 
372   .base.atr_rxval = ANT_SW,
373   // .base.atr_tx_delay =
374   // .base.atr_rx_delay =
375   .common.DIV2 = 0,
376   .common.CP1 = 7,
377   .common.CP2 = 7,
378   .common.spi_mask = SPI_SS_TX_DB,
379   .common.freq_mult = 1  
380 };
381
382
383 struct db_rfx_2400_rx db_rfx_2400_rx = {
384   .base.dbid = 0x0027,
385   .base.is_tx = false,
386   .base.output_enables = 0x00E0,
387   .base.used_pins = 0x00FF,
388   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(2300e6),
389   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2700e6),
390   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
391   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
392   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
393   .base.is_quadrature = true,
394   .base.i_and_q_swapped = true,
395   .base.spectrum_inverted = false,
396   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
397   .base.init = rfx_init_rx,
398   .base.set_freq = rfx_set_freq,
399   .base.set_gain = rfx_set_gain_rx,
400   .base.set_tx_enable = 0,
401   .base.atr_mask = 0x00E0,
402   .base.atr_txval = 0,
403   .base.atr_rxval = MIX_EN,
404   // .base.atr_tx_delay =
405   // .base.atr_rx_delay =
406   .common.DIV2 = 0,
407   .common.CP1 = 7,
408   .common.CP2 = 7,
409   .common.spi_mask = SPI_SS_RX_DB,
410   .common.freq_mult = 1
411 };
412
413
414 struct db_rfx_2400_tx db_rfx_2400_tx = {
415   .base.dbid = 0x002b,
416   .base.is_tx = true,
417   .base.output_enables = 0x00E0,
418   .base.used_pins = 0x00FF,
419   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(2300e6),
420   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2700e6),
421   //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
422   //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
423   //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
424   .base.is_quadrature = true,
425   .base.i_and_q_swapped = true,
426   .base.spectrum_inverted = false,
427   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(12.5e6),
428   .base.init = rfx_init_tx,
429   .base.set_freq = rfx_set_freq,
430   .base.set_gain = rfx_set_gain_tx,
431   .base.set_tx_enable = rfx_set_tx_enable,
432   .base.atr_mask = 0x00E0,
433   .base.atr_txval = MIX_EN, 
434   .base.atr_rxval = ANT_SW,
435   // .base.atr_tx_delay =
436   // .base.atr_rx_delay =
437   .common.DIV2 = 0,
438   .common.CP1 = 7,
439   .common.CP2 = 7,
440   .common.spi_mask = SPI_SS_TX_DB,
441   .common.freq_mult = 1
442 };
443
444
445 bool
446 rfx_init_tx(struct db_base *dbb)
447 {
448   //struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
449   clocks_enable_tx_dboard(true, 0);
450
451   // Set the freq now to get the one time 10ms delay out of the way.
452   u2_fxpt_freq_t        dc;
453   dbb->set_freq(dbb, dbb->freq_min, &dc);
454   return true;
455 }
456
457 bool
458 rfx_init_rx(struct db_base *dbb)
459 {
460   //struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
461   clocks_enable_rx_dboard(true, 0);
462
463   // test gain
464   dbb->set_gain(dbb,U2_DOUBLE_TO_FXPT_GAIN(45.0));
465
466   // Set the freq now to get the one time 10ms delay out of the way.
467   u2_fxpt_freq_t        dc;
468   dbb->set_freq(dbb, dbb->freq_min, &dc);
469
470   return true;
471 }
472
473 bool
474 rfx_set_freq(struct db_base *dbb, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc)
475 {
476   static unsigned char first = true;
477
478   *dc = 0;
479   struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
480   u2_fxpt_freq_t desired_n = (U2_DOUBLE_TO_FXPT_FREQ(1.0)*db->common.freq_mult*freq)/phdet_freq;
481   int N_DIV = u2_fxpt_freq_round_to_int(desired_n);
482   int B = N_DIV/PRESCALER;
483   int A = N_DIV - PRESCALER*B;
484
485   if(B<A)
486     return false;
487
488   int R = (R_RSV<<22)|(R_BSC<<20)|(R_TMB<<19)|(R_LDP<<18)|(R_ABP<<16)|(R_DIV<<2)|1;
489   int N = (DIVSEL<<23)|(db->common.DIV2<<22)|(CPGAIN<<21)|(B<<8)|(N_RSV<<7)|(A<<2)|2;
490   int C = (P<<22)|(PD<<20)|(db->common.CP2<<17)|(db->common.CP1<<14)|(PL<<12)|
491     (MTLD<<11)|(CPGAIN<<10)|(CP3S<<9)|(PDP<<8)|(MUXOUT<<5)|(CR<<4)|(PC<<2)|0;
492
493   spi_transact(SPI_TXONLY,db->common.spi_mask,R,24,SPIF_PUSH_FALL);
494   spi_transact(SPI_TXONLY,db->common.spi_mask,C,24,SPIF_PUSH_FALL);
495   if (first){
496     first = false;
497     mdelay(10);
498   }
499   spi_transact(SPI_TXONLY,db->common.spi_mask,N,24,SPIF_PUSH_FALL);
500
501   //printf("A = %d, B = %d, N_DIV = %d\n",A, B, N_DIV);
502   *dc = (N_DIV * phdet_freq) / db->common.freq_mult;
503   return true;
504 }
505
506 bool
507 rfx_set_gain_tx(struct db_base *dbb, u2_fxpt_gain_t gain)
508 {
509   // There is no analog gain control on TX
510   return true;
511 }
512
513 bool
514 rfx_set_gain_rx(struct db_base *dbb, u2_fxpt_gain_t gain)
515 {
516   struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
517
518   int offset_q8 = (int)(1.2/3.3*4096*(1<<15));  
519   int range_q15 = (int)(-1.0*4096/3.3*256*128);
520   int slope_q8 = range_q15/db->base.gain_max;
521
522   int dacword = ((slope_q8 * gain) + offset_q8)>>15;
523   //printf("DACWORD %d\n",dacword);
524   lsdac_write_rx(1,dacword);
525   return true;
526 }
527
528
529 bool
530 rfx_set_tx_enable(struct db_base *dbb, bool on)
531 {
532   struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
533
534   // FIXME
535
536   return false;
537 }
538
539 bool
540 rfx_lock_detect(struct db_base *dbb)
541 {
542   struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
543   int pins;
544   pins = hal_gpio_read( db->base.is_tx ? GPIO_TX_BANK : GPIO_RX_BANK );
545   if(pins & LOCKDET_MASK)
546     return true;
547   return false;
548 }
549
550 /* 
551     def select_rx_antenna(self, which_antenna):
552         """
553         Specify which antenna port to use for reception.
554         @param which_antenna: either 'TX/RX' or 'RX2'
555         """
556         if which_antenna in (0, 'TX/RX'):
557             self._u.write_io(self._which, 0,        RX2_RX1N)
558         elif which_antenna in (1, 'RX2'):
559             self._u.write_io(self._which, RX2_RX1N, RX2_RX1N)
560         else:
561             raise ValueError, "which_antenna must be either 'TX/RX' or 'RX2'"
562
563     def set_gain(self, gain):
564         """
565         Set the gain.
566
567         @param gain:  gain in decibels
568         @returns True/False
569         """
570         maxgain = self.gain_range()[1] - self._u.pga_max()
571         mingain = self.gain_range()[0]
572         if gain > maxgain:
573             pga_gain = gain-maxgain
574             assert pga_gain <= self._u.pga_max()
575             agc_gain = maxgain
576         else:
577             pga_gain = 0
578             agc_gain = gain
579         V_maxgain = .2
580         V_mingain = 1.2
581         V_fullscale = 3.3
582         dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale
583         assert dac_value>=0 and dac_value<4096
584         return self._u.write_aux_dac(self._which, 0, int(dac_value)) and \
585                self._set_pga(int(pga_gain))
586
587     def gain_range(self):
588         return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) -- For 900-2400
589         return (self._u.pga_min(), self._u.pga_max() + 45, 0.035) -- For 400
590
591 */