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