get_lo_offset -> lo_offset
[debian/gnuradio] / gr-usrp / src / db_flexrf.py
1 #
2 # Copyright 2005,2007 Free Software Foundation, Inc.
3
4 # This file is part of GNU Radio
5
6 # GNU Radio is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3, or (at your option)
9 # any later version.
10
11 # GNU Radio is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with GNU Radio; see the file COPYING.  If not, write to
18 # the Free Software Foundation, Inc., 51 Franklin Street,
19 # Boston, MA 02110-1301, USA.
20
21
22 from gnuradio import usrp1
23 import time,math
24
25 from usrpm import usrp_dbid
26 import db_base
27 import db_instantiator
28 from usrpm.usrp_fpga_regs import *
29
30 #debug_using_gui = True                  # Must be set to True or False
31 debug_using_gui = False                  # Must be set to True or False
32
33 if debug_using_gui:
34     import flexrf_debug_gui
35
36 # d'board i/o pin defs
37 # Tx and Rx have shared defs, but different i/o regs
38 AUX_RXAGC = (1 << 8)
39 POWER_UP = (1 << 7)         # enables power supply
40 RX_TXN = (1 << 6)           # Tx only: T/R antenna switch for TX/RX port
41 RX2_RX1N = (1 << 6)         # Rx only: antenna switch between RX2 and TX/RX port
42 ENABLE = (1 << 5)           # enables mixer
43 AUX_SEN = (1 << 4)
44 AUX_SCLK = (1 << 3)
45 PLL_LOCK_DETECT = (1 << 2)
46 AUX_SDO = (1 << 1)
47 CLOCK_OUT = (1 << 0)
48
49 SPI_ENABLE_TX_A = usrp1.SPI_ENABLE_TX_A
50 SPI_ENABLE_TX_B = usrp1.SPI_ENABLE_TX_B
51 SPI_ENABLE_RX_A = usrp1.SPI_ENABLE_RX_A
52 SPI_ENABLE_RX_B = usrp1.SPI_ENABLE_RX_B
53
54 class flexrf_base(db_base.db_base):
55     """
56     Abstract base class for all flexrf boards.
57
58     Derive board specific subclasses from db_flexrf_base_{tx,rx}
59     """
60     def __init__(self, usrp, which):
61         """
62         @param usrp: instance of usrp.source_c
63         @param which: which side: 0 or 1 corresponding to side A or B respectively
64         @type which: int
65         """
66         # sets _u  _which _tx and _slot
67         db_base.db_base.__init__(self, usrp, which)
68
69         self.first = True
70         self.spi_format = usrp1.SPI_FMT_MSB | usrp1.SPI_FMT_HDR_0
71
72         self._u._write_oe(self._which, 0, 0xffff)   # turn off all outputs
73         self._enable_refclk(False)                      # disable refclk
74
75         g = self.gain_range()                       # initialize gain
76         self.set_gain(float(g[0]+g[1]) / 2)
77
78         self.set_auto_tr(False)
79         
80         if debug_using_gui:
81             title = "FlexRF Debug Rx"
82             if self._tx:
83                 title = "FlexRF Debug Tx"
84             self.gui = flexrf_debug_gui.flexrf_debug_gui(self, title)
85             self.gui.Show(True)
86
87
88     def __del__(self):
89         #print "flexrf_base.__del__"
90         self._u.write_io(self._which, self.power_off, POWER_UP)   # turn off power to board
91         self._enable_refclk(False)                       # turn off refclk
92         self.set_auto_tr(False)
93
94     def _write_all(self, R, control, N):
95         """
96         Write R counter latch, control latch and N counter latch to VCO.
97
98         Adds 10ms delay between writing control and N if this is first call.
99         This is the required power-up sequence.
100         
101         @param R: 24-bit R counter latch
102         @type R: int
103         @param control: 24-bit control latch
104         @type control: int
105         @param N: 24-bit N counter latch
106         @type N: int
107         """
108         self._write_R(R)
109         self._write_control( control)
110         if self.first:
111             time.sleep(0.010)
112             self.first = False
113         self._write_N(N)
114
115     def _write_control(self, control):
116         self._write_it((control & ~0x3) | 0)
117
118     def _write_R(self, R):
119         self._write_it((R & ~0x3) | 1)
120
121     def _write_N(self, N):
122         self._write_it((N & ~0x3) | 2)
123
124     def _write_it(self, v):
125         s = ''.join((chr((v >> 16) & 0xff),
126                      chr((v >>  8) & 0xff),
127                      chr(v & 0xff)))
128         self._u._write_spi(0, self.spi_enable, self.spi_format, s)
129         
130     def _lock_detect(self):
131         """
132         @returns: the value of the VCO/PLL lock detect bit.
133         @rtype: 0 or 1
134         """
135         if self._u.read_io(self._which) & PLL_LOCK_DETECT:
136             return True
137         else:      # Give it a second chance
138             if self._u.read_io(self._which) & PLL_LOCK_DETECT:
139                 return True
140             else:
141                 return False
142         
143     def _compute_regs(self, freq):
144         """
145         Determine values of R, control, and N registers, along with actual freq.
146         
147         @param freq: target frequency in Hz
148         @type freq: float
149         @returns: (R, control, N, actual_freq)
150         @rtype: tuple(int, int, int, float)
151         
152         Override this in derived classes.
153         """
154         raise NotImplementedError
155
156     def _refclk_freq(self):
157         # return float(self._u.fpga_master_clock_freq())/self._refclk_divisor()
158         return 64e6/self._refclk_divisor()
159
160     def set_freq(self, freq):
161         """
162         @returns (ok, actual_baseband_freq) where:
163            ok is True or False and indicates success or failure,
164            actual_baseband_freq is the RF frequency that corresponds to DC in the IF.
165         """
166
167         # Offsetting the LO helps get the Tx carrier leakage out of the way.
168         # This also ensures that on Rx, we're not getting hosed by the
169         # FPGA's DC removal loop's time constant.  We were seeing a
170         # problem when running with discontinuous transmission.
171         # Offsetting the LO made the problem go away.
172         freq += self._lo_offset
173         
174         R, control, N, actual_freq = self._compute_regs(freq)
175         if R==0:
176             return(False,0)
177         self._write_all(R, control, N)
178         return (self._lock_detect(), actual_freq)
179
180     def gain_range(self):
181         """
182         Return range of gain that can be set by this d'board.
183
184         @returns (min_gain, max_gain, step_size)
185         Where gains are expressed in decibels (your mileage may vary)
186         """
187         return (self._u.pga_min(), self._u.pga_max(), self._u.pga_db_per_step())
188
189     def set_gain(self, gain):
190         """
191         Set the gain.
192
193         @param gain:  gain in decibels
194         @returns True/False
195         """
196         return self._set_pga(gain)
197
198     def _set_pga(self, pga_gain):
199         if(self._which == 0):
200             self._u.set_pga (0, pga_gain)
201             self._u.set_pga (1, pga_gain)
202         else:
203             self._u.set_pga (2, pga_gain)
204             self._u.set_pga (3, pga_gain)
205
206     def is_quadrature(self):
207         """
208         Return True if this board requires both I & Q analog channels.
209
210         This bit of info is useful when setting up the USRP Rx mux register.
211         """
212         return True
213
214     def set_lo_offset(self, offset):
215         """
216         Set amount by which LO is offset from requested tuning frequency.
217         
218         @param offset: offset in Hz
219         """
220         self._lo_offset = offset
221
222     def lo_offset(self):
223         """
224         Get amount by which LO is offset from requested tuning frequency.
225         
226         @returns Offset in Hz
227         """
228         return self._lo_offset
229         
230 # ----------------------------------------------------------------
231
232 class flexrf_base_tx(flexrf_base):
233     def __init__(self, usrp, which):
234         """
235         @param usrp: instance of usrp.sink_c
236         @param which: 0 or 1 corresponding to side TX_A or TX_B respectively.
237         """
238         flexrf_base.__init__(self, usrp, which)
239         self.spi_enable = (SPI_ENABLE_TX_A, SPI_ENABLE_TX_B)[which]
240
241         # power up the transmit side, but don't enable the mixer
242         self._u._write_oe(self._which,(POWER_UP|RX_TXN|ENABLE), 0xffff)
243         self._u.write_io(self._which, (self.power_on|RX_TXN), (POWER_UP|RX_TXN|ENABLE))
244         self.set_lo_offset(4e6)
245
246     def __del__(self):
247         #print "flexrf_base_tx.__del__"
248         # Power down and leave the T/R switch in the R position
249         self._u.write_io(self._which, (self.power_off|RX_TXN), (POWER_UP|RX_TXN|ENABLE))
250         flexrf_base.__del__(self)
251
252     def set_auto_tr(self, on):
253         if on:
254             self.set_atr_mask (RX_TXN | ENABLE)
255             self.set_atr_txval(0      | ENABLE)
256             self.set_atr_rxval(RX_TXN | 0)
257         else:
258             self.set_atr_mask (0)
259             self.set_atr_txval(0)
260             self.set_atr_rxval(0)
261
262     def set_enable(self, on):
263         """
264         Enable transmitter if on is True
265         """
266         mask = RX_TXN | ENABLE
267         if on:
268             v = ENABLE
269         else:
270             v = RX_TXN
271         self._u.write_io(self._which, v, mask)
272
273     def gain_range(self):
274         """
275         Return range of gain that can be set by this d'board.
276
277         @returns (min_gain, max_gain, step_size)
278         Where gains are expressed in decibels (your mileage may vary)
279
280         Flex Tx boards require that the PGA be maxed out to properly bias their circuitry.
281         """
282         g = self._u.pga_max()
283         return (g, g, 1.0)
284
285     def set_gain(self, gain):
286         """
287         Set the gain.
288
289         @param gain:  gain in decibels
290         @returns True/False
291         """
292         return self._set_pga(self._u.pga_max())
293
294 class flexrf_base_rx(flexrf_base):
295     def __init__(self, usrp, which):
296         """
297         @param usrp: instance of usrp.source_c
298         @param which: 0 or 1 corresponding to side RX_A or RX_B respectively.
299         """
300         flexrf_base.__init__(self, usrp, which)
301         self.spi_enable = (SPI_ENABLE_RX_A, SPI_ENABLE_RX_B)[which]
302         
303         self._u._write_oe(self._which, (POWER_UP|RX2_RX1N|ENABLE), 0xffff)
304         self._u.write_io(self._which,  (self.power_on|RX2_RX1N|ENABLE), (POWER_UP|RX2_RX1N|ENABLE))
305
306         # set up for RX on TX/RX port
307         self.select_rx_antenna('TX/RX')
308
309         self.bypass_adc_buffers(True)
310         self.set_lo_offset(-4e6)
311
312     def __del__(self):
313         # print "flexrf_base_rx.__del__"
314         # Power down
315         self._u.write_io(self._which, self.power_off, (POWER_UP|ENABLE))
316         flexrf_base.__del__(self)
317     
318     def set_auto_tr(self, on):
319         if on:
320             self.set_atr_mask (ENABLE)
321             self.set_atr_txval(     0)
322             self.set_atr_rxval(ENABLE)
323         else:
324             self.set_atr_mask (0)
325             self.set_atr_txval(0)
326             self.set_atr_rxval(0)
327
328     def select_rx_antenna(self, which_antenna):
329         """
330         Specify which antenna port to use for reception.
331         @param which_antenna: either 'TX/RX' or 'RX2'
332         """
333         if which_antenna in (0, 'TX/RX'):
334             self._u.write_io(self._which, 0,        RX2_RX1N)
335         elif which_antenna in (1, 'RX2'):
336             self._u.write_io(self._which, RX2_RX1N, RX2_RX1N)
337         else:
338             raise ValueError, "which_antenna must be either 'TX/RX' or 'RX2'"
339
340     def set_gain(self, gain):
341         """
342         Set the gain.
343
344         @param gain:  gain in decibels
345         @returns True/False
346         """
347         maxgain = self.gain_range()[1] - self._u.pga_max()
348         mingain = self.gain_range()[0]
349         if gain > maxgain:
350             pga_gain = gain-maxgain
351             assert pga_gain <= self._u.pga_max()
352             agc_gain = maxgain
353         else:
354             pga_gain = 0
355             agc_gain = gain
356         V_maxgain = .2
357         V_mingain = 1.2
358         V_fullscale = 3.3
359         dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale
360         assert dac_value>=0 and dac_value<4096
361         return self._u.write_aux_dac(self._which, 0, int(dac_value)) and \
362                self._set_pga(int(pga_gain))
363
364 # ----------------------------------------------------------------
365
366 class _AD4360_common(object):
367     def __init__(self):
368         # R-Register Common Values
369         self.R_RSV = 0   # bits 23,22
370         self.BSC = 3   # bits 21,20 Div by 8 to be safe
371         self.TEST = 0  # bit 19
372         self.LDP = 1   # bit 18
373         self.ABP = 0   # bit 17,16   3ns
374
375         # N-Register Common Values
376         self.N_RSV = 0      # bit 7
377         
378         # Control Register Common Values
379         self.PD = 0       # bits 21,20   Normal operation
380         self.PL = 0       # bits 13,12   11mA
381         self.MTLD = 1     # bit 11       enabled
382         self.CPG = 0      # bit 10       CP setting 1
383         self.CP3S = 0     # bit 9        Normal
384         self.PDP = 1      # bit 8        Positive
385         self.MUXOUT = 1   # bits 7:5     Digital Lock Detect
386         self.CR = 0       # bit 4        Normal
387         self.PC = 1       # bits 3,2     Core power 10mA
388
389     def _compute_regs(self, freq):
390         """
391         Determine values of R, control, and N registers, along with actual freq.
392         
393         @param freq: target frequency in Hz
394         @type freq: float
395         @returns: (R, control, N, actual_freq)
396         @rtype: tuple(int, int, int, float)
397         """
398
399         #  Band-specific N-Register Values
400         phdet_freq = self._refclk_freq()/self.R_DIV
401         desired_n = round(freq*self.freq_mult/phdet_freq)
402         actual_freq = desired_n * phdet_freq
403         B = math.floor(desired_n/self._prescaler())
404         A = desired_n - self._prescaler()*B
405         self.B_DIV = int(B)    # bits 20:8
406         self.A_DIV = int(A)    # bit 6:2
407         #assert self.B_DIV >= self.A_DIV
408         if self.B_DIV < self.A_DIV:
409             return (0,0,0,0)
410         R = (self.R_RSV<<22) | (self.BSC<<20) | (self.TEST<<19) | (self.LDP<<18) \
411             | (self.ABP<<16) | (self.R_DIV<<2)
412         
413         control = (self.P<<22) | (self.PD<<20) | (self.CP2<<17) | (self.CP1<<14) | (self.PL<<12) \
414                   | (self.MTLD<<11) | (self.CPG<<10) | (self.CP3S<<9) | (self.PDP<<8) | \
415                   (self.MUXOUT<<5) | (self.CR<<4) | (self.PC<<2)
416
417         N = (self.DIVSEL<<23) | (self.DIV2<<22) | (self.CPGAIN<<21) | (self.B_DIV<<8) | \
418             (self.N_RSV<<7) | (self.A_DIV<<2)
419
420         return (R,control,N,actual_freq/self.freq_mult)
421
422     def _refclk_divisor(self):
423         """
424         Return value to stick in REFCLK_DIVISOR register
425         """
426         return 1
427     
428     def _prescaler(self):
429         if self.P == 0:
430             return 8
431         elif self.P == 1:
432             return 16
433         else:
434             return 32
435
436 #----------------------------------------------------------------------
437 class _2400_common(_AD4360_common):
438     def __init__(self):
439         _AD4360_common.__init__(self)
440
441         # Band-specific R-Register Values
442         self.R_DIV = 16  # bits 15:2
443    
444         # Band-specific C-Register values
445         self.P = 1        # bits 23,22   Div by 16/17
446         self.CP2 = 7      # bits 19:17
447         self.CP1 = 7      # bits 16:14
448
449         # Band specifc N-Register Values
450         self.DIVSEL = 0   # bit 23
451         self.DIV2 = 0     # bit 22
452         self.CPGAIN = 0   # bit 21
453         self.freq_mult = 1
454
455     def freq_range(self):           # FIXME
456         return (2300e6, 2700e6, 4e6)
457
458 #----------------------------------------------------------------------
459 class _1200_common(_AD4360_common):
460     def __init__(self):
461         _AD4360_common.__init__(self)
462
463         # Band-specific R-Register Values
464         self.R_DIV = 16  # bits 15:2  DIV by 16 for a 1 MHz phase detector freq
465    
466         # Band-specific C-Register values
467         self.P = 1        # bits 23,22   Div by 16/17
468         self.CP2 = 7      # bits 19:17   1.25 mA
469         self.CP1 = 7      # bits 16:14   1.25 mA
470
471         # Band specifc N-Register Values
472         self.DIVSEL = 0   # bit 23
473         self.DIV2 = 1     # bit 22
474         self.CPGAIN = 0   # bit 21
475         self.freq_mult = 2
476
477     def freq_range(self):           # FIXME
478         return (1150e6, 1350e6, 4e6)
479
480 #-------------------------------------------------------------------------
481 class _1800_common(_AD4360_common):
482     def __init__(self):
483         _AD4360_common.__init__(self)
484
485         # Band-specific R-Register Values
486         self.R_DIV = 16  # bits 15:2  DIV by 16 for a 1 MHz phase detector freq
487    
488         # Band-specific C-Register values
489         self.P = 1        # bits 23,22   Div by 16/17
490         self.CP2 = 7      # bits 19:17   1.25 mA
491         self.CP1 = 7      # bits 16:14   1.25 mA
492
493         # Band specifc N-Register Values
494         self.DIVSEL = 0   # bit 23
495         self.DIV2 = 0     # bit 22
496         self.freq_mult = 1
497         self.CPGAIN = 0   # bit 21
498
499     def freq_range(self):           # FIXME
500         return (1600e6, 2000e6, 4e6)
501
502 #-------------------------------------------------------------------------
503 class _900_common(_AD4360_common):
504     def __init__(self):
505         _AD4360_common.__init__(self)
506
507         # Band-specific R-Register Values
508         self.R_DIV = 16  # bits 15:2  DIV by 16 for a 1 MHz phase detector freq
509    
510         # Band-specific C-Register values
511         self.P = 1        # bits 23,22   Div by 16/17
512         self.CP2 = 7      # bits 19:17   1.25 mA
513         self.CP1 = 7      # bits 16:14   1.25 mA
514
515         # Band specifc N-Register Values
516         self.DIVSEL = 0   # bit 23
517         self.DIV2 = 1     # bit 22
518         self.freq_mult = 2
519         self.CPGAIN = 0   # bit 21
520
521     def freq_range(self):           # FIXME
522         return (800e6, 1000e6, 4e6)
523
524 #-------------------------------------------------------------------------
525 class _400_common(_AD4360_common):
526     def __init__(self):
527         _AD4360_common.__init__(self)
528
529         # Band-specific R-Register Values
530         self.R_DIV = 16  # bits 15:2 
531    
532         # Band-specific C-Register values
533         self.P = 0        # bits 23,22   Div by 8/9
534         self.CP2 = 7      # bits 19:17   1.25 mA
535         self.CP1 = 7      # bits 16:14   1.25 mA
536
537         # Band specifc N-Register Values  These are different for TX/RX
538         self.DIVSEL = 0   # bit 23
539         if self._tx:
540             self.DIV2 = 1 # bit 22
541         else:
542             self.DIV2 = 0 # bit 22   # RX side has built-in DIV2 in AD8348
543         self.freq_mult = 2
544
545         self.CPGAIN = 0   # bit 21
546
547     def freq_range(self):           
548         #return (350e6, 465e6, 1e6)    # FIXME prototype
549         return (400e6, 500e6, 1e6)     # final version
550     
551
552 #------------------------------------------------------------    
553 class db_flexrf_2400_tx(_2400_common, flexrf_base_tx):
554     def __init__(self, usrp, which):
555         self.power_on = ~POWER_UP
556         self.power_off = ~POWER_UP    # powering it off kills the serial bus
557         flexrf_base_tx.__init__(self, usrp, which)
558         _2400_common.__init__(self)
559         
560 class db_flexrf_2400_rx(_2400_common, flexrf_base_rx):
561     def __init__(self, usrp, which):
562         self.power_on = ~POWER_UP
563         self.power_off = ~POWER_UP   # Powering it off kills the serial bus
564         flexrf_base_rx.__init__(self, usrp, which)
565         _2400_common.__init__(self)
566
567     def gain_range(self):
568         """
569         Return range of gain that can be set by this d'board.
570         
571         @returns (min_gain, max_gain, step_size)
572         Where gains are expressed in decibels (your mileage may vary)
573         """
574         return (self._u.pga_min(), self._u.pga_max() + 70, 0.05)
575
576     def i_and_q_swapped(self):
577         return True
578
579 class db_flexrf_1200_tx(_1200_common, flexrf_base_tx):
580     def __init__(self, usrp, which):
581         self.power_on = ~POWER_UP
582         self.power_off = ~POWER_UP    # powering it off kills the serial bus
583         flexrf_base_tx.__init__(self, usrp, which)
584         _1200_common.__init__(self)
585         
586 class db_flexrf_1200_rx(_1200_common, flexrf_base_rx):
587     def __init__(self, usrp, which):
588         self.power_on = ~POWER_UP
589         self.power_off = ~POWER_UP    # powering it off kills the serial bus
590         flexrf_base_rx.__init__(self, usrp, which)
591         _1200_common.__init__(self)
592
593     def gain_range(self):
594         """
595         Return range of gain that can be set by this d'board.
596         
597         @returns (min_gain, max_gain, step_size)
598         Where gains are expressed in decibels (your mileage may vary)
599         """
600         return (self._u.pga_min(), self._u.pga_max() + 70, 0.05)
601
602     def i_and_q_swapped(self):
603         return True
604
605 class db_flexrf_1800_tx(_1800_common, flexrf_base_tx):
606     def __init__(self, usrp, which):
607         self.power_on = ~POWER_UP
608         self.power_off = ~POWER_UP    # powering it off kills the serial bus
609         flexrf_base_tx.__init__(self, usrp, which)
610         _1800_common.__init__(self)
611         
612 class db_flexrf_1800_rx(_1800_common, flexrf_base_rx):
613     def __init__(self, usrp, which):
614         self.power_on = ~POWER_UP
615         self.power_off = ~POWER_UP    # powering it off kills the serial bus
616         flexrf_base_rx.__init__(self, usrp, which)
617         _1800_common.__init__(self)
618
619     def gain_range(self):
620         """
621         Return range of gain that can be set by this d'board.
622         
623         @returns (min_gain, max_gain, step_size)
624         Where gains are expressed in decibels (your mileage may vary)
625         """
626         return (self._u.pga_min(), self._u.pga_max() + 70, 0.05)
627
628     def i_and_q_swapped(self):
629         return True
630
631 class db_flexrf_900_tx(_900_common, flexrf_base_tx):
632     def __init__(self, usrp, which):
633         self.power_on = ~POWER_UP
634         self.power_off = ~POWER_UP    # powering it off kills the serial bus
635         flexrf_base_tx.__init__(self, usrp, which)
636         _900_common.__init__(self)
637         
638 class db_flexrf_900_rx(_900_common, flexrf_base_rx):
639     def __init__(self, usrp, which):
640         self.power_on = ~POWER_UP
641         self.power_off = ~POWER_UP    # powering it off kills the serial bus
642         flexrf_base_rx.__init__(self, usrp, which)
643         _900_common.__init__(self)
644
645     def gain_range(self):
646         """
647         Return range of gain that can be set by this d'board.
648         
649         @returns (min_gain, max_gain, step_size)
650         Where gains are expressed in decibels (your mileage may vary)
651         """
652         return (self._u.pga_min(), self._u.pga_max() + 70, 0.05)
653
654     def i_and_q_swapped(self):
655         return True
656
657 class db_flexrf_400_tx(_400_common, flexrf_base_tx):
658     def __init__(self, usrp, which):
659         self.power_on = POWER_UP
660         self.power_off = ~POWER_UP
661         flexrf_base_tx.__init__(self, usrp, which)
662         _400_common.__init__(self)
663         
664 class db_flexrf_400_rx(_400_common, flexrf_base_rx):
665     def __init__(self, usrp, which):
666         self.power_on = POWER_UP
667         self.power_off = ~POWER_UP
668         flexrf_base_rx.__init__(self, usrp, which)
669         _400_common.__init__(self)
670
671     def gain_range(self):
672         """
673         Return range of gain that can be set by this d'board.
674         
675         @returns (min_gain, max_gain, step_size)
676         Where gains are expressed in decibels (your mileage may vary)
677         """
678         return (self._u.pga_min(), self._u.pga_max() + 45, 0.035)
679
680     def i_and_q_swapped(self):
681         return True
682     
683 # hook these daughterboard classes into the auto-instantiation framework
684
685 db_instantiator.add(usrp_dbid.FLEX_2400_TX, lambda usrp, which : (db_flexrf_2400_tx(usrp, which),))
686 db_instantiator.add(usrp_dbid.FLEX_2400_RX, lambda usrp, which : (db_flexrf_2400_rx(usrp, which),))
687 db_instantiator.add(usrp_dbid.FLEX_1200_TX, lambda usrp, which : (db_flexrf_1200_tx(usrp, which),))
688 db_instantiator.add(usrp_dbid.FLEX_1200_RX, lambda usrp, which : (db_flexrf_1200_rx(usrp, which),))
689 db_instantiator.add(usrp_dbid.FLEX_1800_TX, lambda usrp, which : (db_flexrf_1800_tx(usrp, which),))
690 db_instantiator.add(usrp_dbid.FLEX_1800_RX, lambda usrp, which : (db_flexrf_1800_rx(usrp, which),))
691 db_instantiator.add(usrp_dbid.FLEX_900_TX,  lambda usrp, which : (db_flexrf_900_tx(usrp, which),))
692 db_instantiator.add(usrp_dbid.FLEX_900_RX,  lambda usrp, which : (db_flexrf_900_rx(usrp, which),))
693 db_instantiator.add(usrp_dbid.FLEX_400_TX,  lambda usrp, which : (db_flexrf_400_tx(usrp, which),))
694 db_instantiator.add(usrp_dbid.FLEX_400_RX,  lambda usrp, which : (db_flexrf_400_rx(usrp, which),))