#!/usr/bin/env python
#
# Copyright 2005 Free Software Foundation, Inc.
# 
# This file is part of GNU Radio
# 
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# 
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with GNU Radio; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
# 

from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import blks
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider
from gnuradio.wxgui import stdgui, fftsink, form
from optparse import OptionParser
import sys
import math
import wx


class wfm_test_graph (stdgui.gui_flow_graph):
    def __init__(self,frame,panel,vbox,argv):
        stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv)

        parser=OptionParser(option_class=eng_option)
        parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
                          help="select USRP Rx side A or B (default=A)")
        parser.add_option("-f", "--freq", type="eng_float", default=10.0e3,
                          help="set src freq to FREQ", metavar="FREQ")
        parser.add_option("-s", "--sine", action="store_true", default=False,
                          help="use sine in stead of noise src")

        (options, args) = parser.parse_args()
        if len(args) != 0:
            parser.print_help()
            sys.exit(1)
        
        self.frame = frame
        self.panel = panel

        self.sample_rate=320.0e3
        #sig source
        self.do_noise=not options.sine
        self.waveform_ampl=1.0
        self.waveform_freq=options.freq
        self.waveform_offset=0.0
        if (self.do_noise):
          self.sig = gr.noise_source_f (gr.GR_UNIFORM,
                                           self.waveform_ampl) 
        else:
          self.sig = gr.sig_source_f (self.sample_rate,
                                       gr.GR_SIN_WAVE,
                                       self.waveform_freq,
                                       self.waveform_ampl,
                                       self.waveform_offset) 
        self.src=gr.throttle  	(gr.sizeof_float,self.sample_rate)           
        #mod
        max_dev=75e3
        mod_gain = 2 * math.pi * max_dev / self.sample_rate
        self.fm_mod = gr.frequency_modulator_fc (mod_gain)
        #demod pll
        bandwidth = 200e3
        alpha = 0.25*bandwidth * math.pi / self.sample_rate
        beta = alpha * alpha / 4.0
        max_freq = 2.0*math.pi*100e3/self.sample_rate
        self.fm_demod_pll = gr.pll_freqdet_cf (alpha,beta,max_freq,-max_freq)
        #demod quadrature
        fm_demod_gain = 1.0/mod_gain
        self.fm_demod_quadrature = gr.quadrature_demod_cf (fm_demod_gain)  
        #connect them      
        self.connect (self.sig,self.src, self.fm_mod, self.fm_demod_pll)
        self.connect (self.fm_mod, self.fm_demod_quadrature)
        self._build_gui(vbox, self.sample_rate)


    def _build_gui(self, vbox, sample_rate):
        if 1:
            self.src_fft = fftsink.fft_sink_f(self, self.panel, title="src FFT",
                                               fft_size=512, sample_rate=sample_rate)
            self.connect (self.src, self.src_fft)
            vbox.Add (self.src_fft.win, 4, wx.EXPAND)

        if 1:
            demod_pll_fft = fftsink.fft_sink_f(self, self.panel, title="demod pll FFT", 
                                                fft_size=1024, sample_rate=sample_rate,
                                                y_per_div=10, ref_level=0)
            self.connect (self.fm_demod_pll, demod_pll_fft)
            vbox.Add (demod_pll_fft.win, 4, wx.EXPAND)

        if 1:
            demod_quadrature_fft = fftsink.fft_sink_f (self, self.panel, title="demod quadrature FFT",
                                                  fft_size=512, sample_rate=sample_rate,
                                                  y_per_div=10, ref_level=-20)
            self.connect (self.fm_demod_quadrature, demod_quadrature_fft)
            vbox.Add (demod_quadrature_fft.win, 4, wx.EXPAND)

        self.myform = myform = form.form()
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        hbox.Add((5,0), 0)
        myform['freq_slider'] = \
            form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3,
                                        range=(sample_rate/200, sample_rate/2, sample_rate/200),
                                        callback=self.set_src_freq)
        vbox.Add(hbox, 0, wx.EXPAND)

    def set_src_freq(self, freq):
        self.myform['src_freq'].set_value(freq)     # update displayed value
        if not self.do_noise:
          self.sig.set_freq(freq)
          msg = "Src freq:%r  " % (freq)
        else:
          msg = "Freq cannot be set on noise src"
        self._set_status_msg(msg, 0)
        

if __name__ == '__main__':
    app = stdgui.stdapp (wfm_test_graph, "WFM loopback test")
    app.MainLoop ()


