#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
#         (C) 2019 by Piotr Krysik <ptrkrysik@gmail.com>
# @section LICENSE
#
# Gr-gsm 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 3, or (at your option)
# any later version.
#
# Gr-gsm 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 gr-gsm; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
#

from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser, OptionGroup
import osmosdr
import time
import grgsm
import signal
import sys

class grgsm_capture(gr.top_block):
    def __init__(self,
                 freq,
                 gain=30,
                 samp_rate=1e6,
                 rec_length=float('Inf'),
                 freq_corr=0,
                 output_filename=None,
                 bandwidth=0,
                 bb_gain=20,
                 if_gain=20,
                 antenna="",
                 device_args=""):
        gr.top_block.__init__(self, "Gr-gsm Capture")

        ##################################################
        # Setting up RF source
        ##################################################

        self.sdr_source = osmosdr.source(args="numchan=" + str(1) + " " +
                str(grgsm.device.get_default_args(device_args)))

        self.sdr_source.set_sample_rate(samp_rate)
        self.sdr_source.set_center_freq(freq, 0)
        self.sdr_source.set_freq_corr(freq_corr, 0)
        self.sdr_source.set_dc_offset_mode(2, 0)
        self.sdr_source.set_iq_balance_mode(2, 0)
        self.sdr_source.set_gain_mode(True, 0)
        self.sdr_source.set_gain(gain, 0)
        self.sdr_source.set_if_gain(if_gain, 0)
        self.sdr_source.set_bb_gain(bb_gain, 0)
        self.sdr_source.set_antenna("", 0)
        if bandwidth != 0:
            self.sdr_source.set_bandwidth(bandwidth, 0)

        ##################################################
        # The rest of processing blocks
        ##################################################

        if rec_length != float('Inf'):
            self.head = \
                    blocks.head(gr.sizeof_gr_complex, int(samp_rate*rec_length))

        self.file_sink = blocks.file_sink(gr.sizeof_gr_complex*1, \
                                          output_filename, False)
        self.file_sink.set_unbuffered(False)

        ##################################################
        # Connections
        ##################################################

        if rec_length != float('Inf'): #if recording length is not infinite
                                            #connect head block after the source
            self.connect((self.sdr_source, 0), (self.head, 0))
            self.connect((self.head, 0), (self.file_sink, 0))
        else:
            self.connect((self.sdr_source, 0), (self.file_sink, 0))

if __name__ == '__main__':

    parser = OptionParser(option_class=eng_option, usage="%prog [options] output_filename",
                          description="RTL-SDR capturing app of gr-gsm.")

    parser.add_option("-f", "--freq", dest="freq", type="eng_float",
                      help="Set frequency [default=%default]")

    parser.add_option("-a", "--arfcn", dest="arfcn", type="intx",
                      help="Set ARFCN instead of frequency (for PCS1900 add"
                           "0x8000 (2**15) to the ARFCN number)")

    parser.add_option("-g", "--gain", dest="gain", type="eng_float",
                      default=eng_notation.num_to_str(30),
                      help="Set gain [default=%default]")

    parser.add_option("-s", "--samp-rate", dest="samp_rate", type="eng_float",
                      default=eng_notation.num_to_str(1000000),
                      help="Set samp_rate [default=%default]")

    parser.add_option("-T", "--rec-length", dest="rec_length", type="float",
                      default='Inf', help="Set length of recording in seconds "
                      "[default=infinity]")

    parser.add_option("-p", "--freq-corr", dest="freq_corr", type="eng_float",
                      default="0", help="Set frequency correction in"
                      " ppm [default=%default]")

    osmogroup = OptionGroup(parser, 'Additional osmosdr source options',
                      "Options specific to a subset of SDR receivers "
                      "supported by osmosdr source.")

    osmogroup.add_option("-w", "--bandwidth", dest="bandwidth", type="eng_float",
                      default="0", help="Set bandwidth [default=samp_rate]")

    osmogroup.add_option("", "--bb-gain", dest="bb_gain", type="eng_float",
                      default=eng_notation.num_to_str(20),
                      help="Set baseband gain [default=%default]")

    osmogroup.add_option("", "--if-gain", dest="if_gain", type="eng_float",
                      default=eng_notation.num_to_str(20),
                      help="Set intermediate freque gain [default=%default]")

    osmogroup.add_option("", "--ant", dest="antenna", type="string",
                      default="", help="Set antenna "
                      "[default=%default]")

    osmogroup.add_option("", "--args", dest="device_args", type="string",
                      default="", help="Set device arguments "
                      "[default=%default]. Use --list-devices the view the available devices")

    osmogroup.add_option("-l", "--list-devices", action="store_true",
                      help="List available SDR devices, use --args to specify hints")

    parser.add_option_group(osmogroup)

    (options, args) = parser.parse_args()

    if options.list_devices:
        grgsm.device.print_devices(options.device_args)
        sys.exit(0)

    if not args:
        parser.error("Please provide an output file name to save the captured data\n")

    output_filename = args[0]

    if (options.freq is None and options.arfcn is None) or \
       (options.freq is not None and options.arfcn is not None):
        parser.error("You have to provide either a frequency or"
                     "an ARFCN (but not both).\n")

    arfcn = 0
    freq = 0
    if options.arfcn:
        if not grgsm.arfcn.is_valid_arfcn(options.arfcn):
            parser.error("ARFCN is not valid\n")
        else:
            freq = grgsm.arfcn.arfcn2downlink(options.arfcn)
    elif options.freq:
        freq = options.freq

    tb = grgsm_capture(freq=freq,
                       gain=options.gain,
                       freq_corr=options.freq_corr,
                       samp_rate=options.samp_rate,
                       output_filename=output_filename,
                       rec_length=options.rec_length,
                       bandwidth=options.bandwidth,
                       bb_gain=options.bb_gain,
                       if_gain=options.if_gain,
                       antenna=options.antenna,
                       device_args=options.device_args)

    def signal_handler(signal, frame):
        tb.stop()
        tb.wait()
        sys.exit(0)

    signal.signal(signal.SIGINT, signal_handler)

    tb.start()
    tb.wait()
