aboutsummaryrefslogtreecommitdiffstats
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
parent06ecb02d5e26b79d6ce4c03eb7c09670df792fc8 (diff)
Implemented multiband channelizer as gr-gsm block.
-rw-r--r--grc/gsm_block_tree.xml1
-rw-r--r--grc/receiver/CMakeLists.txt1
-rw-r--r--grc/receiver/gsm_wideband_input.xml78
-rw-r--r--python/CMakeLists.txt4
-rw-r--r--python/__init__.py1
-rw-r--r--python/receiver/gsm_wideband_input.py115
6 files changed, 198 insertions, 2 deletions
diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml
index 9951e71..f49f055 100644
--- a/grc/gsm_block_tree.xml
+++ b/grc/gsm_block_tree.xml
@@ -19,6 +19,7 @@
<block>gsm_fcch_detector</block>
<block>gsm_clock_offset_control</block>
<block>gsm_input</block>
+ <block>gsm_wideband_input</block>
</cat>
<cat>
<name>Logical channels demapping</name>
diff --git a/grc/receiver/CMakeLists.txt b/grc/receiver/CMakeLists.txt
index bcef03d..af7042d 100644
--- a/grc/receiver/CMakeLists.txt
+++ b/grc/receiver/CMakeLists.txt
@@ -19,6 +19,7 @@
install(FILES
gsm_input.xml
+ gsm_wideband_input.xml
gsm_receiver.xml
gsm_fcch_burst_tagger.xml
gsm_sch_detector.xml
diff --git a/grc/receiver/gsm_wideband_input.xml b/grc/receiver/gsm_wideband_input.xml
new file mode 100644
index 0000000..f2f9520
--- /dev/null
+++ b/grc/receiver/gsm_wideband_input.xml
@@ -0,0 +1,78 @@
+<block>
+ <name>GSM wideband input adaptor</name>
+ <key>gsm_wideband_input</key>
+ <category></category>
+ <import>import grgsm</import>
+ <make>grgsm.gsm_wideband_input(
+ ppm=$ppm,
+ osr=$osr,
+ fc=$fc,
+ samp_rate_in=$samp_rate_in,
+ ca=$cell_allocation,
+)</make>
+ <callback>set_ppm($ppm)</callback>
+ <callback>set_osr($osr)</callback>
+ <callback>set_fc($fc)</callback>
+ <callback>set_samp_rate_in($samp_rate_in)</callback>
+ <param>
+ <name>ppm</name>
+ <key>ppm</key>
+ <value>ppm</value>
+ <type>float</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>OSR</name>
+ <key>osr</key>
+ <value>osr</value>
+ <type>int</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>fc</name>
+ <key>fc</key>
+ <value>fc</value>
+ <type>float</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Cell allocation</name>
+ <key>cell_allocation</key>
+ <value>[]</value>
+ <type>float_vector</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>samp_rate_in</name>
+ <key>samp_rate_in</key>
+ <value>samp_rate_in</value>
+ <type>float</type>
+ <hide>part</hide>
+ </param>
+ <param>
+ <name>Num Streams</name>
+ <key>num_streams</key>
+ <value>1</value>
+ <type>int</type>
+ <hide>part</hide>
+ </param>
+ <check>$num_streams &gt;= 0</check>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>1</vlen>
+ </sink>
+ <sink>
+ <name>ppm_in</name>
+ <type>message</type>
+ <optional>True</optional>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <vlen>1</vlen>
+ <nports>$num_streams</nports>
+ </source>
+ <doc>Piotr Krysik
+Adaptor of input stream for the GSM receiver. Contains frequency offset corrector and resampler to correct carrier frequency and sampling frequency offsets. At the end it has LP filter for filtering of a GSM channel.</doc>
+</block>
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)