#!/usr/bin/env python

"""
Read samples from the USRP and write to file formatted as binary
outputs single precision complex float values or complex short values (interleaved 16 bit signed short integers).

"""

from gnuradio import gr, eng_notation
from gnuradio import audio
from gnuradio import usrp
from gnuradio import cxadc
from gnuradio.eng_option import eng_option
from optparse import OptionParser

class my_graph(gr.flow_graph):

    def __init__(self):
        gr.flow_graph.__init__(self)

        usage="%prog: [options] output_filename"
        parser = OptionParser(option_class=eng_option, usage=usage)
        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0),
                          help="select USRP Rx side A or B (default=A)")
        parser.add_option("-d", "--decim", type="int", default=16,
                          help="set fgpa decimation rate to DECIM [default=%default]")
        parser.add_option("-f", "--freq", type="eng_float", default=None,
                          help="set frequency to FREQ", metavar="FREQ")   
        parser.add_option("-g", "--gain", type="eng_float", default=None,
                          help="set gain in dB (default is midpoint)")
        parser.add_option( "-s","--output-shorts", action="store_true", default=True,
                          help="output shorts (this is the default)")
        parser.add_option( "-F","--output-floats", action="store_true", default=False,
                          help="output floats")
        parser.add_option("-N", "--nsamples", type="eng_float", default=None,
                          help="number of samples to collect [default=+inf]")
        (options, args) = parser.parse_args ()
        if len(args) != 1:
            parser.print_help()
            raise SystemExit, 1
        filename = args[0]

        if options.freq is None:
            parser.print_help()
            sys.stderr.write('You must specify the frequency with -f FREQ\n');
            raise SystemExit, 1

        # build the graph
        #standard fpga firmware "std_2rxhb_2tx.rbf" contains 2 Rx paths with halfband filters and 2 tx paths (the default) min decimation 8

        self.u = usrp.source_c(decim_rate=options.decim)

        adc_rate = (27.0/28.8)*32.0e6 #16.0e6 #27e6 #self.u.adc_rate()                # 64 MS/s
        
        #// public shared_ptr constructor
        #cxadc_source_sptr
        #cxadc_make_source (double sampling_freq = 27e6,//sampling_freq is ignored at the moment. TODO: implement sampling_freq 
	#	    int do_avg_frame=1,
        #            double frame_avg_alpha=0.01,
	#	    const std::string dev = "/dev/cxadc") throw (std::runtime_error);
        if True: #options.input_shorts:
           do_remove_dc=0
           self.cxadc=cxadc.source (adc_rate,do_remove_dc,0.1,"/dev/cxadc")
        else:
           self.fsrc= cxadc.source_f (sampling_freq = adc_rate,do_avg_frame=True,frame_avg_alpha=0.01,dev = "/dev/cxadc")


        if options.output_floats:
          self.fsrc=gr.short_to_float()
          self.connect(self.cxadc,self.fsrc)	
          self.dst = gr.file_sink(gr.sizeof_float, filename)
          self.src=self.fsrc
        elif options.output_shorts:
          self.dst = gr.file_sink(gr.sizeof_short, filename)
          self.src=self.cxadc
        
        if options.nsamples is None:
            self.connect(self.src, self.dst)
        else:
            if options.output_shorts:
              self.head = gr.head(gr.sizeof_short, int(options.nsamples))
            else:
              self.head = gr.head(gr.sizeof_float, int(options.nsamples))
            self.connect(self.src, self.head, self.dst)

        if options.rx_subdev_spec is None:
            options.rx_subdev_spec = usrp.pick_rx_subdevice(self.u)
        self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec))

        # determine the daughterboard subdevice we're using
        self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec)
        print "Using RX d'board %s" % (self.subdev.side_and_name(),)
        input_rate = self.u.adc_freq() / self.u.decim_rate()
        print "USB sample rate %s" % (eng_notation.num_to_str(input_rate))

        if options.gain is None:
            # if no gain was specified, use the mid-point in dB
            g = self.subdev.gain_range()
            options.gain = float(g[0]+g[1])/2

        self.subdev.set_gain(options.gain)

        r = self.u.tune(0, self.subdev, options.freq)
        if not r:
            sys.stderr.write('Failed to set frequency\n')
            raise SystemExit, 1

        
if __name__ == '__main__':
    try:
        my_graph().run()
    except KeyboardInterrupt:
        pass

