aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
authorrpp <red@nostack.net>2015-10-01 10:44:34 +0200
committerrpp <red@nostack.net>2015-10-05 09:57:03 +0200
commita49a4d2b966878654c4239f27516efb59ffe1845 (patch)
tree0f0b936f5e1af8cefd9861a0544e7ea0f4a07d23 /python
parent06ecb02d5e26b79d6ce4c03eb7c09670df792fc8 (diff)
Implemented multiband channelizer as gr-gsm block.
Diffstat (limited to 'python')
-rw-r--r--python/CMakeLists.txt4
-rw-r--r--python/__init__.py1
-rw-r--r--python/receiver/gsm_wideband_input.py115
3 files changed, 118 insertions, 2 deletions
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 78cc646..f68100a 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -32,9 +32,10 @@ GR_PYTHON_INSTALL(
FILES
__init__.py
receiver/gsm_input.py
+ receiver/gsm_wideband_input.py
receiver/fcch_burst_tagger.py
receiver/sch_detector.py
- receiver/fcch_detector.py
+ receiver/fcch_detector.py
receiver/chirpz.py
misc_utils/arfcn.py
misc_utils/clock_offset_corrector.py DESTINATION ${GR_PYTHON_DIR}/grgsm
@@ -57,4 +58,3 @@ GR_ADD_TEST(qa_burst_sdcch_subslot_filter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_S
GR_ADD_TEST(qa_burst_fnr_filter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_burst_fnr_filter.py)
GR_ADD_TEST(qa_dummy_burst_filter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_dummy_burst_filter.py)
GR_ADD_TEST(qa_arfcn ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_arfcn.py)
-
diff --git a/python/__init__.py b/python/__init__.py
index 31c0bc5..0c50bdb 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -51,6 +51,7 @@ from sch_detector import sch_detector
from fcch_detector import fcch_detector
from clock_offset_corrector import clock_offset_corrector
from gsm_input import gsm_input
+from gsm_wideband_input import gsm_wideband_input
import arfcn
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)