Merged r6015:6026 from jcorgan/radar.
[debian/gnuradio] / gr-usrp / src / db_flexrf.py
1 #
2 # Copyright 2005 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 2, 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 $: 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 # ----------------------------------------------------------------
215
216 class flexrf_base_tx(flexrf_base):
217     def __init__(self, usrp, which):
218         """
219         @param usrp: instance of usrp.sink_c
220         @param which: 0 or 1 corresponding to side TX_A or TX_B respectively.
221         """
222         flexrf_base.__init__(self, usrp, which)
223         self.spi_enable = (SPI_ENABLE_TX_A, SPI_ENABLE_TX_B)[which]
224
225         # power up the transmit side, but don't enable the mixer
226         self._u._write_oe(self._which,(POWER_UP|RX_TXN|ENABLE), 0xffff)
227         self._u.write_io(self._which, (self.power_on|RX_TXN), (POWER_UP|RX_TXN|ENABLE))
228         self.lo_offset = 4e6 
229
230     def __del__(self):
231         #print "flexrf_base_tx.__del__"
232         # Power down and leave the T/R switch in the R position
233         self._u.write_io(self._which, (self.power_off|RX_TXN), (POWER_UP|RX_TXN|ENABLE))
234         flexrf_base.__del__(self)
235
236     def set_auto_tr(self, on):
237         if on:
238             self.set_atr_mask (RX_TXN | ENABLE)
239             self.set_atr_txval(0      | ENABLE)
240             self.set_atr_rxval(RX_TXN | 0)
241         else:
242             self.set_atr_mask (0)
243             self.set_atr_txval(0)
244             self.set_atr_rxval(0)
245
246     def set_enable(self, on):
247         """
248         Enable transmitter if on is True
249         """
250         mask = RX_TXN | ENABLE
251         if on:
252             v = ENABLE
253         else:
254             v = RX_TXN
255         self._u.write_io(self._which, v, mask)
256
257     def gain_range(self):
258         """
259         Return range of gain that can be set by this d'board.
260
261         @returns (min_gain, max_gain, step_size)
262         Where gains are expressed in decibels (your mileage may vary)
263
264         Flex Tx boards require that the PGA be maxed out to properly bias their circuitry.
265         """
266         g = self._u.pga_max()
267         return (g, g, 1.0)
268
269     def set_gain(self, gain):
270         """
271         Set the gain.
272
273         @param gain:  gain in decibels
274         @returns True/False
275         """
276         return self._set_pga(self._u.pga_max())
277
278     def set_lo_offset(self, offset):
279         """
280         Set amount by which LO is offset from requested tuning frequency.
281         
282         @param offset: offset in Hz
283         """
284         self.lo_offset = offset
285
286     def get_lo_offset(self):
287         """
288         Get amount by which LO is offset from requested tuning frequency.
289         
290         @returns Offset in Hz
291         """
292         return self.lo_offset
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
311         self.lo_offset = -4e6
312
313     def __del__(self):
314         # print "flexrf_base_rx.__del__"
315         # Power down
316         self._u.write_io(self._which, self.power_off, (POWER_UP|ENABLE))
317         flexrf_base.__del__(self)
318     
319     def set_auto_tr(self, on):
320         if on:
321             self.set_atr_mask (ENABLE)
322             self.set_atr_txval(     0)
323             self.set_atr_rxval(ENABLE)
324         else:
325             self.set_atr_mask (0)
326             self.set_atr_txval(0)
327             self.set_atr_rxval(0)
328
329     def select_rx_antenna(self, which_antenna):
330         """
331         Specify which antenna port to use for reception.
332         @param which_antenna: either 'TX/RX' or 'RX2'
333         """
334         if which_antenna in (0, 'TX/RX'):
335             self._u.write_io(self._which, 0,        RX2_RX1N)
336         elif which_antenna in (1, 'RX2'):
337             self._u.write_io(self._which, RX2_RX1N, RX2_RX1N)
338         else:
339             raise ValueError, "which_antenna must be either 'TX/RX' or 'RX2'"
340
341     def set_gain(self, gain):
342         """
343         Set the gain.
344
345         @param gain:  gain in decibels
346         @returns True/False
347         """
348         maxgain = self.gain_range()[1] - self._u.pga_max()
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 + 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     def set_lo_offset(self, offset):
365         """
366         Set amount by which LO is offset from requested tuning frequency.
367         
368         @param offset: offset in Hz
369         """
370         self.lo_offset = offset
371
372     def get_lo_offset(self):
373         """
374         Get amount by which LO is offset from requested tuning frequency.
375         
376         @returns Offset in Hz
377         """
378         return self.lo_offset
379         
380
381 # ----------------------------------------------------------------
382
383 class _AD4360_common(object):
384     def __init__(self):
385         # R-Register Common Values
386         self.R_RSV = 0   # bits 23,22
387         self.BSC = 3   # bits 21,20 Div by 8 to be safe
388         self.TEST = 0  # bit 19
389         self.LDP = 1   # bit 18
390         self.ABP = 0   # bit 17,16   3ns
391
392         # N-Register Common Values
393         self.N_RSV = 0      # bit 7
394         
395         # Control Register Common Values
396         self.PD = 0       # bits 21,20   Normal operation
397         self.PL = 0       # bits 13,12   11mA
398         self.MTLD = 1     # bit 11       enabled
399         self.CPG = 0      # bit 10       CP setting 1
400         self.CP3S = 0     # bit 9        Normal
401         self.PDP = 1      # bit 8        Positive
402         self.MUXOUT = 1   # bits 7:5     Digital Lock Detect
403         self.CR = 0       # bit 4        Normal
404         self.PC = 1       # bits 3,2     Core power 10mA
405
406     def _compute_regs(self, freq):
407         """
408         Determine values of R, control, and N registers, along with actual freq.
409         
410         @param freq: target frequency in Hz
411         @type freq: float
412         @returns: (R, control, N, actual_freq)
413         @rtype: tuple(int, int, int, float)
414         """
415
416         #  Band-specific N-Register Values
417         phdet_freq = self._refclk_freq()/self.R_DIV
418         desired_n = round(freq*self.freq_mult/phdet_freq)
419         actual_freq = desired_n * phdet_freq
420         B = math.floor(desired_n/self._prescaler())
421         A = desired_n - self._prescaler()*B
422         self.B_DIV = int(B)    # bits 20:8
423         self.A_DIV = int(A)    # bit 6:2
424         #assert self.B_DIV >= self.A_DIV
425         if self.B_DIV < self.A_DIV:
426             return (0,0,0,0)
427         R = (self.R_RSV<<22) | (self.BSC<<20) | (self.TEST<<19) | (self.LDP<<18) \
428             | (self.ABP<<16) | (self.R_DIV<<2)
429         
430         control = (self.P<<22) | (self.PD<<20) | (self.CP2<<17) | (self.CP1<<14) | (self.PL<<12) \
431                   | (self.MTLD<<11) | (self.CPG<<10) | (self.CP3S<<9) | (self.PDP<<8) | \
432                   (self.MUXOUT<<5) | (self.CR<<4) | (self.PC<<2)
433
434         N = (self.DIVSEL<<23) | (self.DIV2<<22) | (self.CPGAIN<<21) | (self.B_DIV<<8) | \
435             (self.N_RSV<<7) | (self.A_DIV<<2)
436
437         return (R,control,N,actual_freq/self.freq_mult)
438
439     def _refclk_divisor(self):
440         """
441         Return value to stick in REFCLK_DIVISOR register
442         """
443         return 1
444     
445     def _prescaler(self):
446         if self.P == 0:
447             return 8
448         elif self.P == 1:
449             return 16
450         else:
451             return 32
452
453 #----------------------------------------------------------------------
454 class _2400_common(_AD4360_common):
455     def __init__(self):
456         _AD4360_common.__init__(self)
457
458         # Band-specific R-Register Values
459         self.R_DIV = 16  # bits 15:2
460    
461         # Band-specific C-Register values
462         self.P = 1        # bits 23,22   Div by 16/17
463         self.CP2 = 7      # bits 19:17
464         self.CP1 = 7      # bits 16:14
465
466         # Band specifc N-Register Values
467         self.DIVSEL = 0   # bit 23
468         self.DIV2 = 0     # bit 22
469         self.CPGAIN = 0   # bit 21
470         self.freq_mult = 1
471
472     def freq_range(self):           # FIXME
473         return (2300e6, 2700e6, 4e6)
474
475 #----------------------------------------------------------------------
476 class _1200_common(_AD4360_common):
477     def __init__(self):
478         _AD4360_common.__init__(self)
479
480         # Band-specific R-Register Values
481         self.R_DIV = 16  # bits 15:2  DIV by 16 for a 1 MHz phase detector freq
482    
483         # Band-specific C-Register values
484         self.P = 1        # bits 23,22   Div by 16/17
485         self.CP2 = 7      # bits 19:17   1.25 mA
486         self.CP1 = 7      # bits 16:14   1.25 mA
487
488         # Band specifc N-Register Values
489         self.DIVSEL = 0   # bit 23
490         self.DIV2 = 1     # bit 22
491         self.CPGAIN = 0   # bit 21
492         self.freq_mult = 2
493
494     def freq_range(self):           # FIXME
495         return (1150e6, 1350e6, 4e6)
496
497 #-------------------------------------------------------------------------
498 class _1800_common(_AD4360_common):
499     def __init__(self):
500         _AD4360_common.__init__(self)
501
502         # Band-specific R-Register Values
503         self.R_DIV = 16  # bits 15:2  DIV by 16 for a 1 MHz phase detector freq
504    
505         # Band-specific C-Register values
506         self.P = 1        # bits 23,22   Div by 16/17
507         self.CP2 = 7      # bits 19:17   1.25 mA
508         self.CP1 = 7      # bits 16:14   1.25 mA
509
510         # Band specifc N-Register Values
511         self.DIVSEL = 0   # bit 23
512         self.DIV2 = 0     # bit 22
513         self.freq_mult = 1
514         self.CPGAIN = 0   # bit 21
515
516     def freq_range(self):           # FIXME
517         return (1600e6, 2000e6, 4e6)
518
519 #-------------------------------------------------------------------------
520 class _900_common(_AD4360_common):
521     def __init__(self):
522         _AD4360_common.__init__(self)
523
524         # Band-specific R-Register Values
525         self.R_DIV = 16  # bits 15:2  DIV by 16 for a 1 MHz phase detector freq
526    
527         # Band-specific C-Register values
528         self.P = 1        # bits 23,22   Div by 16/17
529         self.CP2 = 7      # bits 19:17   1.25 mA
530         self.CP1 = 7      # bits 16:14   1.25 mA
531
532         # Band specifc N-Register Values
533         self.DIVSEL = 0   # bit 23
534         self.DIV2 = 1     # bit 22
535         self.freq_mult = 2
536         self.CPGAIN = 0   # bit 21
537
538     def freq_range(self):           # FIXME
539         return (800e6, 1000e6, 4e6)
540
541 #-------------------------------------------------------------------------
542 class _400_common(_AD4360_common):
543     def __init__(self):
544         _AD4360_common.__init__(self)
545
546         # Band-specific R-Register Values
547         self.R_DIV = 16  # bits 15:2 
548    
549         # Band-specific C-Register values
550         self.P = 0        # bits 23,22   Div by 8/9
551         self.CP2 = 7      # bits 19:17   1.25 mA
552         self.CP1 = 7      # bits 16:14   1.25 mA
553
554         # Band specifc N-Register Values  These are different for TX/RX
555         self.DIVSEL = 0   # bit 23
556         if self._tx:
557             self.DIV2 = 1 # bit 22
558         else:
559             self.DIV2 = 0 # bit 22   # RX side has built-in DIV2 in AD8348
560         self.freq_mult = 2
561
562         self.CPGAIN = 0   # bit 21
563
564     def freq_range(self):           
565         #return (350e6, 465e6, 1e6)    # FIXME prototype
566         return (400e6, 500e6, 1e6)     # final version
567     
568
569 #------------------------------------------------------------    
570 class db_flexrf_2400_tx(_2400_common, flexrf_base_tx):
571     def __init__(self, usrp, which):
572         self.power_on = ~POWER_UP
573         self.power_off = ~POWER_UP    # powering it off kills the serial bus
574         flexrf_base_tx.__init__(self, usrp, which)
575         _2400_common.__init__(self)
576         
577 class db_flexrf_2400_rx(_2400_common, flexrf_base_rx):
578     def __init__(self, usrp, which):
579         self.power_on = ~POWER_UP
580         self.power_off = ~POWER_UP   # Powering it off kills the serial bus
581         flexrf_base_rx.__init__(self, usrp, which)
582         _2400_common.__init__(self)
583
584     def gain_range(self):
585         """
586         Return range of gain that can be set by this d'board.
587         
588         @returns (min_gain, max_gain, step_size)
589         Where gains are expressed in decibels (your mileage may vary)
590         """
591         return (self._u.pga_min(), self._u.pga_max() + 70, 0.05)
592
593     def i_and_q_swapped(self):
594         return True
595
596 class db_flexrf_1200_tx(_1200_common, flexrf_base_tx):
597     def __init__(self, usrp, which):
598         self.power_on = ~POWER_UP
599         self.power_off = ~POWER_UP    # powering it off kills the serial bus
600         flexrf_base_tx.__init__(self, usrp, which)
601         _1200_common.__init__(self)
602         
603 class db_flexrf_1200_rx(_1200_common, flexrf_base_rx):
604     def __init__(self, usrp, which):
605         self.power_on = ~POWER_UP
606         self.power_off = ~POWER_UP    # powering it off kills the serial bus
607         flexrf_base_rx.__init__(self, usrp, which)
608         _1200_common.__init__(self)
609
610     def gain_range(self):
611         """
612         Return range of gain that can be set by this d'board.
613         
614         @returns (min_gain, max_gain, step_size)
615         Where gains are expressed in decibels (your mileage may vary)
616         """
617         return (self._u.pga_min(), self._u.pga_max() + 70, 0.05)
618
619     def i_and_q_swapped(self):
620         return True
621
622 class db_flexrf_1800_tx(_1800_common, flexrf_base_tx):
623     def __init__(self, usrp, which):
624         self.power_on = ~POWER_UP
625         self.power_off = ~POWER_UP    # powering it off kills the serial bus
626         flexrf_base_tx.__init__(self, usrp, which)
627         _1800_common.__init__(self)
628         
629 class db_flexrf_1800_rx(_1800_common, flexrf_base_rx):
630     def __init__(self, usrp, which):
631         self.power_on = ~POWER_UP
632         self.power_off = ~POWER_UP    # powering it off kills the serial bus
633         flexrf_base_rx.__init__(self, usrp, which)
634         _1800_common.__init__(self)
635
636     def gain_range(self):
637         """
638         Return range of gain that can be set by this d'board.
639         
640         @returns (min_gain, max_gain, step_size)
641         Where gains are expressed in decibels (your mileage may vary)
642         """
643         return (self._u.pga_min(), self._u.pga_max() + 70, 0.05)
644
645     def i_and_q_swapped(self):
646         return True
647
648 class db_flexrf_900_tx(_900_common, flexrf_base_tx):
649     def __init__(self, usrp, which):
650         self.power_on = ~POWER_UP
651         self.power_off = ~POWER_UP    # powering it off kills the serial bus
652         flexrf_base_tx.__init__(self, usrp, which)
653         _900_common.__init__(self)
654         
655 class db_flexrf_900_rx(_900_common, flexrf_base_rx):
656     def __init__(self, usrp, which):
657         self.power_on = ~POWER_UP
658         self.power_off = ~POWER_UP    # powering it off kills the serial bus
659         flexrf_base_rx.__init__(self, usrp, which)
660         _900_common.__init__(self)
661
662     def gain_range(self):
663         """
664         Return range of gain that can be set by this d'board.
665         
666         @returns (min_gain, max_gain, step_size)
667         Where gains are expressed in decibels (your mileage may vary)
668         """
669         return (self._u.pga_min(), self._u.pga_max() + 70, 0.05)
670
671     def i_and_q_swapped(self):
672         return True
673
674 class db_flexrf_400_tx(_400_common, flexrf_base_tx):
675     def __init__(self, usrp, which):
676         self.power_on = POWER_UP
677         self.power_off = ~POWER_UP
678         flexrf_base_tx.__init__(self, usrp, which)
679         _400_common.__init__(self)
680         
681 class db_flexrf_400_rx(_400_common, flexrf_base_rx):
682     def __init__(self, usrp, which):
683         self.power_on = POWER_UP
684         self.power_off = ~POWER_UP
685         flexrf_base_rx.__init__(self, usrp, which)
686         _400_common.__init__(self)
687
688     def gain_range(self):
689         """
690         Return range of gain that can be set by this d'board.
691         
692         @returns (min_gain, max_gain, step_size)
693         Where gains are expressed in decibels (your mileage may vary)
694         """
695         return (self._u.pga_min(), self._u.pga_max() + 45, 0.035)
696
697     def i_and_q_swapped(self):
698         return True
699     
700 # hook these daughterboard classes into the auto-instantiation framework
701
702 db_instantiator.add(usrp_dbid.FLEX_2400_TX, lambda usrp, which : (db_flexrf_2400_tx(usrp, which),))
703 db_instantiator.add(usrp_dbid.FLEX_2400_RX, lambda usrp, which : (db_flexrf_2400_rx(usrp, which),))
704 db_instantiator.add(usrp_dbid.FLEX_1200_TX, lambda usrp, which : (db_flexrf_1200_tx(usrp, which),))
705 db_instantiator.add(usrp_dbid.FLEX_1200_RX, lambda usrp, which : (db_flexrf_1200_rx(usrp, which),))
706 db_instantiator.add(usrp_dbid.FLEX_1800_TX, lambda usrp, which : (db_flexrf_1800_tx(usrp, which),))
707 db_instantiator.add(usrp_dbid.FLEX_1800_RX, lambda usrp, which : (db_flexrf_1800_rx(usrp, which),))
708 db_instantiator.add(usrp_dbid.FLEX_900_TX,  lambda usrp, which : (db_flexrf_900_tx(usrp, which),))
709 db_instantiator.add(usrp_dbid.FLEX_900_RX,  lambda usrp, which : (db_flexrf_900_rx(usrp, which),))
710 db_instantiator.add(usrp_dbid.FLEX_400_TX,  lambda usrp, which : (db_flexrf_400_tx(usrp, which),))
711 db_instantiator.add(usrp_dbid.FLEX_400_RX,  lambda usrp, which : (db_flexrf_400_rx(usrp, which),))