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