diff --git a/grc/ieee802_11_decode_signal.xml b/grc/ieee802_11_decode_signal.xml
deleted file mode 100644
index 9e0cb19..0000000
--- a/grc/ieee802_11_decode_signal.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
- WiFi Decode Signal
- ieee802_11_decode_signal
- IEEE802.11
- import ieee802_11
- ieee802_11.decode_signal($log, $debug)
-
-
- Log
- log
- False
- bool
-
-
-
-
-
-
- Debug
- debug
- False
- bool
-
-
-
-
-
-
- in
- complex
- 48
- 1
-
-
-
- out
- complex
- 48
- 1
-
-
-
-
-
diff --git a/grc/ieee802_11_equalize_symbols.xml b/grc/ieee802_11_equalize_symbols.xml
deleted file mode 100644
index c274f3a..0000000
--- a/grc/ieee802_11_equalize_symbols.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
- WiFi Equalize Symbols
- ieee802_11_equalize_symbols
- IEEE802.11
- import ieee802_11
- ieee802_11.equalize_symbols($algo, $debug)
- set_algorithm($algo)
-
-
- Algorithm
- algo
- ieee802_11.LINEAR_COMB
- int
-
-
-
-
-
-
- Debug
- debug
- False
- bool
-
-
-
-
-
-
- in
- complex
- 64
- 1
-
-
-
- out
- complex
- 48
- 1
-
-
-
-
diff --git a/grc/ieee802_11_frame_equalizer.xml b/grc/ieee802_11_frame_equalizer.xml
new file mode 100644
index 0000000..59b86ee
--- /dev/null
+++ b/grc/ieee802_11_frame_equalizer.xml
@@ -0,0 +1,105 @@
+
+
+
+ WiFi Frame Equalizer
+ ieee802_11_frame_equalizer
+ IEEE802.11
+ import ieee802_11
+ ieee802_11.frame_equalizer($algo, $freq, $bw, $log, $debug)
+ set_algorithm($algo)
+ set_frequency($freq)
+ set_bandwidth($bw)
+
+
+ Algorithm
+ algo
+ ieee802_11.LS
+ int
+
+
+
+
+
+
+
+
+ Frequency
+ freq
+ 5.89e9
+ real
+
+
+
+ Bandwidth
+ bw
+ 10e6
+ real
+
+
+
+ Log
+ log
+ False
+ bool
+
+
+
+
+
+
+ Debug
+ debug
+ False
+ bool
+
+
+
+
+
+
+ in
+ complex
+ 64
+ 1
+
+
+
+ out
+ byte
+ 48
+ 1
+
+
+
+ symbols
+ message
+ 1
+
+
+
+
+
diff --git a/include/ieee802-11/CMakeLists.txt b/include/ieee802-11/CMakeLists.txt
index c7e375e..4275ad8 100644
--- a/include/ieee802-11/CMakeLists.txt
+++ b/include/ieee802-11/CMakeLists.txt
@@ -72,9 +72,8 @@ list(APPEND include_sources
chunks_to_symbols.h
constellations.h
decode_mac.h
- decode_signal.h
- equalize_symbols.h
ether_encap.h
+ frame_equalizer.h
mac.h
mapper.h
parse_mac.h
diff --git a/include/ieee802-11/decode_signal.h b/include/ieee802-11/decode_signal.h
deleted file mode 100644
index a0442ec..0000000
--- a/include/ieee802-11/decode_signal.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2013, 2016 Bastian Bloessl
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-#ifndef INCLUDED_IEEE802_11_DECODE_SIGNAL_H
-#define INCLUDED_IEEE802_11_DECODE_SIGNAL_H
-
-#include
-#include
-
-namespace gr {
-namespace ieee802_11 {
-
-class IEEE802_11_API decode_signal : virtual public block
-{
-public:
-
- typedef boost::shared_ptr sptr;
- static sptr make(bool log = false, bool debug = false);
-
-};
-
-} // namespace ieee802_11
-} // namespace gr
-
-#endif /* INCLUDED_IEEE802_11_DECODE_SIGNAL_H */
-
diff --git a/include/ieee802-11/equalize_symbols.h b/include/ieee802-11/frame_equalizer.h
similarity index 59%
rename from include/ieee802-11/equalize_symbols.h
rename to include/ieee802-11/frame_equalizer.h
index 31e75ac..45ebbd0 100644
--- a/include/ieee802-11/equalize_symbols.h
+++ b/include/ieee802-11/frame_equalizer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013, 2015, 2016 Bastian Bloessl
+ * Copyright (C) 2016 Bastian Bloessl
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,33 +13,39 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
+ *
*/
-#ifndef INCLUDED_IEEE802_11_EQUALIZE_SYMBOLS_H
-#define INCLUDED_IEEE802_11_EQUALIZE_SYMBOLS_H
+
+
+#ifndef INCLUDED_IEEE802_11_FRAME_EQUALIZER_H
+#define INCLUDED_IEEE802_11_FRAME_EQUALIZER_H
#include
#include
enum Equalizer {
- LMS = 0,
- LINEAR_COMB = 1,
+ LS = 0,
+ LMS = 1,
+ COMB = 2,
+ STA = 3,
};
namespace gr {
namespace ieee802_11 {
-class IEEE802_11_API equalize_symbols : virtual public block
+class IEEE802_11_API frame_equalizer : virtual public gr::block
{
+
public:
-
- typedef boost::shared_ptr sptr;
- static sptr make(Equalizer algo, bool debug = false);
+ typedef boost::shared_ptr sptr;
+ static sptr make(Equalizer algo, double freq, double bw,
+ bool log, bool debug);
virtual void set_algorithm(Equalizer algo) = 0;
-
+ virtual void set_bandwidth(double bw) = 0;
+ virtual void set_frequency(double freq) = 0;
};
-} // namespace ieee802_11
-} // namespace gr
-
-#endif /* INCLUDED_IEEE802_11_EQUALIZE_SYMBOLS_H*/
+} // namespace ieee802_11
+} // namespace gr
+#endif /* INCLUDED_IEEE802_11_FRAME_EQUALIZER_H */
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 2ce36d4..ef27018 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -97,14 +97,13 @@ list(APPEND gr_ieee802_11_sources
chunks_to_symbols_impl.cc
constellations_impl.cc
decode_mac.cc
- decode_signal.cc
- equalize_symbols.cc
equalizer/base.cc
equalizer/comb.cc
equalizer/ls.cc
equalizer/lms.cc
equalizer/sta.cc
ether_encap_impl.cc
+ frame_equalizer_impl.cc
mac.cc
mapper.cc
parse_mac.cc
diff --git a/lib/decode_signal.cc b/lib/decode_signal.cc
deleted file mode 100644
index 1f47573..0000000
--- a/lib/decode_signal.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2013, 2016 Bastian Bloessl
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-#include
-#include
-#include "utils.h"
-
-#include
-
-using namespace gr::ieee802_11;
-using namespace itpp;
-
-
-class decode_signal_impl : public decode_signal {
-
-public:
-decode_signal_impl(bool log, bool debug) : block("decode_signal",
- gr::io_signature::make(1, 1, 48 * sizeof(gr_complex)),
- gr::io_signature::make(1, 1, 48 * sizeof(gr_complex))),
- d_log(log),
- d_debug(debug),
- d_copy_symbols(0) {
-
- decoded_bits.set_size(24);
- set_relative_rate(1);
- set_tag_propagation_policy(block::TPP_DONT);
-}
-
-~decode_signal_impl(){
-}
-
-int general_work (int noutput_items, gr_vector_int& ninput_items,
- gr_vector_const_void_star& input_items,
- gr_vector_void_star& output_items) {
-
- const gr_complex *in = (const gr_complex*)input_items[0];
- gr_complex *out = (gr_complex*)output_items[0];
-
- int i = 0;
- int o = 0;
-
- std::vector tags;
- const uint64_t nread = nitems_read(0);
-
- dout << "Decode Signal: input " << ninput_items[0]
- << " output " << noutput_items << std::endl;
-
- while((i < ninput_items[0]) && (o < noutput_items)) {
-
- get_tags_in_range(tags, 0, nread + i, nread + i + 1,
- pmt::string_to_symbol("wifi_start"));
-
- if(tags.size()) {
- for(int n = 0; n < 48; n++) {
- bits[n] = -real(in[n]);
- }
-
- deinterleave();
-
- decode();
-
- if(print_signal()) {
-
- add_item_tag(0, nitems_written(0) + o,
- pmt::string_to_symbol("wifi_start"),
- pmt::cons(pmt::from_uint64(d_len),
- pmt::from_uint64(d_encoding)),
- pmt::string_to_symbol(name()));
- }
-
- } else if(d_copy_symbols) {
-
- std::memcpy(out, in, 48 * sizeof(gr_complex));
- o++;
- out += 48;
- d_copy_symbols--;
- }
-
- in += 48;
- i++;
- }
-
- dout << "Decode Signal consumed " << i <<
- " produced " << o << std::endl;
-
- consume(0, i);
- return o;
-}
-
-void deinterleave() {
- double tmp[48];
- for(int i = 0; i < 48; i++) {
- tmp[i] = bits[inter[i]];
- }
- for(int i = 0; i < 48; i++) {
- bits[i] = tmp[i];
- }
- for(int i = 0; i < 48; i++) {
- dout << bits[i] << " ";
- }
- dout << std::endl;
-
-}
-
-void decode() {
-
- Convolutional_Code code;
- ivec generator(2);
- generator(0)=0133;
- generator(1)=0171;
- code.set_generator_polynomials(generator, 7);
- code.set_truncation_length(30);
-
- vec rx_signal(bits, 48);
- code.reset();
- code.decode_tail(rx_signal, decoded_bits);
-
- dout << "length rx " << rx_signal.size() << std::endl;
- dout << rx_signal << std::endl;
- dout << "length decoded " << decoded_bits.size() << std::endl;
- dout << decoded_bits << std::endl;
-
-}
-
-bool print_signal() {
-
- int r = 0;
- d_len = 0;
- bool parity = false;
- for(int i = 0; i < 17; i++) {
- parity ^= (bool)decoded_bits[i];
-
- if((i < 4) && decoded_bits[i]) {
- r = r | (1 << i);
- }
-
- if(decoded_bits[i] && (i > 4) && (i < 17)) {
- d_len = d_len | (1 << (i-5));
- }
- }
-
- if(parity != (bool)decoded_bits[17]) {
- dout << "SIGNAL: wrong parity" << std::endl;
- return false;
- }
-
- if(r == 11) {
- d_encoding = 0;
- d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 24);
- dout << "Encoding: 3 Mbit/s ";
- } else if(r == 15) {
- d_encoding = 1;
- d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 36);
- dout << "Encoding: 4.5 Mbit/s ";
- } else if(r == 10) {
- d_encoding = 2;
- d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 48);
- dout << "Encoding: 6 Mbit/s ";
- } else if(r == 14) {
- d_encoding = 3;
- d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 72);
- dout << "Encoding: 9 Mbit/s ";
- } else if(r == 9) {
- d_encoding = 4;
- d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 96);
- dout << "Encoding: 12 Mbit/s ";
- } else if(r == 13) {
- d_encoding = 5;
- d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 144);
- dout << "Encoding: 18 Mbit/s ";
- } else if(r == 8) {
- d_encoding = 6;
- d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 192);
- dout << "Encoding: 24 Mbit/s ";
- } else if(r == 12) {
- d_encoding = 7;
- d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 216);
- dout << "Encoding: 27 Mbit/s ";
- } else {
- dout << "unknown encoding" << std::endl;
- return false;
- }
-
- mylog(boost::format("encoding: %1% - length: %2% - symbols: %3%")
- % d_encoding % d_len % d_copy_symbols);
-
- dout << "d_copy_symbols: " << d_copy_symbols << std::endl;
- dout << "length: " << d_len << std::endl;
- return true;
-}
-
-private:
- int d_len;
- int d_encoding;
- bool d_log;
- bool d_debug;
- double bits[48];
- int d_copy_symbols;
- bvec decoded_bits;
- static int inter[48];
-};
-
-decode_signal::sptr
-decode_signal::make(bool log, bool debug) {
- return gnuradio::get_initial_sptr(new decode_signal_impl(log, debug));
-}
-
-int decode_signal_impl::inter[48]={0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47};
-
diff --git a/lib/equalize_symbols.cc b/lib/equalize_symbols.cc
deleted file mode 100644
index 23eae0b..0000000
--- a/lib/equalize_symbols.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2013, 2016 Bastian Bloessl
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-#include
-
-#include "utils.h"
-#include "equalizer/base.h"
-#include "equalizer/linear_comb.h"
-#include "equalizer/lms.h"
-#include
-
-using namespace gr::ieee802_11;
-
-
-class equalize_symbols_impl : public equalize_symbols {
-
-public:
-equalize_symbols_impl(Equalizer algo, bool debug) : block("equalize_symbols",
- gr::io_signature::make(1, 1, 64 * sizeof(gr_complex)),
- gr::io_signature::make(1, 1, 48 * sizeof(gr_complex))),
- d_debug(debug), d_equalizer(NULL) {
-
- set_relative_rate(1);
- set_tag_propagation_policy(block::TPP_DONT);
- set_algorithm(algo);
-}
-
-~equalize_symbols_impl(){
-}
-
-int general_work (int noutput_items, gr_vector_int& ninput_items,
- gr_vector_const_void_star& input_items,
- gr_vector_void_star& output_items) {
-
- gr::thread::scoped_lock lock(d_mutex);
-
- const gr_complex *in = (const gr_complex*)input_items[0];
- gr_complex *out = (gr_complex*)output_items[0];
-
- int i = 0;
- int o = 0;
-
- dout << "SYMBOLS: input " << ninput_items[0] << " output " << noutput_items << std::endl;
-
- while((i < ninput_items[0]) && (o < noutput_items)) {
-
- get_tags_in_window(tags, 0, i, i + 1, pmt::string_to_symbol("wifi_start"));
-
- // new WiFi frame
- if(tags.size()) {
- d_nsym = 0;
- }
-
- // first data symbol (= signal field)
- if(d_nsym == 2) {
- add_item_tag(0, nitems_written(0) + o,
- pmt::string_to_symbol("wifi_start"),
- pmt::PMT_T,
- pmt::string_to_symbol(name()));
- }
-
- d_equalizer->equalize(in + (i * 64), out + (o * 48), d_nsym);
-
- if(d_nsym > 1) {
- o++;
- }
- i++;
- d_nsym++;
- }
-
- dout << "SYMBOLS: consumed " << i << " produced " << o << std::endl;
-
- consume(0, i);
- return o;
-}
-
-void set_algorithm(Equalizer algo) {
- gr::thread::scoped_lock lock(d_mutex);
- delete d_equalizer;
-
- switch(algo) {
- case LMS:
- dout << "LMS" << std::endl;
- d_equalizer = new equalizer::lms();
- break;
-
- case LINEAR_COMB:
- dout << "Linear Comb" << std::endl;
- d_equalizer = new equalizer::linear_comb();
- break;
- }
-}
-
-private:
- int d_nsym;
- const bool d_debug;
- equalizer::base *d_equalizer;
- std::vector tags;
- gr::thread::mutex d_mutex;
-};
-
-
-equalize_symbols::sptr
-equalize_symbols::make(Equalizer algo, bool debug) {
- return gnuradio::get_initial_sptr(new equalize_symbols_impl(algo, debug));
-}
-
diff --git a/lib/frame_equalizer_impl.cc b/lib/frame_equalizer_impl.cc
new file mode 100644
index 0000000..1bc8355
--- /dev/null
+++ b/lib/frame_equalizer_impl.cc
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2016 Bastian Bloessl
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "frame_equalizer_impl.h"
+#include "equalizer/base.h"
+#include "equalizer/comb.h"
+#include "equalizer/lms.h"
+#include "equalizer/ls.h"
+#include "equalizer/sta.h"
+#include "utils.h"
+#include
+
+namespace gr {
+namespace ieee802_11 {
+
+frame_equalizer::sptr
+frame_equalizer::make(Equalizer algo, double freq, double bw, bool log, bool debug) {
+ return gnuradio::get_initial_sptr
+ (new frame_equalizer_impl(algo, freq, bw, log, debug));
+}
+
+
+frame_equalizer_impl::frame_equalizer_impl(Equalizer algo, double freq, double bw, bool log, bool debug) :
+ gr::block("frame_equalizer",
+ gr::io_signature::make(1, 1, 64 * sizeof(gr_complex)),
+ gr::io_signature::make(1, 1, 48)),
+ d_current_symbol(0), d_log(log), d_debug(debug), d_equalizer(NULL),
+ d_freq(freq), d_bw(bw), d_frame_bytes(0), d_frame_symbols(0) {
+
+ message_port_register_out(pmt::mp("symbols"));
+
+ d_bpsk = constellation_bpsk::make();
+ d_qpsk = constellation_qpsk::make();
+ d_16qam = constellation_16qam::make();
+ d_64qam = constellation_64qam::make();
+
+ d_frame_mod = d_bpsk;
+
+ set_tag_propagation_policy(block::TPP_DONT);
+ set_algorithm(algo);
+}
+
+frame_equalizer_impl::~frame_equalizer_impl() {
+}
+
+
+void
+frame_equalizer_impl::set_algorithm(Equalizer algo) {
+ gr::thread::scoped_lock lock(d_mutex);
+ delete d_equalizer;
+
+ switch(algo) {
+
+ case COMB:
+ dout << "Comb" << std::endl;
+ d_equalizer = new equalizer::comb();
+ break;
+ case LS:
+ dout << "LS" << std::endl;
+ d_equalizer = new equalizer::ls();
+ break;
+ case LMS:
+ dout << "LMS" << std::endl;
+ d_equalizer = new equalizer::lms();
+ break;
+ case STA:
+ dout << "Comb" << std::endl;
+ d_equalizer = new equalizer::sta();
+ break;
+ default:
+ throw std::runtime_error("Algorithm not implemented");
+ }
+}
+
+void
+frame_equalizer_impl::set_bandwidth(double bw) {
+ gr::thread::scoped_lock lock(d_mutex);
+ d_bw = bw;
+}
+
+void
+frame_equalizer_impl::set_frequency(double freq) {
+ gr::thread::scoped_lock lock(d_mutex);
+ d_freq = freq;
+}
+
+void
+frame_equalizer_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) {
+ ninput_items_required[0] = noutput_items;
+}
+
+int
+frame_equalizer_impl::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items) {
+
+ gr::thread::scoped_lock lock(d_mutex);
+
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ uint8_t *out = (uint8_t *) output_items[0];
+
+ int i = 0;
+ int o = 0;
+ gr_complex symbols[48];
+ gr_complex current_symbol[64];
+
+ dout << "FRAME EQUALIZER: input " << ninput_items[0] << " output " << noutput_items << std::endl;
+
+ while((i < ninput_items[0]) && (o < noutput_items)) {
+
+ get_tags_in_window(tags, 0, i, i + 1, pmt::string_to_symbol("wifi_start"));
+
+ // new frame
+ if(tags.size()) {
+ d_current_symbol = 0;
+ d_frame_symbols = 0;
+ d_frame_mod = d_bpsk;
+
+ d_epsilon0 = pmt::to_double(tags.front().value) * d_bw / (2 * M_PI * d_freq);
+ d_er = 0;
+
+ dout << "epsilon: " << d_epsilon0 << std::endl;
+ }
+
+ // not interesting -> skip
+ if(d_current_symbol > (d_frame_symbols + 2)) {
+ i++;
+ continue;
+ }
+
+ std::memcpy(current_symbol, in + i*64, 64*sizeof(gr_complex));
+
+ // compensate sampling offset
+ for(int i = 0; i < 64; i++) {
+ current_symbol[i] *= exp(gr_complex(0, 2*M_PI*d_current_symbol*80*(d_epsilon0 + d_er)*(i-32)/64));
+ }
+
+ gr_complex p = equalizer::base::POLARITY[(d_current_symbol - 2) % 127];
+ gr_complex sum =
+ (current_symbol[11] * p) +
+ (current_symbol[25] * p) +
+ (current_symbol[39] * p) +
+ (current_symbol[53] * -p);
+
+ double beta;
+ if(d_current_symbol < 2) {
+ beta = arg(
+ current_symbol[11] -
+ current_symbol[25] +
+ current_symbol[39] +
+ current_symbol[53]);
+
+ } else {
+ beta = arg(
+ (current_symbol[11] * p) +
+ (current_symbol[39] * p) +
+ (current_symbol[25] * p) +
+ (current_symbol[53] * -p));
+ }
+
+ double er = arg(
+ (conj(d_prev_pilots[0]) * current_symbol[11] * p) +
+ (conj(d_prev_pilots[1]) * current_symbol[25] * p) +
+ (conj(d_prev_pilots[2]) * current_symbol[39] * p) +
+ (conj(d_prev_pilots[3]) * current_symbol[53] * -p));
+
+ er *= d_bw / (2 * M_PI * d_freq * 80);
+
+ d_prev_pilots[0] = current_symbol[11] * p;
+ d_prev_pilots[1] = current_symbol[25] * p;
+ d_prev_pilots[2] = current_symbol[39] * p;
+ d_prev_pilots[3] = current_symbol[53] * -p;
+
+ // compensate residual frequency offset
+ for(int i = 0; i < 64; i++) {
+ current_symbol[i] *= exp(gr_complex(0, -beta));
+ }
+
+ // update estimate of residual frequency offset
+ if(d_current_symbol >= 2) {
+
+ double alpha = 0.1;
+ d_er = (1-alpha) * d_er + alpha * er;
+ }
+
+ // do equalization
+ d_equalizer->equalize(current_symbol, d_current_symbol,
+ symbols, out + o * 48, d_frame_mod);
+
+ // signal field
+ if(d_current_symbol == 2) {
+
+ if(decode_signal_field(out + o * 48)) {
+
+ add_item_tag(0, nitems_written(0) + o,
+ pmt::string_to_symbol("wifi_start"),
+ pmt::make_tuple(pmt::from_uint64(d_frame_bytes),
+ pmt::from_uint64(d_frame_encoding),
+ pmt::from_double(d_equalizer->get_snr())),
+ pmt::string_to_symbol(name()));
+ }
+ }
+
+ if(d_current_symbol > 2) {
+ o++;
+ pmt::pmt_t pdu = pmt::make_dict();
+ message_port_pub(pmt::mp("symbols"), pmt::cons(pmt::make_dict(), pmt::init_c32vector(48, symbols)));
+ }
+
+ i++;
+ d_current_symbol++;
+ }
+
+ consume(0, i);
+ return o;
+}
+
+bool
+frame_equalizer_impl::decode_signal_field(uint8_t *rx_bits) {
+
+ static ofdm_param ofdm(BPSK_1_2);
+ static frame_param frame(ofdm, 0);
+
+ deinterleave(rx_bits);
+ uint8_t *decoded_bits = d_decoder.decode(&ofdm, &frame, d_deinterleaved);
+
+ return parse_signal(decoded_bits);
+}
+
+void
+frame_equalizer_impl::deinterleave(uint8_t *rx_bits) {
+ for(int i = 0; i < 48; i++) {
+ d_deinterleaved[i] = rx_bits[interleaver_pattern[i]];
+ }
+}
+
+bool
+frame_equalizer_impl::parse_signal(uint8_t *decoded_bits) {
+
+ int r = 0;
+ d_frame_bytes = 0;
+ bool parity = false;
+ for(int i = 0; i < 17; i++) {
+ parity ^= decoded_bits[i];
+
+ if((i < 4) && decoded_bits[i]) {
+ r = r | (1 << i);
+ }
+
+ if(decoded_bits[i] && (i > 4) && (i < 17)) {
+ d_frame_bytes = d_frame_bytes | (1 << (i-5));
+ }
+ }
+
+ if(parity != decoded_bits[17]) {
+ dout << "SIGNAL: wrong parity" << std::endl;
+ return false;
+ }
+
+ switch(r) {
+ case 11:
+ d_frame_encoding = 0;
+ d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 24);
+ d_frame_mod = d_bpsk;
+ dout << "Encoding: 3 Mbit/s ";
+ break;
+ case 15:
+ d_frame_encoding = 1;
+ d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 36);
+ d_frame_mod = d_bpsk;
+ dout << "Encoding: 4.5 Mbit/s ";
+ break;
+ case 10:
+ d_frame_encoding = 2;
+ d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 48);
+ d_frame_mod = d_qpsk;
+ dout << "Encoding: 6 Mbit/s ";
+ break;
+ case 14:
+ d_frame_encoding = 3;
+ d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 72);
+ d_frame_mod = d_qpsk;
+ dout << "Encoding: 9 Mbit/s ";
+ break;
+ case 9:
+ d_frame_encoding = 4;
+ d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 96);
+ d_frame_mod = d_16qam;
+ dout << "Encoding: 12 Mbit/s ";
+ break;
+ case 13:
+ d_frame_encoding = 5;
+ d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 144);
+ d_frame_mod = d_16qam;
+ dout << "Encoding: 18 Mbit/s ";
+ break;
+ case 8:
+ d_frame_encoding = 6;
+ d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 192);
+ d_frame_mod = d_64qam;
+ dout << "Encoding: 24 Mbit/s ";
+ break;
+ case 12:
+ d_frame_encoding = 7;
+ d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 216);
+ d_frame_mod = d_64qam;
+ dout << "Encoding: 27 Mbit/s ";
+ break;
+ defaul:
+ dout << "unknown encoding" << std::endl;
+ return false;
+ }
+
+ mylog(boost::format("encoding: %1% - length: %2% - symbols: %3%")
+ % d_frame_encoding % d_frame_bytes % d_frame_symbols);
+ return true;
+}
+
+int
+frame_equalizer_impl::interleaver_pattern[48] = {
+ 0, 3, 6, 9,12,15,18,21,
+ 24,27,30,33,36,39,42,45,
+ 1, 4, 7,10,13,16,19,22,
+ 25,28,31,34,37,40,43,46,
+ 2, 5, 8,11,14,17,20,23,
+ 26,29,32,35,38,41,44,47};
+
+} /* namespace ieee802_11 */
+} /* namespace gr */
diff --git a/lib/frame_equalizer_impl.h b/lib/frame_equalizer_impl.h
new file mode 100644
index 0000000..d7ed540
--- /dev/null
+++ b/lib/frame_equalizer_impl.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 Bastian Bloessl
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef INCLUDED_IEEE802_11_FRAME_EQUALIZER_IMPL_H
+#define INCLUDED_IEEE802_11_FRAME_EQUALIZER_IMPL_H
+
+#include
+#include
+#include "equalizer/base.h"
+#include "viterbi_decoder.h"
+
+namespace gr {
+namespace ieee802_11 {
+
+class frame_equalizer_impl : virtual public frame_equalizer
+{
+
+public:
+ frame_equalizer_impl(Equalizer algo, double freq, double bw, bool log, bool debug);
+ ~frame_equalizer_impl();
+
+ void set_algorithm(Equalizer algo);
+ void set_bandwidth(double bw);
+ void set_frequency(double freq);
+
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+private:
+
+
+ bool parse_signal(uint8_t *signal);
+ bool decode_signal_field(uint8_t *rx_bits);
+ void deinterleave(uint8_t *rx_bits);
+
+ equalizer::base *d_equalizer;
+ gr::thread::mutex d_mutex;
+ std::vector tags;
+ bool d_debug;
+ bool d_log;
+ int d_current_symbol;
+ viterbi_decoder d_decoder;
+
+ // freq offset
+ double d_freq;
+ double d_bw;
+ double d_er;
+ double d_epsilon0;
+ gr_complex d_prev_pilots[4];
+
+ int d_frame_bytes;
+ int d_frame_symbols;
+ int d_frame_encoding;
+
+ uint8_t d_deinterleaved[48];
+ gr_complex symbols[48];
+
+ boost::shared_ptr d_frame_mod;
+ constellation_bpsk::sptr d_bpsk;
+ constellation_qpsk::sptr d_qpsk;
+ constellation_16qam::sptr d_16qam;
+ constellation_64qam::sptr d_64qam;
+
+ static int interleaver_pattern[48];
+};
+
+} // namespace ieee802_11
+} // namespace gr
+
+#endif /* INCLUDED_IEEE802_11_FRAME_EQUALIZER_IMPL_H */
diff --git a/lib/utils.cc b/lib/utils.cc
index a50f750..e4dc39e 100644
--- a/lib/utils.cc
+++ b/lib/utils.cc
@@ -20,62 +20,6 @@
#include
#include
-// constellations for different modulations (normalized to avg power 1)
-const std::complex BPSK_D[2] = {
- std::complex(-1.0, 0.0), std::complex(1.0, 0.0)};
-
-
-const std::complex QPSK_D[4] = {
- std::complex(-0.7071, -0.7071), std::complex(-0.7071, 0.7071),
- std::complex(+0.7071, -0.7071), std::complex(+0.7071, 0.7071)};
-
-
-const std::complex QAM16_D[16] = {
- std::complex(-0.9487, -0.9487), std::complex(-0.9487, -0.3162),
- std::complex(-0.9487, 0.9487), std::complex(-0.9487, 0.3162),
- std::complex(-0.3162, -0.9487), std::complex(-0.3162, -0.3162),
- std::complex(-0.3162, 0.9487), std::complex(-0.3162, 0.3162),
- std::complex(0.9487, -0.9487), std::complex(0.9487, -0.3162),
- std::complex(0.9487, 0.9487), std::complex(0.9487, 0.3162),
- std::complex(0.3162, -0.9487), std::complex(0.3162, -0.3162),
- std::complex(0.3162, 0.9487), std::complex(0.3162, 0.3162)};
-
-
-const std::complex QAM64_D[64] = {
- std::complex(-1.0801, -1.0801), std::complex(-1.0801, -0.7715),
- std::complex(-1.0801, -0.1543), std::complex(-1.0801, -0.4629),
- std::complex(-1.0801, 1.0801), std::complex(-1.0801, 0.7715),
- std::complex(-1.0801, 0.1543), std::complex(-1.0801, 0.4629),
- std::complex(-0.7715, -1.0801), std::complex(-0.7715, -0.7715),
- std::complex(-0.7715, -0.1543), std::complex(-0.7715, -0.4629),
- std::complex(-0.7715, 1.0801), std::complex(-0.7715, 0.7715),
- std::complex(-0.7715, 0.1543), std::complex(-0.7715, 0.4629),
- std::complex(-0.1543, -1.0801), std::complex(-0.1543, -0.7715),
- std::complex(-0.1543, -0.1543), std::complex(-0.1543, -0.4629),
- std::complex(-0.1543, 1.0801), std::complex(-0.1543, 0.7715),
- std::complex(-0.1543, 0.1543), std::complex(-0.1543, 0.4629),
- std::complex(-0.4629, -1.0801), std::complex(-0.4629, -0.7715),
- std::complex(-0.4629, -0.1543), std::complex(-0.4629, -0.4629),
- std::complex(-0.4629, 1.0801), std::complex(-0.4629, 0.7715),
- std::complex(-0.4629, 0.1543), std::complex(-0.4629, 0.4629),
- std::complex(1.0801, -1.0801), std::complex(1.0801, -0.7715),
- std::complex(1.0801, -0.1543), std::complex(1.0801, -0.4629),
- std::complex(1.0801, 1.0801), std::complex(1.0801, 0.7715),
- std::complex(1.0801, 0.1543), std::complex(1.0801, 0.4629),
- std::complex(0.7715, -1.0801), std::complex(0.7715, -0.7715),
- std::complex(0.7715, -0.1543), std::complex(0.7715, -0.4629),
- std::complex(0.7715, 1.0801), std::complex(0.7715, 0.7715),
- std::complex(0.7715, 0.1543), std::complex(0.7715, 0.4629),
- std::complex(0.1543, -1.0801), std::complex(0.1543, -0.7715),
- std::complex(0.1543, -0.1543), std::complex(0.1543, -0.4629),
- std::complex(0.1543, 1.0801), std::complex(0.1543, 0.7715),
- std::complex(0.1543, 0.1543), std::complex(0.1543, 0.4629),
- std::complex(0.4629, -1.0801), std::complex(0.4629, -0.7715),
- std::complex(0.4629, -0.1543), std::complex(0.4629, -0.4629),
- std::complex(0.4629, 1.0801), std::complex(0.4629, 0.7715),
- std::complex(0.4629, 0.1543), std::complex(0.4629, 0.4629)};
-
-
ofdm_param::ofdm_param(Encoding e) {
encoding = e;
@@ -160,11 +104,10 @@ frame_param::frame_param(ofdm_param &ofdm, int psdu_length) {
// number of symbols (17-11)
n_sym = (int) ceil((16 + 8 * psdu_size + 6) / (double) ofdm.n_dbps);
- // number of bits of the data field (17-12)
- n_data = n_sym * ofdm.n_dbps;
+ n_data_bits = n_sym * ofdm.n_dbps;
// number of padding bits (17-13)
- n_pad = n_data - (16 + 8 * psdu_size + 6);
+ n_pad = n_data_bits - (16 + 8 * psdu_size + 6);
n_encoded_bits = n_sym * ofdm.n_cbps;
}
@@ -173,8 +116,9 @@ frame_param::print() {
std::cout << "FRAME Parameters:" << std::endl;
std::cout << "psdu_size: " << psdu_size << std::endl;
std::cout << "n_sym: " << n_sym << std::endl;
- std::cout << "n_data: " << n_data << std::endl;
std::cout << "n_pad: " << n_pad << std::endl;
+ std::cout << "n_encoded_bits: " << n_encoded_bits << std::endl;
+ std::cout << "n_data_bits: " << n_data_bits << std::endl;
}
@@ -183,7 +127,7 @@ void scramble(const char *in, char *out, frame_param &frame, char initial_state)
int state = initial_state;
int feedback;
- for (int i = 0; i < frame.n_data; i++) {
+ for (int i = 0; i < frame.n_data_bits; i++) {
feedback = (!!(state & 64)) ^ (!!(state & 8));
out[i] = feedback ^ in[i];
@@ -193,7 +137,7 @@ void scramble(const char *in, char *out, frame_param &frame, char initial_state)
void reset_tail_bits(char *scrambled_data, frame_param &frame) {
- memset(scrambled_data + frame.n_data - frame.n_pad - 6, 0, 6 * sizeof(char));
+ memset(scrambled_data + frame.n_data_bits - frame.n_pad - 6, 0, 6 * sizeof(char));
}
@@ -212,7 +156,7 @@ void convolutional_encoding(const char *in, char *out, frame_param &frame) {
int state = 0;
- for(int i = 0; i < frame.n_data; i++) {
+ for(int i = 0; i < frame.n_data_bits; i++) {
assert(in[i] == 0 || in[i] == 1);
state = ((state << 1) & 0x7e) | in[i];
out[i * 2] = ones(state & 0155) % 2;
@@ -225,7 +169,7 @@ void puncturing(const char *in, char *out, frame_param &frame, ofdm_param &ofdm)
int mod;
- for (int i = 0; i < frame.n_data * 2; i++) {
+ for (int i = 0; i < frame.n_data_bits * 2; i++) {
switch(ofdm.encoding) {
case BPSK_1_2:
case QPSK_1_2:
@@ -286,33 +230,6 @@ void interleave(const char *in, char *out, frame_param &frame, ofdm_param &ofdm,
}
-void interleave(const double *in, double *out, frame_param &frame, ofdm_param &ofdm, bool reverse) {
-
- int n_cbps = ofdm.n_cbps;
- int first[n_cbps];
- int second[n_cbps];
- int s = std::max(ofdm.n_bpsc / 2, 1);
-
- for(int j = 0; j < n_cbps; j++) {
- first[j] = s * (j / s) + ((j + int(floor(16.0 * j / n_cbps))) % s);
- }
-
- for(int i = 0; i < n_cbps; i++) {
- second[i] = 16 * i - (n_cbps - 1) * int(floor(16.0 * i / n_cbps));
- }
-
- for(int i = 0; i < frame.n_sym; i++) {
- for(int k = 0; k < n_cbps; k++) {
- if(reverse) {
- out[i * n_cbps + second[first[k]]] = in[i * n_cbps + k];
- } else {
- out[i * n_cbps + k] = in[i * n_cbps + second[first[k]]];
- }
- }
- }
-}
-
-
void split_symbols(const char *in, char *out, frame_param &frame, ofdm_param &ofdm) {
int symbols = frame.n_sym * 48;
@@ -321,7 +238,7 @@ void split_symbols(const char *in, char *out, frame_param &frame, ofdm_param &of
out[i] = 0;
for(int k = 0; k < ofdm.n_bpsc; k++) {
assert(*in == 1 || *in == 0);
- out[i] |= (*in << (ofdm.n_bpsc - k - 1));
+ out[i] |= (*in << k);
in++;
}
}
diff --git a/lib/utils.h b/lib/utils.h
index a75a523..2818d85 100644
--- a/lib/utils.h
+++ b/lib/utils.h
@@ -23,8 +23,9 @@
#include
#include
-const int MAX_SYM = 520; // enough for 1500 byte BPSK 1/2
-const int MAX_BITS = 1550 * 8 * 2;
+#define MAX_FRAME_SIZE (1500 + 28 + 4)
+#define MAX_SYM (((16 + 8 * MAX_FRAME_SIZE + 6) / 24) + 1)
+#define MAX_ENCODED_BITS ((16 + 8 * MAX_FRAME_SIZE + 6) * 2 + 288)
#define dout d_debug && std::cout
@@ -34,12 +35,6 @@ const int MAX_BITS = 1550 * 8 * 2;
#define mylog(msg) do { d_log && std::cout << msg << std::endl; } while(0);
#endif
-// same mappings in double (itpp sucks)
-extern const std::complex BPSK_D[2];
-extern const std::complex QPSK_D[4];
-extern const std::complex QAM16_D[16];
-extern const std::complex QAM64_D[64];
-
struct mac_header {
//protocol version, type, subtype, to_ds, from_ds, ...
uint16_t frame_control;
@@ -81,11 +76,11 @@ public:
int psdu_size;
// number of OFDM symbols (17-11)
int n_sym;
- // number of data bits in the DATA field, including service and padding (17-12)
- int n_data;
// number of padding bits in the DATA field (17-13)
int n_pad;
int n_encoded_bits;
+ // number of data bits, including service and padding (17-12)
+ int n_data_bits;
void print();
};
@@ -104,7 +99,6 @@ public:
*/
void generate_mac_data_frame(const char *msdu, int msdu_size, char **psdu, int *psdu_size, char seq);
-
void scramble(const char *input, char *out, frame_param &frame, char initial_state);
void reset_tail_bits(char *scrambled_data, frame_param &frame);
@@ -114,7 +108,6 @@ void convolutional_encoding(const char *input, char *out, frame_param &frame);
void puncturing(const char *input, char *out, frame_param &frame, ofdm_param &ofdm);
void interleave(const char *input, char *out, frame_param &frame, ofdm_param &ofdm, bool reverse = false);
-void interleave(const double *input, double *out, frame_param &frame, ofdm_param &ofdm, bool reverse = false);
void split_symbols(const char *input, char *out, frame_param &frame, ofdm_param &ofdm);
diff --git a/swig/ieee802_11_swig.i b/swig/ieee802_11_swig.i
index 2eba124..905a2f5 100644
--- a/swig/ieee802_11_swig.i
+++ b/swig/ieee802_11_swig.i
@@ -22,22 +22,19 @@
%include "ieee802_11_swig_doc.i"
%{
-#include "gnuradio/digital/packet_header_default.h"
-
#include "ieee802-11/chunks_to_symbols.h"
#include "ieee802-11/constellations.h"
-#include "ieee802-11/ether_encap.h"
-#include "ieee802-11/moving_average_cc.h"
-#include "ieee802-11/moving_average_ff.h"
#include "ieee802-11/decode_mac.h"
-#include "ieee802-11/decode_signal.h"
-#include "ieee802-11/equalize_symbols.h"
+#include "ieee802-11/ether_encap.h"
+#include "ieee802-11/frame_equalizer.h"
#include "ieee802-11/mac.h"
#include "ieee802-11/mapper.h"
+#include "ieee802-11/moving_average_cc.h"
+#include "ieee802-11/moving_average_ff.h"
#include "ieee802-11/parse_mac.h"
+#include "ieee802-11/signal_field.h"
#include "ieee802-11/sync_long.h"
#include "ieee802-11/sync_short.h"
-#include "ieee802-11/signal_field.h"
%}
%include "gnuradio/digital/packet_header_default.h"
@@ -49,28 +46,26 @@
%include "ieee802-11/chunks_to_symbols.h"
%include "ieee802-11/constellations.h"
-%include "ieee802-11/ether_encap.h"
-%include "ieee802-11/moving_average_cc.h"
-%include "ieee802-11/moving_average_ff.h"
%include "ieee802-11/decode_mac.h"
-%include "ieee802-11/decode_signal.h"
-%include "ieee802-11/equalize_symbols.h"
+%include "ieee802-11/ether_encap.h"
+%include "ieee802-11/frame_equalizer.h"
%include "ieee802-11/mac.h"
%include "ieee802-11/mapper.h"
+%include "ieee802-11/moving_average_cc.h"
+%include "ieee802-11/moving_average_ff.h"
%include "ieee802-11/parse_mac.h"
+%include "ieee802-11/signal_field.h"
%include "ieee802-11/sync_long.h"
%include "ieee802-11/sync_short.h"
-%include "ieee802-11/signal_field.h"
GR_SWIG_BLOCK_MAGIC2(ieee802_11, chunks_to_symbols);
-GR_SWIG_BLOCK_MAGIC2(ieee802_11, ether_encap);
-GR_SWIG_BLOCK_MAGIC2(ieee802_11, moving_average_cc);
-GR_SWIG_BLOCK_MAGIC2(ieee802_11, moving_average_ff);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, decode_mac);
-GR_SWIG_BLOCK_MAGIC2(ieee802_11, decode_signal);
-GR_SWIG_BLOCK_MAGIC2(ieee802_11, equalize_symbols);
+GR_SWIG_BLOCK_MAGIC2(ieee802_11, ether_encap);
+GR_SWIG_BLOCK_MAGIC2(ieee802_11, frame_equalizer);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, mac);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, mapper);
+GR_SWIG_BLOCK_MAGIC2(ieee802_11, moving_average_cc);
+GR_SWIG_BLOCK_MAGIC2(ieee802_11, moving_average_ff);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, parse_mac);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, sync_long);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, sync_short);