diff options
author | trondeau | 2009-04-26 21:09:20 +0000 |
---|---|---|
committer | trondeau | 2009-04-26 21:09:20 +0000 |
commit | 0055921e21259ea96b05e7456304731ea05c6a45 (patch) | |
tree | a0a263b30b8c02a39082943fbafc7fb899ff15ef /gr-qtgui/src/python | |
parent | 9d45055a028d83b5614121cf2152af1ab7056d68 (diff) | |
download | gnuradio-0055921e21259ea96b05e7456304731ea05c6a45.tar.gz gnuradio-0055921e21259ea96b05e7456304731ea05c6a45.tar.bz2 gnuradio-0055921e21259ea96b05e7456304731ea05c6a45.zip |
Improving digital GUI analysis tool. Adding receiver carrier and timing recovery loop and ability to control the some of the receiver's parameters.
git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@10919 221aa14e-8319-0410-a670-987f0aec2ac5
Diffstat (limited to 'gr-qtgui/src/python')
-rwxr-xr-x | gr-qtgui/src/python/qt_digital.py | 218 | ||||
-rw-r--r-- | gr-qtgui/src/python/qt_digital_window.ui | 307 |
2 files changed, 384 insertions, 141 deletions
diff --git a/gr-qtgui/src/python/qt_digital.py b/gr-qtgui/src/python/qt_digital.py index ead540c51..33c3794ed 100755 --- a/gr-qtgui/src/python/qt_digital.py +++ b/gr-qtgui/src/python/qt_digital.py @@ -2,6 +2,7 @@ from gnuradio import gr, blks2 from gnuradio.qtgui import qtgui +from gnuradio import eng_notation from PyQt4 import QtGui, QtCore import sys, sip import scipy @@ -14,61 +15,107 @@ except ImportError: sys.exit(1) class dialog_box(QtGui.QMainWindow): - def __init__(self, snkTx, snkRx, channel, parent=None): + def __init__(self, snkTx, snkRx, fg, parent=None): QtGui.QWidget.__init__(self, parent) self.gui = Ui_DigitalWindow() self.gui.setupUi(self) - self.channel = channel + self.fg = fg + + self.set_sample_rate(self.fg.sample_rate()) + + self.set_snr(self.fg.snr()) + self.set_frequency(self.fg.frequency_offset()) + self.set_time_offset(self.fg.timing_offset()) + + self.set_gain_mu(self.fg.rx_gain_mu()) + self.set_alpha(self.fg.rx_alpha()) # Add the qtsnk widgets to the hlayout box self.gui.sinkLayout.addWidget(snkTx) self.gui.sinkLayout.addWidget(snkRx) # Connect up some signals - self.connect(self.gui.noiseEdit, QtCore.SIGNAL("editingFinished()"), - self.noiseEditText) + self.connect(self.gui.sampleRateEdit, QtCore.SIGNAL("editingFinished()"), + self.sampleRateEditText) + + self.connect(self.gui.snrEdit, QtCore.SIGNAL("editingFinished()"), + self.snrEditText) self.connect(self.gui.freqEdit, QtCore.SIGNAL("editingFinished()"), self.freqEditText) self.connect(self.gui.timeEdit, QtCore.SIGNAL("editingFinished()"), self.timeEditText) - - def set_noise(self, noise): - self.noise = noise - self.gui.noiseEdit.setText(QtCore.QString("%1").arg(self.noise)) - def set_frequency(self, freq): - self.freq = freq - self.gui.freqEdit.setText(QtCore.QString("%1").arg(self.freq)) + self.connect(self.gui.gainMuEdit, QtCore.SIGNAL("editingFinished()"), + self.gainMuEditText) + self.connect(self.gui.alphaEdit, QtCore.SIGNAL("editingFinished()"), + self.alphaEditText) - def set_time_offset(self, to): - self.timing_offset = to - self.gui.timeEdit.setText(QtCore.QString("%1").arg(self.timing_offset)) - def noiseEditText(self): + # Accessor functions for Gui to manipulate system parameters + def set_sample_rate(self, sr): + ssr = eng_notation.num_to_str(sr) + self.gui.sampleRateEdit.setText(QtCore.QString("%1").arg(ssr)) + + def sampleRateEditText(self): try: - noise = self.gui.noiseEdit.text().toDouble()[0] - self.channel.set_noise_voltage(noise) + rate = self.gui.sampleRateEdit.text().toAscii() + srate = eng_notation.str_to_num(rate) + self.fg.set_sample_rate(srate) + except RuntimeError: + pass + - self.noise = noise + # Accessor functions for Gui to manipulate channel model + def set_snr(self, snr): + self.gui.snrEdit.setText(QtCore.QString("%1").arg(snr)) + + def set_frequency(self, fo): + self.gui.freqEdit.setText(QtCore.QString("%1").arg(fo)) + + def set_time_offset(self, to): + self.gui.timeEdit.setText(QtCore.QString("%1").arg(to)) + + def snrEditText(self): + try: + snr = self.gui.snrEdit.text().toDouble()[0] + self.fg.set_snr(snr) except RuntimeError: pass def freqEditText(self): try: freq = self.gui.freqEdit.text().toDouble()[0] - self.channel.set_frequency_offset(freq) - - self.freq = freq + self.fg.set_frequency_offset(freq) except RuntimeError: pass def timeEditText(self): try: to = self.gui.timeEdit.text().toDouble()[0] - self.channel.set_timing_offset(to) + self.fg.set_timing_offset(to) + except RuntimeError: + pass + + + # Accessor functions for Gui to manipulate receiver parameters + def set_gain_mu(self, gain): + self.gui.gainMuEdit.setText(QtCore.QString("%1").arg(gain)) + + def set_alpha(self, alpha): + self.gui.alphaEdit.setText(QtCore.QString("%1").arg(alpha)) + + def alphaEditText(self): + try: + alpha = self.gui.alphaEdit.text().toDouble()[0] + self.fg.set_rx_alpha(alpha) + except RuntimeError: + pass - self.timing_offset = to + def gainMuEditText(self): + try: + gain = self.gui.gainMuEdit.text().toDouble()[0] + self.fg.set_rx_gain_mu(gain) except RuntimeError: pass @@ -79,33 +126,58 @@ class my_top_block(gr.top_block): self.qapp = QtGui.QApplication(sys.argv) - sps = 2 - excess_bw = 0.35 - gray_code = True + self._sample_rate = 200e3 + + self.sps = 2 + self.excess_bw = 0.35 + self.gray_code = True fftsize = 2048 - data = scipy.random.randint(0, 255, 1000) - src = gr.vector_source_b(data, True) - mod = blks2.dqpsk_mod(sps, excess_bw, gray_code, False, False) + self.data = scipy.random.randint(0, 255, 1000) + self.src = gr.vector_source_b(self.data, True) + self.mod = blks2.dqpsk_mod(self.sps, self.excess_bw, self.gray_code, False, False) - rrctaps = gr.firdes.root_raised_cosine(1, sps, 1, excess_bw, 21) - rx_rrc = gr.fir_filter_ccf(sps, rrctaps) + self.rrctaps = gr.firdes.root_raised_cosine(1, self.sps, 1, self.excess_bw, 21) + self.rx_rrc = gr.fir_filter_ccf(1, self.rrctaps) - noise = 1e-7 - fo = 1e-6 - to = 1.0 - channel = gr.channel_model(noise, fo, to) - thr = gr.throttle(gr.sizeof_gr_complex, 10*fftsize) + # Set up the carrier & clock recovery parameters + self.arity = 4 + self.mu = 0.5 + self.gain_mu = 0.05 + self.omega = self.sps + self.gain_omega = .25 * self.gain_mu * self.gain_mu + self.omega_rel_lim = 0.05 + + self.alpha = 0.15 + self.beta = 0.25 * self.alpha * self.alpha + self.fmin = -1000/self.sample_rate() + self.fmax = 1000/self.sample_rate() + + self.receiver = gr.mpsk_receiver_cc(self.arity, 0, + self.alpha, self.beta, + self.fmin, self.fmax, + self.mu, self.gain_mu, + self.omega, self.gain_omega, + self.omega_rel_lim) + + + self.snr_dB = 15 + noise = self.get_noise_voltage(self.snr_dB) + self.fo = 100/self.sample_rate() + self.to = 1.0 + self.channel = gr.channel_model(noise, self.fo, self.to) + + self.thr = gr.throttle(gr.sizeof_char, 10*fftsize) self.snk_tx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS, -1/2, 1/2, "Tx", True, True, False, True, True) self.snk_rx = qtgui.sink_c(fftsize, gr.firdes.WIN_BLACKMAN_hARRIS, -1/2, 1/2, "Rx", True, True, False, True, True) - self.connect(src, mod, channel, self.snk_tx) - self.connect(channel, rx_rrc, thr, self.snk_rx) + self.connect(self.src, self.thr, self.mod, self.channel, self.snk_tx) + self.connect(self.channel, self.rx_rrc, self.receiver, self.snk_rx) pyTxQt = self.snk_tx.pyqwidget() pyTx = sip.wrapinstance(pyTxQt, QtGui.QWidget) @@ -113,13 +185,75 @@ class my_top_block(gr.top_block): pyRxQt = self.snk_rx.pyqwidget() pyRx = sip.wrapinstance(pyRxQt, QtGui.QWidget) - self.main_box = dialog_box(pyTx, pyRx, channel); - self.main_box.set_noise(noise) - self.main_box.set_frequency(fo) - self.main_box.set_time_offset(to) + self.main_box = dialog_box(pyTx, pyRx, self); self.main_box.show() + def get_noise_voltage(self, SNR): + S = 0 # dBm, assuming signal power normalized + N = S - SNR # dBm + npwr = pow(10.0, N/10.0) # ratio + nv = scipy.sqrt(npwr * self.sps) # convert the noise voltage + return nv + + + # System Parameters + def sample_rate(self): + return self._sample_rate + + def set_sample_rate(self, sr): + self._sample_rate = sr + + + # Channel Model Parameters + def snr(self): + return self.snr_dB + + def set_snr(self, snr): + self.snr_dB = snr + noise = self.get_noise_voltage(self.snr_dB) + self.channel.set_noise_voltage(noise) + + def frequency_offset(self): + return self.fo * self.sample_rate() + + def set_frequency_offset(self, fo): + self.fo = fo / self.sample_rate() + self.channel.set_frequency_offset(self.fo) + + def timing_offset(self): + return self.to + + def set_timing_offset(self, to): + self.to = to + self.channel.set_timing_offset(self.to) + + + # Receiver Parameters + def rx_gain_mu(self): + return self.gain_mu + + def rx_gain_omega(self): + return self.gain_omega + + def set_rx_gain_mu(self, gain): + self.gain_mu = gain + self.gain_omega = .25 * self.gain_mu * self.gain_mu + self.receiver.set_gain_mu(self.gain_mu) + self.receiver.set_gain_omega(self.gain_omega) + + def rx_alpha(self): + return self.alpha + + def rx_beta(self): + return self.beta + + def set_rx_alpha(self, alpha): + self.alpha = alpha + self.beta = .25 * self.alpha * self.alpha + self.receiver.set_alpha(self.alpha) + self.receiver.set_beta(self.beta) + if __name__ == "__main__": tb = my_top_block(); diff --git a/gr-qtgui/src/python/qt_digital_window.ui b/gr-qtgui/src/python/qt_digital_window.ui index 67b7bbe92..27764e5f2 100644 --- a/gr-qtgui/src/python/qt_digital_window.ui +++ b/gr-qtgui/src/python/qt_digital_window.ui @@ -1,155 +1,264 @@ -<ui version="4.0" > +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> <class>DigitalWindow</class> - <widget class="QMainWindow" name="DigitalWindow" > - <property name="geometry" > + <widget class="QMainWindow" name="DigitalWindow"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>1236</width> - <height>655</height> + <height>739</height> </rect> </property> - <property name="windowTitle" > + <property name="windowTitle"> <string>MainWindow</string> </property> - <widget class="QWidget" name="centralwidget" > - <widget class="QLineEdit" name="noiseEdit" > - <property name="geometry" > + <widget class="QWidget" name="centralwidget"> + <widget class="QPushButton" name="closeButton"> + <property name="geometry"> <rect> - <x>120</x> - <y>520</y> - <width>113</width> - <height>23</height> - </rect> - </property> - </widget> - <widget class="QLabel" name="noiseLabel" > - <property name="geometry" > - <rect> - <x>10</x> - <y>520</y> - <width>111</width> - <height>20</height> - </rect> - </property> - <property name="text" > - <string>Noise Amplitude</string> - </property> - </widget> - <widget class="QPushButton" name="closeButton" > - <property name="geometry" > - <rect> - <x>260</x> - <y>580</y> - <width>80</width> - <height>27</height> + <x>1120</x> + <y>650</y> + <width>101</width> + <height>31</height> </rect> </property> - <property name="text" > + <property name="text"> <string>Close</string> </property> </widget> - <widget class="QLineEdit" name="freqEdit" > - <property name="geometry" > + <widget class="QFrame" name="sinkFrame"> + <property name="geometry"> <rect> - <x>120</x> - <y>550</y> - <width>113</width> - <height>23</height> + <x>10</x> + <y>10</y> + <width>1221</width> + <height>501</height> </rect> </property> - </widget> - <widget class="QLineEdit" name="timeEdit" > - <property name="geometry" > - <rect> - <x>120</x> - <y>580</y> - <width>113</width> - <height>23</height> - </rect> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> </property> + <widget class="QWidget" name="horizontalLayoutWidget"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>1201</width> + <height>481</height> + </rect> + </property> + <layout class="QHBoxLayout" name="sinkLayout"/> + </widget> </widget> - <widget class="QLabel" name="freqLabel" > - <property name="geometry" > + <widget class="QGroupBox" name="channelModeBox"> + <property name="geometry"> <rect> - <x>10</x> - <y>550</y> - <width>101</width> - <height>17</height> + <x>290</x> + <y>520</y> + <width>291</width> + <height>161</height> </rect> </property> - <property name="text" > - <string>Frequency Offset</string> + <property name="title"> + <string>Channel Model Parameters</string> </property> + <widget class="QLabel" name="timeLabel"> + <property name="geometry"> + <rect> + <x>10</x> + <y>90</y> + <width>101</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>Timing Offset</string> + </property> + </widget> + <widget class="QLineEdit" name="timeEdit"> + <property name="geometry"> + <rect> + <x>160</x> + <y>90</y> + <width>113</width> + <height>23</height> + </rect> + </property> + </widget> + <widget class="QLineEdit" name="snrEdit"> + <property name="geometry"> + <rect> + <x>160</x> + <y>30</y> + <width>113</width> + <height>23</height> + </rect> + </property> + </widget> + <widget class="QLabel" name="snrLabel"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>111</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>SNR (dB)</string> + </property> + </widget> + <widget class="QLineEdit" name="freqEdit"> + <property name="geometry"> + <rect> + <x>160</x> + <y>60</y> + <width>113</width> + <height>23</height> + </rect> + </property> + </widget> + <widget class="QLabel" name="freqLabel"> + <property name="geometry"> + <rect> + <x>10</x> + <y>60</y> + <width>141</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>Frequency Offset (Hz)</string> + </property> + </widget> </widget> - <widget class="QLabel" name="timeLabel" > - <property name="geometry" > + <widget class="QGroupBox" name="rxBox"> + <property name="geometry"> <rect> - <x>10</x> - <y>580</y> - <width>101</width> - <height>17</height> + <x>590</x> + <y>520</y> + <width>251</width> + <height>161</height> </rect> </property> - <property name="text" > - <string>Timing Offset</string> + <property name="title"> + <string>Receiver Parameters</string> </property> + <widget class="QLineEdit" name="gainMuEdit"> + <property name="geometry"> + <rect> + <x>120</x> + <y>30</y> + <width>113</width> + <height>23</height> + </rect> + </property> + </widget> + <widget class="QLabel" name="gainMuLabel"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>111</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Gain mu</string> + </property> + </widget> + <widget class="QLineEdit" name="alphaEdit"> + <property name="geometry"> + <rect> + <x>120</x> + <y>60</y> + <width>113</width> + <height>23</height> + </rect> + </property> + </widget> + <widget class="QLabel" name="alphaLabel"> + <property name="geometry"> + <rect> + <x>10</x> + <y>60</y> + <width>111</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Alpha</string> + </property> + </widget> </widget> - <widget class="QFrame" name="sinkFrame" > - <property name="geometry" > + <widget class="QGroupBox" name="sysBox"> + <property name="geometry"> <rect> - <x>10</x> - <y>10</y> - <width>1221</width> - <height>501</height> + <x>20</x> + <y>520</y> + <width>261</width> + <height>161</height> </rect> </property> - <property name="frameShape" > - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow" > - <enum>QFrame::Raised</enum> + <property name="title"> + <string>System Parameters</string> </property> - <widget class="QWidget" name="horizontalLayoutWidget" > - <property name="geometry" > + <widget class="QLineEdit" name="sampleRateEdit"> + <property name="geometry"> + <rect> + <x>140</x> + <y>30</y> + <width>113</width> + <height>23</height> + </rect> + </property> + </widget> + <widget class="QLabel" name="sampleRateLabel"> + <property name="geometry"> <rect> <x>10</x> - <y>10</y> - <width>1201</width> - <height>481</height> + <y>30</y> + <width>121</width> + <height>20</height> </rect> </property> - <layout class="QHBoxLayout" name="sinkLayout" /> + <property name="text"> + <string>Sample Rate (sps)</string> + </property> </widget> </widget> </widget> - <widget class="QMenuBar" name="menubar" > - <property name="geometry" > + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>1236</width> - <height>22</height> + <height>25</height> </rect> </property> - <widget class="QMenu" name="menuFile" > - <property name="title" > + <widget class="QMenu" name="menuFile"> + <property name="title"> <string>&File</string> </property> - <addaction name="actionExit" /> + <addaction name="actionExit"/> </widget> - <addaction name="menuFile" /> + <addaction name="menuFile"/> </widget> - <widget class="QStatusBar" name="statusbar" /> - <action name="actionExit" > - <property name="text" > + <widget class="QStatusBar" name="statusbar"/> + <action name="actionExit"> + <property name="text"> <string>E&xit</string> </property> </action> </widget> <tabstops> <tabstop>closeButton</tabstop> - <tabstop>noiseEdit</tabstop> + <tabstop>snrEdit</tabstop> <tabstop>freqEdit</tabstop> <tabstop>timeEdit</tabstop> </tabstops> @@ -161,11 +270,11 @@ <receiver>DigitalWindow</receiver> <slot>close()</slot> <hints> - <hint type="sourcelabel" > + <hint type="sourcelabel"> <x>322</x> <y>623</y> </hint> - <hint type="destinationlabel" > + <hint type="destinationlabel"> <x>66</x> <y>561</y> </hint> @@ -177,11 +286,11 @@ <receiver>DigitalWindow</receiver> <slot>close()</slot> <hints> - <hint type="sourcelabel" > + <hint type="sourcelabel"> <x>-1</x> <y>-1</y> </hint> - <hint type="destinationlabel" > + <hint type="destinationlabel"> <x>617</x> <y>327</y> </hint> |