summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-digital/grc/digital_ofdm_carrier_allocator_cvc.xml8
-rw-r--r--gr-digital/include/digital/ofdm_carrier_allocator_cvc.h20
-rw-r--r--gr-digital/lib/ofdm_carrier_allocator_cvc_impl.cc49
-rw-r--r--gr-digital/lib/ofdm_carrier_allocator_cvc_impl.h13
-rw-r--r--gr-digital/python/ofdm_txrx.py19
-rwxr-xr-xgr-digital/python/qa_ofdm_carrier_allocator_cvc.py47
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 ()