Implemented multiband channelizer as gr-gsm block.
diff --git a/python/receiver/gsm_wideband_input.py b/python/receiver/gsm_wideband_input.py
new file mode 100644
index 0000000..d1f704b
--- /dev/null
+++ b/python/receiver/gsm_wideband_input.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+##################################################
+# Gnuradio Python Flow Graph
+# Title: GSM wideband input adaptor
+# Author: Piotr Krysik
+# Co-author: Pieter Robyns
+# Description: Adaptor of input stream for the GSM receiver. Contains frequency ofset corrector doing also resampling to integer multiplies of GSM sample rate and LP filter filtering GSM channel.
+##################################################
+
+from gnuradio import filter
+from gnuradio import gr
+from gnuradio import eng_notation
+from gnuradio.filter import firdes
+import grgsm.arfcn as arfcn
+import grgsm
+
+class gsm_wideband_input(gr.hier_block2):
+ def __init__(self, ppm=0, osr=4, fc=925.2e6, samp_rate_in=20e6, ca=[]):
+ self.num_streams = len(ca)
+ gr.hier_block2.__init__(
+ self, "GSM wideband input adaptor",
+ gr.io_signature(1, 1, gr.sizeof_gr_complex*1),
+ gr.io_signature(self.num_streams, self.num_streams, gr.sizeof_gr_complex*1),
+ )
+
+ ##################################################
+ # Parameters
+ ##################################################
+ self.ppm = ppm
+ self.osr = osr
+ self.fc = fc
+ self.samp_rate_in = samp_rate_in
+ self.ca = ca
+ self.blocks_fir_filters = {}
+ self.blocks_resamplers = {}
+ self.blocks_ocs = {}
+ self.band = 'E-GSM' # TODO make selectable
+ band = 'E-GSM'
+
+ ##################################################
+ # Variables
+ ##################################################
+ self.samp_rate_out = samp_rate_out = 1625000.0/6.0*osr
+ #self.samp_rate_out = samp_rate_out = 1000000
+
+ ##################################################
+ # Blocks
+ ##################################################
+ self.ppm_in = None
+ self.message_port_register_hier_out("ppm_in")
+ #self.lpf = firdes.low_pass(1, samp_rate_out, 125e3, 5e3, firdes.WIN_HAMMING, 6.76)
+ self.lpf = firdes.low_pass(1, samp_rate_in, 125e3, 75e3, firdes.WIN_HAMMING, 6.76)
+ self.gsm_clock_offset_corrector_0 = grgsm.clock_offset_corrector(
+ fc=fc,
+ ppm=ppm,
+ samp_rate_in=samp_rate_in,
+ )
+
+ c0_arfcn = arfcn.downlink2arfcn(fc, band)
+ print("Extracting channels %s, given that the center frequency is at ARFCN %d (%s)" % (str(ca), c0_arfcn, eng_notation.num_to_str(fc)))
+
+ self.connect((self, 0), (self.gsm_clock_offset_corrector_0, 0))
+
+
+ output_port = 0
+ for channel in ca:
+ channel_freq = arfcn.arfcn2downlink(channel, band)
+ if channel_freq is None:
+ print("Warning: invalid ARFCN %d for band %s" % (channel, band))
+ continue
+ freq_diff = channel_freq - fc
+ print("ARFCN %d is at C0 %+d KHz" % (channel, int(freq_diff / 1000.0)))
+
+ #self.blocks_ocs[channel] = grgsm.clock_offset_corrector(fc=fc, ppm=ppm, samp_rate_in=samp_rate_in)
+ self.blocks_resamplers[channel] = filter.fractional_resampler_cc(0, samp_rate_in/samp_rate_out)
+ self.blocks_fir_filters[channel] = filter.freq_xlating_fir_filter_ccc(1, (self.lpf), freq_diff, samp_rate_in)
+ self.connect((self.gsm_clock_offset_corrector_0, 0), (self.blocks_fir_filters[channel], 0))
+ self.connect((self.blocks_fir_filters[channel], 0), (self.blocks_resamplers[channel], 0))
+ self.connect((self.blocks_resamplers[channel], 0), (self, output_port))
+ output_port += 1
+
+
+ """"
+ output_port = 0
+ for channel in ca:
+ channel_freq = arfcn.arfcn2downlink(channel, band)
+ if channel_freq is None:
+ print("Warning: invalid ARFCN %d for band %s" % (channel, band))
+ continue
+ freq_diff = channel_freq - fc
+ print("ARFCN %d is at C0 %+d KHz" % (channel, int(freq_diff / 1000.0)))
+ self.blocks_fir_filters[channel] = filter.freq_xlating_fir_filter_ccc(20, (firdes.low_pass(1, samp_rate_in, 300000, 100000)), freq_diff, samp_rate_in)
+ self.connect((self, 0), (self.blocks_fir_filters[channel], 0))
+ self.connect((self.blocks_fir_filters[channel], 0), (self, output_port))
+ output_port += 1
+ """
+
+ ##################################################
+ # Asynch Message Connections
+ ##################################################
+ self.msg_connect(self, "ppm_in", self.gsm_clock_offset_corrector_0, "ppm_in")
+
+ def get_ppm(self):
+ return self.ppm
+
+ def set_ppm(self, ppm):
+ self.ppm = ppm
+ self.gsm_clock_offset_corrector_0.set_ppm(self.ppm)
+
+ def get_fc(self):
+ return self.fc
+
+ def set_fc(self, fc):
+ self.fc = fc
+ self.gsm_clock_offset_corrector_0.set_fc(self.fc)