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