aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorDimitri Stolnikov <horiz0n@gmx.net>2013-05-14 00:04:09 +0200
committerDimitri Stolnikov <horiz0n@gmx.net>2013-05-14 00:04:09 +0200
commit79371104966594f64a18f2a55e4cb6f7ce7a9b39 (patch)
treeb437ca55fdba9fd6a9fa300cadbbdc768a44f1c5 /apps
parentc0b5ece48988d6fed9f2570ba7e95298beab8a0d (diff)
apps: add experimental gsm waveform to siggen app
TODO: implement power ramp
Diffstat (limited to 'apps')
-rw-r--r--apps/osmocom_siggen_base.py73
1 files changed, 71 insertions, 2 deletions
diff --git a/apps/osmocom_siggen_base.py b/apps/osmocom_siggen_base.py
index 6a12015..cc2e4f6 100644
--- a/apps/osmocom_siggen_base.py
+++ b/apps/osmocom_siggen_base.py
@@ -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")