#!/usr/bin/env python


from gnuradio import gr, gru, eng_notation, optfir
from gnuradio import audio
from gnuradio import usrp
from gnuradio import blks
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import slider, powermate
from gnuradio.wxgui import stdgui, fftsink, form
#from gnuradio.wxgui import *
from optparse import OptionParser
import usrp_dbid
import sys
import math
from math import sin, cos
import wx

def pick_subdevice(u):
    """
    The user didn't specify a subdevice on the command line.
    Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A.

    @return a subdev_spec
    """
    return usrp.pick_subdev(u, (usrp_dbid.TV_RX,
                                usrp_dbid.TV_RX_REV_2,
                                usrp_dbid.BASIC_RX))

class parallel_graph_sink_f(gr.hier_block, fftsink.fft_sink_base):
    def __init__(self, fg, parent, baseband_freq=0,
                 y_per_div=10, ref_level=0, sample_rate=1, block_size=512,
                 display_rate=15, average=True, avg_alpha=None, title='',
                 size=fftsink.default_fftsink_size, peak_hold=False,
                 log_type=None,log_offset=0):

        fftsink.fft_sink_base.__init__(self, input_is_real=False, baseband_freq=baseband_freq,
                               y_per_div=y_per_div, ref_level=ref_level,
                               sample_rate=sample_rate, fft_size=block_size,
                               fft_rate=display_rate,
                               average=average, avg_alpha=avg_alpha, title=title,
                               peak_hold=peak_hold)

        one_in_n = gr.keep_one_in_n(gr.sizeof_float * block_size,
                                    max(1, int(sample_rate/block_size/display_rate)))
        self.avg = gr.single_pole_iir_filter_ff(1.0, block_size)
        sink = gr.message_sink(gr.sizeof_float * block_size, self.msgq, True)
        if not (log_type is None):
          log = gr.nlog10_ff(20, block_size, log_offset)
        if log_type is None:
          fg.connect(one_in_n, self.avg, sink)
        elif log_type=='PRE_AVG':
          fg.connect(one_in_n,log, self.avg, sink)
        elif log_type=='POST_AVG':
          fg.connect(one_in_n, self.avg,log, sink)
        else:
          print 'warning log=',log,' not understood.'
          print "use 'PRE_AVG', 'POST_AVG' or None"
        gr.hier_block.__init__(self, fg, one_in_n, sink)
        self.win = fftsink.fft_window(self, parent, size=size)
        self.set_average(self.average)

class parallel_graph_sink_avg_c(gr.hier_block, fftsink.fft_sink_base):
    def __init__(self, fg, parent, baseband_freq=0,
                 y_per_div=10, ref_level=0, sample_rate=1, block_size=512,
                 display_rate=15, average=True, avg_alpha=None, title='',
                 size=fftsink.default_fftsink_size, peak_hold=False,output_type='MAG',
                 log_type=None,log_offset=0,force_decimation=None):

        fftsink.fft_sink_base.__init__(self, input_is_real=False, baseband_freq=baseband_freq,
                               y_per_div=y_per_div, ref_level=ref_level,
                               sample_rate=sample_rate, fft_size=block_size,
                               fft_rate=display_rate,
                               average=average, avg_alpha=avg_alpha, title=title,
                               peak_hold=peak_hold)
        if force_decimation is None:
          dec=max(1, int(sample_rate/block_size/display_rate))
        else:
          dec=force_decimation

        one_in_n = gr.keep_one_in_n(gr.sizeof_gr_complex * block_size, dec)
        self.avg = gr.single_pole_iir_filter_cc(1.0, block_size)
        sink = gr.message_sink(gr.sizeof_float * block_size, self.msgq, True)
        if output_type=='REAL':
          c2f = gr.complex_to_real(block_size) #
        elif output_type=='MAG':
          c2f=gr.complex_to_mag(block_size)
        elif output_type=='ARG':
          c2f=gr.complex_to_arg(block_size)
        else: #output_type='COMPLEX'
          c2f=None #output complex values, FIXME, implement me, add second graph

        if not (log_type is None):
          log = gr.nlog10_ff(20, block_size, log_offset)
        if log_type is None:
          fg.connect(self.avg, one_in_n,c2f,sink)
        elif log_type=='PRE_AVG':
          fg.connect(self.avg, one_in_n,c2f,log,sink) #FIXME
        elif log_type=='POST_AVG':
          fg.connect(self.avg, one_in_n,c2f,log,sink)
        else:
          print 'warning log=',log,' not understood.'
          print "use 'PRE_AVG', 'POST_AVG' or None"

        #fg.connect(self.avg,one_in_n,c2f,sink)
        gr.hier_block.__init__(self, fg, self.avg,sink)
        self.win = fftsink.fft_window(self, parent, size=size)
        self.set_average(self.average)

class correlator_c(gr.hier_block):
    def __init__(self, fg, sample_rate=1, fft_size=512,output_type='COMPLEX',
                 fft_rate=15, pre_abs=False,subset_result=False,force_decimation=None,no_ifft=False): #01.0e-12):
        di = gr.deinterleave(gr.sizeof_gr_complex)
        s2p_a = gr.serial_to_parallel(gr.sizeof_gr_complex, fft_size)
        s2p_b = gr.serial_to_parallel(gr.sizeof_gr_complex, fft_size)
        s2p3 = gr.serial_to_parallel(gr.sizeof_gr_complex, fft_size)
        if force_decimation is None:         
          self.decimation=max(1, int(sample_rate/fft_size/fft_rate))
        else:
          self.decimation=force_decimation
        one_in_n_a = gr.keep_one_in_n(gr.sizeof_gr_complex * fft_size,
                                    self.decimation)
        one_in_n_b = gr.keep_one_in_n(gr.sizeof_gr_complex * fft_size,
                                    self.decimation)
        if subset_result:
          fft_size_result=int(fft_size/4)
        else:
          fft_size_result=fft_size
        mywindow = fftsink.window.blackmanharris(fft_size)
        if pre_abs:
          c2mag1_a = gr.complex_to_mag(fft_size)
          c2mag1_b = gr.complex_to_mag(fft_size)
          fft_a = gr.fft_vfc(fft_size, True, mywindow)
          fft_b = gr.fft_vfc(fft_size, True, mywindow)
        else:
          fft_a = gr.fft_vcc(fft_size, True, mywindow)
          fft_b = gr.fft_vcc(fft_size, True, mywindow)
        self.power = 0
        for tap in mywindow:
            self.power += tap*tap

        p2s_a = gr.parallel_to_serial(gr.sizeof_gr_complex, fft_size)
        p2s_b = gr.parallel_to_serial(gr.sizeof_gr_complex, fft_size)
        conj=gr.conjugate_cc()
        mult=gr.multiply_cc()
        #no_ifft=False
        if no_ifft:
          ifft=gr.keep_one_in_n(gr.sizeof_gr_complex * fft_size,1)
        else:
          ifft=gr.fft_vcc(fft_size, False, mywindow)
        if output_type=='REAL':
          c2mag2 = gr.complex_to_real(fft_size_result) #
        elif output_type=='MAG':
          c2mag2=gr.complex_to_mag(fft_size_result)
        elif output_type=='ARG':
          c2mag2=gr.complex_to_arg(fft_size_result)
        else: #output_type='COMPLEX'
          c2mag2=gr.add_const_cc(0.0) #output complex values, use dummy placeholder

        #self.avg_cc = gr.single_pole_iir_filter_cc(alpha2, fft_size_result)
        fg.connect((di,0),s2p_a,one_in_n_a)
        fg.connect((di,1),s2p_b,one_in_n_b)
        if pre_abs:
          fg.connect(one_in_n_a,c2mag1_a,fft_a,p2s_a)
          fg.connect(one_in_n_b,c2mag1_b,fft_b,p2s_b)
        else:
          fg.connect(one_in_n_a,fft_a,p2s_a)
          fg.connect(one_in_n_b,fft_b,p2s_b)
        dummy=gr.add_const_cc(0.0)
        fg.connect(p2s_a,conj)
        fg.connect(p2s_b,dummy)
        fg.connect(dummy,(mult,0))
        fg.connect(conj,(mult,1))
        fg.connect(mult,s2p3,ifft)
        if subset_result:
          print 'SUBSET'
          p2s4=gr.parallel_to_serial(gr.sizeof_gr_complex*(fft_size_result), 4)
          di2=gr.deinterleave(gr.sizeof_gr_complex*fft_size_result)
          nullsink0=gr.null_sink(gr.sizeof_gr_complex*fft_size_result)
          nullsink1=gr.null_sink(gr.sizeof_gr_complex*fft_size_result)
          #nullsink2=gr.null_sink(gr.sizeof_gr_complex*(fft_size/4))
          nullsink3=gr.null_sink(gr.sizeof_gr_complex*fft_size_result)
          fg.connect(ifft,p2s4,di2)
          fg.connect((di2,0),nullsink0)
          fg.connect((di2,1),nullsink1)
          ifft_result=(di2,2)
          #fg.connect((di2,2),c2mag2)
          #fg.connect((di2,2),nullsink2)
          fg.connect((di2,3),nullsink3)
        else:
          ifft_result=ifft
        if output_type=='COMPLEX':
          sink=ifft_result
        else:
          fg.connect(ifft_result,c2mag2)
          sink=c2mag2

        gr.hier_block.__init__(self, fg, di, sink)

class correlate_sink_c2_arg(gr.hier_block): #determine phase difference per frequency
    def __init__(self, fg, parent, baseband_freq=0,
                 y_per_div=1, ref_level=3.141592653589793236, sample_rate=1, fft_size=512,
                 fft_rate=5, average=False, avg_alpha=None, title='',
                 size=fftsink.default_fftsink_size, peak_hold=False,force_decimation=None):

        corr=correlator_c(fg, sample_rate=sample_rate,fft_size=fft_size,output_type='ARG',
                 fft_rate=fft_rate, pre_abs=False,subset_result=False,force_decimation=force_decimation)
        if force_decimation is None:
          fft_rate_out=fft_rate*1000
        else:
          fft_rate_out=fft_rate*force_decimation
        sink=parallel_graph_sink_f( fg=fg, parent=parent, baseband_freq=0,
                 y_per_div=y_per_div, ref_level=ref_level,
                 sample_rate=sample_rate,block_size=fft_size,
                 display_rate=fft_rate_out, average=average, avg_alpha=avg_alpha, title=title,
                 size=size, peak_hold=peak_hold,
                 log_type=None,log_offset=0) #log_type='POST_AVG'
        self.win=sink.win
        fg.connect(corr,sink)
        gr.hier_block.__init__(self, fg, corr, sink)

class correlate_sink_c2_mag(gr.hier_block): #determine phase difference per frequency
    def __init__(self, fg, parent, baseband_freq=0,
                 y_per_div=1, ref_level=3.141592653589793236, sample_rate=1, fft_size=512,
                 fft_rate=5, average=False, avg_alpha=None,avg_alpha1=1e-5, title='',
                 size=fftsink.default_fftsink_size, peak_hold=False,force_decimation=None):

        corr=correlator_c(fg, sample_rate=sample_rate,fft_size=fft_size,output_type='COMPLEX',
                 fft_rate=fft_rate, pre_abs=False,subset_result=False,force_decimation=force_decimation,no_ifft=False)
        if force_decimation is None:
          fft_rate_out=fft_rate*1000
          force_decimation_out=1
        else:
          fft_rate_out=fft_rate*force_decimation
          force_decimation_out=None

        sink=parallel_graph_sink_avg_c(fg=fg, parent=parent, baseband_freq=0,
                 y_per_div=y_per_div, ref_level=ref_level,
                 sample_rate=sample_rate,block_size=fft_size,
                 display_rate=fft_rate_out, average=average, avg_alpha=avg_alpha, title=title,
                 size=size, peak_hold=peak_hold, output_type='REAL',
                 log_type=None,log_offset=0,force_decimation=force_decimation_out)

        self.win=sink.win
        fg.connect(corr,sink)
        gr.hier_block.__init__(self, fg, corr, sink)

class simple_phase_diff_sink_c(gr.hier_block): #determine phase difference 
    def __init__(self, fg, parent, baseband_freq=0,
                 y_per_div=1, ref_level=3.141592653589793236, sample_rate=1, fft_size=512,
                 fft_rate=15, average=False, avg_alpha=None, title='',
                 size=fftsink.default_fftsink_size, peak_hold=False):
        di = gr.deinterleave(gr.sizeof_gr_complex)
        mult=gr.multiply_cc()
        conj=gr.conjugate_cc()
        dummy=gr.add_const_cc(0) #we really need a dummy block which just copies input to output
                                 # but has the same delay as other process_one_sample_at_a_time blocks
        s2p=gr.serial_to_parallel(gr.sizeof_gr_complex,fft_size)
        c2arg=gr.complex_to_arg(fft_size)
        sink=parallel_graph_sink_f( fg=fg, parent=parent, baseband_freq=0,
                 y_per_div=y_per_div, ref_level=ref_level,
                 sample_rate=sample_rate,block_size=fft_size,
                 display_rate=fft_rate, average=average, avg_alpha=avg_alpha, title=title,
                 size=size, peak_hold=peak_hold,
                 log_type=None,log_offset=0) #log_type='POST_AVG'
        self.win=sink.win
        fg.connect((di,0),dummy,(mult,0))
        fg.connect((di,1),conj,(mult,1))
        fg.connect(mult,s2p,c2arg,sink)
        gr.hier_block.__init__(self, fg, di, sink)

class simple_diff_sink_c(gr.hier_block): #determine difference 
    def __init__(self, fg, parent, baseband_freq=0,
                 y_per_div=0.10, ref_level=0.50, sample_rate=1, fft_size=512,
                 fft_rate=15, average=False, avg_alpha=None, title='',
                 size=fftsink.default_fftsink_size, peak_hold=False):
        di = gr.deinterleave(gr.sizeof_gr_complex)
        sub=gr.sub_cc()
        s2p=gr.serial_to_parallel(gr.sizeof_gr_complex,fft_size)
        c2arg=gr.complex_to_arg(fft_size)
        c2f=gr.complex_to_real(fft_size)
        sink=parallel_graph_sink_f( fg=fg, parent=parent, baseband_freq=0,
                 y_per_div=y_per_div, ref_level=ref_level,
                 sample_rate=sample_rate,block_size=fft_size,
                 display_rate=fft_rate, average=average, avg_alpha=avg_alpha, title=title,
                 size=size, peak_hold=peak_hold,
                 log_type=None,log_offset=0) #log_type='POST_AVG'
        self.win=sink.win
        fg.connect((di,0),(sub,0))
        fg.connect((di,1),(sub,1))
        fg.connect(sub,s2p,c2f,sink)
        gr.hier_block.__init__(self, fg, di, sink)


class phase_align_sink_c(gr.hier_block): #phase align two streams ans show the (fft of the) difference
    def __init__(self, fg, parent, baseband_freq=0,
                 y_per_div=0.2, ref_level=1.2, sample_rate=1, fft_size=512,
                 fft_rate=15, average=False, avg_alpha=None, title='',
                 size=fftsink.default_fftsink_size, peak_hold=False,N=1):
        sink=parallel_graph_sink_f( fg=fg, parent=parent, baseband_freq=0,
                 y_per_div=y_per_div, ref_level=ref_level,
                 sample_rate=sample_rate,block_size=fft_size,
                 display_rate=fft_rate, average=average, avg_alpha=avg_alpha, title=title,
                 size=size, peak_hold=peak_hold,
                 log_type=None,log_offset=0) #log_type='POST_AVG'
        self.win=sink.win
        di = gr.deinterleave(gr.sizeof_gr_complex)
        nullsink = gr.null_sink(gr.sizeof_gr_complex)
        s2p=gr.serial_to_parallel(gr.sizeof_gr_complex,fft_size)
        #dec=gr.keep_one_in_n(gr.size_of_complex,N)
        c2f=gr.complex_to_mag(fft_size)
        al0,al1,phase=self.build_phase_align( fg, input0=(di,0), input1=(di,1),phase_avg_alpha=1e-5) #1e-5
        self.delay_value=0
        agc_alpha=1e-3
        agc0=gr.agc_cc(agc_alpha,1.0,1.0) #1e-3 #rate,reference,gain
        agc1=gr.agc_cc(agc_alpha,1.0,1.0) 
        agc20=gr.agc_cc(agc_alpha,1.0,1.0) 
        agc21=gr.agc_cc(agc_alpha,1.0,1.0) 
        sub=gr.sub_cc()
        add=gr.add_cc()
        fg.connect(al0,agc0,(sub,0))
        fg.connect(al1,agc1,(sub,1))
        fg.connect(sub,agc20)
        fg.connect(agc0,(add,0))
        fg.connect(agc1,(add,1))
        fg.connect(add,agc21)
        txcorr=self.build_time_shift_correlate_adv(fg, agc21,agc20,corr_avg_alpha=1e-6)
        fg.connect(txcorr,s2p,c2f,sink)
        gr.hier_block.__init__(self, fg, di, s2p)


    def build_phase_align(self, fg, input0, input1,phase_avg_alpha=1e-5):
        #di = gr.deinterleave(gr.sizeof_gr_complex)
        mult=gr.multiply_cc()
        conj=gr.conjugate_cc()
        dummy0=gr.add_const_cc(0) #we really need a dummy block which just copies input to output
                                 # but has the same delay as other process_one_sample_at_a_time blocks
        dummy1=gr.add_const_cc(0) #we really need a dummy block which just copies input to output
                                 # but has the same delay as other process_one_sample_at_a_time blocks
        c2arg=gr.complex_to_arg() #fft_size)
        mag=gr.complex_to_mag()
        div=gr.divide_cc() #output of this contains only phase information, magnitude is eliminated (mag==1.0)
        mult2=gr.multiply_cc()
        conj2=gr.conjugate_cc()
        dummy20=gr.add_const_cc(0)
        float_to_complex=gr.float_to_complex()
        dummy30=gr.add_const_cc(0)
        phase_average=gr.single_pole_iir_filter_cc(phase_avg_alpha)
        phase_average_f=gr.single_pole_iir_filter_ff(phase_avg_alpha)
        interleaver= gr.interleave(gr.sizeof_gr_complex)
        fg.connect(input0,dummy0,(mult,0))
        fg.connect(input1,conj,(mult,1))
        if 0:
          #fg.connect(mult,c2arg,phase_average)
          #fg.connect(mult,mag)
          fg.connect(mult,dummy2a,dummy2b,(div,0))
          fg.connect(mult,mag,float_to_complex,(div,1))
          #fg.connect(dummy,dummy2b)
          fg.connect(div,phase_average,(mult2,0))
        elif 1:
          #fg.connect(input1,dummy1)
          agc=gr.agc_cc(1e-4,1.0,1.0) #1e-3 #rate,reference,gain
          mult3=gr.multiply_const_cc(complex(1.0,0.0))
          fg.connect(mult,phase_average,(mult2,0)) #phase_average,
        else:
          phasemod=gr.phase_modulator_fc(1.0)
          fg.connect(mult,c2arg,phasemod,phase_average,(mult2,0))
        fg.connect(input1,(mult2,1))
        #fg.connect(dummy,(interleaver,0))
        #fg.connect(mult2,(interleaver,1))
        return dummy0,mult2,mult
        #gr.hier_block.__init__(self, fg, di, interleaver)

    def build_time_shift_correlate(self, fg, input0, input1,corr_avg_alpha=0.01):
        delay_taps=[]
        for x in range(0,7):
          delay_taps.append(0.0)
        #(0.0,0.0,0.0,0.0,0.0,0.0,0.0)
        initial_delay_value=0
        delay_taps[initial_delay_value+3]=1.0
        self.delay0=gr.fir_filter_ccf(1,delay_taps)
        delay_taps[initial_delay_value+3]=0.0
        delay_taps[-3+3]=1.0
	self.delay1=gr.fir_filter_ccf(1,delay_taps)
        dummy=gr.add_const_cc(0)
        conj=gr.conjugate_cc()
        mult=gr.multiply_cc()
        avg=gr.single_pole_iir_filter_cc(corr_avg_alpha)
        fg.connect(input0,self.delay0,dummy,(mult,0))
        fg.connect(input1,self.delay1,conj,(mult,1))
        fg.connect(mult,avg)
        return avg

    def build_time_shift_correlate_adv(self, fg, input0, sub1,corr_avg_alpha=0.01):
        delay_taps=[]
        for x in range(0,7):
          delay_taps.append(0.0)
        #(0.0,0.0,0.0,0.0,0.0,0.0,0.0)
        initial_delay_value=0
        delay_taps[initial_delay_value+3]=1.0
        self.delay0=gr.fir_filter_ccf(1,delay_taps)
        self.delay3=gr.fir_filter_ccf(1,delay_taps)
        delay_taps[initial_delay_value+3]=0.0
        delay_taps[0+3]=1.0
	self.delay1=gr.fir_filter_ccf(1,delay_taps)
        dummy=gr.add_const_cc(0)
        conj=gr.conjugate_cc()
        mult=gr.multiply_cc()
        sub=gr.sub_cc()
        avg=gr.single_pole_iir_filter_cc(corr_avg_alpha)
        fg.connect(input0,self.delay0,(sub,0))
        fg.connect(input0,self.delay1,(sub,1))
        fg.connect(sub,(mult,0))
        fg.connect(sub1,self.delay3,conj,(mult,1))
        fg.connect(mult,avg)
        return avg

class correlate_alt_sink_c(gr.hier_block): #correlate two streams for one particulat delay value
    def __init__(self, fg, parent, baseband_freq=0,
                 y_per_div=0.2, ref_level=1.2, sample_rate=1, fft_size=512,
                 fft_rate=15, average=False, avg_alpha=None, title='',
                 size=fftsink.default_fftsink_size, peak_hold=False,max_delay=10,N=1):
        sink=parallel_graph_sink_f( fg=fg, parent=parent, baseband_freq=0,
                 y_per_div=y_per_div, ref_level=ref_level,
                 sample_rate=sample_rate,block_size=fft_size,
                 display_rate=fft_rate, average=average, avg_alpha=avg_alpha, title=title,
                 size=size, peak_hold=peak_hold,
                 log_type=None,log_offset=0) #log_type='POST_AVG'
        self.win=sink.win
        di = gr.deinterleave(gr.sizeof_gr_complex)
        s2p=gr.serial_to_parallel(gr.sizeof_gr_complex,fft_size)
        c2f=gr.complex_to_mag(fft_size)
        agc_alpha=1e-3
        agc0=gr.agc_cc(agc_alpha,1.0,1.0) #1e-3 #rate,reference,gain
        agc1=gr.agc_cc(agc_alpha,1.0,1.0) 
        fg.connect((di,0),agc0)
        fg.connect((di,1),agc1)
        self.delay_taps=[]
        tscorr=self.build_time_shift_correlate(fg, agc0,agc1,corr_avg_alpha=1e-6,maxdelay=max_delay)
        fg.connect(tscorr,s2p,c2f,sink)
        gr.hier_block.__init__(self, fg, di, s2p)

    def build_time_shift_correlate(self, fg, input0, input1,maxdelay=10,corr_avg_alpha=0.01,initial_delay=0):
        for x in range(-maxdelay,maxdelay):
          self.delay_taps.append(0.0)
        #(0.0,0.0,0.0,0.0,0.0,0.0,0.0)
        self.delay_taps[int(len(self.delay_taps)/2)]=1.0
        self.delay0=gr.fir_filter_ccf(1,self.delay_taps)
        self.delay_taps[int(len(self.delay_taps)/2)]=0.0
        self.delay_taps[initial_delay+int(len(self.delay_taps)/2)]=1.0
	self.delay1=gr.fir_filter_ccf(1,self.delay_taps)
        dummy=gr.add_const_cc(0)
        conj=gr.conjugate_cc()
        mult=gr.multiply_cc()
        avg=gr.single_pole_iir_filter_cc(corr_avg_alpha)
        fg.connect(input0,self.delay0,dummy,(mult,0))
        fg.connect(input1,self.delay1,conj,(mult,1))
        fg.connect(mult,avg)
        return avg

    def set_delay(self,delay):
        print 'delay',delay
        print 'A',self.delay_taps
        for x in range(0,len(self.delay_taps)):
          self.delay_taps[x]=0.0
        print 'B',self.delay_taps
        self.delay_taps[int(delay)+int(len(self.delay_taps)/2)]=1.0
        print 'C',self.delay_taps
        self.delay1.set_taps(self.delay_taps)

class correlate_sink_c3(gr.hier_block):
    def __init__(self, fg, parent, baseband_freq=0,
                 y_per_div=10, ref_level=50, sample_rate=1, fft_size=512,
                 fft_rate=15, average=False, avg_alpha=None, title='',
                 size=fftsink.default_fftsink_size, peak_hold=False):

        corr0=correlator_c(fg, sample_rate=sample_rate,fft_size=fft_size,output_type='ARG',
                 fft_rate=fft_rate, pre_abs=False,subset_result=False)
        corr1=correlator_c(fg, sample_rate=sample_rate,fft_size=fft_size,output_type='ARG',
                 fft_rate=fft_rate, pre_abs=False,subset_result=False)
        log_offset= -20*math.log10(fft_size)-10*math.log10(corr0.power/fft_size)
        
        sink=parallel_graph_sink_f( fg=fg, parent=parent, baseband_freq=0,
                 y_per_div=y_per_div, ref_level=ref_level,
                 sample_rate=sample_rate,block_size=fft_size,
                 display_rate=fft_rate, average=average, avg_alpha=avg_alpha, title=title,
                 size=size, peak_hold=peak_hold,
                 log_type=None,log_offset=log_offset)
        self.win=sink.win
        fft_size_result=fft_size
        di = gr.deinterleave(gr.sizeof_gr_complex)
        interleaver0= gr.interleave(gr.sizeof_gr_complex)
        fg.connect((di,0),(interleaver0,0))
        fg.connect((di,0),(interleaver0,1))
        interleaver1= gr.interleave(gr.sizeof_gr_complex)
        fg.connect((di,1),(interleaver1,0))
        fg.connect((di,1),(interleaver1,1))
        fg.connect(interleaver0,corr0)
        fg.connect(interleaver1,corr1)
        postdiff=gr.sub_cc()
        postp2s0=gr.parallel_to_serial(gr.sizeof_gr_complex,fft_size_result)
        postp2s1=gr.parallel_to_serial(gr.sizeof_gr_complex,fft_size_result)
        posts2p=gr.serial_to_parallel(gr.sizeof_gr_complex,fft_size_result)
        fg.connect(corr0,postp2s0,(postdiff,0))
        fg.connect(corr1,postp2s1,(postdiff,1))
        c2mag = gr.complex_to_mag(fft_size_result)
        #c2mag = gr.complex_to_real(fft_size_result)
        fg.connect(postdiff,posts2p,c2mag,sink)
        gr.hier_block.__init__(self, fg, di, sink)


class siggen_wfm_source_c(gr.hier_block):
    def __init__(self, fg, sample_rate=64e6,
                 rf_carrier_freq=107.9e6, rf_amp=1.0,
                 audio_tone_freq=1.0e3, audio_tone_amp=0.5, 
                 audio_noise_amp=1.0e-6, if_noise_amp=1.0e-6, rf_noise_amp=1.0e-6): 
        rf_rate = sample_rate #float(int(sample_rate))                   # 64 MS/s
        rf_interp = max(1,int(rf_rate/3200e3)) #20
        print 'rf_interp',rf_interp
        if_rate = rf_rate /rf_interp          # 3200 kS/s
        if_chanfilt_interp = max(1,int(if_rate/320e3)) #10
        mod_rate =if_rate / if_chanfilt_interp # 320 kS/s
        audio_interp = max(1,int(mod_rate/40e3)) # 10
        audio_rate = mod_rate / audio_interp    # 32 kHz


        #audio_rate=32e3
        #audio_interp=max(10,min(1,int(rf_rate/audio_rate)))
        #if_chanfilt_interp=max(10,min(1,int(rf_rate/audio_rate)))
        print 'ar',audio_rate,'mr',mod_rate,'ir',if_rate,'rr',rf_rate
        if audio_tone_amp>1.0: 
           print 'error, audio_tone_amp must be < 1.0, it is ',audio_tone_amp
        audio_tone_src=gr.sig_source_f(audio_rate, gr.GR_SIN_WAVE, audio_tone_freq,audio_tone_amp,0.0 ) #amp must be <=1.0
        audio_noise_src=gr.noise_source_f  	(gr.GR_GAUSSIAN,audio_noise_amp,12345678	)
        #noise types: GR_UNIFORM, GR_GAUSSIAN, GR_LAPLACIAN, GR_IMPULSE
        audio_add=gr.add_ff() 

        fm_modulator=blks.wfm_tx(fg, audio_rate, mod_rate)
        if_chan_filt_coeffs = optfir.low_pass (1,           # gain
                                            if_rate,   # sampling rate
                                            80e3,        # passband cutoff
                                            115e3,       # stopband cutoff
                                            0.1,         # passband ripple
                                            60)          # stopband attenuation
        print 'siggen_fm_source_c::len(if_chan_filt_coeffs)', len(if_chan_filt_coeffs)
        if_chan_filt = gr.interp_fir_filter_ccf(if_chanfilt_interp, if_chan_filt_coeffs)
        if_noise_src=gr.noise_source_c(gr.GR_GAUSSIAN,if_noise_amp,87654321	)
        if_add=gr.add_cc() 
        rf_chan_filt_coeffs = optfir.low_pass (1,           # gain
                                            rf_rate,   # sampling rate
                                            if_rate/4, #0.8 Mhz       # passband cutoff
                                            if_rate/2, #1.6 Mhz      # stopband cutoff
                                            0.1,         # passband ripple
                                            60)          # stopband attenuation  
        print 'siggen_fm_source_c::len(rf_chan_filt_coeffs)', len(rf_chan_filt_coeffs)      
        rf_interp=gr.interp_fir_filter_ccf(rf_interp, rf_chan_filt_coeffs)
        rf_mult=gr.multiply_cc()
        rf_carrier=gr.sig_source_c(rf_rate, gr.GR_SIN_WAVE, rf_carrier_freq,rf_amp,0.0 ) 
        rf_noise_src=gr.noise_source_c(gr.GR_GAUSSIAN,rf_noise_amp,31415926	)
        rf_add=gr.add_cc() 
        if audio_noise_amp!=0:
          fg.connect(audio_tone_src,(audio_add,0))
          fg.connect(audio_noise_src,(audio_add,1))
          audio=audio_add
        else:
          audio=audio_tone_src
        fg.connect(audio,fm_modulator,if_chan_filt)
        if if_noise_amp!=0:
          fg.connect(if_chan_filt,(if_add,0))
          fg.connect(if_noise_src,(if_add,1))
          if_block=if_add
        else:
          if_block=if_chan_filt
        fg.connect(if_block,rf_interp,(rf_mult,0))
        fg.connect(rf_carrier,(rf_mult,1))
        if rf_noise_amp!=0:
          fg.connect(rf_mult,(rf_add,0))
          fg.connect(rf_noise_src,(rf_add,1))
          rf=rf_add
          print 'RF noise'
        else:
          rf=rf_mult
        gr.hier_block.__init__(self, fg, None, rf)

class fake_usrp_source_c(gr.hier_block):
    def __init__(self,fg, which=0, decim_rate=64, nchan=1, mux=0x32103210, mode=0,target_freq=0,do_filter=True,do_avg=False):
        self.adc_rate=long(64e6)
        factor=100 #200,100,40,20,10,1
        self.sample_rate=self.adc_rate/factor
        self.decim_rate= decim_rate/(factor) #int(max(1,int(decim_rate/(self.adc_rate/self.sample_rate))))
        print 'sr',self.adc_rate,self.sample_rate,self.decim_rate
        self.nchan=nchan
        self.mux=mux
        self.target_freq=target_freq
        self.do_filter=do_filter
        self.do_avg=do_avg
        #self.fm_src=siggen_wfm_source_c(fg=fg,sample_rate=self.adc_rate)
        self.fm_src=siggen_wfm_source_c(fg=fg,sample_rate=self.sample_rate,
                 rf_carrier_freq=target_freq,audio_noise_amp=0.1, if_noise_amp=0, rf_noise_amp=0.1) #0.25)
        self.fg=fg
        self.tune(None,None,target_freq)

    def tune(self, chan, subdev, target_freq):
        self.target_freq=target_freq
        self.connect_blocks()

    def connect_blocks(self):
        if self.do_filter:
          self.rf_chan_filt_coeffs = optfir.low_pass (1,           # gain
                                            self.sample_rate,   # sampling rate
                                            self.sample_rate/(self.decim_rate*2),        # passband cutoff
                                            self.sample_rate/(self.decim_rate),       # stopband cutoff
                                            0.1,         # passband ripple
                                            60)          # stopband attenuation
          self.dec=gr.freq_xlating_fir_filter_ccf (self.decim_rate, self.rf_chan_filt_coeffs , self.target_freq, self.sample_rate)
        else:
          if self.do_avg:
            avg.coeffs=[]
            for tap in range (1,decimation):
              avg.coeffs.append(1.0)
            self.dec=gr.fir_filter_ccf(self.decim_rate,avg_coeffs,self.sample_rate)
          else:
            self.dec=gr.keep_one_in_n(gr.sizeof_gr_complex,self.decim_rate)
        self.fg.connect(self.fm_src,self.dec)
        gr.hier_block.__init__(self, self.fg, None, self.dec)

class wfm_rx_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-directional", type="subdev", default=(0,0),
                          help="select USRP Rx side A or B (default=A)")
        parser.add_option("-S", "--rx-subdev-spec-omni", type="subdev", default=(1,0),
                          help="select USRP Rx side A or B (default=B)")
        parser.add_option("-f", "--freq", type="eng_float", default=None, #100.1e6,
                          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("-V", "--volume", type="eng_float", default=None,
                          help="set volume (default is midpoint)")
        parser.add_option("-O", "--audio-output", type="string", default="",
                          help="pcm device name.  E.g., hw:0,0 or surround51 or /dev/dsp")

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

        # build graph
        usrp_decim = 200        
        self.u = usrp.source_c(0,usrp_decim,2)                    # usrp is data source
        adc_rate = self.u.adc_rate()                # 64 MS/s
        self.u.set_decim_rate(usrp_decim)
        usrp_rate = adc_rate / usrp_decim           # 320 kS/s

        from_file=False
        to_file=False
        file_time=100e-3
        filename="fake_usrp_wfm_100msec_1.dat"
        do_fake_u=False
        do_simple_fake_u=True
        if 0: #do_simple_fake_u:
          self.fake_u=siggen_wfm_source_c(self, sample_rate=usrp_rate,
                 rf_carrier_freq=0, rf_amp=1.0, #1.0
                 audio_tone_freq=1.0e3, audio_tone_amp=0.0, # 0.5
                 audio_noise_amp=0, if_noise_amp=0, rf_noise_amp=0) #audio_noise_amp=1.0e-6, if_noise_amp=1.0e-6, rf_noise_amp=0
        if do_simple_fake_u:
          self.fake_u=audio_noise_src=gr.noise_source_c(gr.GR_GAUSSIAN,1.0,12345678	)
        if do_fake_u:
          if from_file:
            self.fake_u=gr.file_source(gr.sizeof_gr_complex,filename,True)
          else:
            self.fake_u=fake_usrp_source_c(self,0, usrp_decim, 1, 0x32103210, 0,options.freq,do_filter=False,do_avg=False)
        nullsink_fake=gr.null_sink(gr.sizeof_gr_complex)


        if to_file:
          saver=gr.file_sink(gr.sizeof_gr_complex,filename)
          sh=gr.skiphead(gr.sizeof_gr_complex,1024)
          hd=gr.head(gr.sizeof_gr_complex,int(float(usrp_rate)*float(file_time))) # save ten seconds
          #self.connect(self.fake_u,nullsink_fake)
          self.connect(self.fake_u,sh,hd,saver) #nullsink_fake) #keep it happy when not used
        chanfilt_decim = 1
        demod_rate = usrp_rate / chanfilt_decim
        audio_decimation = 10
        audio_rate = demod_rate / audio_decimation  # 32 kHz
        print 'audio_rate',audio_rate

        if options.rx_subdev_spec_directional is None:
            options.rx_subdev_spec_directional = pick_subdevice(self.u)

        mux_d=usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec_directional)
        print "mux_d",mux_d
        mux_o=usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec_omni)<<8
        print "mux_o",mux_o
        mux=mux_d | mux_o
        self.u.set_mux(mux)
        self.subdev_d = usrp.selected_subdev(self.u, options.rx_subdev_spec_directional)
        print "Using directional RX d'board %s" % (self.subdev_d.side_and_name(),)
        self.subdev_o = usrp.selected_subdev(self.u, options.rx_subdev_spec_omni)
        print "Using omni RX d'board %s" % (self.subdev_o.side_and_name(),)

        self.skiphead=gr.skiphead(gr.sizeof_gr_complex,1024)#2*512*8) #size_t sizeof_stream_item, int nitems
        # deinterleave two channels from FPGA
        self.di = gr.deinterleave(gr.sizeof_gr_complex)
        self.agc_d=gr.agc_cc(1e-4,1.0,1.0) #defaults (float rate = 1e-4, float reference = 1.0, float gain = 1.0)
        self.agc_o=gr.agc_cc(1e-4,1.0,1.0)
        pshift=2.0*3.1415926535384626*45.0/360.0
        self.phase_shifter=gr.multiply_const_cc(complex(cos(0),sin(0)))
        self.phase_shifter2=gr.multiply_const_cc(complex(cos(pshift),sin(pshift)))
        self.phase_shiftery1=gr.multiply_const_cc(complex(cos(pshift),sin(pshift)))
        self.phase_shiftery2=gr.multiply_const_cc(complex(cos(-pshift),sin(-pshift)))
        delay_taps=[]
        for x in range(0,7):
          delay_taps.append(0.0)
        #(0.0,0.0,0.0,0.0,0.0,0.0,0.0)
        self.delay_value=0
        delay_taps[self.delay_value+3]=1.0
        self.delay_d=gr.fir_filter_ccf  	(1,delay_taps)
	self.delay_o=gr.fir_filter_ccf  	(1,delay_taps)
        self.diff=gr.sub_cc()
        #chan_filt_coeffs = optfir.low_pass (1,           # gain
        #                                    usrp_rate,   # sampling rate
        #                                    80e3,        # passband cutoff
        #                                    115e3,       # stopband cutoff
        #                                    0.1,         # passband ripple
        #                                    60)          # stopband attenuation
        chan_filt_coeffs = optfir.low_pass (1,           # gain
                                            usrp_rate,   # sampling rate
                                            80e3,        # passband cutoff
                                            115e3,       # stopband cutoff
                                            0.1,         # passband ripple
                                            60)          # stopband attenuation
        #print len(chan_filt_coeffs)
        self.chan_filt_d = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
        self.chan_filt_o = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs)
        self.guts = blks.wfm_rcv (self, demod_rate, audio_decimation)

        self.volume_control = gr.multiply_const_ff(self.vol)

        # sound card as final sink
        audio_sink = audio.sink (int (audio_rate), options.audio_output)

        
        # now wire it all together
        if (not do_simple_fake_u) and (not do_fake_u):
          self.connect (self.u, self.skiphead,self.di)
          self.connect((self.di,0), self.chan_filt_d, self.guts, self.volume_control, audio_sink)
        else:
          self.connect(self.fake_u, self.chan_filt_d, self.guts, self.volume_control, audio_sink)

        #self.connect((self.di,0), self.phase_shifter,self.delay_d,self.agc_d, self.chan_filt_d, self.guts, self.volume_control, audio_sink)
        #nullsink_di1=gr.null_sink(gr.sizeof_gr_complex)
        #self.connect((self.di,1), self.phase_shifter2,self.delay_o,self.agc_o, self.chan_filt_o,nullsink_di1)
        #self.connect((self.di,0), self.agc_d) #, self.chan_filt_d)#, self.guts, self.volume_control, audio_sink)
        #nullx=gr.null_sink(gr.sizeof_gr_complex)
        #self.connect(self.agc_d,nullx)
        #self.connect((self.di,0), self.chan_filt_d, self.guts, self.volume_control, audio_sink)
        nullsink_di1=gr.null_sink(gr.sizeof_gr_complex)
        #self.connect((self.di,1), self.agc_o, self.chan_filt_o,nullsink_di1)

        #self.connect((self.di,1),nullsink_di1)
        self._build_gui(vbox, usrp_rate, demod_rate, audio_rate, options.freq)

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

        if options.volume is None:
            g = self.volume_range()
            options.volume = float(g[0]+g[1])/2

        if options.freq is None:
            options.freq=940.4 #gsm900 channel 27 downlink (vodafone)

        if abs(options.freq) < 1e6:
            options.freq *= 1e6            


        # set initial values

        self.set_gain(options.gain)
        self.set_vol(options.volume)
        if not(self.set_freq(options.freq)):
            self._set_status_msg("Failed to set initial frequency")


    def _set_status_msg(self, msg, which=0):
        self.frame.GetStatusBar().SetStatusText(msg, which)


    def _build_gui(self, vbox, usrp_rate, demod_rate, audio_rate,freq_center):

        def _form_set_freq(kv):
            return self.set_freq(kv['freq'])



        
        # control area form at bottom
        self.myform = myform = form.form()

        hbox = wx.BoxSizer(wx.HORIZONTAL)
        hbox.Add((5,0), 0)
        myform['freq'] = form.float_field(
            parent=self.panel, sizer=hbox, label="Freq", weight=1,
            callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg))

        hbox.Add((5,0), 0)
        freq_low_standard=939.2e6 #gsm900 channel 21 downlink            87.9e6
        freq_high_standard=948.0e6#gsm900 channel 65 downlink            108.1e6
#gsm frequencies The Netherlands
#ProRail                                        KPN Mobile                                      Vodafone
#20 Kanalen GSM-R                               62 kanalen GSM900 en 88 kanalen GSM1800 	57 Kanalen GSM900 en 26 Kanalen GSM1800
#Kanalen 	Uplink	 	Downlink 	Kanalen 	Uplink	 	Downlink 	Kanalen 	Uplink	 	Downlink
#n/a(20) 	876,2-880,0 	921,2-925,0 	1-20(20) 	890,2-894,0 	935,2-939,0 	21-65(45) 	894,2-903,0 	939,2-948,0
#                                               66-106(42) 	881,0-882,2 	926,0-925,2 	975-978(4) 	880,2-880,8 	925,2-925,8
#                                               108-119(12) 	911,6-913,8 	956,6-958,8 	537-549(13) 	1715,2-1717,6 	1810,2-1812,6
#                                               525 -536(12) 	1712,8-1715,0 	1807,2-1810,0 	512-524(13) 	1710,2-1805,2 	1805,2-1807,6
#                                               562-574(13) 	1720,2-1722,6 	1818,2-1817,2 	837-849(13) 	1775,2-1777,6 	1870,2-1872,6
#                                               587-611(25) 	1725,4-1730,0 	1820,4-1825,0 	637-649(13) 	1735,2-1830,6 	1830,2-1832,6
#                                               812-836(25) 	1770,2-1775,0 	1865,2-1870,0 			
#Telfort                                        Orange                                          T-Mobile
#25 Kanalen E-GSM en 87 Kanalen GSM1800 	25 Kanalen E-GSM en 75 Kanalen GSM1800          84 Kanalen GSM1800
#Kanalen 	Uplink	 	Downlink 	Kanalen 	Uplink	 	Downlink 	Kanalen 	Uplink	 	Downlink
#979-985(7) 	881,0-882,2 	926,0-925,2 	975-978(4) 	880,2-880,8 	925,2-925,8 	537-549(13) 	1715,2-1717,6 	1810,2-1812,6
#1007-1024(18) 	886,6-890,0 	931,6-935,0 	986-1006(21) 	882,4-886,4 	927,4-931,4 	575-586(12) 	1722,8-1725,0 	1817,8-1820,0
#550-561(12) 	1717,8-1720,0 	1812,8-1815,0 	662-736(75) 	1740,2-1755,0 	1835,2-1850,0 	612-636(25) 	1730,2-1735,0 	1825,2-1830,0
#737-811(75) 	1755,2-1770,0 	1850,2-1865,0                                                   650-661(12) 	1737,8-1740,0 	1832,8-1835,0
#                                                                                               850-871(22) 	1777,8-1782,0 	1872,8-1877,0
# alle frequenties in MHz
        freq_center_standard=(freq_low_standard+freq_high_standard)/2.0
        if freq_center is None:
          freq_center=freq_center_standard
        if abs(freq_center) < 1e6:
            freq_center *= 1e6   
        freq_low=freq_low_standard + freq_center - freq_center_standard
        freq_high=freq_high_standard + freq_center - freq_center_standard
        myform['freq_slider'] = \
            form.quantized_slider_field(parent=self.panel, sizer=hbox, weight=3,
                                        range=(freq_low, freq_high, 0.1e6),
                                        callback=self.set_freq)
        hbox.Add((5,0), 0)
        vbox.Add(hbox, 0, wx.EXPAND)

        hbox = wx.BoxSizer(wx.HORIZONTAL)
        hbox.Add((5,0), 0)

        myform['volume'] = \
            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Volume",
                                        weight=3, range=self.volume_range(),
                                        callback=self.set_vol)
        hbox.Add((5,0), 1)

        myform['gain'] = \
            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Gain",
                                        weight=3, range=self.subdev_d.gain_range(),
                                        callback=self.set_gain)
        hbox.Add((5,0), 2)
        myform['phase'] = \
            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Phase",
                                        weight=3, range=(-180, 180, 3),
                                        callback=self.set_phase)
        self.set_phase(45.0)
        self.max_delay=10
        hbox.Add((5,0), 3)
        myform['delay'] = \
            form.quantized_slider_field(parent=self.panel, sizer=hbox, label="Delay",
                                        weight=3, range=(-self.max_delay, self.max_delay, 1),
                                        callback=self.set_delay)
        hbox.Add((5,0), 0)
        vbox.Add(hbox, 0, wx.EXPAND)
        display_rate=5
        alpha=2.0/display_rate
        if 0:
            self.src_fft_diff = fftsink.fft_sink_c (self, self.panel, title="Data from USRP d",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate,avg_alpha=alpha)
            #self.connect (self.chan_filt_d, self.src_fft_diff)
            self.connect (self.agc_d, self.src_fft_diff)
            vbox.Add (self.src_fft_diff.win, 4, wx.EXPAND)
        if 0:
            self.src_fft_d = fftsink.fft_sink_c (self, self.panel, title="Data from fake_usrp",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate*1,avg_alpha=alpha)
            self.connect (self.fake_u, self.src_fft_d)
            vbox.Add (self.src_fft_d.win, 4, wx.EXPAND)
        if 0:
            self.src_fft_d = autocorrelate_sink_c (self, self.panel, title="autocorrelate d",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate,avg_alpha=alpha)
            self.connect (self.chan_filt_d, self.src_fft_d)
            vbox.Add (self.src_fft_d.win, 4, wx.EXPAND)

        self.connect(self.fake_u,self.agc_d) 
        #self.connect(self.fake_u, self.agc_o) 
        if 1:
            self.src_fft_d = correlate_sink_c2_mag(self, self.panel, title="auto correlate d mag ",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate,avg_alpha=1e-4,
                                     y_per_div=1*512, ref_level=3*512,  average=True, size=(640,240),force_decimation=1)
            self.interleaver=gr.interleave(gr.sizeof_gr_complex)
            self.connect(self.agc_d,(self.interleaver,0))
            self.connect(self.agc_d,(self.interleaver,1))
            self.connect (self.interleaver, self.src_fft_d)
            vbox.Add (self.src_fft_d.win, 4, wx.EXPAND)

        if 0:
            self.src_fft_diff = simple_phase_diff_sink_c (self, self.panel, title="Phase diff simple",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate,avg_alpha=alpha)
            self.connect (self.u, self.src_fft_diff)
            vbox.Add (self.src_fft_diff.win, 4, wx.EXPAND)

        if 0:
            self.src_fft_d = phase_align_sink_c(self, self.panel, title="phase align synthetic phase_diff d o",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate/5,avg_alpha=alpha/4)
            self.interleaverx=gr.interleave(gr.sizeof_gr_complex)
            #self.connect(self.skiphead,self.src_fft_d)
            dummy=gr.add_const_cc(0)
            #self.connect(self.agc_o, self.phase_shifter, (self.interleaverx,0)) 
            add=gr.add_cc()
            sub=gr.sub_cc()
            delayz_taps=[]
            for x in range(0,7):
              delayz_taps.append(0.0)
            #(0.0,0.0,0.0,0.0,0.0,0.0,0.0)
            initial_delay_value0=0
            initial_delay_value1=-2
            delayz_taps[initial_delay_value0+3]=1.0
            self.delayz0=gr.fir_filter_ccf(1,delayz_taps)
            delayz_taps[initial_delay_value0+3]=0.0
            delayz_taps[initial_delay_value1+3]=0.01
	    self.delayz1=gr.fir_filter_ccf(1,delayz_taps)
            self.connect(self.agc_d, self.delayz0, (add,0)) 
            self.connect(self.agc_d, self.delayz1, (add,1)) 
            self.connect( self.delayz0, (sub,0)) 
            self.connect(self.delayz1, (sub,1))
            #self.connect(self.agc_o, dummy, (self.interleaverx,1)) 
            self.connect(sub,(self.interleaverx,0))
            self.connect(add, (self.interleaverx,1))
            # #self.connect(self.chan_filt_d,(self.interleaver,0))
            # #self.connect(self.chan_filt_o,(self.interleaver,1))
            self.connect (self.interleaverx, self.src_fft_d)
            vbox.Add (self.src_fft_d.win, 4, wx.EXPAND)

        if 0:
            self.src_fft_d = phase_align_sink_c(self, self.panel, title="phase align phase_diff d o",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate/5,avg_alpha=alpha/4)
            self.interleaverx=gr.interleave(gr.sizeof_gr_complex)
            self.connect(self.agc_o,(self.interleaverx,0))
            self.connect(self.agc_d, (self.interleaverx,1))
            # #self.connect(self.chan_filt_d,(self.interleaver,0))
            # #self.connect(self.chan_filt_o,(self.interleaver,1))
            self.connect (self.interleaverx, self.src_fft_d)
            vbox.Add (self.src_fft_d.win, 4, wx.EXPAND)
            c2arg=gr.complex_to_arg(512)
            self.sink_arg=parallel_graph_sink_f( fg=self, parent=self.panel, baseband_freq=0,
                 y_per_div=3.1415926, ref_level=2*3.1415926,
                 sample_rate=usrp_rate,block_size=512,
                 display_rate=display_rate/5, average=True, avg_alpha=alpha/4, title='phase align d o arg',
                 size=(640,120), peak_hold=False,
                 log_type=None,log_offset=0) 
            self.connect (self.src_fft_d, c2arg ,self.sink_arg)
            vbox.Add (self.sink_arg.win, 4, wx.EXPAND)

        if 1:
            self.src_fft_d = correlate_alt_sink_c(self, self.panel, title="alt autocorrelate d d mag",
                                               fft_size=512, sample_rate=usrp_rate, fft_rate=display_rate/5, avg_alpha=alpha/4,
                                               max_delay=self.max_delay)
            self.interleaverx=gr.interleave(gr.sizeof_gr_complex)
            self.connect((self.di,0),(self.interleaverx,0))
            self.connect((self.di,1),(self.interleaverx,1))
            self.connect (self.interleaverx, self.src_fft_d)
            vbox.Add (self.src_fft_d.win, 4, wx.EXPAND)
            c2arg=gr.complex_to_arg(512)
            self.sink_arg=parallel_graph_sink_f( fg=self, parent=self.panel, baseband_freq=0,
                 y_per_div=3.1415926, ref_level=2*3.1415926,
                 sample_rate=usrp_rate,block_size=512,
                 display_rate=display_rate/5, average=True, avg_alpha=alpha/4, title='alt autocorrelate d d arg',
                 size=(640,120), peak_hold=False,
                 log_type=None,log_offset=0) 
            self.connect (self.src_fft_d, c2arg ,self.sink_arg)
            vbox.Add (self.sink_arg.win, 4, wx.EXPAND)



        if 0:
            self.src_fft_diff = simple_diff_sink_c (self, self.panel, title="Phase diff simple",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate/5,avg_alpha=alpha)
            self.connect (self.interleaverx, self.src_fft_diff)
            vbox.Add (self.src_fft_diff.win, 4, wx.EXPAND)

        if 0:
            self.src_fft_diff = simple_diff_sink_c (self, self.panel, title="Phase diff simple test",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate/5,avg_alpha=alpha,
                                                y_per_div=0.001, ref_level=0.005,)
            shift=2.0*3.1415926535384626*45.0/360.0
            interleavery=gr.interleave(gr.sizeof_gr_complex)
            dummy1=gr.add_const_cc(0)
            dummy2=gr.add_const_cc(0)
            self.connect(self.agc_o, self.phase_shiftery1,self.phase_shiftery2, (interleavery,0)) 
            self.connect(self.agc_o, dummy1,dummy2,(interleavery,1)) 
            
            self.connect (interleavery, self.src_fft_diff)
            vbox.Add (self.src_fft_diff.win, 4, wx.EXPAND)

        if 0:
            self.src_fft_diff = simple_diff_sink_c (self, self.panel, title="Phase diff simple test2",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate/5,avg_alpha=alpha,
                                                y_per_div=0.001, ref_level=0.005,)
            interleavery=gr.interleave(gr.sizeof_gr_complex)
            dummy1=gr.add_const_cc(0)
            dummy2=gr.add_const_cc(0)
            dummy3=gr.add_const_cc(0)
            c2mag=gr.complex_to_mag()
            c2arg=gr.complex_to_arg()
            f2c=gr.float_to_complex()
            mult=gr.multiply_cc()
            phase_mod=gr.phase_modulator_fc(1.0)
            self.connect(self.agc_o, c2arg,phase_mod,(mult,0))
            self.connect(self.agc_o, c2mag,f2c,(mult,1))
            self.connect(mult, (interleavery,0)) 
            self.connect(self.agc_o, dummy1,dummy2,dummy3,(interleavery,1)) 
            
            self.connect (interleavery, self.src_fft_diff)
            vbox.Add (self.src_fft_diff.win, 4, wx.EXPAND)

        if 0:
            self.src_fft_d = correlate_sink_c2(self, self.panel, title="correlate d and o c2",
                                               fft_size=512*4, sample_rate=usrp_rate,fft_rate=display_rate/5,avg_alpha=alpha/4)
            self.interleaver=gr.interleave(gr.sizeof_gr_complex)
            #self.connect(self.u,self.src_fft_d)
            self.connect((self.di,0), self.phase_shifter, (self.interleaver,0)) 
            self.connect((self.di,1), self.phase_shifter2, (self.interleaver,1)) 
            #self.connect(self.chan_filt_d,(self.interleaver,0))
            #self.connect(self.chan_filt_o,(self.interleaver,1))
            self.connect (self.interleaver, self.src_fft_d)
            vbox.Add (self.src_fft_d.win, 4, wx.EXPAND)
        #self.connect ((self.di,0),self.agc_d)
        #self.connect ((self.di,1),self.agc_o)
        if 0:
            x=1.0
            self.src_fft_d = correlate_sink_c3 (self, self.panel, title="correlate d and o c3",
                                               fft_size=int(1024*x), sample_rate=usrp_rate,fft_rate=display_rate/x,avg_alpha=alpha/5)
            self.interleaver=gr.interleave(gr.sizeof_gr_complex)
            self.connect(self.chan_filt_d,(self.interleaver,0))
            self.connect(self.chan_filt_o,(self.interleaver,1))
            self.connect (self.interleaver, self.src_fft_d)
            vbox.Add (self.src_fft_d.win, 4, wx.EXPAND)
        if 0:
            self.src_fft_o = fftsink.fft_sink_c (self, self.panel, title="Data from USRP o",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate)
            self.connect ((self.di,1), self.src_fft_o)
            vbox.Add (self.src_fft_o.win, 4, wx.EXPAND)
        if 0:
            self.src_fft_diff = fftsink.fft_sink_c (self, self.panel, title="Data from USRP o",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate)
            self.connect ((self.di,1), self.src_fft_diff)
            vbox.Add (self.src_fft_diff.win, 4, wx.EXPAND)

        if 0:
            self.src_fft_diff = fftsink.fft_sink_c (self, self.panel, title="Data from USRP d with agc",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate,avg_alpha=alpha)
            self.connect ((self.di,0),self.agc_d,self.src_fft_diff)
            #self.connect ((self.di,1),self.agc_o,(self.diff,1))
            #self.connect (self.diff,self.src_fft_diff)
            vbox.Add (self.src_fft_diff.win, 4, wx.EXPAND)

        if 0:
            self.src_fft_diff = fftsink.fft_sink_c (self, self.panel, title="diff",
                                               fft_size=512, sample_rate=usrp_rate,fft_rate=display_rate,avg_alpha=alpha)
            self.connect (self.agc_d,(self.diff,0))
            self.connect (self.agc_o,(self.diff,1))
            self.connect (self.diff,self.src_fft_diff)
            vbox.Add (self.src_fft_diff.win, 4, wx.EXPAND)

        if 0:
            post_deemph_fft = fftsink.fft_sink_f (self, self.panel, title="Post Deemph",
                                                  fft_size=512, sample_rate=demod_rate,
                                                  y_per_div=10, ref_level=-40,fft_rate=display_rate)
            self.connect (self.guts.deemph, post_deemph_fft)
            vbox.Add (post_deemph_fft.win, 4, wx.EXPAND)

        if 0:
            post_filt_fft = fftsink.fft_sink_f (self, self.panel, title="Post Filter", 
                                                fft_size=512, sample_rate=audio_rate,
                                                y_per_div=10, ref_level=-40,fft_rate=display_rate)
            self.connect (self.guts.audio_filter, post_filt)
            vbox.Add (fft_win4, 4, wx.EXPAND)
        try:
            self.knob = powermate.powermate(self.frame)
            self.rot = 0
            powermate.EVT_POWERMATE_ROTATE (self.frame, self.on_rotate)
            powermate.EVT_POWERMATE_BUTTON (self.frame, self.on_button)
        except:
            print "FYI: No Powermate or Contour Knob found"


    def on_rotate (self, event):
        self.rot += event.delta
        if (self.state == "FREQ"):
            if self.rot >= 3:
                self.set_freq(self.freq + .1e6)
                self.rot -= 3
            elif self.rot <=-3:
                self.set_freq(self.freq - .1e6)
                self.rot += 3
        else:
            step = self.volume_range()[2]
            if self.rot >= 3:
                self.set_vol(self.vol + step)
                self.rot -= 3
            elif self.rot <=-3:
                self.set_vol(self.vol - step)
                self.rot += 3
            
    def on_button (self, event):
        if event.value == 0:        # button up
            return
        self.rot = 0
        if self.state == "FREQ":
            self.state = "VOL"
        else:
            self.state = "FREQ"
        self.update_status_bar ()
        

    def set_vol (self, vol):
        g = self.volume_range()
        self.vol = max(g[0], min(g[1], vol))
        self.volume_control.set_k(10**(self.vol/10))
        self.myform['volume'].set_value(self.vol)
        self.update_status_bar ()
                                        
    def set_freq(self, target_freq):
        """
        Set the center frequency we're interested in.

        @param target_freq: frequency in Hz
        @rypte: bool

        Tuning is a two step process.  First we ask the front-end to
        tune as close to the desired frequency as it can.  Then we use
        the result of that operation and our target_frequency to
        determine the value for the digital down converter.
        """
        r_d = usrp.tune(self.u, 0, self.subdev_d, target_freq)
        r_o = usrp.tune(self.u, 1, self.subdev_o, target_freq)
        
        if r_d:
            self.freq = target_freq
            self.myform['freq'].set_value(target_freq)         # update displayed value
            self.myform['freq_slider'].set_value(target_freq)  # update displayed value
            self.update_status_bar()
            self._set_status_msg("OK", 0)
            return True

        self._set_status_msg("Failed", 0)
        return False

    def set_gain(self, gain):
        self.myform['gain'].set_value(gain)     # update displayed value
        self.subdev_d.set_gain(gain)
        self.subdev_o.set_gain(gain)
        #print 'set gain'

    def set_phase(self, phase):
        self.myform['phase'].set_value(phase)     # update displayed value
        angle_in_radians=2.0*3.141592653538463*phase/360.0
        self.phase_shifter.set_k(complex(cos(angle_in_radians),sin(angle_in_radians)))
        self.phase_shiftery1.set_k(complex(cos(angle_in_radians),sin(angle_in_radians)))
        self.phase_shiftery2.set_k(complex(cos(-angle_in_radians),sin(-angle_in_radians)))
        self.update_status_bar ()

    def set_delay(self, delay):
        self.myform['delay'].set_value(delay)     # update displayed value
        delay_taps=[]
        for x in range(0,7):
          delay_taps.append(0.0)
        delay_taps[int(delay)+3]=1.0
        self.delay_value=delay
        self.delay_d.set_taps(delay_taps)
        self.src_fft_d.set_delay(delay)
        print 'Blaaaaaaaaaaaaaaaa'
        self.update_status_bar ()

    def update_status_bar (self):
        msg = "Volume:%r  Setting:%s agc_d.gain:%s delay %s" % (self.vol, self.state,self.agc_d.gain(),self.delay_value)
        self._set_status_msg(msg, 1)
        #self.src_fft_d.set_baseband_freq(self.freq)
        #self.src_fft_diff.set_baseband_freq(self.freq)
        #self.src_fft_o.set_baseband_freq(self.freq)

    def volume_range(self):
        return (-20.0, 0.0, 0.5)
        

if __name__ == '__main__':
    app = stdgui.stdapp (wfm_rx_graph, "USRP WFM RX")
    app.MainLoop ()
