#!/usr/bin/python2

# Copyright 2014 Jared Boone <jared@sharebrained.com>
#
# This file is part of gr-tpms.
#
# This program 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.
#
# This program 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 this program; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#

import math

from gnuradio import blocks
from gnuradio import digital
from gnuradio import gr

from gnuradio import filter
from gnuradio.filter import firdes

import tpms

from tpms.source import source_file
from tpms.ask import ask_channel_filter
from tpms.decode import clock_recovery, tag_print

class top_block(gr.top_block):
	def __init__(self, args):
		super(top_block, self).__init__(
			"top_block"
		)

		sample_rate = args.sample_rate
		offset = args.offset
		channel_bandwidth = args.channel_bandwidth
		symbol_rate = args.symbol_rate
		access_code = args.access_code

		nyquist = sample_rate / 2.0

		self.source = source_file(args.file)

		# Temporary work-around for poor structuring of TPMS library code
		# Moving the channel filter *before* conversion to magnitude.
		filter_attenuation_db = 40
		filter_cutoff = channel_bandwidth / 2.0
		filter_transition = filter_cutoff * 0.2
		if (filter_cutoff + filter_transition) > nyquist:
			raise RuntimeError('ASK channel filter exceeds Nyquist frequency')

		filter_taps = firdes.low_pass_2(1.0, sample_rate, filter_cutoff, filter_transition, filter_attenuation_db)
		print(len(filter_taps))
		#self.filter = filter.freq_xlating_fir_filter_ccf(1, (filter_taps), offset, sample_rate)
		#self.connect((self.source, 0), (self.filter, 0))
		self.rotator = blocks.rotator_cc(float(-offset) / sample_rate * 2.0 * math.pi)
		self.connect((self.source, 0), (self.rotator, 0))
		self.filter = filter.fft_filter_ccf(1, (filter_taps))
		self.connect((self.rotator, 0), (self.filter, 0))

		self.complex_to_mag = blocks.complex_to_mag(1)
		self.connect((self.filter, 0), (self.complex_to_mag, 0))

		self.envelope = tpms.ask_env(alpha=0.02)
		self.connect((self.complex_to_mag, 0), (self.envelope, 0))

		self.clock_recovery = clock_recovery(sample_rate, symbol_rate)
		self.connect((self.envelope, 0), (self.clock_recovery, 0))

		self.correlator = digital.correlate_access_code_tag_bb(access_code, 0, "preamble")
		self.connect((self.clock_recovery, 0), (self.correlator, 0))

		self.tag_print = tag_print(args.symbol_rate, args.length)
		self.connect((self.correlator, 0), (self.tag_print, 0))

def main():
	from argparse import ArgumentParser

	parser = ArgumentParser()
	parser.add_argument('-f', '--file', type=str, default=None, help="Input file path")
	parser.add_argument('-r', '--sample-rate', type=float, default=None, help="Sample rate")
	parser.add_argument('-o', '--offset', type=float, default=0, help="Carrier offset from 0 Hz")
	parser.add_argument('-c', '--channel-bandwidth', type=float, default=0, help="Channel filter bandwidth")
	parser.add_argument('-s', '--symbol-rate', type=float, default=None, help="Symbol rate")
	parser.add_argument('-a', '--access-code', type=str, default=None, help="Access code")
	parser.add_argument('-l', '--length', type=int, default=None, help="Number of bits to dump after detected access code")
	args = parser.parse_args()

	tb = top_block(args)
	tb.start()

	try:
		tb.wait()
	except KeyboardInterrupt:
		tb.stop()

if __name__ == '__main__':
	main()
