apps: add experimental gsm waveform to siggen app

TODO: implement power ramp
This commit is contained in:
Dimitri Stolnikov 2013-05-14 00:04:09 +02:00
parent c0b5ece489
commit 7937110496
1 changed files with 71 additions and 2 deletions

View File

@ -38,12 +38,17 @@ TYPE_KEY = 'type'
def setter(ps, key, val): ps[key] = val def setter(ps, key, val): ps[key] = val
import osmosdr import osmosdr
from gnuradio import blocks
from gnuradio import filter
from gnuradio import digital
from gnuradio import gr, gru, eng_notation from gnuradio import gr, gru, eng_notation
from gnuradio.gr.pubsub import pubsub from gnuradio.gr.pubsub import pubsub
from gnuradio.eng_option import eng_option from gnuradio.eng_option import eng_option
from optparse import OptionParser from optparse import OptionParser
import sys import sys
import math import math
import numpy
import random
n2s = eng_notation.num_to_str n2s = eng_notation.num_to_str
@ -52,7 +57,62 @@ waveforms = { gr.GR_SIN_WAVE : "Sinusoid",
gr.GR_GAUSSIAN : "Gaussian Noise", gr.GR_GAUSSIAN : "Gaussian Noise",
gr.GR_UNIFORM : "Uniform Noise", gr.GR_UNIFORM : "Uniform Noise",
"2tone" : "Two Tone (IMD)", "2tone" : "Two Tone (IMD)",
"sweep" : "Freq. Sweep" } "sweep" : "Freq. Sweep",
"gsm" : "GSM Bursts" }
class gsm_source_c(gr.hier_block2):
def __init__(self, sample_rate, amplitude):
gr.hier_block2.__init__(self, "gsm_source_c",
gr.io_signature(0, 0, 0), # Input signature
gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
self._bits = gr.vector_source_b(self.gen_gsm_seq(), True)
self._symb_rate = 270833
self._samples_per_symbol = 2
bits_per_symbol = 1
self._pack = gr.unpacked_to_packed_bb(bits_per_symbol, gr.GR_MSB_FIRST)
self._mod = digital.gmsk_mod( self._samples_per_symbol, bt=0.35 )
self._interpolate = filter.fractional_interpolator_cc( 0,
(self._symb_rate * self._samples_per_symbol) / sample_rate )
self._scale = gr.multiply_const_cc(amplitude)
self.connect(self._bits, self._pack, self._mod, self._interpolate, self._scale, self)
def set_amplitude(self, amplitude):
self._scale.set_k(amplitude)
def set_sampling_freq(self, sample_rate):
self._interpolate.set_interp_ratio( (self._symb_rate * self._samples_per_symbol) / sample_rate )
def gen_gsm_burst(self, l):
chunks = [
[0,0,0],
list(numpy.random.randint(0, 2, 58)),
[0,0,1,0,0,1,0,1,1,1,0,0,0,0,1,0,0,0,1,0,0,1,0,1,1,1],
list(numpy.random.randint(0, 2, 58)),
[0,0,0],
[1] * (l-148)
]
return map(int, sum(chunks,[]))
def gen_gsm_frame(self):
return \
self.gen_gsm_burst(158) + \
self.gen_gsm_burst(158) + \
self.gen_gsm_burst(158) + \
self.gen_gsm_burst(159) + \
self.gen_gsm_burst(158) + \
self.gen_gsm_burst(158) + \
self.gen_gsm_burst(158) + \
self.gen_gsm_burst(159)
def gen_gsm_seq(self):
return sum([self.gen_gsm_frame() for i in range(10)], [])
# #
# GUI-unaware GNU Radio flowgraph. This may be used either with command # GUI-unaware GNU Radio flowgraph. This may be used either with command
@ -142,6 +202,8 @@ class top_block(gr.top_block, pubsub):
elif self[TYPE_KEY] == "sweep": elif self[TYPE_KEY] == "sweep":
self._src1.set_sampling_freq(self[SAMP_RATE_KEY]) self._src1.set_sampling_freq(self[SAMP_RATE_KEY])
self._src2.set_sampling_freq(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY]) self._src2.set_sampling_freq(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY])
elif self[TYPE_KEY] == "gsm":
self._src.set_sampling_freq(self[SAMP_RATE_KEY])
else: else:
return True # Waveform not yet set return True # Waveform not yet set
@ -262,6 +324,8 @@ class top_block(gr.top_block, pubsub):
self._src2 = gr.frequency_modulator_fc(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY]) self._src2 = gr.frequency_modulator_fc(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY])
self._src = gr.multiply_const_cc(self[AMPLITUDE_KEY]) self._src = gr.multiply_const_cc(self[AMPLITUDE_KEY])
self.connect(self._src1,self._src2,self._src) self.connect(self._src1,self._src2,self._src)
elif type == "gsm":
self._src = gsm_source_c(self[SAMP_RATE_KEY], self[AMPLITUDE_KEY])
else: else:
raise RuntimeError("Unknown waveform type") raise RuntimeError("Unknown waveform type")
@ -279,9 +343,10 @@ class top_block(gr.top_block, pubsub):
elif type == "sweep": elif type == "sweep":
print "Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0),n2s(self[WAVEFORM_FREQ_KEY]/2.0)) print "Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0),n2s(self[WAVEFORM_FREQ_KEY]/2.0))
print "Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),) print "Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)
elif type == "gsm":
print "GSM Burst Sequence"
print "TX amplitude:", self[AMPLITUDE_KEY] print "TX amplitude:", self[AMPLITUDE_KEY]
def set_amplitude(self, amplitude): def set_amplitude(self, amplitude):
if amplitude < 0.0 or amplitude > 1.0: if amplitude < 0.0 or amplitude > 1.0:
if self._verbose: if self._verbose:
@ -295,6 +360,8 @@ class top_block(gr.top_block, pubsub):
self._src2.set_amplitude(amplitude/2.0) self._src2.set_amplitude(amplitude/2.0)
elif self[TYPE_KEY] == "sweep": elif self[TYPE_KEY] == "sweep":
self._src.set_k(amplitude) self._src.set_k(amplitude)
elif self[TYPE_KEY] == "gsm":
self._src.set_amplitude(amplitude)
else: else:
return True # Waveform not yet set return True # Waveform not yet set
@ -338,6 +405,8 @@ def get_options():
help="Generate Two Tone signal for IMD testing") help="Generate Two Tone signal for IMD testing")
parser.add_option("--sweep", dest="type", action="store_const", const="sweep", parser.add_option("--sweep", dest="type", action="store_const", const="sweep",
help="Generate a swept sine wave") help="Generate a swept sine wave")
parser.add_option("--gsm", dest="type", action="store_const", const="gsm",
help="Generate GMSK modulated GSM Burst Sequence")
parser.add_option("", "--amplitude", type="eng_float", default=0.3, parser.add_option("", "--amplitude", type="eng_float", default=0.3,
help="Set output amplitude to AMPL (0.1-1.0) [default=%default]", help="Set output amplitude to AMPL (0.1-1.0) [default=%default]",
metavar="AMPL") metavar="AMPL")