#!/usr/bin/env python

# GMSK modulation and demodulation.  
#
#
# Copyright 2005 Free Software Foundation, Inc.
# 
# This file is part of GNU Radio
# 
# GNU Radio 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.
# 
# GNU Radio 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 GNU Radio; see the file COPYING.  If not, write to
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# 

# See gnuradio-examples/python/gmsk2 for examples

from gnuradio import gr
from math import pi
import Numeric

# /////////////////////////////////////////////////////////////////////////////
#            ASK demod with steams of bytes as data i/o
# /////////////////////////////////////////////////////////////////////////////

class ask_demod(gr.hier_block):

    def __init__(self, fg, carrier_frq = 0, spb = 10, omega=None, gain_mu=0.001,
                  mu=0.5, freq_error=0.0, omega_relative_limit=0.000100):
        """
	Hierarchical block for Amplitude Shift Key (ASK) demodulation.

	The input is the complex modulated signal at baseband.
	The output is a stream of symbols ready to be sliced at zero.

	@param fg: flow graph
	@type fg: flow graph
	@param spb: samples per baud
	@type spb: integer

        Clock recovery parameters.  These all have reasonble defaults.
        
        @param omega: nominal relative freq (defaults to spb)
        @type omega: float
        @param gain_mu: controls rate of mu adjustment
        @type gain_mu: float
        @param mu: fractional delay [0.0, 1.0]
        @type mu: float
        @param omega_relative_limit: sets max variation in omega
        @type omega_relative_limit: float, typically 0.000200 (200 ppm)
        @param freq_error: bit rate error as a fraction
        @param float
	"""
	if spb < 2:
		raise TypeError, "sbp >= 2"
	self.spb = spb
	
	print "self = ", self

	# Using default values in gmsk.py
	if omega is None:
		omega = spb*(1+freq_error)
	gain_omega = 0.25*gain_mu*gain_mu        # critically damped

	input_rate = self.adc_freq() / self.decim_rate() # 64 MS/s // 250 = 

	# Let's decimate it some more
	if_rate = 9000				# reduce sampling down to
	print "Desired IF rate =", if_rate 
	if_decim = int ( input_rate // if_rate )
	if_rate = input_rate // if_decim	# recalculate because interger effects 
	print "Actual IF rate=", if_rate
	
	# Create decimate filter
	chan_filter_coeffs = gr.firdes.low_pass (1.0,		# gain
						 if_rate,	# sampling rate
						 2e3,		# low pass cutoff freq
						 0.1e3,		# width of trans. band
						 gr.firdes.WIN_HANN)

	print "len(rx_chan_coeffs) =", len(chan_filter_coeffs)
	# Decimating Channel complex in and out, float taps
	self.chan_filter = gr.fir_filter_ccf(if_decim, chan_filter_coeffs)

	# Translate it down
	base_decim = 1
	base_rate = if_rate /base_decim

	# Create coefficiant
	base_filter_coeffs = gr.firdes.low_pass(1.0,		# gain
						base_rate,	# sampling rate
						800,		# low pass cutoff freq
						300,		# width of trans. band
						gr.firdes.WIN_HANN)
	print "len(base_chan_coeffs) =", len(base_filter_coeffs)
	self.askdemod = gr.freq_xlating_fir_filter_ccf(base_decim, base_filter_coeffs,
							carrier_frq, base_rate)

	self.c2m = gr.complex_to_mag()

	# Offset and Gain adjustment
	self.adj = gr.add_const_ff(-3000.0)
	fg.connect(self.u, self.chan_filter, self.askdemod, self.c2m, self.adj)

	# the clock recovery block tracks the symbol clock and resamples as needed.
	# the output of the block is a stream of soft symbols (float)
	self.clock_recovery = gr.clock_recovery_mm_ff(omega, gain_omega, mu, gain_mu,
                                                      omega_relative_limit)

	fg.connect(u.adj, u.clock_recovery)

	print 'USRP ADC rate = 64 Ms/s'
	print 'USRP decimate = %g' % actual_decim
	print 'USB input rate = %g Ms/s' % input_rate
	print 'IF decimate = %g' % if_decim
	print 'IF rate = %g' % if_rate
	print 'Baseband decimate = %g' % base_decim
	print 'Baseband rate = %g' % base_rate
	
	# Initialize base class
	gr.hier_block.__init__(self, fg, self.u, self.clock_recovery)
