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