3 from gnuradio import gr, blks2
4 from gnuradio.qtgui import qtgui
5 from gnuradio import eng_notation
6 from PyQt4 import QtGui, QtCore
11 from qt_digital_window import Ui_DigitalWindow
13 print "Error: could not find qt_digital_window.py:"
14 print "\t\"pyuic4 qt_digital_window.ui -o qt_digital_window.py\""
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)
25 self.set_sample_rate(self.fg.sample_rate())
27 self.set_snr(self.fg.snr())
28 self.set_frequency(self.fg.frequency_offset())
29 self.set_time_offset(self.fg.timing_offset())
31 self.set_gain_mu(self.fg.rx_gain_mu())
32 self.set_alpha(self.fg.rx_alpha())
34 # Add the qtsnk widgets to the hlayout box
35 self.gui.sinkLayout.addWidget(snkTx)
36 self.gui.sinkLayout.addWidget(snkRx)
38 # Connect up some signals
39 self.connect(self.gui.sampleRateEdit, QtCore.SIGNAL("editingFinished()"),
40 self.sampleRateEditText)
42 self.connect(self.gui.snrEdit, QtCore.SIGNAL("editingFinished()"),
44 self.connect(self.gui.freqEdit, QtCore.SIGNAL("editingFinished()"),
46 self.connect(self.gui.timeEdit, QtCore.SIGNAL("editingFinished()"),
49 self.connect(self.gui.gainMuEdit, QtCore.SIGNAL("editingFinished()"),
51 self.connect(self.gui.alphaEdit, QtCore.SIGNAL("editingFinished()"),
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))
60 def sampleRateEditText(self):
62 rate = self.gui.sampleRateEdit.text().toAscii()
63 srate = eng_notation.str_to_num(rate)
64 self.fg.set_sample_rate(srate)
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))
73 def set_frequency(self, fo):
74 self.gui.freqEdit.setText(QtCore.QString("%1").arg(fo))
76 def set_time_offset(self, to):
77 self.gui.timeEdit.setText(QtCore.QString("%1").arg(to))
79 def snrEditText(self):
81 snr = self.gui.snrEdit.text().toDouble()[0]
86 def freqEditText(self):
88 freq = self.gui.freqEdit.text().toDouble()[0]
89 self.fg.set_frequency_offset(freq)
93 def timeEditText(self):
95 to = self.gui.timeEdit.text().toDouble()[0]
96 self.fg.set_timing_offset(to)
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))
105 def set_alpha(self, alpha):
106 self.gui.alphaEdit.setText(QtCore.QString("%1").arg(alpha))
108 def alphaEditText(self):
110 alpha = self.gui.alphaEdit.text().toDouble()[0]
111 self.fg.set_rx_alpha(alpha)
115 def gainMuEditText(self):
117 gain = self.gui.gainMuEdit.text().toDouble()[0]
118 self.fg.set_rx_gain_mu(gain)
123 class my_top_block(gr.top_block):
125 gr.top_block.__init__(self)
127 self.qapp = QtGui.QApplication(sys.argv)
129 self._sample_rate = 200e3
132 self.excess_bw = 0.35
133 self.gray_code = True
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)
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)
145 # Set up the carrier & clock recovery parameters
149 self.omega = self.sps
150 self.gain_omega = .25 * self.gain_mu * self.gain_mu
151 self.omega_rel_lim = 0.05
154 self.beta = 0.25 * self.alpha * self.alpha
155 self.fmin = -1000/self.sample_rate()
156 self.fmax = 1000/self.sample_rate()
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,
167 noise = self.get_noise_voltage(self.snr_dB)
168 self.fo = 100/self.sample_rate()
170 self.channel = gr.channel_model(noise, self.fo, self.to)
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)
176 self.snk_rx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS, -1/2, 1/2,
177 "Rx", True, True, False, True, True)
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)
182 pyTxQt = self.snk_tx.pyqwidget()
183 pyTx = sip.wrapinstance(pyTxQt, QtGui.QWidget)
185 pyRxQt = self.snk_rx.pyqwidget()
186 pyRx = sip.wrapinstance(pyRxQt, QtGui.QWidget)
188 self.main_box = dialog_box(pyTx, pyRx, self);
192 def get_noise_voltage(self, SNR):
193 S = 0 # dBm, assuming signal power normalized
195 npwr = pow(10.0, N/10.0) # ratio
196 nv = scipy.sqrt(npwr * self.sps) # convert the noise voltage
201 def sample_rate(self):
202 return self._sample_rate
204 def set_sample_rate(self, sr):
205 self._sample_rate = sr
208 # Channel Model Parameters
212 def set_snr(self, snr):
214 noise = self.get_noise_voltage(self.snr_dB)
215 self.channel.set_noise_voltage(noise)
217 def frequency_offset(self):
218 return self.fo * self.sample_rate()
220 def set_frequency_offset(self, fo):
221 self.fo = fo / self.sample_rate()
222 self.channel.set_frequency_offset(self.fo)
224 def timing_offset(self):
227 def set_timing_offset(self, to):
229 self.channel.set_timing_offset(self.to)
232 # Receiver Parameters
233 def rx_gain_mu(self):
236 def rx_gain_omega(self):
237 return self.gain_omega
239 def set_rx_gain_mu(self, 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)
251 def set_rx_alpha(self, alpha):
253 self.beta = .25 * self.alpha * self.alpha
254 self.receiver.set_alpha(self.alpha)
255 self.receiver.set_beta(self.beta)
258 if __name__ == "__main__":