commit
1afe0c2985
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 >= 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>
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
#!/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 = band = 'E-GSM' # TODO make selectable
|
||||
|
||||
##################################################
|
||||
# Variables
|
||||
##################################################
|
||||
self.samp_rate_out = samp_rate_out = 1625000.0/6.0*osr
|
||||
|
||||
##################################################
|
||||
# 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_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
|
||||
|
||||
##################################################
|
||||
# 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)
|
||||
|
||||
def get_osr(self):
|
||||
return self.osr
|
||||
|
||||
def set_osr(self, osr):
|
||||
self.osr = osr
|
||||
self.set_samp_rate_out(1625000.0/6.0*self.osr)
|
||||
|
||||
def get_samp_rate_in(self):
|
||||
return self.samp_rate_in
|
||||
|
||||
def set_samp_rate_in(self, samp_rate_in):
|
||||
self.samp_rate_in = samp_rate_in
|
||||
for channel in self.blocks_resamplers:
|
||||
self.blocks_resamplers[channel].set_resamp_ratio(self.samp_rate_in / self.samp_rate_out)
|
||||
self.gsm_clock_offset_corrector_0.set_samp_rate_in(self.samp_rate_in)
|
||||
|
||||
def get_samp_rate_out(self):
|
||||
return self.samp_rate_out
|
||||
|
||||
def set_samp_rate_out(self, samp_rate_out):
|
||||
self.samp_rate_out = samp_rate_out
|
||||
for channel in self.blocks_resamplers:
|
||||
self.blocks_resamplers[channel].set_resamp_ratio(self.samp_rate_in / self.samp_rate_out)
|
Loading…
Reference in New Issue