diff options
author | Tom Rondeau <trondeau@vt.edu> | 2013-04-01 12:30:55 -0400 |
---|---|---|
committer | Tom Rondeau <trondeau@vt.edu> | 2013-04-01 12:30:55 -0400 |
commit | fbd74560b72196fba9de8c6d01378b0715df758a (patch) | |
tree | f737a9f99d93efd3125c2f4260b6850e466da5d9 | |
parent | 007b401cf14fcfc067d11f5e4d2ca1730407803b (diff) | |
parent | 4918f83127c63e0d7c1ac8bfe0b0dd0d38dcfefd (diff) |
Merge remote-tracking branch 'mbant/sword2' into next
-rw-r--r-- | gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml | 8 | ||||
-rw-r--r-- | gr-digital/include/digital/ofdm_carrier_allocator_cvc.h | 20 | ||||
-rw-r--r-- | gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc | 49 | ||||
-rw-r--r-- | gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h | 13 | ||||
-rw-r--r-- | gr-digital/python/ofdm_txrx.py | 19 | ||||
-rwxr-xr-x | gr-digital/python/qa_ofdm_carrier_allocator_cvc.py | 47 |
6 files changed, 121 insertions, 35 deletions
diff --git a/gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml b/gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml index 826778ff37..b9bdde543d 100644 --- a/gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml +++ b/gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml @@ -3,7 +3,7 @@ <name>OFDM Carrier Allocator</name> <key>digital_ofdm_carrier_allocator_cvc</key> <import>from gnuradio import digital</import> - <make>digital.ofdm_carrier_allocator_cvc($fft_len, $occupied_carriers, $pilot_carriers, $pilot_symbols, $len_tag_key)</make> + <make>digital.ofdm_carrier_allocator_cvc($fft_len, $occupied_carriers, $pilot_carriers, $pilot_symbols, $sync_words, $len_tag_key)</make> <param> <name>FFT length</name> <key>fft_len</key> @@ -28,6 +28,12 @@ <type>raw</type> </param> <param> + <name>Sync Words</name> + <key>sync_words</key> + <value>()</value> + <type>raw</type> + </param> + <param> <name>Length tag key</name> <key>len_tag_key</key> <value>"packet_len"</value> diff --git a/gr-digital/include/digital/ofdm_carrier_allocator_cvc.h b/gr-digital/include/digital/ofdm_carrier_allocator_cvc.h index 8915c23c45..9c743e66b3 100644 --- a/gr-digital/include/digital/ofdm_carrier_allocator_cvc.h +++ b/gr-digital/include/digital/ofdm_carrier_allocator_cvc.h @@ -45,12 +45,15 @@ namespace gr { * containing the number of complex symbols in this frame. * Output: A tagged stream of complex vectors of length fft_len. This can directly * be connected to an FFT block. Make sure to set this block to 'reverse' - * for the IFFT and to deactivate FFT shifting. + * for the IFFT. If \p output_is_shifted is true, the FFT block must activate + * FFT shifting, otherwise, set shifting to false. If given, sync words are + * prepended to the output. Note that sync words are prepended verbatim, + * make sure they are shifted (or not). * * Carrier indexes are always such that index 0 is the DC carrier (note: you should * not allocate this carrier). The carriers below the DC carrier are either indexed - * with negative numbers, or with indexes larger than fft_len/2. Index -1 and index - * fft_len-1 both identify the carrier below the DC carrier. + * with negative numbers, or with indexes larger than \p fft_len/2. Index -1 and index + * \p fft_len-1 both identify the carrier below the DC carrier. * */ class DIGITAL_API ofdm_carrier_allocator_cvc : virtual public gr_tagged_stream_block @@ -63,6 +66,9 @@ namespace gr { virtual std::vector<std::vector<int> > occupied_carriers() = 0; /* + * \param fft_len FFT length, is also the maximum width of the OFDM symbols, the + * output vector size and maximum value for elements in + * \p occupied_carriers and \p pilot_carriers. * \param occupied_carriers A vector of vectors of indexes. Example: if * occupied_carriers = ((1, 2, 3), (1, 2, 4)), the first * three input symbols will be mapped to carriers 1, 2 @@ -78,6 +84,10 @@ namespace gr { * \param pilot_symbols The pilot symbols which are placed onto the pilot carriers. * pilot_symbols[0][0] is placed onto the first OFDM symbol, on * carrier index pilot_carriers[0][0] etc. + * \param sync_words OFDM symbols that are prepended to the OFDM frame (usually for + * synchronisation purposes, e.g. OFDM symbols with every second + * sub-carrier being idle). Is a vector of complex vectors of length + * \p fft_len * \param len_tag_key The key of the tag identifying the length of the input packet. */ static sptr make( @@ -85,7 +95,9 @@ namespace gr { const std::vector<std::vector<int> > &occupied_carriers, const std::vector<std::vector<int> > &pilot_carriers, const std::vector<std::vector<gr_complex> > &pilot_symbols, - const std::string &len_tag_key = "packet_len"); + const std::vector<std::vector<gr_complex> > &sync_words, + const std::string &len_tag_key = "packet_len", + const bool output_is_shifted=true); }; } // namespace digital diff --git a/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc index d7159547b4..afeb10e1d5 100644 --- a/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc +++ b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc @@ -36,7 +36,10 @@ namespace gr { const std::vector<std::vector<int> > &occupied_carriers, const std::vector<std::vector<int> > &pilot_carriers, const std::vector<std::vector<gr_complex> > &pilot_symbols, - const std::string &len_tag_key) + const std::vector<std::vector<gr_complex> > &sync_words, + const std::string &len_tag_key, + const bool output_is_shifted + ) { return gnuradio::get_initial_sptr( new ofdm_carrier_allocator_cvc_impl( @@ -44,20 +47,31 @@ namespace gr { occupied_carriers, pilot_carriers, pilot_symbols, - len_tag_key + sync_words, + len_tag_key, + output_is_shifted ) ); } - ofdm_carrier_allocator_cvc_impl::ofdm_carrier_allocator_cvc_impl(int fft_len, const std::vector<std::vector<int> > &occupied_carriers, const std::vector<std::vector<int> > &pilot_carriers, const std::vector<std::vector<gr_complex> > &pilot_symbols, const std::string &len_tag_key) - : gr_tagged_stream_block("ofdm_carrier_allocator_cvc", + ofdm_carrier_allocator_cvc_impl::ofdm_carrier_allocator_cvc_impl( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + const std::vector<std::vector<gr_complex> > &sync_words, + const std::string &len_tag_key, + const bool output_is_shifted + ) : gr_tagged_stream_block("ofdm_carrier_allocator_cvc", gr_make_io_signature(1, 1, sizeof (gr_complex)), gr_make_io_signature(1, 1, sizeof (gr_complex) * fft_len), len_tag_key), d_fft_len(fft_len), d_occupied_carriers(occupied_carriers), d_pilot_carriers(pilot_carriers), d_pilot_symbols(pilot_symbols), - d_symbols_per_set(0) + d_sync_words(sync_words), + d_symbols_per_set(0), + d_output_is_shifted(output_is_shifted) { for (unsigned i = 0; i < d_occupied_carriers.size(); i++) { for (unsigned j = 0; j < d_occupied_carriers[i].size(); j++) { @@ -67,6 +81,9 @@ namespace gr { if (d_occupied_carriers[i][j] > d_fft_len || d_occupied_carriers[i][j] < 0) { throw std::invalid_argument("data carrier index out of bounds"); } + if (d_output_is_shifted) { + d_occupied_carriers[i][j] = (d_occupied_carriers[i][j] + fft_len/2) % fft_len; + } } } for (unsigned i = 0; i < d_pilot_carriers.size(); i++) { @@ -80,6 +97,14 @@ namespace gr { if (d_pilot_carriers[i][j] > d_fft_len || d_pilot_carriers[i][j] < 0) { throw std::invalid_argument("pilot carrier index out of bounds"); } + if (d_output_is_shifted) { + d_pilot_carriers[i][j] = (d_pilot_carriers[i][j] + fft_len/2) % fft_len; + } + } + } + for (unsigned i = 0; i < d_sync_words.size(); i++) { + if (d_sync_words[i].size() != (unsigned) d_fft_len) { + throw std::invalid_argument("sync words must be fft length"); } } @@ -104,7 +129,7 @@ namespace gr { nout++; i += d_occupied_carriers[k % d_occupied_carriers.size()].size(); } - return nout; + return nout + d_sync_words.size(); } int @@ -115,10 +140,16 @@ namespace gr { { const gr_complex *in = (const gr_complex *) input_items[0]; gr_complex *out = (gr_complex *) output_items[0]; - std::vector<gr_tag_t> tags; memset((void *) out, 0x00, sizeof(gr_complex) * d_fft_len * noutput_items); + // Copy Sync word + for (unsigned i = 0; i < d_sync_words.size(); i++) { + memcpy((void *) out, (void *) &d_sync_words[i][0], sizeof(gr_complex) * d_fft_len); + out += d_fft_len; + } + + // Copy data symbols long n_ofdm_symbols = 0; int curr_set = 0; int symbols_to_allocate = d_occupied_carriers[0].size(); @@ -145,7 +176,7 @@ namespace gr { symbols_allocated = 0; } } - // 2) Copy pilot symbols + // Copy pilot symbols curr_set = 0; for (int i = 0; i < n_ofdm_symbols; i++) { for (unsigned k = 0; k < d_pilot_carriers[curr_set].size(); k++) { @@ -154,7 +185,7 @@ namespace gr { curr_set = (curr_set + 1) % d_pilot_carriers.size(); } - return n_ofdm_symbols; + return n_ofdm_symbols + d_sync_words.size(); } } /* namespace digital */ diff --git a/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h index 5da14332a5..6e478b3389 100644 --- a/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h +++ b/gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h @@ -39,13 +39,24 @@ namespace gr { std::vector<std::vector<int> > d_pilot_carriers; //! Value of said pilot symbols const std::vector<std::vector<gr_complex> > d_pilot_symbols; + //! Synch words + const std::vector<std::vector<gr_complex> > d_sync_words; int d_symbols_per_set; + const bool d_output_is_shifted; protected: int calculate_output_stream_length(const gr_vector_int &ninput_items); public: - ofdm_carrier_allocator_cvc_impl(int fft_len, const std::vector<std::vector<int> > &occupied_carriers, const std::vector<std::vector<int> > &pilot_carriers, const std::vector<std::vector<gr_complex> > &pilot_symbols, const std::string &len_tag_key); + ofdm_carrier_allocator_cvc_impl( + int fft_len, + const std::vector<std::vector<int> > &occupied_carriers, + const std::vector<std::vector<int> > &pilot_carriers, + const std::vector<std::vector<gr_complex> > &pilot_symbols, + const std::vector<std::vector<gr_complex> > &sync_words, + const std::string &len_tag_key, + const bool output_is_shifted + ); ~ofdm_carrier_allocator_cvc_impl(); std::string len_tag_key() { return d_length_tag_key_str; }; diff --git a/gr-digital/python/ofdm_txrx.py b/gr-digital/python/ofdm_txrx.py index c403ef6cbf..190354e262 100644 --- a/gr-digital/python/ofdm_txrx.py +++ b/gr-digital/python/ofdm_txrx.py @@ -118,17 +118,17 @@ class ofdm_tx(gr.hier_block2): 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_words = [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 + self.sync_words.append(self.sync_word2) crc = digital.crc32_bb(False, self.frame_length_tag_key) formatter_object = digital.packet_header_ofdm( - occupied_carriers, 1, "", "", "", + occupied_carriers, 1, self.frame_length_tag_key, self.frame_length_tag_key, "", bps_header ) header_gen = digital.packet_headergenerator_bb(formatter_object.base()) @@ -142,29 +142,22 @@ class ofdm_tx(gr.hier_block2): payload_mod, (header_payload_mux, 1) ) - self.connect(payload_mod, gr.tag_debug(gr.sizeof_gr_complex, "pmod")) - sync_word_gen = blocks.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, + sync_words=self.sync_words, 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) + ffter = fft.fft_vcc(self.fft_len, False, (), True) 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) + self.connect(header_payload_mux, allocator, ffter, cyclic_prefixer, self) class ofdm_rx(gr.hier_block2): diff --git a/gr-digital/python/qa_ofdm_carrier_allocator_cvc.py b/gr-digital/python/qa_ofdm_carrier_allocator_cvc.py index 0f5803a270..e1f017ba9e 100755 --- a/gr-digital/python/qa_ofdm_carrier_allocator_cvc.py +++ b/gr-digital/python/qa_ofdm_carrier_allocator_cvc.py @@ -35,14 +35,17 @@ class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase): def test_001_t (self): """ - pretty simple + pretty simple (the carrier allocation is not a practical OFDM configuration!) """ fft_len = 6 tx_symbols = (1, 2, 3) + # ^ this gets mapped to the DC carrier because occupied_carriers[0][0] == 0 pilot_symbols = ((1j,),) occupied_carriers = ((0, 1, 2),) pilot_carriers = ((3,),) - expected_result = (1, 2, 3, 1j, 0, 0) + sync_word = (range(fft_len),) + expected_result = tuple(sync_word[0] + [1j, 0, 0, 1, 2, 3]) + # ^ DC carrier tag_name = "len" tag = gr.gr_tag_t() tag.offset = 0 @@ -52,7 +55,35 @@ class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase): alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, - pilot_symbols, + pilot_symbols, sync_word, + tag_name) + sink = blocks.vector_sink_c(fft_len) + self.tb.connect(src, alloc, sink) + self.tb.run () + self.assertEqual(sink.data(), expected_result) + + def test_001_t2 (self): + """ + pretty simple (same as before, but odd fft len) + """ + fft_len = 5 + tx_symbols = (1, 2, 3) + # ^ this gets mapped to the DC carrier because occupied_carriers[0][0] == 0 + occupied_carriers = ((0, 1, 2),) + pilot_carriers = ((-2,),) + pilot_symbols = ((1j,),) + expected_result = (1j, 0, 1, 2, 3) + # ^ DC carrier + tag_name = "len" + tag = gr.gr_tag_t() + tag.offset = 0 + tag.key = pmt.string_to_symbol(tag_name) + tag.value = pmt.from_long(len(tx_symbols)) + src = blocks.vector_source_c(tx_symbols, False, 1, (tag,)) + alloc = digital.ofdm_carrier_allocator_cvc(fft_len, + occupied_carriers, + pilot_carriers, + pilot_symbols, (), tag_name) sink = blocks.vector_sink_c(fft_len) self.tb.connect(src, alloc, sink) @@ -68,7 +99,7 @@ class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase): pilot_symbols = ((1j,),) occupied_carriers = ((-1, 1, 2),) pilot_carriers = ((3,),) - expected_result = (0, 2, 3, 1j, 0, 1) + expected_result = (1j, 0, 1, 0, 2, 3) tag_name = "len" tag = gr.gr_tag_t() tag.offset = 0 @@ -78,7 +109,7 @@ class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase): alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, - pilot_symbols, + pilot_symbols, (), tag_name) sink = blocks.vector_sink_c(fft_len) self.tb.connect(src, alloc, sink) @@ -93,6 +124,7 @@ class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase): - have enough data for nearly 3 OFDM symbols - send that twice - add some random tags + - don't shift """ tx_symbols = range(1, 16); # 15 symbols pilot_symbols = ((1j, 2j), (3j, 4j)) @@ -132,8 +164,9 @@ class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase): alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, - pilot_symbols, - tag_name) + pilot_symbols, (), + tag_name, + False) sink = blocks.vector_sink_c(fft_len) self.tb.connect(src, alloc, sink) self.tb.run () |