Compare commits

...

4 Commits

Author SHA1 Message Date
Vadim Yanitskiy d1c95940ca apps/grgsm_trx: introduce initial LMS driver support
Change-Id: Ie983b10d1814906b6e659213f865e58d0f5c08e4
2019-01-22 14:41:42 +07:00
Vadim Yanitskiy ca49a3e621 apps/grgsm_trx: add RadioInterface driver selection argument
Change-Id: Ic11f878c176bad16b057f25725ab0cfecc01782f
2019-01-22 14:41:30 +07:00
Vadim Yanitskiy dbb3daae1a trx/radio_if.py: print type of RadioInterface
Change-Id: I6c1ba8546caec122cd1ea0ed87656f691abec068
2019-01-22 14:41:30 +07:00
Vadim Yanitskiy 89e1ad1138 python/trx: fork RadioInterfaceUHD from RadioInterface
Change-Id: I1644a3f6b8da0d5f2a1a133058269e5383948fda
2019-01-22 14:41:30 +07:00
6 changed files with 181 additions and 33 deletions

View File

@ -57,8 +57,15 @@ class Application:
# Set up signal handlers # Set up signal handlers
signal.signal(signal.SIGINT, self.sig_handler) signal.signal(signal.SIGINT, self.sig_handler)
if argv.driver == "uhd":
from grgsm.trx.radio_if_uhd import RadioInterfaceUHD as Radio
elif argv.driver == "lms":
from grgsm.trx.radio_if_lms import RadioInterfaceLMS as Radio
else:
raise ValueError("Unknown RadioInterface driver '%s'" % argv.driver)
# Init Radio interface # Init Radio interface
self.radio = RadioInterface(self.phy_args, self.phy_sample_rate, self.radio = Radio(self.phy_args, self.phy_sample_rate,
self.phy_rx_gain, self.phy_tx_gain, self.phy_ppm, self.phy_rx_gain, self.phy_tx_gain, self.phy_ppm,
self.phy_rx_antenna, self.phy_tx_antenna, self.phy_rx_antenna, self.phy_tx_antenna,
self.phy_freq_offset, self.bind_addr, self.phy_freq_offset, self.bind_addr,
@ -110,6 +117,10 @@ def parse_argv():
# PHY specific # PHY specific
phy_group = parser.add_argument_group("PHY parameters") phy_group = parser.add_argument_group("PHY parameters")
phy_group.add_argument("--driver",
dest = "driver", type = str, default = "uhd",
choices = ["uhd", "lms"],
help = "Set device driver (default %(default)s)")
phy_group.add_argument("-a", "--args", phy_group.add_argument("-a", "--args",
dest = "args", type = str, default = "", dest = "args", type = str, default = "",
help = "Set device arguments") help = "Set device arguments")

View File

@ -24,6 +24,8 @@ GR_PYTHON_INSTALL(
ctrl_if.py ctrl_if.py
ctrl_if_bb.py ctrl_if_bb.py
radio_if.py radio_if.py
radio_if_uhd.py
radio_if_lms.py
radio_if_grc.py radio_if_grc.py
transceiver.py transceiver.py
dict_toggle_sign.py dict_toggle_sign.py

View File

@ -23,7 +23,6 @@ This is a set of helper classes for the grgsm_trx application.
from udp_link import UDPLink from udp_link import UDPLink
from ctrl_if import CTRLInterface from ctrl_if import CTRLInterface
from ctrl_if_bb import CTRLInterfaceBB from ctrl_if_bb import CTRLInterfaceBB
from radio_if_grc import RadioInterfaceGRC
from radio_if import RadioInterface from radio_if import RadioInterface
from transceiver import Transceiver from transceiver import Transceiver

View File

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# GR-GSM based transceiver # GR-GSM based transceiver
# Follow graph implementation # Generic (device independent) flow-graph implementation
# #
# (C) 2016-2019 by Vadim Yanitskiy <axilirator@gmail.com> # (C) 2016-2019 by Vadim Yanitskiy <axilirator@gmail.com>
# (C) 2017 by Piotr Krysik <ptrkrysik@gmail.com> # (C) 2017 by Piotr Krysik <ptrkrysik@gmail.com>
@ -33,7 +33,6 @@ from math import pi
from gnuradio import eng_notation from gnuradio import eng_notation
from gnuradio import digital from gnuradio import digital
from gnuradio import blocks from gnuradio import blocks
from gnuradio import uhd
from gnuradio import gr from gnuradio import gr
from gnuradio import filter from gnuradio import filter
@ -66,14 +65,18 @@ class RadioInterface(gr.top_block):
# basically, the DL freq. of ARFCN 0 # basically, the DL freq. of ARFCN 0
DUMMY_FREQ = 935e6 DUMMY_FREQ = 935e6
# Human-readable description
def __str__(self):
return "(generic)"
def __init__(self, phy_args, phy_sample_rate, def __init__(self, phy_args, phy_sample_rate,
phy_rx_gain, phy_tx_gain, phy_ppm, phy_rx_gain, phy_tx_gain, phy_ppm,
phy_rx_antenna, phy_tx_antenna, phy_rx_antenna, phy_tx_antenna,
phy_freq_offset, trx_bind_addr, phy_freq_offset, trx_bind_addr,
trx_remote_addr, trx_base_port): trx_remote_addr, trx_base_port):
print("[i] Init Radio interface (L:%s:%u <-> R:%s:%u)" print("[i] Init %s Radio interface (L:%s:%u <-> R:%s:%u)"
% (trx_bind_addr, trx_base_port + 2, % (self, trx_bind_addr, trx_base_port + 2,
trx_remote_addr, trx_base_port + 102)) trx_remote_addr, trx_base_port + 102))
# PHY specific variables # PHY specific variables
@ -83,6 +86,10 @@ class RadioInterface(gr.top_block):
self.ppm = phy_ppm self.ppm = phy_ppm
self.freq_offset = phy_freq_offset self.freq_offset = phy_freq_offset
self.phy_args = phy_args
self.rx_antenna = phy_rx_antenna
self.tx_antenna = phy_tx_antenna
gr.top_block.__init__(self, "GR-GSM TRX") gr.top_block.__init__(self, "GR-GSM TRX")
# TRX Burst Interface # TRX Burst Interface
@ -91,15 +98,7 @@ class RadioInterface(gr.top_block):
str(trx_base_port)) str(trx_base_port))
# RX path definition # RX path definition
self.phy_src = uhd.usrp_source(phy_args, self.phy_init_source()
uhd.stream_args(cpu_format="fc32",
channels=range(1)))
self.phy_src.set_clock_rate(26e6, uhd.ALL_MBOARDS)
self.phy_src.set_antenna(phy_rx_antenna, 0)
self.phy_src.set_samp_rate(phy_sample_rate)
self.phy_src.set_bandwidth(650e3, 0)
self.phy_src.set_gain(phy_rx_gain)
self.msg_to_tag_src = grgsm.msg_to_tag() self.msg_to_tag_src = grgsm.msg_to_tag()
@ -115,7 +114,7 @@ class RadioInterface(gr.top_block):
# Connections # Connections
self.connect( self.connect(
(self.phy_src, 0), (self._phy_src, 0),
(self.msg_to_tag_src, 0)) (self.msg_to_tag_src, 0))
self.connect( self.connect(
@ -140,14 +139,7 @@ class RadioInterface(gr.top_block):
# TX Path Definition # TX Path Definition
self.phy_sink = uhd.usrp_sink(phy_args, self.phy_init_sink()
uhd.stream_args(cpu_format="fc32",
channels=range(1)), "packet_len")
self.phy_sink.set_clock_rate(26e6, uhd.ALL_MBOARDS)
self.phy_sink.set_antenna(phy_tx_antenna, 0)
self.phy_sink.set_samp_rate(phy_sample_rate)
self.phy_sink.set_gain(self.tx_gain)
self.tx_time_setter = grgsm.txtime_setter( self.tx_time_setter = grgsm.txtime_setter(
0xffffffff, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0,
@ -200,7 +192,7 @@ class RadioInterface(gr.top_block):
self.connect( self.connect(
(self.rotator_sink, 0), (self.rotator_sink, 0),
(self.phy_sink, 0)) (self._phy_sink, 0))
# RX & TX synchronization # RX & TX synchronization
@ -245,11 +237,11 @@ class RadioInterface(gr.top_block):
(self.dict_toggle_sign, 'dict_out'), (self.dict_toggle_sign, 'dict_out'),
(self.msg_to_tag_sink, 'msg')) (self.msg_to_tag_sink, 'msg'))
def phy_init_source(self):
raise NotImplementedError
# Some UHD devices (such as UmTRX) do start the clock def phy_init_sink(self):
# not from 0, so it's required to reset it manually. raise NotImplementedError
# Resetting UHD source will also affect the sink.
self.phy_src.set_time_now(uhd.time_spec(0.0))
def shutdown(self): def shutdown(self):
print("[i] Shutdown Radio interface") print("[i] Shutdown Radio interface")
@ -281,9 +273,10 @@ class RadioInterface(gr.top_block):
print("[#] Shifting RX freq. to %s (offset is %s)" print("[#] Shifting RX freq. to %s (offset is %s)"
% (eng_notation.num_to_str(fc), % (eng_notation.num_to_str(fc),
eng_notation.num_to_str(self.freq_offset))) eng_notation.num_to_str(self.freq_offset)))
self.phy_src.set_center_freq(fc, 0)
self.rotator_src.set_phase_inc(self.calc_phase_inc(fc)) self.rotator_src.set_phase_inc(self.calc_phase_inc(fc))
self.gsm_clck_ctrl.set_fc(fc) self.gsm_clck_ctrl.set_fc(fc)
self.phy_set_rx_freq(fc)
self.rx_freq = fc self.rx_freq = fc
def set_tx_freq(self, fc): def set_tx_freq(self, fc):
@ -292,16 +285,17 @@ class RadioInterface(gr.top_block):
print("[#] Shifting TX freq. to %s (offset is %s)" print("[#] Shifting TX freq. to %s (offset is %s)"
% (eng_notation.num_to_str(fc), % (eng_notation.num_to_str(fc),
eng_notation.num_to_str(self.freq_offset))) eng_notation.num_to_str(self.freq_offset)))
self.phy_sink.set_center_freq(fc, 0)
self.rotator_sink.set_phase_inc(-self.calc_phase_inc(fc)) self.rotator_sink.set_phase_inc(-self.calc_phase_inc(fc))
self.phy_set_tx_freq(fc)
self.tx_freq = fc self.tx_freq = fc
def set_rx_gain(self, gain): def set_rx_gain(self, gain):
self.phy_src.set_gain(gain, 0) self.phy_set_rx_gain(gain)
self.rx_gain = gain self.rx_gain = gain
def set_tx_gain(self, gain): def set_tx_gain(self, gain):
self.phy_sink.set_gain(gain, 0) self.phy_set_tx_gain(gain)
self.tx_gain = gain self.tx_gain = gain
def set_slot(self, slot, config): def set_slot(self, slot, config):

View File

@ -0,0 +1,72 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# GR-GSM based transceiver
# Radio interface for Lime devices
#
# (C) 2019 by Vadim Yanitskiy <axilirator@gmail.com>
#
# All Rights Reserved
#
# This program 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 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import limesdr
from radio_if import RadioInterface
class RadioInterfaceLMS(RadioInterface):
LMS_DEV_TYPE_LIMESDR_MINI = 0x01
LMS_DEV_TYPE_LIMENET_MICRO = 0x02
LMS_DEV_TYPE_LIMESDR_USB = 0x03
# FIXME: hard-coded variables shall be replaced
# by command line arguments (or even auto-detected)!
lms_dev_serial = "1D3937DA65C85F"
lms_dev_type = LMS_DEV_TYPE_LIMESDR_MINI
lms_len_tag_name = "packet_len"
lms_dev_ch_mode = 1
# Human-readable description
def __str__(self):
return "LMS"
def phy_init_source(self):
self._phy_src = limesdr.source(
self.lms_dev_serial, self.lms_dev_type,
self.lms_dev_ch_mode, 0, "")
self._phy_src.set_sample_rate(self.sample_rate)
self._phy_src.set_gain(self.rx_gain, 0)
def phy_init_sink(self):
self._phy_sink = limesdr.sink(
self.lms_dev_serial, self.lms_dev_type,
self.lms_dev_ch_mode, 0, "",
self.lms_len_tag_name)
self._phy_sink.set_sample_rate(self.sample_rate)
self._phy_sink.set_gain(self.tx_gain, 0)
def phy_set_rx_freq(self, freq):
self._phy_src.set_center_freq(freq, 0)
def phy_set_tx_freq(self, freq):
self._phy_sink.set_center_freq(freq, 0)
def phy_set_rx_gain(self, gain):
self._phy_src.set_gain(gain, 0)
def phy_set_tx_gain(self, gain):
self._phy_sink.set_gain(gain, 0)

View File

@ -0,0 +1,70 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# GR-GSM based transceiver
# Radio interface for UHD devices
#
# (C) 2019 by Vadim Yanitskiy <axilirator@gmail.com>
#
# All Rights Reserved
#
# This program 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 of the License, or
# (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from gnuradio import uhd
from radio_if import RadioInterface
class RadioInterfaceUHD(RadioInterface):
# Human-readable description
def __str__(self):
return "UHD"
def phy_init_source(self):
self._phy_src = uhd.usrp_source(self.phy_args,
uhd.stream_args(cpu_format = "fc32",
channels = range(1)))
self._phy_src.set_clock_rate(26e6, uhd.ALL_MBOARDS)
self._phy_src.set_antenna(self.rx_antenna, 0)
self._phy_src.set_samp_rate(self.sample_rate)
self._phy_src.set_bandwidth(650e3, 0)
self._phy_src.set_gain(self.rx_gain)
# Some UHD devices (such as UmTRX) do start the clock
# not from 0, so it's required to reset it manually.
# Resetting UHD source will also affect the sink.
self._phy_src.set_time_now(uhd.time_spec(0.0))
def phy_init_sink(self):
self._phy_sink = uhd.usrp_sink(self.phy_args,
uhd.stream_args(cpu_format = "fc32",
channels = range(1)), "packet_len")
self._phy_sink.set_clock_rate(26e6, uhd.ALL_MBOARDS)
self._phy_sink.set_antenna(self.tx_antenna, 0)
self._phy_sink.set_samp_rate(self.sample_rate)
self._phy_sink.set_gain(self.tx_gain)
def phy_set_rx_freq(self, freq):
self._phy_src.set_center_freq(freq, 0)
def phy_set_tx_freq(self, freq):
self._phy_sink.set_center_freq(freq, 0)
def phy_set_rx_gain(self, gain):
self._phy_src.set_gain(gain, 0)
def phy_set_tx_gain(self, gain):
self._phy_sink.set_gain(gain, 0)