def test_wo_tags_2s_rolloff(self): " No tags, but have a 2-sample rolloff " fft_len = 8 cp_len = 2 rolloff = 2 expected_result = ( 7.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 7.0 / 2 + 1.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8) src = gr.vector_source_c(range(1, fft_len + 1) * 2, False, fft_len) cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, rolloff) sink = gr.vector_sink_c() self.tb.connect(src, cp, sink) self.tb.run() self.assertEqual(sink.data(), expected_result)
def test_with_tags_2s_rolloff(self): " With tags and a 2-sample rolloff " fft_len = 8 cp_len = 2 tag_name = "length" expected_result = (7.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 7.0/2+1.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1.0/2) tag = gr.gr_tag_t() tag.offset = 0 tag.key = pmt.pmt_string_to_symbol(tag_name) tag.value = pmt.pmt_from_long(2) tag2 = gr.gr_tag_t() tag2.offset = 1 tag2.key = pmt.pmt_string_to_symbol("random_tag") tag2.value = pmt.pmt_from_long(42) src = gr.vector_source_c(range(1, fft_len+1) * 2, False, fft_len, (tag, tag2)) cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, 2, tag_name) sink = gr.vector_sink_c() self.tb.connect(src, cp, sink) self.tb.run() self.assertEqual(sink.data(), expected_result) tags = [gr.tag_to_python(x) for x in sink.tags()] tags = sorted([(x.offset, x.key, x.value) for x in tags]) expected_tags = [ (0, tag_name, len(expected_result)), (fft_len+cp_len, "random_tag", 42) ] self.assertEqual(tags, expected_tags)
def test_wo_tags_no_rolloff(self): " The easiest test: make sure the CP is added correctly. " fft_len = 8 cp_len = 2 expected_result = (6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7) src = gr.vector_source_c(range(fft_len) * 2, False, fft_len) cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len) sink = gr.vector_sink_c() self.tb.connect(src, cp, sink) self.tb.run() self.assertEqual(sink.data(), expected_result)
def test_wo_tags_2s_rolloff(self): " No tags, but have a 2-sample rolloff " fft_len = 8 cp_len = 2 rolloff = 2 expected_result = (7.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 7.0/2+1.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8) src = gr.vector_source_c(range(1, fft_len+1) * 2, False, fft_len) cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, rolloff) sink = gr.vector_sink_c() self.tb.connect(src, cp, sink) self.tb.run() self.assertEqual(sink.data(), expected_result)
def test_with_tags_2s_rolloff(self): " With tags and a 2-sample rolloff " fft_len = 8 cp_len = 2 tag_name = "length" expected_result = ( 7.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 7.0 / 2 + 1.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1.0 / 2) tag = gr.gr_tag_t() tag.offset = 0 tag.key = pmt.pmt_string_to_symbol(tag_name) tag.value = pmt.pmt_from_long(2) tag2 = gr.gr_tag_t() tag2.offset = 1 tag2.key = pmt.pmt_string_to_symbol("random_tag") tag2.value = pmt.pmt_from_long(42) src = gr.vector_source_c( range(1, fft_len + 1) * 2, False, fft_len, (tag, tag2)) cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, 2, tag_name) sink = gr.vector_sink_c() self.tb.connect(src, cp, sink) self.tb.run() self.assertEqual(sink.data(), expected_result) tags = [gr.tag_to_python(x) for x in sink.tags()] tags = sorted([(x.offset, x.key, x.value) for x in tags]) expected_tags = [(0, tag_name, len(expected_result)), (fft_len + cp_len, "random_tag", 42)] self.assertEqual(tags, expected_tags)
def __init__(self, options, msgq_limit=2, pad_for_usrp=True): """ Hierarchical block for sending packets Packets to be sent are enqueued by calling send_pkt. The output is the complex modulated signal at baseband. @param options: pass modulation options from higher layers (fft length, occupied tones, etc.) @param msgq_limit: maximum number of messages in message queue @type msgq_limit: int @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples """ gr.hier_block2.__init__(self, "ofdm_mod", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._pad_for_usrp = pad_for_usrp self._modulation = options.modulation self._fft_length = options.fft_length self._occupied_tones = options.occupied_tones self._cp_length = options.cp_length win = [] #[1 for i in range(self._fft_length)] # Use freq domain to get doubled-up known symbol for correlation in time domain zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0)) ksfreq = known_symbols_4512_3[0:self._occupied_tones] for i in range(len(ksfreq)): if((zeros_on_left + i) & 1): ksfreq[i] = 0 # hard-coded known symbols preambles = (ksfreq,) padded_preambles = list() for pre in preambles: padded = self._fft_length*[0,] padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre padded_preambles.append(padded) symbol_length = options.fft_length + options.cp_length mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256} arity = mods[self._modulation] rot = 1 if self._modulation == "qpsk": rot = (0.707+0.707j) # FIXME: pass the constellation objects instead of just the points if(self._modulation.find("psk") >= 0): constel = psk.psk_constellation(arity) rotated_const = map(lambda pt: pt * rot, constel.points()) elif(self._modulation.find("qam") >= 0): constel = qam.qam_constellation(arity) rotated_const = map(lambda pt: pt * rot, constel.points()) #print rotated_const self._pkt_input = digital_swig.ofdm_mapper_bcv(rotated_const, msgq_limit, options.occupied_tones, options.fft_length) self.preambles = digital_swig.ofdm_insert_preamble(self._fft_length, padded_preambles) self.ifft = gr.fft_vcc(self._fft_length, False, win, True) self.cp_adder = digital_swig.ofdm_cyclic_prefixer(self._fft_length, symbol_length) self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length)) self.connect((self._pkt_input, 0), (self.preambles, 0)) self.connect((self._pkt_input, 1), (self.preambles, 1)) self.connect(self.preambles, self.ifft, self.cp_adder, self.scale, self) if options.verbose: self._print_verbage() if options.log: self.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_mapper_c.dat")) self.connect(self.preambles, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_preambles.dat")) self.connect(self.ifft, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_ifft_c.dat")) self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder_c.dat"))
def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len, packet_length_tag_key=_def_packet_length_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, rolloff=0, debug_log=False, scramble_bits=False): gr.hier_block2.__init__(self, "ofdm_tx", gr.io_signature(1, 1, gr.sizeof_char), gr.io_signature(1, 1, gr.sizeof_gr_complex)) ### Param init / sanity check ######################################## self.fft_len = fft_len self.cp_len = cp_len self.packet_length_tag_key = packet_length_tag_key self.occupied_carriers = occupied_carriers self.pilot_carriers = pilot_carriers self.pilot_symbols = pilot_symbols self.bps_header = bps_header self.bps_payload = bps_payload self.sync_word1 = sync_word1 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_words = [ self.sync_word1, ] if sync_word2 is None: self.sync_word2 = _make_sync_word2(fft_len, occupied_carriers, pilot_carriers) else: self.sync_word2 = sync_word2 if len(self.sync_word2): if len(self.sync_word2) != fft_len: raise ValueError( "Length of sync sequence(s) must be FFT length.") self.sync_word2 = list(self.sync_word2) self.sync_words.append(self.sync_word2) if scramble_bits: self.scramble_seed = 0x7f else: self.scramble_seed = 0x00 # We deactivate the scrambler by init'ing it with zeros ### Header modulation ################################################ crc = digital.crc32_bb(False, self.packet_length_tag_key) header_constellation = _get_constellation(bps_header) header_mod = digital.chunks_to_symbols_bc( header_constellation.points()) formatter_object = digital.packet_header_ofdm( occupied_carriers=occupied_carriers, n_syms=1, bits_per_header_sym=self.bps_header, bits_per_payload_sym=self.bps_payload, scramble_header=scramble_bits) header_gen = digital.packet_headergenerator_bb( formatter_object.base(), self.packet_length_tag_key) header_payload_mux = blocks.tagged_stream_mux( itemsize=gr.sizeof_gr_complex * 1, lengthtagname=self.packet_length_tag_key, tag_preserve_head_pos= 1 # Head tags on the payload stream stay on the head ) self.connect(self, crc, header_gen, header_mod, (header_payload_mux, 0)) if debug_log: self.connect(header_gen, blocks.file_sink(1, 'tx-hdr.dat')) ### Payload modulation ############################################### payload_constellation = _get_constellation(bps_payload) payload_mod = digital.chunks_to_symbols_bc( payload_constellation.points()) payload_scrambler = digital.additive_scrambler_bb( 0x8a, self.scramble_seed, 7, 0, # Don't reset after fixed length (let the reset tag do that) bits_per_byte=8, # This is before unpacking reset_tag_key=self.packet_length_tag_key) payload_unpack = blocks.repack_bits_bb( 8, # Unpack 8 bits per byte bps_payload, self.packet_length_tag_key) self.connect(crc, payload_scrambler, payload_unpack, payload_mod, (header_payload_mux, 1)) ### Create OFDM frame ################################################ allocator = digital.ofdm_carrier_allocator_cvc( self.fft_len, occupied_carriers=self.occupied_carriers, pilot_carriers=self.pilot_carriers, pilot_symbols=self.pilot_symbols, sync_words=self.sync_words, len_tag_key=self.packet_length_tag_key) ffter = fft.fft_vcc( self.fft_len, False, # Inverse FFT (), # No window True # Shift ) cyclic_prefixer = digital.ofdm_cyclic_prefixer( self.fft_len, self.fft_len + self.cp_len, rolloff, self.packet_length_tag_key) self.connect(header_payload_mux, allocator, ffter, cyclic_prefixer, self) if debug_log: self.connect( allocator, blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'tx-post-allocator.dat')) self.connect( cyclic_prefixer, blocks.file_sink(gr.sizeof_gr_complex, 'tx-signal.dat'))
def __init__(self, options, msgq_limit=2, pad_for_usrp=True): """ Hierarchical block for sending packets Packets to be sent are enqueued by calling send_pkt. The output is the complex modulated signal at baseband. @param options: pass modulation options from higher layers (fft length, occupied tones, etc.) @param msgq_limit: maximum number of messages in message queue @type msgq_limit: int @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples """ gr.hier_block2.__init__(self, "ofdm_mod", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._pad_for_usrp = pad_for_usrp self._modulation = options.modulation self._fft_length = options.fft_length self._occupied_tones = options.occupied_tones self._cp_length = options.cp_length win = [] #[1 for i in range(self._fft_length)] # Use freq domain to get doubled-up known symbol for correlation in time domain zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0)) # ksfreq = known_symbols_4512_3[0:self._occupied_tones] # This fixed the bug, when the occupied tones are greater that the known symbols ksfreq = [0] * self._occupied_tones known_symbols_len = len(known_symbols_4512_3) for i in range(self._occupied_tones): ksfreq[i] = known_symbols_4512_3[i % known_symbols_len] for i in range(len(ksfreq)): if((zeros_on_left + i) & 1): ksfreq[i] = 0 # hard-coded known symbols preambles = (ksfreq,) padded_preambles = list() for pre in preambles: padded = self._fft_length*[0,] padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre padded_preambles.append(padded) symbol_length = options.fft_length + options.cp_length mods = {"qpsk": 4, "qam16": 16, "qam64": 64} arity = mods[self._modulation] rot = 1 #Create constellation objects for payload data. if(self._modulation.find("qpsk") >= 0): constel = dvbt_constellations.dvbt_qpsk_constellation(arity) elif(self._modulation.find("qam16") >= 0): constel = dvbt_constellations.dvbt_16qam_constellation(arity,False,mod_codes.GRAY_CODE) elif(self._modulation.find("qam64") >= 0): constel = dvbt_constellations.dvbt_64qam_constellation(arity,False,mod_codes.GRAY_CODE) rotated_const = constel.points() print rotated_const #Create constellation objects for pilot signals cs_constel = dvbt_constellations.dvbt_cs_pilots() tps_constel = dvbt_constellations.dvbt_tps_pilots() #print cs_constel.points() #print "\n" #print tps_constel.points() self._pkt_input = digital_swig.dvbt_ofdm_mapper_bcv(rotated_const,tps_constel.points(), cs_constel.points(), msgq_limit, options.occupied_tones, options.fft_length) self.preambles = digital_swig.ofdm_insert_preamble(self._fft_length, padded_preambles) self.ifft = gr.fft_vcc(self._fft_length, False, win, True) self.cp_adder = digital_swig.ofdm_cyclic_prefixer(self._fft_length, symbol_length) self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length)) self.connect((self._pkt_input, 0), (self.preambles, 0)) self.connect((self._pkt_input, 1), (self.preambles, 1)) self.connect(self.preambles, self.ifft, self.cp_adder, self.scale, self) if options.verbose: self._print_verbage() if options.log: self.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_mapper_c.dat")) self.connect(self.preambles, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_preambles.dat")) self.connect(self.ifft, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_ifft_c.dat")) self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder_c.dat"))
def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len, packet_length_tag_key=_def_packet_length_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, rolloff=0, debug_log=False, scramble_bits=False ): gr.hier_block2.__init__(self, "ofdm_tx", gr.io_signature(1, 1, gr.sizeof_char), gr.io_signature(1, 1, gr.sizeof_gr_complex)) ### Param init / sanity check ######################################## self.fft_len = fft_len self.cp_len = cp_len self.packet_length_tag_key = packet_length_tag_key self.occupied_carriers = occupied_carriers self.pilot_carriers = pilot_carriers self.pilot_symbols = pilot_symbols self.bps_header = bps_header self.bps_payload = bps_payload self.sync_word1 = sync_word1 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_words = [self.sync_word1,] if sync_word2 is None: self.sync_word2 = _make_sync_word2(fft_len, occupied_carriers, pilot_carriers) else: self.sync_word2 = sync_word2 if len(self.sync_word2): if len(self.sync_word2) != fft_len: raise ValueError("Length of sync sequence(s) must be FFT length.") self.sync_word2 = list(self.sync_word2) self.sync_words.append(self.sync_word2) if scramble_bits: self.scramble_seed = 0x7f else: self.scramble_seed = 0x00 # We deactivate the scrambler by init'ing it with zeros ### Header modulation ################################################ crc = digital.crc32_bb(False, self.packet_length_tag_key) header_constellation = _get_constellation(bps_header) header_mod = digital.chunks_to_symbols_bc(header_constellation.points()) formatter_object = digital.packet_header_ofdm( occupied_carriers=occupied_carriers, n_syms=1, bits_per_header_sym=self.bps_header, bits_per_payload_sym=self.bps_payload, scramble_header=scramble_bits ) header_gen = digital.packet_headergenerator_bb(formatter_object.base(), self.packet_length_tag_key) header_payload_mux = blocks.tagged_stream_mux( itemsize=gr.sizeof_gr_complex*1, lengthtagname=self.packet_length_tag_key, tag_preserve_head_pos=1 # Head tags on the payload stream stay on the head ) self.connect( self, crc, header_gen, header_mod, (header_payload_mux, 0) ) if debug_log: self.connect(header_gen, blocks.file_sink(1, 'tx-hdr.dat')) ### Payload modulation ############################################### payload_constellation = _get_constellation(bps_payload) payload_mod = digital.chunks_to_symbols_bc(payload_constellation.points()) payload_scrambler = digital.additive_scrambler_bb( 0x8a, self.scramble_seed, 7, 0, # Don't reset after fixed length (let the reset tag do that) bits_per_byte=8, # This is before unpacking reset_tag_key=self.packet_length_tag_key ) payload_unpack = blocks.repack_bits_bb( 8, # Unpack 8 bits per byte bps_payload, self.packet_length_tag_key ) self.connect( crc, payload_scrambler, payload_unpack, payload_mod, (header_payload_mux, 1) ) ### Create OFDM frame ################################################ allocator = digital.ofdm_carrier_allocator_cvc( self.fft_len, occupied_carriers=self.occupied_carriers, pilot_carriers=self.pilot_carriers, pilot_symbols=self.pilot_symbols, sync_words=self.sync_words, len_tag_key=self.packet_length_tag_key ) ffter = fft.fft_vcc( self.fft_len, False, # Inverse FFT (), # No window True # Shift ) cyclic_prefixer = digital.ofdm_cyclic_prefixer( self.fft_len, self.fft_len+self.cp_len, rolloff, self.packet_length_tag_key ) self.connect(header_payload_mux, allocator, ffter, cyclic_prefixer, self) if debug_log: self.connect(allocator, blocks.file_sink(gr.sizeof_gr_complex * fft_len, 'tx-post-allocator.dat')) self.connect(cyclic_prefixer, blocks.file_sink(gr.sizeof_gr_complex, 'tx-signal.dat'))
def __init__(self, options, msgq_limit=2, pad_for_usrp=True): """ Hierarchical block for sending packets Packets to be sent are enqueued by calling send_pkt. The output is the complex modulated signal at baseband. @param options: pass modulation options from higher layers (fft length, occupied tones, etc.) @param msgq_limit: maximum number of messages in message queue @type msgq_limit: int @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples """ gr.hier_block2.__init__(self, "ofdm_mod", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._pad_for_usrp = pad_for_usrp self._modulation = options.modulation self._fft_length = options.fft_length self._occupied_tones = options.occupied_tones self._cp_length = options.cp_length win = [] #[1 for i in range(self._fft_length)] # Use freq domain to get doubled-up known symbol for correlation in time domain zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0)) ksfreq = known_symbols_4512_3[0:self._occupied_tones] for i in range(len(ksfreq)): if((zeros_on_left + i) & 1): ksfreq[i] = 0 # hard-coded known symbols preambles = (ksfreq,) # print preambles padded_preambles = list() for pre in preambles: padded = self._fft_length*[0,] padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre padded_preambles.append(padded) # print # print padded_preambles symbol_length = options.fft_length + options.cp_length mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256} arity = mods[self._modulation] rot = 1 if self._modulation == "qpsk": rot = (0.707+0.707j) # FIXME: pass the constellation objects instead of just the points if(self._modulation.find("psk") >= 0): constel = psk.psk_constellation(arity) rotated_const = map(lambda pt: pt * rot, constel.points()) elif(self._modulation.find("qam") >= 0): constel = qam.qam_constellation(arity) rotated_const = map(lambda pt: pt * rot, constel.points()) #print rotated_const self._pkt_input = digital_swig.ofdm_mapper_bcv(rotated_const, msgq_limit, options.occupied_tones, options.fft_length) self.preambles = digital_swig.ofdm_insert_preamble(self._fft_length, padded_preambles) self.ifft = gr.fft_vcc(self._fft_length, False, win, True) self.cp_adder = digital_swig.ofdm_cyclic_prefixer(self._fft_length, symbol_length) self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length)) self.v2s = gr.vector_to_stream(gr.sizeof_gr_complex, self._fft_length+self._cp_length) self.connect((self._pkt_input, 0), (self.preambles, 0)) self.connect((self._pkt_input, 1), (self.preambles, 1)) self.connect((self._pkt_input, 2), (self.preambles, 2)) self.connect(self.preambles, self.ifft, self.cp_adder) self.connect((self.preambles, 1), gr.null_sink(gr.sizeof_char)) self.connect((self.preambles, 2), (self.cp_adder, 1)) self.connect(self.cp_adder, self.scale, self) if options.verbose: self._print_verbage() if options.log: self.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_mapper_c.dat")) self.connect(self.preambles, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_preambles.dat")) self.connect((self.preambles, 2), gr.file_sink(gr.sizeof_char, "ofdm_preambles_debug.dat")) self.connect(self.ifft, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_ifft_c.dat")) self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder_c.dat"))
def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len, packet_length_tag_key=_def_packet_length_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, rolloff=0, debug_log=False): gr.hier_block2.__init__(self, "ofdm_tx", gr.io_signature(1, 1, gr.sizeof_char), gr.io_signature(1, 1, gr.sizeof_gr_complex)) ### Param init / sanity check ######################################## self.fft_len = fft_len self.cp_len = cp_len self.packet_length_tag_key = packet_length_tag_key self.occupied_carriers = occupied_carriers self.pilot_carriers = pilot_carriers self.pilot_symbols = pilot_symbols self.bps_header = bps_header self.bps_payload = bps_payload n_sync_words = 1 self.sync_word1 = sync_word1 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_words = [ self.sync_word1, ] self.sync_word2 = () if sync_word2 is None: self.sync_word2 = _make_sync_word2(fft_len, occupied_carriers, pilot_carriers) if len(self.sync_word2): if len(self.sync_word2) != fft_len: raise ValueError( "Length of sync sequence(s) must be FFT length.") self.sync_word2 = list(self.sync_word2) n_sync_words = 2 self.sync_words.append(self.sync_word2) ### Header modulation ################################################ crc = digital.crc32_bb(False, self.packet_length_tag_key) header_constellation = _get_constellation(bps_header) header_mod = digital.chunks_to_symbols_bc( header_constellation.points()) formatter_object = digital.packet_header_ofdm( occupied_carriers=occupied_carriers, n_syms=1, bits_per_header_sym=self.bps_header, bits_per_payload_sym=self.bps_payload) header_gen = digital.packet_headergenerator_bb( formatter_object.base(), self.packet_length_tag_key) header_payload_mux = blocks.tagged_stream_mux( gr.sizeof_gr_complex * 1, self.packet_length_tag_key) self.connect(self, crc, header_gen, header_mod, (header_payload_mux, 0)) if debug_log: self.connect(header_gen, blocks.file_sink(1, 'tx-hdr.dat')) ### Payload modulation ############################################### payload_constellation = _get_constellation(bps_payload) payload_mod = digital.chunks_to_symbols_bc( payload_constellation.points()) self.connect( crc, blocks.repack_bits_bb( 8, # Unpack 8 bits per byte bps_payload, self.packet_length_tag_key), payload_mod, (header_payload_mux, 1)) ### Create OFDM frame ################################################ allocator = digital.ofdm_carrier_allocator_cvc( self.fft_len, occupied_carriers=self.occupied_carriers, pilot_carriers=self.pilot_carriers, pilot_symbols=self.pilot_symbols, sync_words=self.sync_words, len_tag_key=self.packet_length_tag_key) ffter = fft.fft_vcc( self.fft_len, False, # Inverse FFT (), # No window True # Shift ) cyclic_prefixer = digital.ofdm_cyclic_prefixer( self.fft_len, self.fft_len + self.cp_len, rolloff, self.packet_length_tag_key) self.connect(header_payload_mux, allocator, ffter, cyclic_prefixer, self) if debug_log: self.connect(allocator, blocks.file_sink(8 * 64, 'tx-post-allocator.dat')) self.connect(cyclic_prefixer, blocks.file_sink(8, 'tx-signal.dat'))
def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len, packet_length_tag_key=_def_packet_length_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, rolloff=0, debug_log=False ): gr.hier_block2.__init__(self, "ofdm_tx", gr.io_signature(1, 1, gr.sizeof_char), gr.io_signature(1, 1, gr.sizeof_gr_complex)) ### Param init / sanity check ######################################## self.fft_len = fft_len self.cp_len = cp_len self.packet_length_tag_key = packet_length_tag_key self.occupied_carriers = occupied_carriers self.pilot_carriers = pilot_carriers self.pilot_symbols = pilot_symbols self.bps_header = bps_header self.bps_payload = bps_payload n_sync_words = 1 self.sync_word1 = sync_word1 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_words = [self.sync_word1,] self.sync_word2 = () if sync_word2 is None: self.sync_word2 = _make_sync_word2(fft_len, occupied_carriers, pilot_carriers) if len(self.sync_word2): if len(self.sync_word2) != fft_len: raise ValueError("Length of sync sequence(s) must be FFT length.") self.sync_word2 = list(self.sync_word2) n_sync_words = 2 self.sync_words.append(self.sync_word2) ### Header modulation ################################################ crc = digital.crc32_bb(False, self.packet_length_tag_key) header_constellation = _get_constellation(bps_header) header_mod = digital.chunks_to_symbols_bc(header_constellation.points()) formatter_object = digital.packet_header_ofdm( occupied_carriers=occupied_carriers, n_syms=1, bits_per_header_sym=self.bps_header, bits_per_payload_sym=self.bps_payload ) header_gen = digital.packet_headergenerator_bb(formatter_object.base(), self.packet_length_tag_key) header_payload_mux = blocks.tagged_stream_mux(gr.sizeof_gr_complex*1, self.packet_length_tag_key) self.connect(self, crc, header_gen, header_mod, (header_payload_mux, 0)) if debug_log: self.connect(header_gen, blocks.file_sink(1, 'tx-hdr.dat')) ### Payload modulation ############################################### payload_constellation = _get_constellation(bps_payload) payload_mod = digital.chunks_to_symbols_bc(payload_constellation.points()) self.connect( crc, blocks.repack_bits_bb( 8, # Unpack 8 bits per byte bps_payload, self.packet_length_tag_key ), payload_mod, (header_payload_mux, 1) ) ### Create OFDM frame ################################################ allocator = digital.ofdm_carrier_allocator_cvc( self.fft_len, occupied_carriers=self.occupied_carriers, pilot_carriers=self.pilot_carriers, pilot_symbols=self.pilot_symbols, sync_words=self.sync_words, len_tag_key=self.packet_length_tag_key ) ffter = fft.fft_vcc( self.fft_len, False, # Inverse FFT (), # No window True # Shift ) cyclic_prefixer = digital.ofdm_cyclic_prefixer( self.fft_len, self.fft_len+self.cp_len, rolloff, self.packet_length_tag_key ) self.connect(header_payload_mux, allocator, ffter, cyclic_prefixer, self) if debug_log: self.connect(allocator, blocks.file_sink(8*64, 'tx-post-allocator.dat')) self.connect(cyclic_prefixer, blocks.file_sink(8, 'tx-signal.dat'))
def __init__(self, fft_len=_def_fft_len, cp_len=_def_cp_len, frame_length_tag_key=_def_frame_length_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, rolloff=0 ): gr.hier_block2.__init__(self, "ofdm_tx", gr.io_signature(1, 1, gr.sizeof_char), gr.io_signature(1, 1, gr.sizeof_gr_complex)) self.fft_len = fft_len self.cp_len = cp_len self.frame_length_tag_key = frame_length_tag_key self.occupied_carriers = occupied_carriers self.pilot_carriers = pilot_carriers self.pilot_symbols = pilot_symbols self.bps_header = bps_header self.bps_payload = bps_payload n_sync_words = 1 header_constellation = _get_constellation(bps_header) header_mod = digital.chunks_to_symbols_bc(header_constellation.points()) self.sync_word1 = sync_word1 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.") total_sync_word = self.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 total_sync_word = sync_word1 + sync_word2 crc = digital.crc32_bb(False, self.frame_length_tag_key) formatter_object = digital.packet_header_ofdm( occupied_carriers, 1, "", "", "", bps_header ) header_gen = digital.packet_headergenerator_bb(formatter_object.base()) header_payload_mux = blocks.tagged_stream_mux(gr.sizeof_gr_complex*1, self.frame_length_tag_key) self.connect(self, crc, header_gen, header_mod, (header_payload_mux, 0)) payload_constellation = _get_constellation(bps_payload) payload_mod = digital.chunks_to_symbols_bc(payload_constellation.points()) self.connect( crc, blocks.repack_bits_bb(8, bps_payload, frame_length_tag_key), payload_mod, (header_payload_mux, 1) ) self.connect(payload_mod, gr.tag_debug(gr.sizeof_gr_complex, "pmod")) sync_word_gen = gr.vector_source_c( total_sync_word, True, self.fft_len, tagged_streams.make_lengthtags((n_sync_words,), (0,), self.frame_length_tag_key) ) allocator = digital.ofdm_carrier_allocator_cvc( self.fft_len, occupied_carriers=self.occupied_carriers, pilot_carriers=self.pilot_carriers, pilot_symbols=self.pilot_symbols, len_tag_key=self.frame_length_tag_key ) syncword_data_mux = blocks.tagged_stream_mux(gr.sizeof_gr_complex*self.fft_len, self.frame_length_tag_key) self.connect(sync_word_gen, (syncword_data_mux, 0)) self.connect(header_payload_mux, allocator, (syncword_data_mux, 1)) ffter = fft.fft_vcc(self.fft_len, False, (), False) cyclic_prefixer = digital.ofdm_cyclic_prefixer( self.fft_len, self.fft_len+self.cp_len, rolloff, self.frame_length_tag_key ) self.connect(syncword_data_mux, ffter, cyclic_prefixer, self)
def __init__(self, options, msgq_limit=2, pad_for_usrp=True): """ Hierarchical block for sending packets Packets to be sent are enqueued by calling send_pkt. The output is the complex modulated signal at baseband. @param options: pass modulation options from higher layers (fft length, occupied tones, etc.) @param msgq_limit: maximum number of messages in message queue @type msgq_limit: int @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples """ gr.hier_block2.__init__(self, "ofdm_mod", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._pad_for_usrp = pad_for_usrp self._modulation = options.modulation self._fft_length = options.fft_length self._occupied_tones = options.occupied_tones self._cp_length = options.cp_length # apurv++ start # self._id = options.id self._fec_n = options.fec_n self._fec_k = options.fec_k self._batch_size = options.batch_size self._ack = options.ack if(self._fec_n < self._fec_k): print "ERROR: K > N in FEC!\n" exit(0); # apurv++ end # win = [] #[1 for i in range(self._fft_length)] # Use freq domain to get doubled-up known symbol for correlation in time domain zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0)) # apurv: use the preamble as a function of hop number # #ksfreq = known_symbols_4512_3[0:self._occupied_tones] start_index = (options.hop) * self._occupied_tones ksfreq = known_symbols_4512_3[start_index:start_index + self._occupied_tones] # allow another full preamble (no intermediate 0s for accurate channel estimate/snr measurement) preamble2_offset = 10*self._occupied_tones; ksfreq2 = known_symbols_4512_3[preamble2_offset:preamble2_offset+self._occupied_tones] ''' # inserting zeros in every other frequency bin # for i in range(len(ksfreq)): if((zeros_on_left + i) & 1): ksfreq[i] = 0 ''' # hard-coded known symbols preambles = (ksfreq, ksfreq2, ksfreq2) padded_preambles = list() for pre in preambles: padded = self._fft_length*[0,] padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre padded_preambles.append(padded) symbol_length = options.fft_length + options.cp_length mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256} hdr_rot = 1 hdr_arity = mods["bpsk"] hdr_constel = psk.psk_constellation(hdr_arity) hdr_rotated_const = map(lambda pt: pt * hdr_rot, hdr_constel.points()) data_rot = 1 data_arity = mods[self._modulation] if self._modulation == "qpsk": data_rot = (0.707+0.707j) if(self._modulation.find("psk") >= 0): data_constel = psk.psk_constellation(data_arity) data_rotated_const = map(lambda pt: pt * data_rot, data_constel.points()) elif(self._modulation.find("qam") >= 0): data_constel = qam.qam_constellation(data_arity) data_rotated_const = map(lambda pt: pt * data_rot, data_constel.points()) self._bits_per_symbol = int(math.log(mods[self._modulation], 2)) # just a useless parameter now # self._pkt_input = digital_swig.ofdm_mapper_bcv(hdr_rotated_const, data_rotated_const, padded_preambles,msgq_limit, options.occupied_tones, options.fft_length, options.tdma, options.proto, options.ack, options.id, options.src, options.batch_size, options.dst_id, options.fec_n, options.fec_k) self.ifft = gr.fft_vcc(self._fft_length, False, win, True) self.cp_adder = digital_swig.ofdm_cyclic_prefixer(self._fft_length, symbol_length) self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length)) self.burst_tagger = gr.burst_tagger(gr.sizeof_gr_complex) # 1 sample use_burst_tagger = 1 manual = options.tx_manual if manual == 0: if use_burst_tagger == 0: self.connect((self._pkt_input, 0), self.ifft, self.cp_adder, self.scale, self) else: # some burst tagger connections # self.connect((self._pkt_input, 0), self.ifft, self.cp_adder, self.burst_tagger, self.scale, self) self.connect((self._pkt_input, 1), (self.cp_adder, 1), (self.burst_tagger,1)) # Connect Apurv's trigger data to the burst tagger self.connect((self._pkt_input, 2), (self.cp_adder, 2)) # CDD elif manual == 1: # punt the pkt_input and use file source # self.connect(gr.file_source(gr.sizeof_gr_complex*options.fft_length, "fwd_tx_data.dat"), self.cp_adder, self.scale, self) self.connect(self.scale, gr.file_sink(gr.sizeof_gr_complex, "ofdm_fwd.dat")) if options.verbose: self._print_verbage() if options.log: self.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_mapper_c.dat")) self.connect(self.ifft, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "ofdm_ifft_c.dat")) self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder_c.dat")) #self.connect(self.cp_adder, gr.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder_c.dat")) self.connect(self._pkt_input, gr.file_sink(gr.sizeof_gr_complex*options.fft_length, "symbols_src.dat")) self.connect((self._pkt_input, 3), gr.file_sink(gr.sizeof_char, "timing.dat")) self.connect((self._pkt_input, 4), gr.file_sink(gr.sizeof_char*options.fft_length, "timing_src.dat"))