~ubuntu-branches/ubuntu/trusty/gnuradio/trusty

« back to all changes in this revision

Viewing changes to gnuradio-examples/python/digital-bert/receive_path.py

  • Committer: Bazaar Package Importer
  • Author(s): Kamal Mostafa
  • Date: 2010-03-13 07:46:01 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100313074601-zjsa893a87bozyh7
Tags: 3.2.2.dfsg-1ubuntu1
* Fix build for Ubuntu lucid (LP: #260406)
  - add binary package dep for libusrp0, libusrp2-0: adduser
  - debian/rules clean: remove pre-built Qt moc files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Copyright 2008 Free Software Foundation, Inc.
 
3
#
 
4
# This file is part of GNU Radio
 
5
#
 
6
# GNU Radio is free software; you can redistribute it and/or modify
 
7
# it under the terms of the GNU General Public License as published by
 
8
# the Free Software Foundation; either version 3, or (at your option)
 
9
# any later version.
 
10
#
 
11
# GNU Radio is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License
 
17
# along with GNU Radio; see the file COPYING.  If not, write to
 
18
# the Free Software Foundation, Inc., 51 Franklin Street,
 
19
# Boston, MA 02110-1301, USA.
 
20
#
 
21
 
 
22
from gnuradio import gr, eng_notation
 
23
import math
 
24
 
 
25
n2s = eng_notation.num_to_str
 
26
 
 
27
class receive_path(gr.hier_block2):
 
28
    def __init__(self,
 
29
                 if_rate,        # Incoming sample rate
 
30
                 symbol_rate,    # Original symbol rate
 
31
                 excess_bw,      # RRC excess bandwidth, typically 0.35-0.5
 
32
                 costas_alpha,   # Costas loop 1st order gain, typically 0.01-0.2
 
33
                 costas_beta,    # Costas loop 2nd order gain, typically alpha^2/4.0
 
34
                 costas_max,     # Costas loop max frequency offset in radians/sample
 
35
                 mm_gain_mu,     # M&M loop 1st order gain, typically 0.001-0.2
 
36
                 mm_gain_omega,  # M&M loop 2nd order gain, typically alpha^2/4.0
 
37
                 mm_omega_limit, # M&M loop max timing error
 
38
                 ):
 
39
        
 
40
        gr.hier_block2.__init__(self, "receive_path",
 
41
                                gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
 
42
                                gr.io_signature(0, 0, 0))                    # Output signature
 
43
 
 
44
        self._if_rate = if_rate
 
45
        self._sps = int(self._if_rate/symbol_rate)
 
46
        print "IF sample rate:", n2s(self._if_rate)
 
47
        print "Symbol rate:", n2s(symbol_rate)
 
48
        print "Samples/symbol:", self._sps
 
49
        print "RRC bandwidth:", excess_bw
 
50
        
 
51
        # Create AGC to scale input to unity
 
52
        self._agc = gr.agc_cc(1e-5, 1.0, 1.0, 1.0)
 
53
 
 
54
        # Create RRC with specified excess bandwidth
 
55
        taps = gr.firdes.root_raised_cosine(1.0,          # Gain
 
56
                                            self._sps,    # Sampling rate
 
57
                                            1.0,          # Symbol rate
 
58
                                            excess_bw,    # Roll-off factor
 
59
                                            11*self._sps) # Number of taps
 
60
 
 
61
        self._rrc = gr.fir_filter_ccf(1, taps)
 
62
        
 
63
        # Create a Costas loop frequency/phase recovery block
 
64
 
 
65
        print "Costas alpha:", costas_alpha
 
66
        print "Costas beta:", costas_beta
 
67
        print "Costas max:", costas_max
 
68
        
 
69
        self._costas = gr.costas_loop_cc(costas_alpha,  # PLL first order gain
 
70
                                         costas_beta,   # PLL second order gain
 
71
                                         costas_max,    # Max frequency offset rad/sample
 
72
                                         -costas_max,   # Min frequency offset rad/sample
 
73
                                         2)             # BPSK
 
74
 
 
75
        # Create a M&M bit synchronization retiming block
 
76
        mm_mu = 0.5
 
77
        mm_omega = self._sps
 
78
 
 
79
        print "MM gain mu:", mm_gain_mu
 
80
        print "MM gain omega:", mm_gain_omega
 
81
        print "MM omega limit:", mm_omega_limit
 
82
        
 
83
        self._mm = gr.clock_recovery_mm_cc(mm_omega,       # Initial samples/symbol
 
84
                                           mm_gain_omega,  # Second order gain
 
85
                                           mm_mu,          # Initial symbol phase
 
86
                                           mm_gain_mu,     # First order gain
 
87
                                           mm_omega_limit) # Maximum timing offset
 
88
 
 
89
        # Add an SNR probe on the demodulated constellation
 
90
        self._snr_probe = gr.probe_mpsk_snr_c(10.0/symbol_rate)
 
91
        self.connect(self._mm, self._snr_probe)
 
92
        
 
93
        # Slice the resulting constellation into bits.
 
94
        # Get inphase channel and make decision about 0
 
95
        self._c2r = gr.complex_to_real()
 
96
        self._slicer = gr.binary_slicer_fb() 
 
97
        
 
98
        # Descramble BERT sequence.  A channel error will create 3 incorrect bits
 
99
        self._descrambler = gr.descrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit descrambler
 
100
 
 
101
        # Measure BER by the density of 0s in the stream
 
102
        self._ber = gr.probe_density_b(1.0/symbol_rate)
 
103
 
 
104
        self.connect(self, self._agc, self._rrc, self._costas, self._mm, 
 
105
                     self._c2r, self._slicer, self._descrambler, self._ber)
 
106
 
 
107
    def frequency_offset(self):
 
108
        return self._costas.freq()*self._if_rate/(2*math.pi)
 
109
 
 
110
    def timing_offset(self):
 
111
        return self._mm.omega()/self._sps-1.0
 
112
 
 
113
    def snr(self):
 
114
        return self._snr_probe.snr()
 
115
 
 
116
    def ber(self):
 
117
        return (1.0-self._ber.density())/3.0
 
118