forked from sdr/gr-osmosdr
apps: add experimental gsm waveform to siggen app
TODO: implement power ramp
This commit is contained in:
parent
c0b5ece489
commit
7937110496
|
@ -38,12 +38,17 @@ TYPE_KEY = 'type'
|
|||
def setter(ps, key, val): ps[key] = val
|
||||
|
||||
import osmosdr
|
||||
from gnuradio import blocks
|
||||
from gnuradio import filter
|
||||
from gnuradio import digital
|
||||
from gnuradio import gr, gru, eng_notation
|
||||
from gnuradio.gr.pubsub import pubsub
|
||||
from gnuradio.eng_option import eng_option
|
||||
from optparse import OptionParser
|
||||
import sys
|
||||
import math
|
||||
import numpy
|
||||
import random
|
||||
|
||||
n2s = eng_notation.num_to_str
|
||||
|
||||
|
@ -52,7 +57,62 @@ waveforms = { gr.GR_SIN_WAVE : "Sinusoid",
|
|||
gr.GR_GAUSSIAN : "Gaussian Noise",
|
||||
gr.GR_UNIFORM : "Uniform Noise",
|
||||
"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
|
||||
|
@ -142,6 +202,8 @@ class top_block(gr.top_block, pubsub):
|
|||
elif self[TYPE_KEY] == "sweep":
|
||||
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])
|
||||
elif self[TYPE_KEY] == "gsm":
|
||||
self._src.set_sampling_freq(self[SAMP_RATE_KEY])
|
||||
else:
|
||||
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._src = gr.multiply_const_cc(self[AMPLITUDE_KEY])
|
||||
self.connect(self._src1,self._src2,self._src)
|
||||
elif type == "gsm":
|
||||
self._src = gsm_source_c(self[SAMP_RATE_KEY], self[AMPLITUDE_KEY])
|
||||
else:
|
||||
raise RuntimeError("Unknown waveform type")
|
||||
|
||||
|
@ -279,9 +343,10 @@ class top_block(gr.top_block, pubsub):
|
|||
elif type == "sweep":
|
||||
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]),)
|
||||
elif type == "gsm":
|
||||
print "GSM Burst Sequence"
|
||||
print "TX amplitude:", self[AMPLITUDE_KEY]
|
||||
|
||||
|
||||
def set_amplitude(self, amplitude):
|
||||
if amplitude < 0.0 or amplitude > 1.0:
|
||||
if self._verbose:
|
||||
|
@ -295,6 +360,8 @@ class top_block(gr.top_block, pubsub):
|
|||
self._src2.set_amplitude(amplitude/2.0)
|
||||
elif self[TYPE_KEY] == "sweep":
|
||||
self._src.set_k(amplitude)
|
||||
elif self[TYPE_KEY] == "gsm":
|
||||
self._src.set_amplitude(amplitude)
|
||||
else:
|
||||
return True # Waveform not yet set
|
||||
|
||||
|
@ -338,6 +405,8 @@ def get_options():
|
|||
help="Generate Two Tone signal for IMD testing")
|
||||
parser.add_option("--sweep", dest="type", action="store_const", const="sweep",
|
||||
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,
|
||||
help="Set output amplitude to AMPL (0.1-1.0) [default=%default]",
|
||||
metavar="AMPL")
|
||||
|
|
Loading…
Reference in New Issue