#!/usr/bin/env python

from gnuradio import gr, eng_notation
from gnuradio import usrp
from gnuradio import audio
from gnuradio.eng_option import eng_option
from optparse import OptionParser
import math
import socket
from gmsk import gmsk_demod

from gnuradio.wxgui import stdgui, fftsink
import wx


class fsk_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 ("-c", "--cordic-freq", type="eng_float", default=29.32e6,
                           help="set Tx cordic frequency to FREQ", metavar="FREQ")
        parser.add_option ("-p", "--payload", type="long", default=1024,
                           help="payload size (bytes)", metavar="xxx")
        parser.add_option ("-r", "--data-rate", type="eng_float", default=100e3)
        parser.add_option ("-f", "--filename", type="string",
                           default="rx.dat", help="write data to FILENAME")
        parser.add_option ("-N", "--no-gui", action="store_true", default=False)
        # socket
        parser.add_option ("-s", "--socket", type="long", default=0,
                           help="read from socket #")
        # use gmsk modulation
        parser.add_option ("-g", "--gmsk", action="store_true", default=True,
                           help="use gmsk mod")
        # use named pipe
        parser.add_option ("-P", "--pipe", action="store_true", default=False,
                           help="named pipe")

        (options, args) = parser.parse_args ()
        print "cordic_freq = %s" % (eng_notation.num_to_str (options.cordic_freq))

        # ----------------------------------------------------------------

        data_rate = options.data_rate
        self.samples_per_symbol = 8
        self.usrp_decim = int (64e6 / self.samples_per_symbol / data_rate)
        self.fs = data_rate * self.samples_per_symbol
        demod_gain = 1
        payload_size = options.payload             # bytes

        max_deviation = data_rate / 4

        if (options.pipe):
            # read from named pipe
            #first param is itemsize
            u = gr.file_source (gr.sizeof_gr_complex, "/channel")

        else:
            u = usrp.source_c (0, self.usrp_decim)
            u.set_rx_freq (0, -options.cordic_freq)         # FIXME sign
            
        filter_taps =  gr.firdes.low_pass (1,                   # gain
                                           self.fs,             # sampling rate
                                           data_rate / 2 * 1.1, # cutoff
                                           data_rate,           # trans width
                                           gr.firdes.WIN_HANN)

        print "len = ", len (filter_taps)

        filter = gr.fir_filter_ccf (1, filter_taps)

        if (options.socket):
            # write to fd (socket)
            fd = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
            fd.bind(('0.0.0.0',options.socket))
            fd.listen(1)
            (self.conn, self.connaddr) = fd.accept()
            print "Connection:", self.conn
            print "Address:", self.connaddr
            # sink to file descriptor
            filesink = gr.file_descriptor_sink (gr.sizeof_char, self.conn.fileno())
            print ("data to socket")

        else:
            filesink = gr.file_sink (gr.sizeof_char, options.filename)
            print ("data to file")

        
        if (options.gmsk):
            # frame, samples-per-symbol, symbol-rate (syms/sec * sym rate),
            # filter bw /symbol time, packet-size
            fmdemod = gmsk_demod (self, 8, data_rate, payload_size)
            print ("GMSK demod")
            self.connect (fmdemod,filesink)
            
        else:
            print ("FM demod")
            k = 2 * math.pi * max_deviation / self.fs
            fmdemod = gr.quadrature_demod_cf (demod_gain)
            corr = gr.simple_correlator (payload_size)
            self.connect (fmdemod,corr)
            self.connect (corr,filesink)

        self.connect (u, filter)
        self.connect (filter, fmdemod)


        if 1 and not(options.no_gui):
            fft_input, fft_win1 = fftsink.make_fft_sink_c (self, panel, "Input", 512, self.fs)
            self.connect (u, fft_input)
            vbox.Add (fft_win1, 1, wx.EXPAND)

        if 0:
            post_mod, fft_win2 = fftsink.make_fft_sink_c (self, panel, "Post Modulation", 512, self.fs)
            self.connect (sum, post_mod)
            vbox.Add (fft_win2, 1, wx.EXPAND)
            

def main ():
    app = stdgui.stdapp (fsk_rx_graph, "FSK Rx")
    app.MainLoop ()

if __name__ == '__main__':
    main ()
