Split HRPT script into live receive and post-processing
[debian/gnuradio] / gr-noaa / apps / usrp_rx_hrpt.py
1 #!/usr/bin/env python
2 ##################################################
3 # Gnuradio Python Flow Graph
4 # Title: USRP HRPT Receiver
5 # Generated: Wed Sep 23 11:32:04 2009
6 ##################################################
7
8 from gnuradio import eng_notation
9 from gnuradio import gr
10 from gnuradio import noaa
11 from gnuradio.eng_option import eng_option
12 from gnuradio.gr import firdes
13 from gnuradio.wxgui import fftsink2
14 from gnuradio.wxgui import forms
15 from gnuradio.wxgui import scopesink2
16 from grc_gnuradio import usrp as grc_usrp
17 from grc_gnuradio import wxgui as grc_wxgui
18 from optparse import OptionParser
19 import ConfigParser
20 import math
21 import wx
22
23 class usrp_rx_hrpt(grc_wxgui.top_block_gui):
24
25         def __init__(self):
26                 grc_wxgui.top_block_gui.__init__(self, title="USRP HRPT Receiver")
27
28                 ##################################################
29                 # Variables
30                 ##################################################
31                 self.config_filename = config_filename = 'usrp_rx_hrpt.cfg'
32                 self._decim_config = ConfigParser.ConfigParser()
33                 self._decim_config.read(config_filename)
34                 try: decim = self._decim_config.getfloat('usrp', 'decim')
35                 except: decim = 16
36                 self.decim = decim
37                 self.sym_rate = sym_rate = 600*1109
38                 self.sample_rate = sample_rate = 64e6/decim
39                 self.sps = sps = sample_rate/sym_rate
40                 self._side_config = ConfigParser.ConfigParser()
41                 self._side_config.read(config_filename)
42                 try: side = self._side_config.get('usrp', 'side')
43                 except: side = 'A'
44                 self.side = side
45                 self._saved_sync_alpha_config = ConfigParser.ConfigParser()
46                 self._saved_sync_alpha_config.read(config_filename)
47                 try: saved_sync_alpha = self._saved_sync_alpha_config.getfloat('demod', 'sync_alpha')
48                 except: saved_sync_alpha = 0.05
49                 self.saved_sync_alpha = saved_sync_alpha
50                 self._saved_pll_alpha_config = ConfigParser.ConfigParser()
51                 self._saved_pll_alpha_config.read(config_filename)
52                 try: saved_pll_alpha = self._saved_pll_alpha_config.getfloat('demod', 'pll_alpha')
53                 except: saved_pll_alpha = 0.05
54                 self.saved_pll_alpha = saved_pll_alpha
55                 self._saved_gain_config = ConfigParser.ConfigParser()
56                 self._saved_gain_config.read(config_filename)
57                 try: saved_gain = self._saved_gain_config.getfloat('usrp', 'gain')
58                 except: saved_gain = 35
59                 self.saved_gain = saved_gain
60                 self._saved_freq_config = ConfigParser.ConfigParser()
61                 self._saved_freq_config.read(config_filename)
62                 try: saved_freq = self._saved_freq_config.getfloat('usrp', 'freq')
63                 except: saved_freq = 1698e6
64                 self.saved_freq = saved_freq
65                 self.sync_alpha = sync_alpha = saved_sync_alpha
66                 self.side_text = side_text = side
67                 self.pll_alpha = pll_alpha = saved_pll_alpha
68                 self._output_filename_config = ConfigParser.ConfigParser()
69                 self._output_filename_config.read(config_filename)
70                 try: output_filename = self._output_filename_config.get('output', 'filename')
71                 except: output_filename = 'frames.dat'
72                 self.output_filename = output_filename
73                 self.max_sync_offset = max_sync_offset = 0.01
74                 self.max_carrier_offset = max_carrier_offset = 2*math.pi*100e3/sample_rate
75                 self.hs = hs = int(sps/2.0)
76                 self.gain = gain = saved_gain
77                 self.freq = freq = saved_freq
78                 self.decim_text = decim_text = decim
79
80                 ##################################################
81                 # Notebooks
82                 ##################################################
83                 self.displays = wx.Notebook(self.GetWin(), style=wx.NB_TOP)
84                 self.displays.AddPage(grc_wxgui.Panel(self.displays), "RX")
85                 self.displays.AddPage(grc_wxgui.Panel(self.displays), "Demod")
86                 self.GridAdd(self.displays, 2, 0, 1, 4)
87
88                 ##################################################
89                 # Controls
90                 ##################################################
91                 _sync_alpha_sizer = wx.BoxSizer(wx.VERTICAL)
92                 self._sync_alpha_text_box = forms.text_box(
93                         parent=self.GetWin(),
94                         sizer=_sync_alpha_sizer,
95                         value=self.sync_alpha,
96                         callback=self.set_sync_alpha,
97                         label="SYNC Alpha",
98                         converter=forms.float_converter(),
99                         proportion=0,
100                 )
101                 self._sync_alpha_slider = forms.slider(
102                         parent=self.GetWin(),
103                         sizer=_sync_alpha_sizer,
104                         value=self.sync_alpha,
105                         callback=self.set_sync_alpha,
106                         minimum=0.0,
107                         maximum=0.5,
108                         num_steps=100,
109                         style=wx.SL_HORIZONTAL,
110                         cast=float,
111                         proportion=1,
112                 )
113                 self.GridAdd(_sync_alpha_sizer, 0, 3, 1, 1)
114                 self._side_text_static_text = forms.static_text(
115                         parent=self.GetWin(),
116                         value=self.side_text,
117                         callback=self.set_side_text,
118                         label="USRP Side",
119                         converter=forms.str_converter(),
120                 )
121                 self.GridAdd(self._side_text_static_text, 1, 0, 1, 1)
122                 _pll_alpha_sizer = wx.BoxSizer(wx.VERTICAL)
123                 self._pll_alpha_text_box = forms.text_box(
124                         parent=self.GetWin(),
125                         sizer=_pll_alpha_sizer,
126                         value=self.pll_alpha,
127                         callback=self.set_pll_alpha,
128                         label="PLL Alpha",
129                         converter=forms.float_converter(),
130                         proportion=0,
131                 )
132                 self._pll_alpha_slider = forms.slider(
133                         parent=self.GetWin(),
134                         sizer=_pll_alpha_sizer,
135                         value=self.pll_alpha,
136                         callback=self.set_pll_alpha,
137                         minimum=0.0,
138                         maximum=0.5,
139                         num_steps=100,
140                         style=wx.SL_HORIZONTAL,
141                         cast=float,
142                         proportion=1,
143                 )
144                 self.GridAdd(_pll_alpha_sizer, 0, 2, 1, 1)
145                 _gain_sizer = wx.BoxSizer(wx.VERTICAL)
146                 self._gain_text_box = forms.text_box(
147                         parent=self.GetWin(),
148                         sizer=_gain_sizer,
149                         value=self.gain,
150                         callback=self.set_gain,
151                         label="RX Gain",
152                         converter=forms.float_converter(),
153                         proportion=0,
154                 )
155                 self._gain_slider = forms.slider(
156                         parent=self.GetWin(),
157                         sizer=_gain_sizer,
158                         value=self.gain,
159                         callback=self.set_gain,
160                         minimum=0,
161                         maximum=100,
162                         num_steps=100,
163                         style=wx.SL_HORIZONTAL,
164                         cast=float,
165                         proportion=1,
166                 )
167                 self.GridAdd(_gain_sizer, 0, 1, 1, 1)
168                 self._freq_text_box = forms.text_box(
169                         parent=self.GetWin(),
170                         value=self.freq,
171                         callback=self.set_freq,
172                         label="Frequency",
173                         converter=forms.float_converter(),
174                 )
175                 self.GridAdd(self._freq_text_box, 0, 0, 1, 1)
176                 self._decim_text_static_text = forms.static_text(
177                         parent=self.GetWin(),
178                         value=self.decim_text,
179                         callback=self.set_decim_text,
180                         label="Decimation",
181                         converter=forms.float_converter(),
182                 )
183                 self.GridAdd(self._decim_text_static_text, 1, 1, 1, 1)
184
185                 ##################################################
186                 # Blocks
187                 ##################################################
188                 self.agc = gr.agc_cc(1e-6, 1.0, 1.0, 1.0)
189                 self.decoder = noaa.hrpt_decoder()
190                 self.deframer = noaa.hrpt_deframer()
191                 self.frame_sink = gr.file_sink(gr.sizeof_short*1, output_filename)
192                 self.matched_filter = gr.moving_average_cc(hs, 1.0/hs, 4000)
193                 self.pll = noaa.hrpt_pll_cf(pll_alpha, pll_alpha**2/4.0, max_carrier_offset)
194                 self.pll_scope = scopesink2.scope_sink_f(
195                         self.displays.GetPage(1).GetWin(),
196                         title="Post-PLL",
197                         sample_rate=sample_rate,
198                         v_scale=0.5,
199                         t_scale=20.0/sample_rate,
200                         ac_couple=False,
201                         xy_mode=False,
202                         num_inputs=1,
203                 )
204                 self.displays.GetPage(1).GridAdd(self.pll_scope.win, 0, 0, 1, 1)
205                 self.rx_fft = fftsink2.fft_sink_c(
206                         self.displays.GetPage(0).GetWin(),
207                         baseband_freq=freq,
208                         y_per_div=5,
209                         y_divs=8,
210                         ref_level=-5,
211                         ref_scale=2.0,
212                         sample_rate=sample_rate,
213                         fft_size=1024,
214                         fft_rate=30,
215                         average=True,
216                         avg_alpha=0.1,
217                         title="RX Spectrum",
218                         peak_hold=False,
219                 )
220                 self.displays.GetPage(0).GridAdd(self.rx_fft.win, 0, 0, 1, 1)
221                 self.rx_scope = scopesink2.scope_sink_c(
222                         self.displays.GetPage(0).GetWin(),
223                         title="RX Waveform",
224                         sample_rate=sample_rate,
225                         v_scale=0,
226                         t_scale=20.0/sample_rate,
227                         ac_couple=False,
228                         xy_mode=False,
229                         num_inputs=1,
230                 )
231                 self.displays.GetPage(0).GridAdd(self.rx_scope.win, 1, 0, 1, 1)
232                 self.sync = noaa.hrpt_sync_fb(sync_alpha, sync_alpha**2/4.0, sps, max_sync_offset)
233                 self.usrp_source = grc_usrp.simple_source_c(which=0, side=side, rx_ant="RXA")
234                 self.usrp_source.set_decim_rate(decim)
235                 self.usrp_source.set_frequency(freq, verbose=True)
236                 self.usrp_source.set_gain(gain)
237
238                 ##################################################
239                 # Connections
240                 ##################################################
241                 self.connect((self.deframer, 0), (self.frame_sink, 0))
242                 self.connect((self.sync, 0), (self.deframer, 0))
243                 self.connect((self.pll, 0), (self.sync, 0))
244                 self.connect((self.pll, 0), (self.pll_scope, 0))
245                 self.connect((self.agc, 0), (self.rx_scope, 0))
246                 self.connect((self.agc, 0), (self.rx_fft, 0))
247                 self.connect((self.agc, 0), (self.matched_filter, 0))
248                 self.connect((self.matched_filter, 0), (self.pll, 0))
249                 self.connect((self.deframer, 0), (self.decoder, 0))
250                 self.connect((self.usrp_source, 0), (self.agc, 0))
251
252         def set_config_filename(self, config_filename):
253                 self.config_filename = config_filename
254                 self._side_config = ConfigParser.ConfigParser()
255                 self._side_config.read(self.config_filename)
256                 if not self._side_config.has_section('usrp'):
257                         self._side_config.add_section('usrp')
258                 self._side_config.set('usrp', 'side', str(self.side))
259                 self._side_config.write(open(self.config_filename, 'w'))
260                 self._decim_config = ConfigParser.ConfigParser()
261                 self._decim_config.read(self.config_filename)
262                 if not self._decim_config.has_section('usrp'):
263                         self._decim_config.add_section('usrp')
264                 self._decim_config.set('usrp', 'decim', str(self.decim))
265                 self._decim_config.write(open(self.config_filename, 'w'))
266                 self._saved_freq_config = ConfigParser.ConfigParser()
267                 self._saved_freq_config.read(self.config_filename)
268                 if not self._saved_freq_config.has_section('usrp'):
269                         self._saved_freq_config.add_section('usrp')
270                 self._saved_freq_config.set('usrp', 'freq', str(self.freq))
271                 self._saved_freq_config.write(open(self.config_filename, 'w'))
272                 self._saved_gain_config = ConfigParser.ConfigParser()
273                 self._saved_gain_config.read(self.config_filename)
274                 if not self._saved_gain_config.has_section('usrp'):
275                         self._saved_gain_config.add_section('usrp')
276                 self._saved_gain_config.set('usrp', 'gain', str(self.gain))
277                 self._saved_gain_config.write(open(self.config_filename, 'w'))
278                 self._saved_pll_alpha_config = ConfigParser.ConfigParser()
279                 self._saved_pll_alpha_config.read(self.config_filename)
280                 if not self._saved_pll_alpha_config.has_section('demod'):
281                         self._saved_pll_alpha_config.add_section('demod')
282                 self._saved_pll_alpha_config.set('demod', 'pll_alpha', str(self.pll_alpha))
283                 self._saved_pll_alpha_config.write(open(self.config_filename, 'w'))
284                 self._saved_sync_alpha_config = ConfigParser.ConfigParser()
285                 self._saved_sync_alpha_config.read(self.config_filename)
286                 if not self._saved_sync_alpha_config.has_section('demod'):
287                         self._saved_sync_alpha_config.add_section('demod')
288                 self._saved_sync_alpha_config.set('demod', 'sync_alpha', str(self.sync_alpha))
289                 self._saved_sync_alpha_config.write(open(self.config_filename, 'w'))
290                 self._output_filename_config = ConfigParser.ConfigParser()
291                 self._output_filename_config.read(self.config_filename)
292                 if not self._output_filename_config.has_section('output'):
293                         self._output_filename_config.add_section('output')
294                 self._output_filename_config.set('output', 'filename', str(self.output_filename))
295                 self._output_filename_config.write(open(self.config_filename, 'w'))
296
297         def set_decim(self, decim):
298                 self.decim = decim
299                 self.set_sample_rate(64e6/self.decim)
300                 self._decim_config = ConfigParser.ConfigParser()
301                 self._decim_config.read(self.config_filename)
302                 if not self._decim_config.has_section('usrp'):
303                         self._decim_config.add_section('usrp')
304                 self._decim_config.set('usrp', 'decim', str(self.decim))
305                 self._decim_config.write(open(self.config_filename, 'w'))
306                 self.set_decim_text(self.decim)
307                 self.usrp_source.set_decim_rate(self.decim)
308
309         def set_sym_rate(self, sym_rate):
310                 self.sym_rate = sym_rate
311                 self.set_sps(self.sample_rate/self.sym_rate)
312
313         def set_sample_rate(self, sample_rate):
314                 self.sample_rate = sample_rate
315                 self.set_max_carrier_offset(2*math.pi*100e3/self.sample_rate)
316                 self.set_sps(self.sample_rate/self.sym_rate)
317                 self.rx_scope.set_sample_rate(self.sample_rate)
318                 self.rx_fft.set_sample_rate(self.sample_rate)
319                 self.pll_scope.set_sample_rate(self.sample_rate)
320
321         def set_sps(self, sps):
322                 self.sps = sps
323                 self.set_hs(int(self.sps/2.0))
324
325         def set_side(self, side):
326                 self.side = side
327                 self.set_side_text(self.side)
328                 self._side_config = ConfigParser.ConfigParser()
329                 self._side_config.read(self.config_filename)
330                 if not self._side_config.has_section('usrp'):
331                         self._side_config.add_section('usrp')
332                 self._side_config.set('usrp', 'side', str(self.side))
333                 self._side_config.write(open(self.config_filename, 'w'))
334
335         def set_saved_sync_alpha(self, saved_sync_alpha):
336                 self.saved_sync_alpha = saved_sync_alpha
337                 self.set_sync_alpha(self.saved_sync_alpha)
338
339         def set_saved_pll_alpha(self, saved_pll_alpha):
340                 self.saved_pll_alpha = saved_pll_alpha
341                 self.set_pll_alpha(self.saved_pll_alpha)
342
343         def set_saved_gain(self, saved_gain):
344                 self.saved_gain = saved_gain
345                 self.set_gain(self.saved_gain)
346
347         def set_saved_freq(self, saved_freq):
348                 self.saved_freq = saved_freq
349                 self.set_freq(self.saved_freq)
350
351         def set_sync_alpha(self, sync_alpha):
352                 self.sync_alpha = sync_alpha
353                 self._sync_alpha_slider.set_value(self.sync_alpha)
354                 self._sync_alpha_text_box.set_value(self.sync_alpha)
355                 self._saved_sync_alpha_config = ConfigParser.ConfigParser()
356                 self._saved_sync_alpha_config.read(self.config_filename)
357                 if not self._saved_sync_alpha_config.has_section('demod'):
358                         self._saved_sync_alpha_config.add_section('demod')
359                 self._saved_sync_alpha_config.set('demod', 'sync_alpha', str(self.sync_alpha))
360                 self._saved_sync_alpha_config.write(open(self.config_filename, 'w'))
361                 self.sync.set_alpha(self.sync_alpha)
362                 self.sync.set_beta(self.sync_alpha**2/4.0)
363
364         def set_side_text(self, side_text):
365                 self.side_text = side_text
366                 self._side_text_static_text.set_value(self.side_text)
367
368         def set_pll_alpha(self, pll_alpha):
369                 self.pll_alpha = pll_alpha
370                 self._pll_alpha_slider.set_value(self.pll_alpha)
371                 self._pll_alpha_text_box.set_value(self.pll_alpha)
372                 self._saved_pll_alpha_config = ConfigParser.ConfigParser()
373                 self._saved_pll_alpha_config.read(self.config_filename)
374                 if not self._saved_pll_alpha_config.has_section('demod'):
375                         self._saved_pll_alpha_config.add_section('demod')
376                 self._saved_pll_alpha_config.set('demod', 'pll_alpha', str(self.pll_alpha))
377                 self._saved_pll_alpha_config.write(open(self.config_filename, 'w'))
378                 self.pll.set_alpha(self.pll_alpha)
379                 self.pll.set_beta(self.pll_alpha**2/4.0)
380
381         def set_output_filename(self, output_filename):
382                 self.output_filename = output_filename
383                 self._output_filename_config = ConfigParser.ConfigParser()
384                 self._output_filename_config.read(self.config_filename)
385                 if not self._output_filename_config.has_section('output'):
386                         self._output_filename_config.add_section('output')
387                 self._output_filename_config.set('output', 'filename', str(self.output_filename))
388                 self._output_filename_config.write(open(self.config_filename, 'w'))
389
390         def set_max_sync_offset(self, max_sync_offset):
391                 self.max_sync_offset = max_sync_offset
392                 self.sync.set_max_offset(self.max_sync_offset)
393
394         def set_max_carrier_offset(self, max_carrier_offset):
395                 self.max_carrier_offset = max_carrier_offset
396                 self.pll.set_max_offset(self.max_carrier_offset)
397
398         def set_hs(self, hs):
399                 self.hs = hs
400                 self.matched_filter.set_length_and_scale(self.hs, 1.0/self.hs)
401
402         def set_gain(self, gain):
403                 self.gain = gain
404                 self._gain_slider.set_value(self.gain)
405                 self._gain_text_box.set_value(self.gain)
406                 self._saved_gain_config = ConfigParser.ConfigParser()
407                 self._saved_gain_config.read(self.config_filename)
408                 if not self._saved_gain_config.has_section('usrp'):
409                         self._saved_gain_config.add_section('usrp')
410                 self._saved_gain_config.set('usrp', 'gain', str(self.gain))
411                 self._saved_gain_config.write(open(self.config_filename, 'w'))
412                 self.usrp_source.set_gain(self.gain)
413
414         def set_freq(self, freq):
415                 self.freq = freq
416                 self._freq_text_box.set_value(self.freq)
417                 self._saved_freq_config = ConfigParser.ConfigParser()
418                 self._saved_freq_config.read(self.config_filename)
419                 if not self._saved_freq_config.has_section('usrp'):
420                         self._saved_freq_config.add_section('usrp')
421                 self._saved_freq_config.set('usrp', 'freq', str(self.freq))
422                 self._saved_freq_config.write(open(self.config_filename, 'w'))
423                 self.usrp_source.set_frequency(self.freq)
424                 self.rx_fft.set_baseband_freq(self.freq)
425
426         def set_decim_text(self, decim_text):
427                 self.decim_text = decim_text
428                 self._decim_text_static_text.set_value(self.decim_text)
429
430 if __name__ == '__main__':
431         parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
432         (options, args) = parser.parse_args()
433         tb = usrp_rx_hrpt()
434         tb.Run(True)
435