def test_003_ofdm (self):
     """ Header 1: 193 bytes
     Header 2: 8 bytes
     2 bits per complex symbol, 32 carriers => 64 bits = 8 bytes per OFDM symbol
     """
     encoded_headers = (
         #   | Number of bytes                    | Packet number                                  | Parity
             1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0,
             0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,
     )
     packet_len_tagname = "packet_len"
     frame_len_tagname = "frame_len"
     src = gr.vector_source_b(encoded_headers)
     header_formatter = digital.packet_header_ofdm(
             (range(32),), # 32 carriers are occupied (which doesn't matter here)
             1,         # 1 OFDM symbol per header (= 32 bits)
             packet_len_tagname,
             frame_len_tagname,
             "packet_num",
             1,         # 1 bit per header symbols (BPSK)
             2          # 2 bits per payload symbol (QPSK)
     )
     parser = digital.packet_headerparser_b(header_formatter.base())
     sink = gr.message_debug()
     self.tb.connect(src, parser)
     self.tb.msg_connect(parser, "header_data", sink, "store")
     self.tb.start()
     time.sleep(1)
     self.tb.stop()
     self.tb.wait()
     self.assertEqual(sink.num_messages(), 2)
     msg1 = pmt.to_python(sink.get_message(0))
     msg2 = pmt.to_python(sink.get_message(1))
     self.assertEqual(msg1, {'packet_len': 193*4, 'frame_len': 25, 'packet_num': 0})
     self.assertEqual(msg2, {'packet_len': 8*4, 'frame_len': 1, 'packet_num': 1})
    def test_001_t (self):
        """
        First header: Packet length 4, packet num 0
        Second header: Packet 2, packet num 1
        Third header: Invalid (parity bit does not check) (would be len 4, num 2)
        """
        encoded_headers = (
            #   | Number of bytes                    | Packet number                                  | Parity
                0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0,
                0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,
                0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0
        )
        packet_len_tagname = "packet_len"

        random_tag = gr.gr_tag_t()
        random_tag.offset = 5
        random_tag.key = pmt.pmt_string_to_symbol("foo")
        random_tag.value = pmt.pmt_from_long(42)
        src = gr.vector_source_b(encoded_headers, tags=(random_tag,))
        parser = digital.packet_headerparser_b(32, packet_len_tagname)
        sink = gr.message_debug()
        self.tb.connect(src, parser)
        self.tb.msg_connect(parser, "header_data", sink, "store")
        self.tb.start()
        time.sleep(1)
        self.tb.stop()
        self.tb.wait()
        self.assertEqual(sink.num_messages(), 3)
        msg1 = pmt.to_python(sink.get_message(0))
        msg2 = pmt.to_python(sink.get_message(1))
        msg3 = pmt.to_python(sink.get_message(2))
        self.assertEqual(msg1, {'packet_len': 4, 'packet_num': 0, 'foo': 42})
        self.assertEqual(msg2, {'packet_len': 2, 'packet_num': 1})
        self.assertEqual(msg3, False)
    def test_001_t (self):
        """
        First header: Packet length 4, packet num 0
        Second header: Packet 2, packet num 1
        Third header: Invalid (parity bit does not check) (would be len 4, num 2)
        """
        encoded_headers = (
            #   | Number of bytes                    | Packet number                                  | Parity
                0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0,
                0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,
                0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0
        )
        packet_len_tagname = "packet_len"

        src = gr.vector_source_b(encoded_headers)
        parser = digital.packet_headerparser_b(32, packet_len_tagname)
        sink = gr.message_debug()
        self.tb.connect(src, parser)
        self.tb.msg_connect(parser, "header_data", sink, "store")
        self.tb.start()
        time.sleep(1)
        self.tb.stop()
        self.tb.wait()
        self.assertEqual(sink.num_messages(), 3)
        msg1 = pmt.to_python(sink.get_message(0))
        msg2 = pmt.to_python(sink.get_message(1))
        msg3 = pmt.to_python(sink.get_message(2))
        self.assertEqual(msg1, {'packet_len': 4, 'packet_num': 0})
        self.assertEqual(msg2, {'packet_len': 2, 'packet_num': 1})
        self.assertEqual(msg3, False)
    def test_001_t (self):
        expected_data = (
            #   | Number of symbols                  | Packet number                                  | Parity
                0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0,
                0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0,
                0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  1, 0, 0, 0
        )
        tagname = "packet_len"

        src = gr.vector_source_b(expected_data)
        parser = digital.packet_headerparser_b(32, tagname)
        sink = gr.message_debug()

        self.tb.connect(src, parser)
        self.tb.msg_connect(parser, "header_data", sink, "store")
        self.tb.start ()
        time.sleep(1)
        self.tb.stop()
        self.tb.wait()

        self.assertEqual(sink.num_messages(), 3)
        msg = sink.get_message(0)
 def test_002_pipe(self):
     """
     Create N packets of random length, pipe them through header generator,
     back to header parser, make sure output is the same.
     """
     N = 20
     header_len = 32
     packet_len_tagname = "packet_len"
     packet_lengths = [random.randint(1, 100) for x in range(N)]
     data, tags = tagged_streams.packets_to_vectors([range(packet_lengths[i]) for i in range(N)], packet_len_tagname)
     src = gr.vector_source_b(data, False, 1, tags)
     header_gen = digital.packet_headergenerator_bb(header_len, packet_len_tagname)
     header_parser = digital.packet_headerparser_b(header_len, packet_len_tagname)
     sink = gr.message_debug()
     self.tb.connect(src, header_gen, header_parser)
     self.tb.msg_connect(header_parser, "header_data", sink, "store")
     self.tb.start()
     time.sleep(1)
     self.tb.stop()
     self.tb.wait()
     self.assertEqual(sink.num_messages(), N)
     for i in xrange(N):
         msg = pmt.to_python(sink.get_message(i))
         self.assertEqual(msg, {'packet_len': packet_lengths[i], 'packet_num': i})
Beispiel #6
0
 def __init__(self,
              fft_len=_def_fft_len,
              cp_len=_def_cp_len,
              frame_length_tag_key=_def_frame_length_tag_key,
              packet_length_tag_key=_def_packet_length_tag_key,
              packet_num_tag_key=_def_packet_num_tag_key,
              occupied_carriers=_def_occupied_carriers,
              pilot_carriers=_def_pilot_carriers,
              pilot_symbols=_def_pilot_symbols,
              bps_header=1,
              bps_payload=1,
              sync_word1=None,
              sync_word2=None,
              debug_log=False,
              scramble_bits=False):
     gr.hier_block2.__init__(self, "ofdm_rx",
                             gr.io_signature(1, 1, gr.sizeof_gr_complex),
                             gr.io_signature(1, 1, gr.sizeof_char))
     ### Param init / sanity check ########################################
     self.fft_len = fft_len
     self.cp_len = cp_len
     self.frame_length_tag_key = frame_length_tag_key
     self.packet_length_tag_key = packet_length_tag_key
     self.occupied_carriers = occupied_carriers
     self.bps_header = bps_header
     self.bps_payload = bps_payload
     n_sync_words = 1
     if sync_word1 is None:
         self.sync_word1 = _make_sync_word1(fft_len, occupied_carriers,
                                            pilot_carriers)
     else:
         if len(sync_word1) != self.fft_len:
             raise ValueError(
                 "Length of sync sequence(s) must be FFT length.")
         self.sync_word1 = sync_word1
     self.sync_word2 = ()
     if sync_word2 is None:
         self.sync_word2 = _make_sync_word2(fft_len, occupied_carriers,
                                            pilot_carriers)
         n_sync_words = 2
     elif len(sync_word2):
         if len(sync_word2) != fft_len:
             raise ValueError(
                 "Length of sync sequence(s) must be FFT length.")
         self.sync_word2 = sync_word2
         n_sync_words = 2
     if scramble_bits:
         self.scramble_seed = 0x7f
     else:
         self.scramble_seed = 0x00  # We deactivate the scrambler by init'ing it with zeros
     ### Sync ############################################################
     sync_detect = digital.ofdm_sync_sc_cfb(fft_len, cp_len)
     delay = blocks.delay(gr.sizeof_gr_complex, fft_len + cp_len)
     oscillator = analog.frequency_modulator_fc(-2.0 / fft_len)
     mixer = blocks.multiply_cc()
     hpd = digital.header_payload_demux(
         n_sync_words +
         1,  # Number of OFDM symbols before payload (sync + 1 sym header)
         fft_len,
         cp_len,  # FFT length, guard interval
         frame_length_tag_key,  # Frame length tag key
         "",  # We're not using trigger tags
         True  # One output item is one OFDM symbol (False would output complex scalars)
     )
     self.connect(self, sync_detect)
     self.connect(self, delay, (mixer, 0), (hpd, 0))
     self.connect((sync_detect, 0), oscillator, (mixer, 1))
     self.connect((sync_detect, 1), (hpd, 1))
     if debug_log:
         self.connect((sync_detect, 0),
                      blocks.file_sink(gr.sizeof_float, 'freq-offset.dat'))
         self.connect((sync_detect, 1),
                      blocks.file_sink(gr.sizeof_char, 'sync-detect.dat'))
     ### Header demodulation ##############################################
     header_fft = fft.fft_vcc(self.fft_len, True, (), True)
     chanest = digital.ofdm_chanest_vcvc(self.sync_word1, self.sync_word2,
                                         1)
     header_constellation = _get_constellation(bps_header)
     header_equalizer = digital.ofdm_equalizer_simpledfe(
         fft_len,
         header_constellation.base(),
         occupied_carriers,
         pilot_carriers,
         pilot_symbols,
         symbols_skipped=0,
     )
     header_eq = digital.ofdm_frame_equalizer_vcvc(
         header_equalizer.base(),
         cp_len,
         self.frame_length_tag_key,
         True,
         1  # Header is 1 symbol long
     )
     header_serializer = digital.ofdm_serializer_vcc(
         fft_len, occupied_carriers, self.frame_length_tag_key)
     header_demod = digital.constellation_decoder_cb(
         header_constellation.base())
     header_formatter = digital.packet_header_ofdm(
         occupied_carriers,
         1,
         packet_length_tag_key,
         frame_length_tag_key,
         packet_num_tag_key,
         bps_header,
         bps_payload,
         scramble_header=scramble_bits)
     header_parser = digital.packet_headerparser_b(
         header_formatter.formatter())
     self.connect((hpd, 0), header_fft, chanest, header_eq,
                  header_serializer, header_demod, header_parser)
     self.msg_connect(header_parser, "header_data", hpd, "header_data")
     if debug_log:
         self.connect((chanest, 1),
                      blocks.file_sink(gr.sizeof_gr_complex * fft_len,
                                       'channel-estimate.dat'))
         self.connect((chanest, 0),
                      blocks.file_sink(gr.sizeof_gr_complex * fft_len,
                                       'post-hdr-chanest.dat'))
         self.connect((chanest, 0),
                      blocks.tag_debug(gr.sizeof_gr_complex * fft_len,
                                       'post-hdr-chanest'))
         self.connect(
             header_eq,
             blocks.file_sink(gr.sizeof_gr_complex * fft_len,
                              'post-hdr-eq.dat'))
         self.connect(
             header_serializer,
             blocks.file_sink(gr.sizeof_gr_complex,
                              'post-hdr-serializer.dat'))
         self.connect(header_descrambler,
                      blocks.file_sink(1, 'post-hdr-demod.dat'))
     ### Payload demod ####################################################
     payload_fft = fft.fft_vcc(self.fft_len, True, (), True)
     payload_constellation = _get_constellation(bps_payload)
     payload_equalizer = digital.ofdm_equalizer_simpledfe(
         fft_len,
         payload_constellation.base(),
         occupied_carriers,
         pilot_carriers,
         pilot_symbols,
         symbols_skipped=1,  # (that was already in the header)
         alpha=0.1)
     payload_eq = digital.ofdm_frame_equalizer_vcvc(
         payload_equalizer.base(), cp_len, self.frame_length_tag_key)
     payload_serializer = digital.ofdm_serializer_vcc(
         fft_len,
         occupied_carriers,
         self.frame_length_tag_key,
         self.packet_length_tag_key,
         1  # Skip 1 symbol (that was already in the header)
     )
     payload_demod = digital.constellation_decoder_cb(
         payload_constellation.base())
     self.payload_descrambler = digital.additive_scrambler_bb(
         0x8a,
         self.scramble_seed,
         7,
         0,  # Don't reset after fixed length
         bits_per_byte=8,  # This is after packing
         reset_tag_key=self.packet_length_tag_key)
     payload_pack = blocks.repack_bits_bb(bps_payload, 8,
                                          self.packet_length_tag_key, True)
     self.crc = digital.crc32_bb(True, self.packet_length_tag_key)
     self.connect((hpd, 1), payload_fft, payload_eq, payload_serializer,
                  payload_demod, payload_pack, self.payload_descrambler,
                  self.crc, self)
     if debug_log:
         self.connect((hpd, 1),
                      blocks.tag_debug(gr.sizeof_gr_complex * fft_len,
                                       'post-hpd'))
         self.connect(
             payload_fft,
             blocks.file_sink(gr.sizeof_gr_complex * fft_len,
                              'post-payload-fft.dat'))
         self.connect(
             payload_eq,
             blocks.file_sink(gr.sizeof_gr_complex * fft_len,
                              'post-payload-eq.dat'))
         self.connect(
             payload_serializer,
             blocks.file_sink(gr.sizeof_gr_complex,
                              'post-payload-serializer.dat'))
         self.connect(payload_demod,
                      blocks.file_sink(1, 'post-payload-demod.dat'))
         self.connect(payload_pack,
                      blocks.file_sink(1, 'post-payload-pack.dat'))
         self.connect(crc, blocks.file_sink(1, 'post-payload-crc.dat'))
Beispiel #7
0
 def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len,
              frame_length_tag_key=_def_frame_length_tag_key,
              packet_length_tag_key=_def_packet_length_tag_key,
              packet_num_tag_key=_def_packet_num_tag_key,
              occupied_carriers=_def_occupied_carriers,
              pilot_carriers=_def_pilot_carriers,
              pilot_symbols=_def_pilot_symbols,
              bps_header=1,
              bps_payload=1,
              sync_word1=None,
              sync_word2=None,
              debug_log=False,
              scramble_bits=False
              ):
     gr.hier_block2.__init__(self, "ofdm_rx",
                 gr.io_signature(1, 1, gr.sizeof_gr_complex),
                 gr.io_signature(1, 1, gr.sizeof_char))
     ### Param init / sanity check ########################################
     self.fft_len           = fft_len
     self.cp_len            = cp_len
     self.frame_length_tag_key    = frame_length_tag_key
     self.packet_length_tag_key   = packet_length_tag_key
     self.occupied_carriers = occupied_carriers
     self.bps_header        = bps_header
     self.bps_payload       = bps_payload
     n_sync_words = 1
     if sync_word1 is None:
         self.sync_word1 = _make_sync_word1(fft_len, occupied_carriers, pilot_carriers)
     else:
         if len(sync_word1) != self.fft_len:
             raise ValueError("Length of sync sequence(s) must be FFT length.")
         self.sync_word1 = sync_word1
     self.sync_word2 = ()
     if sync_word2 is None:
         self.sync_word2 = _make_sync_word2(fft_len, occupied_carriers, pilot_carriers)
         n_sync_words = 2
     elif len(sync_word2):
         if len(sync_word2) != fft_len:
             raise ValueError("Length of sync sequence(s) must be FFT length.")
         self.sync_word2 = sync_word2
         n_sync_words = 2
     if scramble_bits:
         self.scramble_seed = 0x7f
     else:
         self.scramble_seed = 0x00 # We deactivate the scrambler by init'ing it with zeros
     ### Sync ############################################################
     sync_detect = digital.ofdm_sync_sc_cfb(fft_len, cp_len)
     delay = blocks.delay(gr.sizeof_gr_complex, fft_len+cp_len)
     oscillator = analog.frequency_modulator_fc(-2.0 / fft_len)
     mixer = blocks.multiply_cc()
     hpd = digital.header_payload_demux(
         n_sync_words+1,       # Number of OFDM symbols before payload (sync + 1 sym header)
         fft_len, cp_len,      # FFT length, guard interval
         frame_length_tag_key, # Frame length tag key
         "",                   # We're not using trigger tags
         True                  # One output item is one OFDM symbol (False would output complex scalars)
     )
     self.connect(self, sync_detect)
     self.connect(self, delay, (mixer, 0), (hpd, 0))
     self.connect((sync_detect, 0), oscillator, (mixer, 1))
     self.connect((sync_detect, 1), (hpd, 1))
     if debug_log:
         self.connect((sync_detect, 0), blocks.file_sink(gr.sizeof_float, 'freq-offset.dat'))
         self.connect((sync_detect, 1), blocks.file_sink(gr.sizeof_char, 'sync-detect.dat'))
     ### Header demodulation ##############################################
     header_fft           = fft.fft_vcc(self.fft_len, True, (), True)
     chanest              = digital.ofdm_chanest_vcvc(self.sync_word1, self.sync_word2, 1)
     header_constellation = _get_constellation(bps_header)
     header_equalizer     = digital.ofdm_equalizer_simpledfe(
         fft_len,
         header_constellation.base(),
         occupied_carriers,
         pilot_carriers,
         pilot_symbols,
         symbols_skipped=0,
     )
     header_eq = digital.ofdm_frame_equalizer_vcvc(
             header_equalizer.base(),
             cp_len,
             self.frame_length_tag_key,
             True,
             1 # Header is 1 symbol long
     )
     header_serializer = digital.ofdm_serializer_vcc(
             fft_len, occupied_carriers,
             self.frame_length_tag_key
     )
     header_demod     = digital.constellation_decoder_cb(header_constellation.base())
     header_formatter = digital.packet_header_ofdm(
             occupied_carriers, 1,
             packet_length_tag_key,
             frame_length_tag_key,
             packet_num_tag_key,
             bps_header,
             bps_payload,
             scramble_header=scramble_bits
     )
     header_parser = digital.packet_headerparser_b(header_formatter.formatter())
     self.connect(
             (hpd, 0),
             header_fft,
             chanest,
             header_eq,
             header_serializer,
             header_demod,
             header_parser
     )
     self.msg_connect(header_parser, "header_data", hpd, "header_data")
     if debug_log:
         self.connect((chanest, 1),      blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'channel-estimate.dat'))
         self.connect((chanest, 0),      blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'post-hdr-chanest.dat'))
         self.connect((chanest, 0),      blocks.tag_debug(gr.sizeof_gr_complex * fft_len, 'post-hdr-chanest'))
         self.connect(header_eq,         blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'post-hdr-eq.dat'))
         self.connect(header_serializer, blocks.file_sink(gr.sizeof_gr_complex,           'post-hdr-serializer.dat'))
         self.connect(header_descrambler, blocks.file_sink(1,                             'post-hdr-demod.dat'))
     ### Payload demod ####################################################
     payload_fft = fft.fft_vcc(self.fft_len, True, (), True)
     payload_constellation = _get_constellation(bps_payload)
     payload_equalizer = digital.ofdm_equalizer_simpledfe(
             fft_len,
             payload_constellation.base(),
             occupied_carriers,
             pilot_carriers,
             pilot_symbols,
             symbols_skipped=1, # (that was already in the header)
             alpha=0.1
     )
     payload_eq = digital.ofdm_frame_equalizer_vcvc(
             payload_equalizer.base(),
             cp_len,
             self.frame_length_tag_key
     )
     payload_serializer = digital.ofdm_serializer_vcc(
             fft_len, occupied_carriers,
             self.frame_length_tag_key,
             self.packet_length_tag_key,
             1 # Skip 1 symbol (that was already in the header)
     )
     payload_demod = digital.constellation_decoder_cb(payload_constellation.base())
     self.payload_descrambler = digital.additive_scrambler_bb(
         0x8a,
         self.scramble_seed,
         7,
         0, # Don't reset after fixed length
         bits_per_byte=8, # This is after packing
         reset_tag_key=self.packet_length_tag_key
     )
     payload_pack = blocks.repack_bits_bb(bps_payload, 8, self.packet_length_tag_key, True)
     self.crc = digital.crc32_bb(True, self.packet_length_tag_key)
     self.connect(
             (hpd, 1),
             payload_fft,
             payload_eq,
             payload_serializer,
             payload_demod,
             payload_pack,
             self.payload_descrambler,
             self.crc,
             self
     )
     if debug_log:
         self.connect((hpd, 1),           blocks.tag_debug(gr.sizeof_gr_complex*fft_len, 'post-hpd'))
         self.connect(payload_fft,        blocks.file_sink(gr.sizeof_gr_complex*fft_len, 'post-payload-fft.dat'))
         self.connect(payload_eq,         blocks.file_sink(gr.sizeof_gr_complex*fft_len, 'post-payload-eq.dat'))
         self.connect(payload_serializer, blocks.file_sink(gr.sizeof_gr_complex,         'post-payload-serializer.dat'))
         self.connect(payload_demod,      blocks.file_sink(1,                            'post-payload-demod.dat'))
         self.connect(payload_pack,       blocks.file_sink(1,                            'post-payload-pack.dat'))
         self.connect(crc,                blocks.file_sink(1,                            'post-payload-crc.dat'))
Beispiel #8
0
 def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len,
              frame_length_tag_key=_def_frame_length_tag_key,
              packet_length_tag_key=_def_packet_length_tag_key,
              packet_num_tag_key=_def_packet_num_tag_key,
              occupied_carriers=_def_occupied_carriers,
              pilot_carriers=_def_pilot_carriers,
              pilot_symbols=_def_pilot_symbols,
              bps_header=1,
              bps_payload=1,
              sync_word1=None,
              sync_word2=None
              ):
     gr.hier_block2.__init__(self, "ofdm_rx",
                 gr.io_signature(1, 1, gr.sizeof_gr_complex),
                 gr.io_signature(1, 1, gr.sizeof_char))
     self.fft_len           = fft_len
     self.cp_len            = cp_len
     self.frame_length_tag_key    = frame_length_tag_key
     self.packet_length_tag_key   = packet_length_tag_key
     self.occupied_carriers = occupied_carriers
     self.bps_header        = bps_header
     self.bps_payload       = bps_payload
     n_sync_words = 1
     header_constellation  = _get_constellation(bps_header)
     if sync_word1 is None:
         self.sync_word1 = _make_sync_word(fft_len, occupied_carriers, header_constellation)
     else:
         if len(sync_word1) != self.fft_len:
             raise ValueError("Length of sync sequence(s) must be FFT length.")
         self.sync_word1 = sync_word1
     self.sync_word2 = ()
     if sync_word2 is not None:
         if len(sync_word2) != fft_len:
             raise ValueError("Length of sync sequence(s) must be FFT length.")
         self.sync_word2 = sync_word2
         n_sync_words = 2
     else:
         sync_word2 = ()
     # Receiver path
     sync_detect = digital.ofdm_sync_sc_cfb(fft_len, cp_len)
     oscillator = analog.frequency_modulator_fc(-2.0 / fft_len)
     delay = gr.delay(gr.sizeof_gr_complex, fft_len+cp_len)
     mixer = gr.multiply_cc()
     hpd = digital.header_payload_demux(n_sync_words, fft_len, cp_len,
             frame_length_tag_key, "", True)
     self.connect(self, sync_detect)
     self.connect((sync_detect, 0), oscillator, (mixer, 0))
     self.connect(self, delay, (mixer, 1))
     self.connect(mixer, (hpd, 0))
     self.connect((sync_detect, 1), (hpd, 1))
     # Header demodulation
     header_fft = fft.fft_vcc(self.fft_len, True, (), True)
     chanest = digital.ofdm_chanest_vcvc(self.sync_word1, self.sync_word2, 1)
     header_equalizer = digital.ofdm_equalizer_simpledfe(
             fft_len, header_constellation.base(),
             occupied_carriers, pilot_carriers, pilot_symbols
     )
     header_eq = digital.ofdm_frame_equalizer_vcvc(header_equalizer.base(), frame_length_tag_key, True)
     header_serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers)
     header_constellation = _get_constellation(bps_header)
     header_demod = digital.constellation_decoder_cb(header_constellation.base())
     header_formatter = digital.packet_header_ofdm(
             occupied_carriers, 1,
             packet_length_tag_key,
             frame_length_tag_key,
             packet_num_tag_key,
             bps_header
     )
     header_parser = digital.packet_headerparser_b(header_formatter.formatter())
     self.connect((hpd, 0), header_fft, chanest, header_eq, header_serializer, header_demod, header_parser)
     self.msg_connect(header_parser, "header_data", hpd, "header_data")
     # Payload demodulation
     payload_fft = fft.fft_vcc(self.fft_len, True, (), True)
     payload_equalizer = digital.ofdm_equalizer_simpledfe(
             fft_len, header_constellation.base(),
             occupied_carriers, pilot_carriers, pilot_symbols, 1
     )
     payload_eq = digital.ofdm_frame_equalizer_vcvc(payload_equalizer.base(), frame_length_tag_key)
     payload_serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers)
     payload_constellation = _get_constellation(bps_payload)
     payload_demod = digital.constellation_decoder_cb(payload_constellation.base())
     bit_packer = blocks.repack_bits_bb(bps_payload, 8, packet_length_tag_key, True)
     self.connect((hpd, 1), payload_fft, payload_eq, payload_serializer, payload_demod, bit_packer, self)