Statistics
| Branch: | Tag: | Revision:

root / gr-qtgui / apps / qt_digital.py @ abb70ac7

History | View | Annotate | Download (9.5 kB)

1
#!/usr/bin/env python
2
#
3
# Copyright 2011 Free Software Foundation, Inc.
4
# 
5
# This file is part of GNU Radio
6
# 
7
# GNU Radio is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3, or (at your option)
10
# any later version.
11
# 
12
# GNU Radio is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU General Public License for more details.
16
# 
17
# You should have received a copy of the GNU General Public License
18
# along with GNU Radio; see the file COPYING.  If not, write to
19
# the Free Software Foundation, Inc., 51 Franklin Street,
20
# Boston, MA 02110-1301, USA.
21
# 
22
23
from gnuradio import gr, blks2
24
from gnuradio import eng_notation
25
import sys
26
27
try:
28
    from gnuradio import qtgui
29
    from PyQt4 import QtGui, QtCore
30
    import sip
31
except ImportError:
32
    print "Error: Program requires PyQt4 and gr-qtgui."
33
    sys.exit(1)
34
35
try:
36
    import scipy
37
except ImportError:
38
    print "Error: Program requires scipy (see: www.scipy.org)."
39
    sys.exit(1)
40
41
try:
42
    from qt_digital_window import Ui_DigitalWindow
43
except ImportError:
44
    print "Error: could not find qt_digital_window.py:"
45
    print "\t\"Please run: pyuic4 qt_digital_window.ui -o qt_digital_window.py\""
46
    sys.exit(1)
47
48
class dialog_box(QtGui.QMainWindow):
49
    def __init__(self, snkTx, snkRx, fg, parent=None):
50
        QtGui.QWidget.__init__(self, parent)
51
        self.gui = Ui_DigitalWindow()
52
        self.gui.setupUi(self)
53
54
        self.fg = fg
55
56
        self.set_sample_rate(self.fg.sample_rate())
57
58
        self.set_snr(self.fg.snr())
59
        self.set_frequency(self.fg.frequency_offset())
60
        self.set_time_offset(self.fg.timing_offset())
61
62
        self.set_gain_mu(self.fg.rx_gain_mu())
63
        self.set_alpha(self.fg.rx_alpha())
64
65
        # Add the qtsnk widgets to the hlayout box
66
        self.gui.sinkLayout.addWidget(snkTx)
67
        self.gui.sinkLayout.addWidget(snkRx)
68
69
70
        # Connect up some signals
71
        self.connect(self.gui.pauseButton, QtCore.SIGNAL("clicked()"),
72
                     self.pauseFg)
73
74
        self.connect(self.gui.sampleRateEdit, QtCore.SIGNAL("editingFinished()"),
75
                     self.sampleRateEditText)
76
77
        self.connect(self.gui.snrEdit, QtCore.SIGNAL("editingFinished()"),
78
                     self.snrEditText)
79
        self.connect(self.gui.freqEdit, QtCore.SIGNAL("editingFinished()"),
80
                     self.freqEditText)
81
        self.connect(self.gui.timeEdit, QtCore.SIGNAL("editingFinished()"),
82
                     self.timeEditText)
83
84
        self.connect(self.gui.gainMuEdit, QtCore.SIGNAL("editingFinished()"),
85
                     self.gainMuEditText)
86
        self.connect(self.gui.alphaEdit, QtCore.SIGNAL("editingFinished()"),
87
                     self.alphaEditText)
88
89
90
    def pauseFg(self):
91
        if(self.gui.pauseButton.text() == "Pause"):
92
            self.fg.stop()
93
            self.fg.wait()
94
            self.gui.pauseButton.setText("Unpause")
95
        else:
96
            self.fg.start()
97
            self.gui.pauseButton.setText("Pause")
98
99
    # Accessor functions for Gui to manipulate system parameters
100
    def set_sample_rate(self, sr):
101
        ssr = eng_notation.num_to_str(sr)
102
        self.gui.sampleRateEdit.setText(QtCore.QString("%1").arg(ssr))
103
104
    def sampleRateEditText(self):
105
        try:
106
            rate = self.gui.sampleRateEdit.text().toAscii()
107
            srate = eng_notation.str_to_num(rate)
108
            self.fg.set_sample_rate(srate)
109
        except RuntimeError:
110
            pass
111
112
113
    # Accessor functions for Gui to manipulate channel model
114
    def set_snr(self, snr):
115
        self.gui.snrEdit.setText(QtCore.QString("%1").arg(snr))
116
117
    def set_frequency(self, fo):
118
        self.gui.freqEdit.setText(QtCore.QString("%1").arg(fo))
119
120
    def set_time_offset(self, to):
121
        self.gui.timeEdit.setText(QtCore.QString("%1").arg(to))
122
123
    def snrEditText(self):
124
        try:
125
            snr = self.gui.snrEdit.text().toDouble()[0]
126
            self.fg.set_snr(snr)
127
        except RuntimeError:
128
            pass
129
130
    def freqEditText(self):
131
        try:
132
            freq = self.gui.freqEdit.text().toDouble()[0]
133
            self.fg.set_frequency_offset(freq)
134
        except RuntimeError:
135
            pass
136
137
    def timeEditText(self):
138
        try:
139
            to = self.gui.timeEdit.text().toDouble()[0]
140
            self.fg.set_timing_offset(to)
141
        except RuntimeError:
142
            pass
143
144
145
    # Accessor functions for Gui to manipulate receiver parameters
146
    def set_gain_mu(self, gain):
147
        self.gui.gainMuEdit.setText(QtCore.QString("%1").arg(gain))
148
149
    def set_alpha(self, alpha):
150
        self.gui.alphaEdit.setText(QtCore.QString("%1").arg(alpha))
151
152
    def alphaEditText(self):
153
        try:
154
            alpha = self.gui.alphaEdit.text().toDouble()[0]
155
            self.fg.set_rx_alpha(alpha)
156
        except RuntimeError:
157
            pass
158
159
    def gainMuEditText(self):
160
        try:
161
            gain = self.gui.gainMuEdit.text().toDouble()[0]
162
            self.fg.set_rx_gain_mu(gain)
163
        except RuntimeError:
164
            pass
165
166
167
class my_top_block(gr.top_block):
168
    def __init__(self):
169
        gr.top_block.__init__(self)
170
171
        self.qapp = QtGui.QApplication(sys.argv)
172
173
        self._sample_rate = 2000e3
174
175
        self.sps = 2
176
        self.excess_bw = 0.35
177
        self.gray_code = True
178
        
179
        fftsize = 2048
180
181
        self.data = scipy.random.randint(0, 255, 1000)
182
        self.src = gr.vector_source_b(self.data.tolist(), True)
183
        self.mod = blks2.dqpsk_mod(self.sps, self.excess_bw, self.gray_code, False, False)
184
185
        self.rrctaps = gr.firdes.root_raised_cosine(1, self.sps, 1, self.excess_bw, 21)
186
        self.rx_rrc = gr.fir_filter_ccf(1, self.rrctaps)
187
188
189
        # Set up the carrier & clock recovery parameters
190
        self.arity = 4
191
        self.mu = 0.5
192
        self.gain_mu = 0.05
193
        self.omega = self.sps
194
        self.gain_omega = .25 * self.gain_mu * self.gain_mu
195
        self.omega_rel_lim = 0.05
196
        
197
        self.alpha = 0.15
198
        self.beta  = 0.25 * self.alpha * self.alpha
199
        self.fmin = -1000/self.sample_rate()
200
        self.fmax = 1000/self.sample_rate()
201
        
202
        self.receiver = gr.mpsk_receiver_cc(self.arity, 0,
203
                                            self.alpha, self.beta,
204
                                            self.fmin, self.fmax,
205
                                            self.mu, self.gain_mu,
206
                                            self.omega, self.gain_omega,
207
                                            self.omega_rel_lim)
208
        
209
        
210
        self.snr_dB = 15
211
        noise = self.get_noise_voltage(self.snr_dB)
212
        self.fo = 100/self.sample_rate()
213
        self.to = 1.0
214
        self.channel = gr.channel_model(noise, self.fo, self.to)
215
216
        self.thr = gr.throttle(gr.sizeof_char, self._sample_rate)
217
        self.snk_tx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS, 
218
                                   0, self._sample_rate*self.sps,
219
                                   "Tx", True, True, True, True)
220
221
        self.snk_rx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS,
222
                                   0, self._sample_rate,
223
                                   "Rx", True, True, True, True)
224
225
        self.connect(self.src, self.thr, self.mod, self.channel, self.snk_tx)
226
        self.connect(self.channel, self.rx_rrc, self.receiver, self.snk_rx)
227
        
228
        pyTxQt  = self.snk_tx.pyqwidget()
229
        pyTx = sip.wrapinstance(pyTxQt, QtGui.QWidget)
230
231
        pyRxQt  = self.snk_rx.pyqwidget()
232
        pyRx = sip.wrapinstance(pyRxQt, QtGui.QWidget)
233
234
        self.main_box = dialog_box(pyTx, pyRx, self);
235
        self.main_box.show()
236
237
238
    def get_noise_voltage(self, SNR):
239
        S = 0                            # dBm, assuming signal power normalized
240
        N = S - SNR                      # dBm
241
        npwr = pow(10.0, N/10.0)         # ratio
242
        nv = scipy.sqrt(npwr * self.sps) # convert the noise voltage
243
        return nv
244
245
246
    # System Parameters
247
    def sample_rate(self):
248
        return self._sample_rate
249
    
250
    def set_sample_rate(self, sr):
251
        self._sample_rate = sr
252
253
254
    # Channel Model Parameters
255
    def snr(self):
256
        return self.snr_dB
257
    
258
    def set_snr(self, snr):
259
        self.snr_dB = snr
260
        noise = self.get_noise_voltage(self.snr_dB)
261
        self.channel.set_noise_voltage(noise)
262
263
    def frequency_offset(self):
264
        return self.fo * self.sample_rate()
265
266
    def set_frequency_offset(self, fo):
267
        self.fo = fo / self.sample_rate()
268
        self.channel.set_frequency_offset(self.fo)
269
270
    def timing_offset(self):
271
        return self.to
272
    
273
    def set_timing_offset(self, to):
274
        self.to = to
275
        self.channel.set_timing_offset(self.to)
276
277
278
    # Receiver Parameters
279
    def rx_gain_mu(self):
280
        return self.gain_mu
281
282
    def rx_gain_omega(self):
283
        return self.gain_omega
284
    
285
    def set_rx_gain_mu(self, gain):
286
        self.gain_mu = gain
287
        self.gain_omega = .25 * self.gain_mu * self.gain_mu
288
        self.receiver.set_gain_mu(self.gain_mu)
289
        self.receiver.set_gain_omega(self.gain_omega)
290
291
    def rx_alpha(self):
292
        return self.alpha
293
294
    def rx_beta(self):
295
        return self.beta
296
    
297
    def set_rx_alpha(self, alpha):
298
        self.alpha = alpha
299
        self.beta = .25 * self.alpha * self.alpha
300
        self.receiver.set_alpha(self.alpha)
301
        self.receiver.set_beta(self.beta)
302
303
    
304
if __name__ == "__main__":
305
    tb = my_top_block();
306
    tb.start()
307
    tb.qapp.exec_()
308
    tb.stop()