#!/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_mod

from gnuradio.wxgui import stdgui, fftsink
import wx


class fsk_tx_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 ("-f", "--filename", type="string",
                           default="./payload.dat",
                           help="read data from FILENAME")
        parser.add_option ("-R", "--repeat", action="store_true", default=False)
        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 ("-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.sw_interp = 8
        self.usrp_interp = int (128e6 / self.sw_interp / data_rate)
        self.fs = 128e6 / self.usrp_interp

        max_deviation = data_rate / 4
        payload_size = options.payload             # bytes
    
        print "data_rate = ", data_rate
        print "sw_interp = ", self.sw_interp
        print "usrp_interp = ", self.usrp_interp
        print "fs = ", self.fs

        if (options.socket):
            # read from  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
            src = gr.file_descriptor_source (gr.sizeof_char, self.conn.fileno())

        else:
            src = gr.file_source (gr.sizeof_char, options.filename, options.repeat)

        framer = gr.simple_framer (payload_size)
        
        bytes_to_syms = gr.bytes_to_syms ()


        interp_taps =  gr.firdes.low_pass (self.sw_interp,      # gain
                                           self.fs,             # sampling rate
                                           data_rate / 2 * 1.2, # cutoff
                                           data_rate/2 * 0.4,   # trans width
                                           gr.firdes.WIN_HANN)

        print "len = ", len (interp_taps)

        interp = gr.interp_fir_filter_fff (self.sw_interp, interp_taps)

        if (options.gmsk):
            print ("GMSK modulation")
            # frame, samples-per-symbol, symbol-rate (syms/sec * sym rate),
            # filter bw /symbol time, packet-size
            fmmod = gmsk_mod (self,8,data_rate,0.3,payload_size)
            self.connect (src,fmmod)

        else:
            k = 2 * math.pi * max_deviation / self.fs
            fmmod = gr.frequency_modulator_fc (k)

            self.connect (src, framer)
            self.connect (framer, bytes_to_syms)
            self.connect (bytes_to_syms, interp)
            self.connect (interp, fmmod)

        gain = gr.multiply_const_cc (8000)

        if (options.pipe):
            # write to named pipe
            u = gr.file_sink (gr.sizeof_gr_complex, "/channel")
        else:
            u = usrp.sink_c (0, self.usrp_interp)
            u.set_tx_freq (0, options.cordic_freq)

        self.connect (fmmod, gain)
        self.connect (gain, u)

        if 0:
            post_interp, fft_win1 = fftsink.make_fft_sink_f (self, panel, "Post Interp", 512, self.fs)
            self.connect (interp, post_interp)
            vbox.Add (fft_win1, 1, wx.EXPAND)

        if 1 and not(options.no_gui):
            post_mod, fft_win2 = fftsink.make_fft_sink_c (self, panel, "Post Modulation", 512, self.fs)
            self.connect (fmmod, post_mod)
            vbox.Add (fft_win2, 1, wx.EXPAND)
            

def main ():
    app = stdgui.stdapp (fsk_tx_graph, "FSK Tx")
    app.MainLoop ()

if __name__ == '__main__':
    main ()
