clang format, similar to GNU Radio
This commit is contained in:
@@ -22,76 +22,76 @@
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
chunks_to_symbols::sptr
|
||||
chunks_to_symbols::make()
|
||||
chunks_to_symbols::sptr chunks_to_symbols::make()
|
||||
{
|
||||
return gnuradio::get_initial_sptr(new chunks_to_symbols_impl());
|
||||
return gnuradio::get_initial_sptr(new chunks_to_symbols_impl());
|
||||
}
|
||||
|
||||
chunks_to_symbols_impl::chunks_to_symbols_impl() :
|
||||
tagged_stream_block("chunks_to_symbols",
|
||||
io_signature::make(1, 1, sizeof(char)),
|
||||
io_signature::make(1, 1, sizeof(gr_complex)), "packet_len") {
|
||||
chunks_to_symbols_impl::chunks_to_symbols_impl()
|
||||
: tagged_stream_block("chunks_to_symbols",
|
||||
io_signature::make(1, 1, sizeof(char)),
|
||||
io_signature::make(1, 1, sizeof(gr_complex)),
|
||||
"packet_len")
|
||||
{
|
||||
|
||||
d_bpsk = constellation_bpsk::make();
|
||||
d_qpsk = constellation_qpsk::make();
|
||||
d_16qam = constellation_16qam::make();
|
||||
d_64qam = constellation_64qam::make();
|
||||
d_bpsk = constellation_bpsk::make();
|
||||
d_qpsk = constellation_qpsk::make();
|
||||
d_16qam = constellation_16qam::make();
|
||||
d_64qam = constellation_64qam::make();
|
||||
|
||||
d_mapping = d_bpsk;
|
||||
d_mapping = d_bpsk;
|
||||
}
|
||||
|
||||
chunks_to_symbols_impl::~chunks_to_symbols_impl() { }
|
||||
chunks_to_symbols_impl::~chunks_to_symbols_impl() {}
|
||||
|
||||
|
||||
int
|
||||
chunks_to_symbols_impl::work(int noutput_items,
|
||||
gr_vector_int &ninput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items) {
|
||||
int chunks_to_symbols_impl::work(int noutput_items,
|
||||
gr_vector_int& ninput_items,
|
||||
gr_vector_const_void_star& input_items,
|
||||
gr_vector_void_star& output_items)
|
||||
{
|
||||
|
||||
const unsigned char *in = (unsigned char*)input_items[0];
|
||||
gr_complex *out = (gr_complex*)output_items[0];
|
||||
const unsigned char* in = (unsigned char*)input_items[0];
|
||||
gr_complex* out = (gr_complex*)output_items[0];
|
||||
|
||||
std::vector<tag_t> tags;
|
||||
get_tags_in_range(tags, 0, nitems_read(0),
|
||||
nitems_read(0) + ninput_items[0],
|
||||
pmt::mp("encoding"));
|
||||
if(tags.size() != 1) {
|
||||
throw std::runtime_error("no encoding in input stream");
|
||||
}
|
||||
std::vector<tag_t> tags;
|
||||
get_tags_in_range(
|
||||
tags, 0, nitems_read(0), nitems_read(0) + ninput_items[0], pmt::mp("encoding"));
|
||||
if (tags.size() != 1) {
|
||||
throw std::runtime_error("no encoding in input stream");
|
||||
}
|
||||
|
||||
Encoding encoding = (Encoding)pmt::to_long(tags[0].value);
|
||||
Encoding encoding = (Encoding)pmt::to_long(tags[0].value);
|
||||
|
||||
switch (encoding) {
|
||||
case BPSK_1_2:
|
||||
case BPSK_3_4:
|
||||
d_mapping = d_bpsk;
|
||||
break;
|
||||
switch (encoding) {
|
||||
case BPSK_1_2:
|
||||
case BPSK_3_4:
|
||||
d_mapping = d_bpsk;
|
||||
break;
|
||||
|
||||
case QPSK_1_2:
|
||||
case QPSK_3_4:
|
||||
d_mapping = d_qpsk;
|
||||
break;
|
||||
case QPSK_1_2:
|
||||
case QPSK_3_4:
|
||||
d_mapping = d_qpsk;
|
||||
break;
|
||||
|
||||
case QAM16_1_2:
|
||||
case QAM16_3_4:
|
||||
d_mapping = d_16qam;
|
||||
break;
|
||||
case QAM16_1_2:
|
||||
case QAM16_3_4:
|
||||
d_mapping = d_16qam;
|
||||
break;
|
||||
|
||||
case QAM64_2_3:
|
||||
case QAM64_3_4:
|
||||
d_mapping = d_64qam;
|
||||
break;
|
||||
case QAM64_2_3:
|
||||
case QAM64_3_4:
|
||||
d_mapping = d_64qam;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("wrong encoding");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::invalid_argument("wrong encoding");
|
||||
break;
|
||||
}
|
||||
|
||||
for(int i = 0; i < ninput_items[0]; i++) {
|
||||
d_mapping->map_to_points(in[i], out + i);
|
||||
}
|
||||
for (int i = 0; i < ninput_items[0]; i++) {
|
||||
d_mapping->map_to_points(in[i], out + i);
|
||||
}
|
||||
|
||||
return ninput_items[0];
|
||||
return ninput_items[0];
|
||||
}
|
||||
|
||||
@@ -26,20 +26,20 @@ namespace ieee802_11 {
|
||||
class chunks_to_symbols_impl : public chunks_to_symbols
|
||||
{
|
||||
public:
|
||||
chunks_to_symbols_impl();
|
||||
~chunks_to_symbols_impl();
|
||||
chunks_to_symbols_impl();
|
||||
~chunks_to_symbols_impl();
|
||||
|
||||
int work(int noutput_items,
|
||||
gr_vector_int &ninput_itmes,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
int work(int noutput_items,
|
||||
gr_vector_int& ninput_itmes,
|
||||
gr_vector_const_void_star& input_items,
|
||||
gr_vector_void_star& output_items);
|
||||
|
||||
private:
|
||||
boost::shared_ptr<gr::digital::constellation> d_mapping;
|
||||
constellation_bpsk::sptr d_bpsk;
|
||||
constellation_qpsk::sptr d_qpsk;
|
||||
constellation_16qam::sptr d_16qam;
|
||||
constellation_64qam::sptr d_64qam;
|
||||
boost::shared_ptr<gr::digital::constellation> d_mapping;
|
||||
constellation_bpsk::sptr d_bpsk;
|
||||
constellation_qpsk::sptr d_qpsk;
|
||||
constellation_16qam::sptr d_16qam;
|
||||
constellation_64qam::sptr d_64qam;
|
||||
};
|
||||
|
||||
} /* namespace ieee802_11 */
|
||||
|
||||
+160
-162
@@ -18,218 +18,216 @@
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
constellation_bpsk::sptr
|
||||
constellation_bpsk::make() {
|
||||
return constellation_bpsk::sptr(new constellation_bpsk_impl());
|
||||
constellation_bpsk::sptr constellation_bpsk::make()
|
||||
{
|
||||
return constellation_bpsk::sptr(new constellation_bpsk_impl());
|
||||
}
|
||||
|
||||
constellation_bpsk::constellation_bpsk() {}
|
||||
|
||||
constellation_bpsk_impl::constellation_bpsk_impl() {
|
||||
d_constellation.resize(2);
|
||||
d_constellation[0] = gr_complex(-1, 0);
|
||||
d_constellation[1] = gr_complex(1, 0);
|
||||
d_rotational_symmetry = 2;
|
||||
d_dimensionality = 1;
|
||||
calc_arity();
|
||||
constellation_bpsk_impl::constellation_bpsk_impl()
|
||||
{
|
||||
d_constellation.resize(2);
|
||||
d_constellation[0] = gr_complex(-1, 0);
|
||||
d_constellation[1] = gr_complex(1, 0);
|
||||
d_rotational_symmetry = 2;
|
||||
d_dimensionality = 1;
|
||||
calc_arity();
|
||||
}
|
||||
|
||||
constellation_bpsk_impl::~constellation_bpsk_impl() {
|
||||
}
|
||||
constellation_bpsk_impl::~constellation_bpsk_impl() {}
|
||||
|
||||
unsigned int
|
||||
constellation_bpsk_impl::decision_maker(const gr_complex *sample) {
|
||||
return (real(*sample) > 0);
|
||||
unsigned int constellation_bpsk_impl::decision_maker(const gr_complex* sample)
|
||||
{
|
||||
return (real(*sample) > 0);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
|
||||
constellation_qpsk::sptr
|
||||
constellation_qpsk::make() {
|
||||
return constellation_qpsk::sptr(new constellation_qpsk_impl());
|
||||
constellation_qpsk::sptr constellation_qpsk::make()
|
||||
{
|
||||
return constellation_qpsk::sptr(new constellation_qpsk_impl());
|
||||
}
|
||||
|
||||
constellation_qpsk::constellation_qpsk() {}
|
||||
|
||||
constellation_qpsk_impl::constellation_qpsk_impl() {
|
||||
const float level = sqrt(float(0.5));
|
||||
d_constellation.resize(4);
|
||||
// Gray-coded
|
||||
d_constellation[0] = gr_complex(-level, -level);
|
||||
d_constellation[1] = gr_complex( level, -level);
|
||||
d_constellation[2] = gr_complex(-level, level);
|
||||
d_constellation[3] = gr_complex( level, level);
|
||||
constellation_qpsk_impl::constellation_qpsk_impl()
|
||||
{
|
||||
const float level = sqrt(float(0.5));
|
||||
d_constellation.resize(4);
|
||||
// Gray-coded
|
||||
d_constellation[0] = gr_complex(-level, -level);
|
||||
d_constellation[1] = gr_complex(level, -level);
|
||||
d_constellation[2] = gr_complex(-level, level);
|
||||
d_constellation[3] = gr_complex(level, level);
|
||||
|
||||
d_rotational_symmetry = 4;
|
||||
d_dimensionality = 1;
|
||||
calc_arity();
|
||||
d_rotational_symmetry = 4;
|
||||
d_dimensionality = 1;
|
||||
calc_arity();
|
||||
}
|
||||
|
||||
constellation_qpsk_impl::~constellation_qpsk_impl() {
|
||||
}
|
||||
constellation_qpsk_impl::~constellation_qpsk_impl() {}
|
||||
|
||||
unsigned int
|
||||
constellation_qpsk_impl::decision_maker(const gr_complex *sample) {
|
||||
return 2*(imag(*sample)>0) + (real(*sample)>0);
|
||||
unsigned int constellation_qpsk_impl::decision_maker(const gr_complex* sample)
|
||||
{
|
||||
return 2 * (imag(*sample) > 0) + (real(*sample) > 0);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
|
||||
constellation_16qam::sptr
|
||||
constellation_16qam::make() {
|
||||
return constellation_16qam::sptr(new constellation_16qam_impl());
|
||||
constellation_16qam::sptr constellation_16qam::make()
|
||||
{
|
||||
return constellation_16qam::sptr(new constellation_16qam_impl());
|
||||
}
|
||||
|
||||
constellation_16qam::constellation_16qam() {}
|
||||
|
||||
constellation_16qam_impl::constellation_16qam_impl()
|
||||
{
|
||||
const float level = sqrt(float(0.1));
|
||||
d_constellation.resize(16);
|
||||
const float level = sqrt(float(0.1));
|
||||
d_constellation.resize(16);
|
||||
|
||||
d_constellation[ 0] = gr_complex(-3*level,-3*level);
|
||||
d_constellation[ 1] = gr_complex( 3*level,-3*level);
|
||||
d_constellation[ 2] = gr_complex(-1*level,-3*level);
|
||||
d_constellation[ 3] = gr_complex( 1*level,-3*level);
|
||||
d_constellation[ 4] = gr_complex(-3*level, 3*level);
|
||||
d_constellation[ 5] = gr_complex( 3*level, 3*level);
|
||||
d_constellation[ 6] = gr_complex(-1*level, 3*level);
|
||||
d_constellation[ 7] = gr_complex( 1*level, 3*level);
|
||||
d_constellation[ 8] = gr_complex(-3*level,-1*level);
|
||||
d_constellation[ 9] = gr_complex( 3*level,-1*level);
|
||||
d_constellation[10] = gr_complex(-1*level,-1*level);
|
||||
d_constellation[11] = gr_complex( 1*level,-1*level);
|
||||
d_constellation[12] = gr_complex(-3*level, 1*level);
|
||||
d_constellation[13] = gr_complex( 3*level, 1*level);
|
||||
d_constellation[14] = gr_complex(-1*level, 1*level);
|
||||
d_constellation[15] = gr_complex( 1*level, 1*level);
|
||||
d_constellation[0] = gr_complex(-3 * level, -3 * level);
|
||||
d_constellation[1] = gr_complex(3 * level, -3 * level);
|
||||
d_constellation[2] = gr_complex(-1 * level, -3 * level);
|
||||
d_constellation[3] = gr_complex(1 * level, -3 * level);
|
||||
d_constellation[4] = gr_complex(-3 * level, 3 * level);
|
||||
d_constellation[5] = gr_complex(3 * level, 3 * level);
|
||||
d_constellation[6] = gr_complex(-1 * level, 3 * level);
|
||||
d_constellation[7] = gr_complex(1 * level, 3 * level);
|
||||
d_constellation[8] = gr_complex(-3 * level, -1 * level);
|
||||
d_constellation[9] = gr_complex(3 * level, -1 * level);
|
||||
d_constellation[10] = gr_complex(-1 * level, -1 * level);
|
||||
d_constellation[11] = gr_complex(1 * level, -1 * level);
|
||||
d_constellation[12] = gr_complex(-3 * level, 1 * level);
|
||||
d_constellation[13] = gr_complex(3 * level, 1 * level);
|
||||
d_constellation[14] = gr_complex(-1 * level, 1 * level);
|
||||
d_constellation[15] = gr_complex(1 * level, 1 * level);
|
||||
|
||||
d_rotational_symmetry = 4;
|
||||
d_dimensionality = 1;
|
||||
calc_arity();
|
||||
d_rotational_symmetry = 4;
|
||||
d_dimensionality = 1;
|
||||
calc_arity();
|
||||
}
|
||||
|
||||
constellation_16qam_impl::~constellation_16qam_impl() {
|
||||
}
|
||||
constellation_16qam_impl::~constellation_16qam_impl() {}
|
||||
|
||||
unsigned int
|
||||
constellation_16qam_impl::decision_maker(const gr_complex *sample)
|
||||
unsigned int constellation_16qam_impl::decision_maker(const gr_complex* sample)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
const float level = sqrt(float(0.1));
|
||||
float re = sample->real();
|
||||
float im = sample->imag();
|
||||
unsigned int ret = 0;
|
||||
const float level = sqrt(float(0.1));
|
||||
float re = sample->real();
|
||||
float im = sample->imag();
|
||||
|
||||
ret |= re > 0;
|
||||
ret |= (std::abs(re) < (2*level)) << 1;
|
||||
ret |= (im > 0) << 2;
|
||||
ret |= (std::abs(im) < (2*level)) << 3;
|
||||
ret |= re > 0;
|
||||
ret |= (std::abs(re) < (2 * level)) << 1;
|
||||
ret |= (im > 0) << 2;
|
||||
ret |= (std::abs(im) < (2 * level)) << 3;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************/
|
||||
|
||||
constellation_64qam::sptr
|
||||
constellation_64qam::make() {
|
||||
return constellation_64qam::sptr(new constellation_64qam_impl());
|
||||
constellation_64qam::sptr constellation_64qam::make()
|
||||
{
|
||||
return constellation_64qam::sptr(new constellation_64qam_impl());
|
||||
}
|
||||
|
||||
constellation_64qam::constellation_64qam() {}
|
||||
|
||||
constellation_64qam_impl::constellation_64qam_impl() {
|
||||
const float level = sqrt(float(1/42.0));
|
||||
d_constellation.resize(64);
|
||||
constellation_64qam_impl::constellation_64qam_impl()
|
||||
{
|
||||
const float level = sqrt(float(1 / 42.0));
|
||||
d_constellation.resize(64);
|
||||
|
||||
d_constellation[ 0] = gr_complex(-7*level,-7*level);
|
||||
d_constellation[ 1] = gr_complex( 7*level,-7*level);
|
||||
d_constellation[ 2] = gr_complex(-1*level,-7*level);
|
||||
d_constellation[ 3] = gr_complex( 1*level,-7*level);
|
||||
d_constellation[ 4] = gr_complex(-5*level,-7*level);
|
||||
d_constellation[ 5] = gr_complex( 5*level,-7*level);
|
||||
d_constellation[ 6] = gr_complex(-3*level,-7*level);
|
||||
d_constellation[ 7] = gr_complex( 3*level,-7*level);
|
||||
d_constellation[ 8] = gr_complex(-7*level, 7*level);
|
||||
d_constellation[ 9] = gr_complex( 7*level, 7*level);
|
||||
d_constellation[10] = gr_complex(-1*level, 7*level);
|
||||
d_constellation[11] = gr_complex( 1*level, 7*level);
|
||||
d_constellation[12] = gr_complex(-5*level, 7*level);
|
||||
d_constellation[13] = gr_complex( 5*level, 7*level);
|
||||
d_constellation[14] = gr_complex(-3*level, 7*level);
|
||||
d_constellation[15] = gr_complex( 3*level, 7*level);
|
||||
d_constellation[16] = gr_complex(-7*level,-1*level);
|
||||
d_constellation[17] = gr_complex( 7*level,-1*level);
|
||||
d_constellation[18] = gr_complex(-1*level,-1*level);
|
||||
d_constellation[19] = gr_complex( 1*level,-1*level);
|
||||
d_constellation[20] = gr_complex(-5*level,-1*level);
|
||||
d_constellation[21] = gr_complex( 5*level,-1*level);
|
||||
d_constellation[22] = gr_complex(-3*level,-1*level);
|
||||
d_constellation[23] = gr_complex( 3*level,-1*level);
|
||||
d_constellation[24] = gr_complex(-7*level, 1*level);
|
||||
d_constellation[25] = gr_complex( 7*level, 1*level);
|
||||
d_constellation[26] = gr_complex(-1*level, 1*level);
|
||||
d_constellation[27] = gr_complex( 1*level, 1*level);
|
||||
d_constellation[28] = gr_complex(-5*level, 1*level);
|
||||
d_constellation[29] = gr_complex( 5*level, 1*level);
|
||||
d_constellation[30] = gr_complex(-3*level, 1*level);
|
||||
d_constellation[31] = gr_complex( 3*level, 1*level);
|
||||
d_constellation[32] = gr_complex(-7*level,-5*level);
|
||||
d_constellation[33] = gr_complex( 7*level,-5*level);
|
||||
d_constellation[34] = gr_complex(-1*level,-5*level);
|
||||
d_constellation[35] = gr_complex( 1*level,-5*level);
|
||||
d_constellation[36] = gr_complex(-5*level,-5*level);
|
||||
d_constellation[37] = gr_complex( 5*level,-5*level);
|
||||
d_constellation[38] = gr_complex(-3*level,-5*level);
|
||||
d_constellation[39] = gr_complex( 3*level,-5*level);
|
||||
d_constellation[40] = gr_complex(-7*level, 5*level);
|
||||
d_constellation[41] = gr_complex( 7*level, 5*level);
|
||||
d_constellation[42] = gr_complex(-1*level, 5*level);
|
||||
d_constellation[43] = gr_complex( 1*level, 5*level);
|
||||
d_constellation[44] = gr_complex(-5*level, 5*level);
|
||||
d_constellation[45] = gr_complex( 5*level, 5*level);
|
||||
d_constellation[46] = gr_complex(-3*level, 5*level);
|
||||
d_constellation[47] = gr_complex( 3*level, 5*level);
|
||||
d_constellation[48] = gr_complex(-7*level,-3*level);
|
||||
d_constellation[49] = gr_complex( 7*level,-3*level);
|
||||
d_constellation[50] = gr_complex(-1*level,-3*level);
|
||||
d_constellation[51] = gr_complex( 1*level,-3*level);
|
||||
d_constellation[52] = gr_complex(-5*level,-3*level);
|
||||
d_constellation[53] = gr_complex( 5*level,-3*level);
|
||||
d_constellation[54] = gr_complex(-3*level,-3*level);
|
||||
d_constellation[55] = gr_complex( 3*level,-3*level);
|
||||
d_constellation[56] = gr_complex(-7*level, 3*level);
|
||||
d_constellation[57] = gr_complex( 7*level, 3*level);
|
||||
d_constellation[58] = gr_complex(-1*level, 3*level);
|
||||
d_constellation[59] = gr_complex( 1*level, 3*level);
|
||||
d_constellation[60] = gr_complex(-5*level, 3*level);
|
||||
d_constellation[61] = gr_complex( 5*level, 3*level);
|
||||
d_constellation[62] = gr_complex(-3*level, 3*level);
|
||||
d_constellation[63] = gr_complex( 3*level, 3*level);
|
||||
d_constellation[0] = gr_complex(-7 * level, -7 * level);
|
||||
d_constellation[1] = gr_complex(7 * level, -7 * level);
|
||||
d_constellation[2] = gr_complex(-1 * level, -7 * level);
|
||||
d_constellation[3] = gr_complex(1 * level, -7 * level);
|
||||
d_constellation[4] = gr_complex(-5 * level, -7 * level);
|
||||
d_constellation[5] = gr_complex(5 * level, -7 * level);
|
||||
d_constellation[6] = gr_complex(-3 * level, -7 * level);
|
||||
d_constellation[7] = gr_complex(3 * level, -7 * level);
|
||||
d_constellation[8] = gr_complex(-7 * level, 7 * level);
|
||||
d_constellation[9] = gr_complex(7 * level, 7 * level);
|
||||
d_constellation[10] = gr_complex(-1 * level, 7 * level);
|
||||
d_constellation[11] = gr_complex(1 * level, 7 * level);
|
||||
d_constellation[12] = gr_complex(-5 * level, 7 * level);
|
||||
d_constellation[13] = gr_complex(5 * level, 7 * level);
|
||||
d_constellation[14] = gr_complex(-3 * level, 7 * level);
|
||||
d_constellation[15] = gr_complex(3 * level, 7 * level);
|
||||
d_constellation[16] = gr_complex(-7 * level, -1 * level);
|
||||
d_constellation[17] = gr_complex(7 * level, -1 * level);
|
||||
d_constellation[18] = gr_complex(-1 * level, -1 * level);
|
||||
d_constellation[19] = gr_complex(1 * level, -1 * level);
|
||||
d_constellation[20] = gr_complex(-5 * level, -1 * level);
|
||||
d_constellation[21] = gr_complex(5 * level, -1 * level);
|
||||
d_constellation[22] = gr_complex(-3 * level, -1 * level);
|
||||
d_constellation[23] = gr_complex(3 * level, -1 * level);
|
||||
d_constellation[24] = gr_complex(-7 * level, 1 * level);
|
||||
d_constellation[25] = gr_complex(7 * level, 1 * level);
|
||||
d_constellation[26] = gr_complex(-1 * level, 1 * level);
|
||||
d_constellation[27] = gr_complex(1 * level, 1 * level);
|
||||
d_constellation[28] = gr_complex(-5 * level, 1 * level);
|
||||
d_constellation[29] = gr_complex(5 * level, 1 * level);
|
||||
d_constellation[30] = gr_complex(-3 * level, 1 * level);
|
||||
d_constellation[31] = gr_complex(3 * level, 1 * level);
|
||||
d_constellation[32] = gr_complex(-7 * level, -5 * level);
|
||||
d_constellation[33] = gr_complex(7 * level, -5 * level);
|
||||
d_constellation[34] = gr_complex(-1 * level, -5 * level);
|
||||
d_constellation[35] = gr_complex(1 * level, -5 * level);
|
||||
d_constellation[36] = gr_complex(-5 * level, -5 * level);
|
||||
d_constellation[37] = gr_complex(5 * level, -5 * level);
|
||||
d_constellation[38] = gr_complex(-3 * level, -5 * level);
|
||||
d_constellation[39] = gr_complex(3 * level, -5 * level);
|
||||
d_constellation[40] = gr_complex(-7 * level, 5 * level);
|
||||
d_constellation[41] = gr_complex(7 * level, 5 * level);
|
||||
d_constellation[42] = gr_complex(-1 * level, 5 * level);
|
||||
d_constellation[43] = gr_complex(1 * level, 5 * level);
|
||||
d_constellation[44] = gr_complex(-5 * level, 5 * level);
|
||||
d_constellation[45] = gr_complex(5 * level, 5 * level);
|
||||
d_constellation[46] = gr_complex(-3 * level, 5 * level);
|
||||
d_constellation[47] = gr_complex(3 * level, 5 * level);
|
||||
d_constellation[48] = gr_complex(-7 * level, -3 * level);
|
||||
d_constellation[49] = gr_complex(7 * level, -3 * level);
|
||||
d_constellation[50] = gr_complex(-1 * level, -3 * level);
|
||||
d_constellation[51] = gr_complex(1 * level, -3 * level);
|
||||
d_constellation[52] = gr_complex(-5 * level, -3 * level);
|
||||
d_constellation[53] = gr_complex(5 * level, -3 * level);
|
||||
d_constellation[54] = gr_complex(-3 * level, -3 * level);
|
||||
d_constellation[55] = gr_complex(3 * level, -3 * level);
|
||||
d_constellation[56] = gr_complex(-7 * level, 3 * level);
|
||||
d_constellation[57] = gr_complex(7 * level, 3 * level);
|
||||
d_constellation[58] = gr_complex(-1 * level, 3 * level);
|
||||
d_constellation[59] = gr_complex(1 * level, 3 * level);
|
||||
d_constellation[60] = gr_complex(-5 * level, 3 * level);
|
||||
d_constellation[61] = gr_complex(5 * level, 3 * level);
|
||||
d_constellation[62] = gr_complex(-3 * level, 3 * level);
|
||||
d_constellation[63] = gr_complex(3 * level, 3 * level);
|
||||
|
||||
d_rotational_symmetry = 4;
|
||||
d_dimensionality = 1;
|
||||
calc_arity();
|
||||
d_rotational_symmetry = 4;
|
||||
d_dimensionality = 1;
|
||||
calc_arity();
|
||||
}
|
||||
|
||||
constellation_64qam_impl::~constellation_64qam_impl() {
|
||||
}
|
||||
|
||||
unsigned int
|
||||
constellation_64qam_impl::decision_maker(const gr_complex *sample) {
|
||||
unsigned int ret = 0;
|
||||
const float level = sqrt(float(1/42.0));
|
||||
float re = sample->real();
|
||||
float im = sample->imag();
|
||||
|
||||
ret |= re > 0;
|
||||
ret |= (std::abs(re) < (4*level)) << 1;
|
||||
ret |= (std::abs(re) < (6*level) && std::abs(re) > (2*level)) << 2;
|
||||
ret |= (im > 0) << 3;
|
||||
ret |= (std::abs(im) < (4*level)) << 4;
|
||||
ret |= (std::abs(im) < (6*level) && std::abs(im) > (2*level)) << 5;
|
||||
|
||||
return ret;
|
||||
constellation_64qam_impl::~constellation_64qam_impl() {}
|
||||
|
||||
unsigned int constellation_64qam_impl::decision_maker(const gr_complex* sample)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
const float level = sqrt(float(1 / 42.0));
|
||||
float re = sample->real();
|
||||
float im = sample->imag();
|
||||
|
||||
ret |= re > 0;
|
||||
ret |= (std::abs(re) < (4 * level)) << 1;
|
||||
ret |= (std::abs(re) < (6 * level) && std::abs(re) > (2 * level)) << 2;
|
||||
ret |= (im > 0) << 3;
|
||||
ret |= (std::abs(im) < (4 * level)) << 4;
|
||||
ret |= (std::abs(im) < (6 * level) && std::abs(im) > (2 * level)) << 5;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+12
-15
@@ -25,43 +25,40 @@ namespace ieee802_11 {
|
||||
class constellation_bpsk_impl : public constellation_bpsk
|
||||
{
|
||||
public:
|
||||
constellation_bpsk_impl();
|
||||
~constellation_bpsk_impl();
|
||||
constellation_bpsk_impl();
|
||||
~constellation_bpsk_impl();
|
||||
|
||||
unsigned int decision_maker(const gr_complex *sample);
|
||||
unsigned int decision_maker(const gr_complex* sample);
|
||||
};
|
||||
|
||||
|
||||
class constellation_qpsk_impl : public constellation_qpsk
|
||||
{
|
||||
public:
|
||||
constellation_qpsk_impl();
|
||||
~constellation_qpsk_impl();
|
||||
constellation_qpsk_impl();
|
||||
~constellation_qpsk_impl();
|
||||
|
||||
unsigned int decision_maker(const gr_complex *sample);
|
||||
unsigned int decision_maker(const gr_complex* sample);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class constellation_16qam_impl : public constellation_16qam
|
||||
{
|
||||
public:
|
||||
constellation_16qam_impl();
|
||||
~constellation_16qam_impl();
|
||||
constellation_16qam_impl();
|
||||
~constellation_16qam_impl();
|
||||
|
||||
unsigned int decision_maker(const gr_complex *sample);
|
||||
unsigned int decision_maker(const gr_complex* sample);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class constellation_64qam_impl : public constellation_64qam
|
||||
{
|
||||
public:
|
||||
constellation_64qam_impl();
|
||||
~constellation_64qam_impl();
|
||||
constellation_64qam_impl();
|
||||
~constellation_64qam_impl();
|
||||
|
||||
unsigned int decision_maker(const gr_complex *sample);
|
||||
unsigned int decision_maker(const gr_complex* sample);
|
||||
};
|
||||
|
||||
|
||||
|
||||
+201
-180
@@ -19,234 +19,255 @@
|
||||
#include "utils.h"
|
||||
#include "viterbi_decoder/viterbi_decoder.h"
|
||||
|
||||
#include <boost/crc.hpp>
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <boost/crc.hpp>
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
#define LINKTYPE_IEEE802_11 105 /* http://www.tcpdump.org/linktypes.html */
|
||||
|
||||
class decode_mac_impl : public decode_mac {
|
||||
class decode_mac_impl : public decode_mac
|
||||
{
|
||||
|
||||
public:
|
||||
decode_mac_impl(bool log, bool debug) :
|
||||
block("decode_mac",
|
||||
gr::io_signature::make(1, 1, 48),
|
||||
gr::io_signature::make(0, 0, 0)),
|
||||
d_log(log),
|
||||
d_debug(debug),
|
||||
d_snr(0),
|
||||
d_nom_freq(0.0),
|
||||
d_freq_offset(0.0),
|
||||
d_ofdm(BPSK_1_2),
|
||||
d_frame(d_ofdm, 0),
|
||||
d_frame_complete(true) {
|
||||
decode_mac_impl(bool log, bool debug)
|
||||
: block("decode_mac",
|
||||
gr::io_signature::make(1, 1, 48),
|
||||
gr::io_signature::make(0, 0, 0)),
|
||||
d_log(log),
|
||||
d_debug(debug),
|
||||
d_snr(0),
|
||||
d_nom_freq(0.0),
|
||||
d_freq_offset(0.0),
|
||||
d_ofdm(BPSK_1_2),
|
||||
d_frame(d_ofdm, 0),
|
||||
d_frame_complete(true)
|
||||
{
|
||||
|
||||
message_port_register_out(pmt::mp("out"));
|
||||
}
|
||||
message_port_register_out(pmt::mp("out"));
|
||||
}
|
||||
|
||||
int general_work (int noutput_items, gr_vector_int& ninput_items,
|
||||
gr_vector_const_void_star& input_items,
|
||||
gr_vector_void_star& output_items) {
|
||||
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 uint8_t *in = (const uint8_t*)input_items[0];
|
||||
const uint8_t* in = (const uint8_t*)input_items[0];
|
||||
|
||||
int i = 0;
|
||||
int i = 0;
|
||||
|
||||
std::vector<gr::tag_t> tags;
|
||||
const uint64_t nread = this->nitems_read(0);
|
||||
std::vector<gr::tag_t> tags;
|
||||
const uint64_t nread = this->nitems_read(0);
|
||||
|
||||
dout << "Decode MAC: input " << ninput_items[0] << std::endl;
|
||||
dout << "Decode MAC: input " << ninput_items[0] << std::endl;
|
||||
|
||||
while(i < ninput_items[0]) {
|
||||
while (i < ninput_items[0]) {
|
||||
|
||||
get_tags_in_range(tags, 0, nread + i, nread + i + 1,
|
||||
pmt::string_to_symbol("wifi_start"));
|
||||
get_tags_in_range(
|
||||
tags, 0, nread + i, nread + i + 1, pmt::string_to_symbol("wifi_start"));
|
||||
|
||||
if(tags.size()) {
|
||||
if (d_frame_complete == false) {
|
||||
dout << "Warning: starting to receive new frame before old frame was complete" << std::endl;
|
||||
dout << "Already copied " << copied << " out of " << d_frame.n_sym << " symbols of last frame" << std::endl;
|
||||
}
|
||||
d_frame_complete = false;
|
||||
if (tags.size()) {
|
||||
if (d_frame_complete == false) {
|
||||
dout << "Warning: starting to receive new frame before old frame was "
|
||||
"complete"
|
||||
<< std::endl;
|
||||
dout << "Already copied " << copied << " out of " << d_frame.n_sym
|
||||
<< " symbols of last frame" << std::endl;
|
||||
}
|
||||
d_frame_complete = false;
|
||||
|
||||
pmt::pmt_t dict = tags[0].value;
|
||||
int len_data = pmt::to_uint64(pmt::dict_ref(dict, pmt::mp("frame_bytes"), pmt::from_uint64(MAX_PSDU_SIZE+1)));
|
||||
int encoding = pmt::to_uint64(pmt::dict_ref(dict, pmt::mp("encoding"), pmt::from_uint64(0)));
|
||||
d_snr = pmt::to_double(pmt::dict_ref(dict, pmt::mp("snr"), pmt::from_double(0)));
|
||||
d_nom_freq = pmt::to_double(pmt::dict_ref(dict, pmt::mp("freq"), pmt::from_double(0)));
|
||||
d_freq_offset = pmt::to_double(pmt::dict_ref(dict, pmt::mp("freq_offset"), pmt::from_double(0)));
|
||||
d_beta = pmt::to_double(pmt::dict_ref(dict, pmt::mp("beta"), pmt::from_double(0)));
|
||||
d_csi = pmt::c32vector_elements(pmt::dict_ref(dict, pmt::mp("csi"), pmt::make_c32vector(52, 0)));
|
||||
ofdm_param ofdm = ofdm_param((Encoding)encoding);
|
||||
frame_param frame = frame_param(ofdm, len_data);
|
||||
pmt::pmt_t dict = tags[0].value;
|
||||
int len_data = pmt::to_uint64(pmt::dict_ref(
|
||||
dict, pmt::mp("frame_bytes"), pmt::from_uint64(MAX_PSDU_SIZE + 1)));
|
||||
int encoding = pmt::to_uint64(
|
||||
pmt::dict_ref(dict, pmt::mp("encoding"), pmt::from_uint64(0)));
|
||||
d_snr = pmt::to_double(
|
||||
pmt::dict_ref(dict, pmt::mp("snr"), pmt::from_double(0)));
|
||||
d_nom_freq = pmt::to_double(
|
||||
pmt::dict_ref(dict, pmt::mp("freq"), pmt::from_double(0)));
|
||||
d_freq_offset = pmt::to_double(
|
||||
pmt::dict_ref(dict, pmt::mp("freq_offset"), pmt::from_double(0)));
|
||||
d_beta = pmt::to_double(
|
||||
pmt::dict_ref(dict, pmt::mp("beta"), pmt::from_double(0)));
|
||||
d_csi = pmt::c32vector_elements(
|
||||
pmt::dict_ref(dict, pmt::mp("csi"), pmt::make_c32vector(52, 0)));
|
||||
ofdm_param ofdm = ofdm_param((Encoding)encoding);
|
||||
frame_param frame = frame_param(ofdm, len_data);
|
||||
|
||||
// check for maximum frame size
|
||||
if(frame.n_sym <= MAX_SYM && frame.psdu_size <= MAX_PSDU_SIZE) {
|
||||
d_ofdm = ofdm;
|
||||
d_frame = frame;
|
||||
copied = 0;
|
||||
dout << "Decode MAC: frame start -- len " << len_data
|
||||
<< " symbols " << frame.n_sym << " encoding "
|
||||
<< encoding << std::endl;
|
||||
} else {
|
||||
dout << "Dropping frame which is too large (symbols or bits)" << std::endl;
|
||||
}
|
||||
}
|
||||
// check for maximum frame size
|
||||
if (frame.n_sym <= MAX_SYM && frame.psdu_size <= MAX_PSDU_SIZE) {
|
||||
d_ofdm = ofdm;
|
||||
d_frame = frame;
|
||||
copied = 0;
|
||||
dout << "Decode MAC: frame start -- len " << len_data << " symbols "
|
||||
<< frame.n_sym << " encoding " << encoding << std::endl;
|
||||
} else {
|
||||
dout << "Dropping frame which is too large (symbols or bits)"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if(copied < d_frame.n_sym) {
|
||||
dout << "copy one symbol, copied " << copied << " out of " << d_frame.n_sym << std::endl;
|
||||
std::memcpy(d_rx_symbols + (copied * 48), in, 48);
|
||||
copied++;
|
||||
if (copied < d_frame.n_sym) {
|
||||
dout << "copy one symbol, copied " << copied << " out of "
|
||||
<< d_frame.n_sym << std::endl;
|
||||
std::memcpy(d_rx_symbols + (copied * 48), in, 48);
|
||||
copied++;
|
||||
|
||||
if(copied == d_frame.n_sym) {
|
||||
dout << "received complete frame - decoding" << std::endl;
|
||||
decode();
|
||||
in += 48;
|
||||
i++;
|
||||
d_frame_complete = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (copied == d_frame.n_sym) {
|
||||
dout << "received complete frame - decoding" << std::endl;
|
||||
decode();
|
||||
in += 48;
|
||||
i++;
|
||||
d_frame_complete = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
in += 48;
|
||||
i++;
|
||||
}
|
||||
in += 48;
|
||||
i++;
|
||||
}
|
||||
|
||||
consume(0, i);
|
||||
consume(0, i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void decode() {
|
||||
void decode()
|
||||
{
|
||||
|
||||
for(int i = 0; i < d_frame.n_sym * 48; i++) {
|
||||
for(int k = 0; k < d_ofdm.n_bpsc; k++) {
|
||||
d_rx_bits[i*d_ofdm.n_bpsc + k] = !!(d_rx_symbols[i] & (1 << k));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < d_frame.n_sym * 48; i++) {
|
||||
for (int k = 0; k < d_ofdm.n_bpsc; k++) {
|
||||
d_rx_bits[i * d_ofdm.n_bpsc + k] = !!(d_rx_symbols[i] & (1 << k));
|
||||
}
|
||||
}
|
||||
|
||||
deinterleave();
|
||||
uint8_t *decoded = d_decoder.decode(&d_ofdm, &d_frame, d_deinterleaved_bits);
|
||||
descramble(decoded);
|
||||
print_output();
|
||||
deinterleave();
|
||||
uint8_t* decoded = d_decoder.decode(&d_ofdm, &d_frame, d_deinterleaved_bits);
|
||||
descramble(decoded);
|
||||
print_output();
|
||||
|
||||
// skip service field
|
||||
boost::crc_32_type result;
|
||||
result.process_bytes(out_bytes + 2, d_frame.psdu_size);
|
||||
if(result.checksum() != 558161692) {
|
||||
dout << "checksum wrong -- dropping" << std::endl;
|
||||
return;
|
||||
}
|
||||
// skip service field
|
||||
boost::crc_32_type result;
|
||||
result.process_bytes(out_bytes + 2, d_frame.psdu_size);
|
||||
if (result.checksum() != 558161692) {
|
||||
dout << "checksum wrong -- dropping" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
mylog(boost::format("encoding: %1% - length: %2% - symbols: %3%")
|
||||
% d_ofdm.encoding % d_frame.psdu_size % d_frame.n_sym);
|
||||
mylog(boost::format("encoding: %1% - length: %2% - symbols: %3%") %
|
||||
d_ofdm.encoding % d_frame.psdu_size % d_frame.n_sym);
|
||||
|
||||
// create PDU
|
||||
pmt::pmt_t blob = pmt::make_blob(out_bytes + 2, d_frame.psdu_size - 4);
|
||||
pmt::pmt_t enc = pmt::from_uint64(d_ofdm.encoding);
|
||||
pmt::pmt_t dict = pmt::make_dict();
|
||||
dict = pmt::dict_add(dict, pmt::mp("encoding"), enc);
|
||||
dict = pmt::dict_add(dict, pmt::mp("snr"), pmt::from_double(d_snr));
|
||||
dict = pmt::dict_add(dict, pmt::mp("nomfreq"), pmt::from_double(d_nom_freq));
|
||||
dict = pmt::dict_add(dict, pmt::mp("freqofs"), pmt::from_double(d_freq_offset));
|
||||
dict = pmt::dict_add(dict, pmt::mp("beta"), pmt::from_double(d_beta));
|
||||
dict = pmt::dict_add(dict, pmt::mp("csi"), pmt::init_c32vector(52, d_csi));
|
||||
dict = pmt::dict_add(dict, pmt::mp("dlt"), pmt::from_long(LINKTYPE_IEEE802_11));
|
||||
message_port_pub(pmt::mp("out"), pmt::cons(dict, blob));
|
||||
}
|
||||
// create PDU
|
||||
pmt::pmt_t blob = pmt::make_blob(out_bytes + 2, d_frame.psdu_size - 4);
|
||||
pmt::pmt_t enc = pmt::from_uint64(d_ofdm.encoding);
|
||||
pmt::pmt_t dict = pmt::make_dict();
|
||||
dict = pmt::dict_add(dict, pmt::mp("encoding"), enc);
|
||||
dict = pmt::dict_add(dict, pmt::mp("snr"), pmt::from_double(d_snr));
|
||||
dict = pmt::dict_add(dict, pmt::mp("nomfreq"), pmt::from_double(d_nom_freq));
|
||||
dict = pmt::dict_add(dict, pmt::mp("freqofs"), pmt::from_double(d_freq_offset));
|
||||
dict = pmt::dict_add(dict, pmt::mp("beta"), pmt::from_double(d_beta));
|
||||
dict = pmt::dict_add(dict, pmt::mp("csi"), pmt::init_c32vector(52, d_csi));
|
||||
dict = pmt::dict_add(dict, pmt::mp("dlt"), pmt::from_long(LINKTYPE_IEEE802_11));
|
||||
message_port_pub(pmt::mp("out"), pmt::cons(dict, blob));
|
||||
}
|
||||
|
||||
void deinterleave() {
|
||||
void deinterleave()
|
||||
{
|
||||
|
||||
int n_cbps = d_ofdm.n_cbps;
|
||||
int first[n_cbps];
|
||||
int second[n_cbps];
|
||||
int s = std::max(d_ofdm.n_bpsc / 2, 1);
|
||||
int n_cbps = d_ofdm.n_cbps;
|
||||
int first[n_cbps];
|
||||
int second[n_cbps];
|
||||
int s = std::max(d_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 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 < n_cbps; i++) {
|
||||
second[i] = 16 * i - (n_cbps - 1) * int(floor(16.0 * i / n_cbps));
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for(int i = 0; i < d_frame.n_sym; i++) {
|
||||
for(int k = 0; k < n_cbps; k++) {
|
||||
d_deinterleaved_bits[i * n_cbps + second[first[k]]] = d_rx_bits[i * n_cbps + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
int count = 0;
|
||||
for (int i = 0; i < d_frame.n_sym; i++) {
|
||||
for (int k = 0; k < n_cbps; k++) {
|
||||
d_deinterleaved_bits[i * n_cbps + second[first[k]]] =
|
||||
d_rx_bits[i * n_cbps + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void descramble (uint8_t *decoded_bits) {
|
||||
void descramble(uint8_t* decoded_bits)
|
||||
{
|
||||
|
||||
int state = 0;
|
||||
std::memset(out_bytes, 0, d_frame.psdu_size+2);
|
||||
int state = 0;
|
||||
std::memset(out_bytes, 0, d_frame.psdu_size + 2);
|
||||
|
||||
for(int i = 0; i < 7; i++) {
|
||||
if(decoded_bits[i]) {
|
||||
state |= 1 << (6 - i);
|
||||
}
|
||||
}
|
||||
out_bytes[0] = state;
|
||||
for (int i = 0; i < 7; i++) {
|
||||
if (decoded_bits[i]) {
|
||||
state |= 1 << (6 - i);
|
||||
}
|
||||
}
|
||||
out_bytes[0] = state;
|
||||
|
||||
int feedback;
|
||||
int bit;
|
||||
int feedback;
|
||||
int bit;
|
||||
|
||||
for(int i = 7; i < d_frame.psdu_size*8+16; i++) {
|
||||
feedback = ((!!(state & 64))) ^ (!!(state & 8));
|
||||
bit = feedback ^ (decoded_bits[i] & 0x1);
|
||||
out_bytes[i/8] |= bit << (i%8);
|
||||
state = ((state << 1) & 0x7e) | feedback;
|
||||
}
|
||||
}
|
||||
for (int i = 7; i < d_frame.psdu_size * 8 + 16; i++) {
|
||||
feedback = ((!!(state & 64))) ^ (!!(state & 8));
|
||||
bit = feedback ^ (decoded_bits[i] & 0x1);
|
||||
out_bytes[i / 8] |= bit << (i % 8);
|
||||
state = ((state << 1) & 0x7e) | feedback;
|
||||
}
|
||||
}
|
||||
|
||||
void print_output() {
|
||||
void print_output()
|
||||
{
|
||||
|
||||
dout << std::endl;
|
||||
dout << "psdu size" << d_frame.psdu_size << std::endl;
|
||||
for(int i = 2; i < d_frame.psdu_size+2; i++) {
|
||||
dout << std::setfill('0') << std::setw(2) << std::hex << ((unsigned int)out_bytes[i] & 0xFF) << std::dec << " ";
|
||||
if(i % 16 == 15) {
|
||||
dout << std::endl;
|
||||
}
|
||||
}
|
||||
dout << std::endl;
|
||||
for(int i = 2; i < d_frame.psdu_size+2; i++) {
|
||||
if((out_bytes[i] > 31) && (out_bytes[i] < 127)) {
|
||||
dout << ((char) out_bytes[i]);
|
||||
} else {
|
||||
dout << ".";
|
||||
}
|
||||
}
|
||||
dout << std::endl;
|
||||
}
|
||||
dout << std::endl;
|
||||
dout << "psdu size" << d_frame.psdu_size << std::endl;
|
||||
for (int i = 2; i < d_frame.psdu_size + 2; i++) {
|
||||
dout << std::setfill('0') << std::setw(2) << std::hex
|
||||
<< ((unsigned int)out_bytes[i] & 0xFF) << std::dec << " ";
|
||||
if (i % 16 == 15) {
|
||||
dout << std::endl;
|
||||
}
|
||||
}
|
||||
dout << std::endl;
|
||||
for (int i = 2; i < d_frame.psdu_size + 2; i++) {
|
||||
if ((out_bytes[i] > 31) && (out_bytes[i] < 127)) {
|
||||
dout << ((char)out_bytes[i]);
|
||||
} else {
|
||||
dout << ".";
|
||||
}
|
||||
}
|
||||
dout << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
bool d_debug;
|
||||
bool d_log;
|
||||
bool d_debug;
|
||||
bool d_log;
|
||||
|
||||
frame_param d_frame;
|
||||
ofdm_param d_ofdm;
|
||||
double d_snr; // dB
|
||||
double d_nom_freq; // nominal frequency, Hz
|
||||
double d_freq_offset; // frequency offset, Hz
|
||||
double d_beta;
|
||||
std::vector<gr_complex> d_csi;
|
||||
viterbi_decoder d_decoder;
|
||||
frame_param d_frame;
|
||||
ofdm_param d_ofdm;
|
||||
double d_snr; // dB
|
||||
double d_nom_freq; // nominal frequency, Hz
|
||||
double d_freq_offset; // frequency offset, Hz
|
||||
double d_beta;
|
||||
std::vector<gr_complex> d_csi;
|
||||
viterbi_decoder d_decoder;
|
||||
|
||||
uint8_t d_rx_symbols[48 * MAX_SYM];
|
||||
uint8_t d_rx_bits[MAX_ENCODED_BITS];
|
||||
uint8_t d_deinterleaved_bits[MAX_ENCODED_BITS];
|
||||
uint8_t out_bytes[MAX_PSDU_SIZE + 2]; // 2 for signal field
|
||||
uint8_t d_rx_symbols[48 * MAX_SYM];
|
||||
uint8_t d_rx_bits[MAX_ENCODED_BITS];
|
||||
uint8_t d_deinterleaved_bits[MAX_ENCODED_BITS];
|
||||
uint8_t out_bytes[MAX_PSDU_SIZE + 2]; // 2 for signal field
|
||||
|
||||
int copied;
|
||||
bool d_frame_complete;
|
||||
int copied;
|
||||
bool d_frame_complete;
|
||||
};
|
||||
|
||||
decode_mac::sptr
|
||||
decode_mac::make(bool log, bool debug) {
|
||||
return gnuradio::get_initial_sptr(new decode_mac_impl(log, debug));
|
||||
decode_mac::sptr decode_mac::make(bool log, bool debug)
|
||||
{
|
||||
return gnuradio::get_initial_sptr(new decode_mac_impl(log, debug));
|
||||
}
|
||||
|
||||
+23
-27
@@ -21,34 +21,30 @@
|
||||
|
||||
using namespace gr::ieee802_11::equalizer;
|
||||
|
||||
const gr_complex base::LONG[] = {
|
||||
0, 0, 0, 0, 0, 0, 1, 1, -1, -1,
|
||||
1, 1, -1, 1, -1, 1, 1, 1, 1, 1,
|
||||
1, -1, -1, 1, 1, -1, 1, -1, 1, 1,
|
||||
1, 1, 0, 1, -1, -1, 1, 1, -1, 1,
|
||||
-1, 1, -1, -1, -1, -1, -1, 1, 1, -1,
|
||||
-1, 1, -1, 1, -1, 1, 1, 1, 1, 0,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
const gr_complex base::LONG[] = { 0, 0, 0, 0, 0, 0, 1, 1, -1, -1, 1, 1, -1,
|
||||
1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1,
|
||||
1, -1, 1, 1, 1, 1, 0, 1, -1, -1, 1, 1, -1,
|
||||
1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1,
|
||||
-1, 1, -1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
|
||||
|
||||
const gr_complex base::POLARITY[127] = {
|
||||
1, 1, 1, 1,-1,-1,-1, 1,-1,-1,-1,-1, 1, 1,-1, 1,
|
||||
-1,-1, 1, 1,-1, 1, 1,-1, 1, 1, 1, 1, 1, 1,-1, 1,
|
||||
1, 1,-1, 1, 1,-1,-1, 1, 1, 1,-1, 1,-1,-1,-1, 1,
|
||||
-1, 1,-1,-1, 1,-1,-1, 1, 1, 1, 1, 1,-1,-1, 1, 1,
|
||||
-1,-1, 1,-1, 1,-1, 1, 1,-1,-1,-1, 1, 1,-1,-1,-1,
|
||||
-1, 1,-1,-1, 1,-1, 1, 1, 1, 1,-1, 1,-1, 1,-1, 1,
|
||||
-1,-1,-1,-1,-1, 1,-1, 1, 1,-1, 1,-1, 1, 1, 1,-1,
|
||||
-1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1,-1,-1,-1,-1 };
|
||||
1, 1, 1, 1, -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1,
|
||||
1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, 1,
|
||||
-1, -1, -1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1,
|
||||
1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1,
|
||||
1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, 1,
|
||||
1, -1, -1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
std::vector<gr_complex> base::get_csi() {
|
||||
std::vector<gr_complex> csi;
|
||||
csi.reserve(52);
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if ((i == 32) || (i < 6) || (i > 58)) {
|
||||
continue;
|
||||
}
|
||||
csi.push_back(d_H[i]);
|
||||
}
|
||||
return csi;
|
||||
std::vector<gr_complex> base::get_csi()
|
||||
{
|
||||
std::vector<gr_complex> csi;
|
||||
csi.reserve(52);
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if ((i == 32) || (i < 6) || (i > 58)) {
|
||||
continue;
|
||||
}
|
||||
csi.push_back(d_H[i]);
|
||||
}
|
||||
return csi;
|
||||
}
|
||||
|
||||
+15
-10
@@ -18,30 +18,35 @@
|
||||
#ifndef INCLUDED_IEEE802_11_EQUALIZER_BASE_H
|
||||
#define INCLUDED_IEEE802_11_EQUALIZER_BASE_H
|
||||
|
||||
#include <gnuradio/gr_complex.h>
|
||||
#include <gnuradio/digital/constellation.h>
|
||||
#include <gnuradio/gr_complex.h>
|
||||
|
||||
namespace gr {
|
||||
namespace ieee802_11 {
|
||||
namespace equalizer {
|
||||
|
||||
class base {
|
||||
class base
|
||||
{
|
||||
public:
|
||||
virtual ~base() {};
|
||||
virtual void equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod) = 0;
|
||||
virtual double get_snr() = 0;
|
||||
virtual ~base(){};
|
||||
virtual void equalize(gr_complex* in,
|
||||
int n,
|
||||
gr_complex* symbols,
|
||||
uint8_t* bits,
|
||||
boost::shared_ptr<gr::digital::constellation> mod) = 0;
|
||||
virtual double get_snr() = 0;
|
||||
|
||||
static const gr_complex POLARITY[127];
|
||||
static const gr_complex POLARITY[127];
|
||||
|
||||
std::vector<gr_complex> get_csi();
|
||||
std::vector<gr_complex> get_csi();
|
||||
|
||||
protected:
|
||||
static const gr_complex LONG[64];
|
||||
static const gr_complex LONG[64];
|
||||
|
||||
gr_complex d_H[64];
|
||||
gr_complex d_H[64];
|
||||
};
|
||||
|
||||
} /* namespace channel_estimation */
|
||||
} // namespace equalizer
|
||||
} /* namespace ieee802_11 */
|
||||
} /* namespace gr */
|
||||
|
||||
|
||||
+55
-48
@@ -19,59 +19,66 @@
|
||||
|
||||
using namespace gr::ieee802_11::equalizer;
|
||||
|
||||
void comb::equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod) {
|
||||
void comb::equalize(gr_complex* in,
|
||||
int n,
|
||||
gr_complex* symbols,
|
||||
uint8_t* bits,
|
||||
boost::shared_ptr<gr::digital::constellation> mod)
|
||||
{
|
||||
|
||||
gr_complex pilot[4];
|
||||
gr_complex pilot[4];
|
||||
|
||||
if(n < 2) {
|
||||
pilot[0] = in[11];
|
||||
pilot[1] = -in[25];
|
||||
pilot[2] = in[39];
|
||||
pilot[3] = in[53];
|
||||
} else {
|
||||
gr_complex p = POLARITY[(n - 2) % 127];
|
||||
pilot[0] = in[11] * p;
|
||||
pilot[1] = in[25] * p;
|
||||
pilot[2] = in[39] * p;
|
||||
pilot[3] = in[53] * -p;
|
||||
}
|
||||
if (n < 2) {
|
||||
pilot[0] = in[11];
|
||||
pilot[1] = -in[25];
|
||||
pilot[2] = in[39];
|
||||
pilot[3] = in[53];
|
||||
} else {
|
||||
gr_complex p = POLARITY[(n - 2) % 127];
|
||||
pilot[0] = in[11] * p;
|
||||
pilot[1] = in[25] * p;
|
||||
pilot[2] = in[39] * p;
|
||||
pilot[3] = in[53] * -p;
|
||||
}
|
||||
|
||||
gr_complex avg = (pilot[0] + pilot[1] + pilot[2] + pilot[3]) / gr_complex(4, 0);
|
||||
gr_complex avg = (pilot[0] + pilot[1] + pilot[2] + pilot[3]) / gr_complex(4, 0);
|
||||
|
||||
for(int i = 0; i < 64; i++) {
|
||||
gr_complex H;
|
||||
if(i <= 11) {
|
||||
H = gr_complex((11-i) / 11.0, 0) * avg + gr_complex( i / 11.0, 0) * pilot[0];
|
||||
} else if(i <= 25) {
|
||||
H = gr_complex((25-i) / 14.0, 0) * pilot[0] + gr_complex((i-11) / 14.0, 0) * pilot[1];
|
||||
} else if(i <= 39) {
|
||||
H = gr_complex((39-i) / 14.0, 0) * pilot[1] + gr_complex((i-25) / 14.0, 0) * pilot[2];
|
||||
} else if(i <= 53) {
|
||||
H = gr_complex((53-i) / 14.0, 0) * pilot[2] + gr_complex((i-39) / 14.0, 0) * pilot[3];
|
||||
} else {
|
||||
H = gr_complex((64-i) / 11.0, 0) * pilot[3] + gr_complex((i-53) / 11.0, 0) * avg;
|
||||
}
|
||||
for (int i = 0; i < 64; i++) {
|
||||
gr_complex H;
|
||||
if (i <= 11) {
|
||||
H = gr_complex((11 - i) / 11.0, 0) * avg + gr_complex(i / 11.0, 0) * pilot[0];
|
||||
} else if (i <= 25) {
|
||||
H = gr_complex((25 - i) / 14.0, 0) * pilot[0] +
|
||||
gr_complex((i - 11) / 14.0, 0) * pilot[1];
|
||||
} else if (i <= 39) {
|
||||
H = gr_complex((39 - i) / 14.0, 0) * pilot[1] +
|
||||
gr_complex((i - 25) / 14.0, 0) * pilot[2];
|
||||
} else if (i <= 53) {
|
||||
H = gr_complex((53 - i) / 14.0, 0) * pilot[2] +
|
||||
gr_complex((i - 39) / 14.0, 0) * pilot[3];
|
||||
} else {
|
||||
H = gr_complex((64 - i) / 11.0, 0) * pilot[3] +
|
||||
gr_complex((i - 53) / 11.0, 0) * avg;
|
||||
}
|
||||
|
||||
if(n == 0) {
|
||||
d_H[i] = H;
|
||||
} else {
|
||||
d_H[i] = gr_complex(1-alpha, 0) * d_H[i] + gr_complex(alpha, 0) * H;
|
||||
}
|
||||
}
|
||||
if (n == 0) {
|
||||
d_H[i] = H;
|
||||
} else {
|
||||
d_H[i] = gr_complex(1 - alpha, 0) * d_H[i] + gr_complex(alpha, 0) * H;
|
||||
}
|
||||
}
|
||||
|
||||
int c = 0;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if( (i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) || (i < 6) || ( i > 58)) {
|
||||
continue;
|
||||
} else {
|
||||
symbols[c] = in[i] / d_H[i];
|
||||
bits[c] = mod->decision_maker(&symbols[c]);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
int c = 0;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if ((i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) || (i < 6) ||
|
||||
(i > 58)) {
|
||||
continue;
|
||||
} else {
|
||||
symbols[c] = in[i] / d_H[i];
|
||||
bits[c] = mod->decision_maker(&symbols[c]);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
comb::get_snr() {
|
||||
return 42;
|
||||
}
|
||||
double comb::get_snr() { return 42; }
|
||||
|
||||
+10
-6
@@ -24,18 +24,22 @@ namespace gr {
|
||||
namespace ieee802_11 {
|
||||
namespace equalizer {
|
||||
|
||||
class comb: public base {
|
||||
class comb : public base
|
||||
{
|
||||
public:
|
||||
virtual void equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod);
|
||||
double get_snr();
|
||||
virtual void equalize(gr_complex* in,
|
||||
int n,
|
||||
gr_complex* symbols,
|
||||
uint8_t* bits,
|
||||
boost::shared_ptr<gr::digital::constellation> mod);
|
||||
double get_snr();
|
||||
|
||||
private:
|
||||
const double alpha = 0.2;
|
||||
const double alpha = 0.2;
|
||||
};
|
||||
|
||||
} /* namespace channel_estimation */
|
||||
} // namespace equalizer
|
||||
} /* namespace ieee802_11 */
|
||||
} /* namespace gr */
|
||||
|
||||
#endif /* INCLUDED_IEEE802_11_EQUALIZER_COMB_H */
|
||||
|
||||
|
||||
+39
-35
@@ -21,44 +21,48 @@
|
||||
|
||||
using namespace gr::ieee802_11::equalizer;
|
||||
|
||||
void lms::equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod) {
|
||||
void lms::equalize(gr_complex* in,
|
||||
int n,
|
||||
gr_complex* symbols,
|
||||
uint8_t* bits,
|
||||
boost::shared_ptr<gr::digital::constellation> mod)
|
||||
{
|
||||
|
||||
if(n == 0) {
|
||||
std::memcpy(d_H, in, 64 * sizeof(gr_complex));
|
||||
if (n == 0) {
|
||||
std::memcpy(d_H, in, 64 * sizeof(gr_complex));
|
||||
|
||||
} else if(n == 1) {
|
||||
double signal = 0;
|
||||
double noise = 0;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if((i == 32) || (i < 6) || ( i > 58)) {
|
||||
continue;
|
||||
}
|
||||
noise += std::pow(std::abs(d_H[i] - in[i]), 2);
|
||||
signal += std::pow(std::abs(d_H[i] + in[i]), 2);
|
||||
d_H[i] += in[i];
|
||||
d_H[i] /= LONG[i] * gr_complex(2, 0);
|
||||
}
|
||||
} else if (n == 1) {
|
||||
double signal = 0;
|
||||
double noise = 0;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if ((i == 32) || (i < 6) || (i > 58)) {
|
||||
continue;
|
||||
}
|
||||
noise += std::pow(std::abs(d_H[i] - in[i]), 2);
|
||||
signal += std::pow(std::abs(d_H[i] + in[i]), 2);
|
||||
d_H[i] += in[i];
|
||||
d_H[i] /= LONG[i] * gr_complex(2, 0);
|
||||
}
|
||||
|
||||
d_snr = 10 * std::log10(signal / noise / 2);
|
||||
d_snr = 10 * std::log10(signal / noise / 2);
|
||||
|
||||
} else {
|
||||
int c = 0;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if( (i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) || (i < 6) || ( i > 58)) {
|
||||
continue;
|
||||
} else {
|
||||
symbols[c] = in[i] / d_H[i];
|
||||
bits[c] = mod->decision_maker(&symbols[c]);
|
||||
gr_complex point;
|
||||
mod->map_to_points(bits[c], &point);
|
||||
d_H[i] = gr_complex(1-alpha,0) * d_H[i] + gr_complex(alpha,0) * in[i] / point;
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int c = 0;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if ((i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) ||
|
||||
(i < 6) || (i > 58)) {
|
||||
continue;
|
||||
} else {
|
||||
symbols[c] = in[i] / d_H[i];
|
||||
bits[c] = mod->decision_maker(&symbols[c]);
|
||||
gr_complex point;
|
||||
mod->map_to_points(bits[c], &point);
|
||||
d_H[i] = gr_complex(1 - alpha, 0) * d_H[i] +
|
||||
gr_complex(alpha, 0) * in[i] / point;
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
lms::get_snr() {
|
||||
return d_snr;
|
||||
}
|
||||
double lms::get_snr() { return d_snr; }
|
||||
|
||||
+13
-7
@@ -25,17 +25,23 @@ namespace gr {
|
||||
namespace ieee802_11 {
|
||||
namespace equalizer {
|
||||
|
||||
class lms: public base {
|
||||
class lms : public base
|
||||
{
|
||||
public:
|
||||
virtual void equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod);
|
||||
private:
|
||||
double get_snr();
|
||||
virtual void equalize(gr_complex* in,
|
||||
int n,
|
||||
gr_complex* symbols,
|
||||
uint8_t* bits,
|
||||
boost::shared_ptr<gr::digital::constellation> mod);
|
||||
|
||||
double d_snr;
|
||||
const double alpha = 0.5;
|
||||
private:
|
||||
double get_snr();
|
||||
|
||||
double d_snr;
|
||||
const double alpha = 0.5;
|
||||
};
|
||||
|
||||
} /* namespace channel_estimation */
|
||||
} // namespace equalizer
|
||||
} /* namespace ieee802_11 */
|
||||
} /* namespace gr */
|
||||
|
||||
|
||||
+35
-31
@@ -21,41 +21,45 @@
|
||||
|
||||
using namespace gr::ieee802_11::equalizer;
|
||||
|
||||
void ls::equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod) {
|
||||
void ls::equalize(gr_complex* in,
|
||||
int n,
|
||||
gr_complex* symbols,
|
||||
uint8_t* bits,
|
||||
boost::shared_ptr<gr::digital::constellation> mod)
|
||||
{
|
||||
|
||||
if(n == 0) {
|
||||
std::memcpy(d_H, in, 64 * sizeof(gr_complex));
|
||||
if (n == 0) {
|
||||
std::memcpy(d_H, in, 64 * sizeof(gr_complex));
|
||||
|
||||
} else if(n == 1) {
|
||||
double signal = 0;
|
||||
double noise = 0;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if((i == 32) || (i < 6) || ( i > 58)) {
|
||||
continue;
|
||||
}
|
||||
noise += std::pow(std::abs(d_H[i] - in[i]), 2);
|
||||
signal += std::pow(std::abs(d_H[i] + in[i]), 2);
|
||||
d_H[i] += in[i];
|
||||
d_H[i] /= LONG[i] * gr_complex(2, 0);
|
||||
}
|
||||
} else if (n == 1) {
|
||||
double signal = 0;
|
||||
double noise = 0;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if ((i == 32) || (i < 6) || (i > 58)) {
|
||||
continue;
|
||||
}
|
||||
noise += std::pow(std::abs(d_H[i] - in[i]), 2);
|
||||
signal += std::pow(std::abs(d_H[i] + in[i]), 2);
|
||||
d_H[i] += in[i];
|
||||
d_H[i] /= LONG[i] * gr_complex(2, 0);
|
||||
}
|
||||
|
||||
d_snr = 10 * std::log10(signal / noise / 2);
|
||||
d_snr = 10 * std::log10(signal / noise / 2);
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
int c = 0;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if( (i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) || (i < 6) || ( i > 58)) {
|
||||
continue;
|
||||
} else {
|
||||
symbols[c] = in[i] / d_H[i];
|
||||
bits[c] = mod->decision_maker(&symbols[c]);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
int c = 0;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if ((i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) ||
|
||||
(i < 6) || (i > 58)) {
|
||||
continue;
|
||||
} else {
|
||||
symbols[c] = in[i] / d_H[i];
|
||||
bits[c] = mod->decision_maker(&symbols[c]);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double ls::get_snr() {
|
||||
return d_snr;
|
||||
}
|
||||
double ls::get_snr() { return d_snr; }
|
||||
|
||||
+11
-6
@@ -25,17 +25,22 @@ namespace gr {
|
||||
namespace ieee802_11 {
|
||||
namespace equalizer {
|
||||
|
||||
class ls: public base {
|
||||
class ls : public base
|
||||
{
|
||||
public:
|
||||
virtual void equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod);
|
||||
virtual double get_snr();
|
||||
virtual void equalize(gr_complex* in,
|
||||
int n,
|
||||
gr_complex* symbols,
|
||||
uint8_t* bits,
|
||||
boost::shared_ptr<gr::digital::constellation> mod);
|
||||
virtual double get_snr();
|
||||
|
||||
private:
|
||||
double d_snr;
|
||||
double d_snr;
|
||||
};
|
||||
|
||||
} /* namespace channel_estimation */
|
||||
} // namespace equalizer
|
||||
} /* namespace ieee802_11 */
|
||||
} /* namespace gr */
|
||||
|
||||
#endif /* INCLUDED_IEEE802_11_EQUALIZER_LS_H */
|
||||
|
||||
|
||||
+64
-60
@@ -21,75 +21,79 @@
|
||||
|
||||
using namespace gr::ieee802_11::equalizer;
|
||||
|
||||
void sta::equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod) {
|
||||
void sta::equalize(gr_complex* in,
|
||||
int n,
|
||||
gr_complex* symbols,
|
||||
uint8_t* bits,
|
||||
boost::shared_ptr<gr::digital::constellation> mod)
|
||||
{
|
||||
|
||||
if(n == 0) {
|
||||
std::memcpy(d_H, in, 64 * sizeof(gr_complex));
|
||||
if (n == 0) {
|
||||
std::memcpy(d_H, in, 64 * sizeof(gr_complex));
|
||||
|
||||
} else if(n == 1) {
|
||||
double signal = 0;
|
||||
double noise = 0;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if((i == 32) || (i < 6) || ( i > 58)) {
|
||||
continue;
|
||||
}
|
||||
noise += std::pow(std::abs(d_H[i] - in[i]), 2);
|
||||
signal += std::pow(std::abs(d_H[i] + in[i]), 2);
|
||||
d_H[i] += in[i];
|
||||
d_H[i] /= LONG[i] * gr_complex(2, 0);
|
||||
}
|
||||
} else if (n == 1) {
|
||||
double signal = 0;
|
||||
double noise = 0;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if ((i == 32) || (i < 6) || (i > 58)) {
|
||||
continue;
|
||||
}
|
||||
noise += std::pow(std::abs(d_H[i] - in[i]), 2);
|
||||
signal += std::pow(std::abs(d_H[i] + in[i]), 2);
|
||||
d_H[i] += in[i];
|
||||
d_H[i] /= LONG[i] * gr_complex(2, 0);
|
||||
}
|
||||
|
||||
d_snr = 10 * std::log10(signal / noise / 2);
|
||||
d_snr = 10 * std::log10(signal / noise / 2);
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
gr_complex H_update[64];
|
||||
gr_complex H[64];
|
||||
gr_complex H_update[64];
|
||||
gr_complex H[64];
|
||||
|
||||
gr_complex p = POLARITY[(n - 2) % 127];
|
||||
gr_complex p = POLARITY[(n - 2) % 127];
|
||||
|
||||
H[11] = in[11] * p;
|
||||
H[25] = in[25] * p;
|
||||
H[39] = in[39] * p;
|
||||
H[53] = in[53] * -p;
|
||||
H[11] = in[11] * p;
|
||||
H[25] = in[25] * p;
|
||||
H[39] = in[39] * p;
|
||||
H[53] = in[53] * -p;
|
||||
|
||||
int c = 0;
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if( (i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) || (i < 6) || ( i > 58)) {
|
||||
continue;
|
||||
} else {
|
||||
symbols[c] = in[i] / d_H[i];
|
||||
bits[c] = mod->decision_maker(&symbols[c]);
|
||||
gr_complex point;
|
||||
mod->map_to_points(bits[c], &point);
|
||||
H[i] = in[i] / point;
|
||||
c++;
|
||||
}
|
||||
}
|
||||
int c = 0;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if ((i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) ||
|
||||
(i < 6) || (i > 58)) {
|
||||
continue;
|
||||
} else {
|
||||
symbols[c] = in[i] / d_H[i];
|
||||
bits[c] = mod->decision_maker(&symbols[c]);
|
||||
gr_complex point;
|
||||
mod->map_to_points(bits[c], &point);
|
||||
H[i] = in[i] / point;
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < 64; i++) {
|
||||
int n = 0;
|
||||
gr_complex s = 0;
|
||||
for(int k = i-beta; k <= i+beta; k++) {
|
||||
if((k == 32) || (k < 6) || ( k > 58)) {
|
||||
continue;
|
||||
}
|
||||
n++;
|
||||
s += H[k];
|
||||
}
|
||||
H_update[i] = s / gr_complex(n, 0);
|
||||
}
|
||||
for (int i = 0; i < 64; i++) {
|
||||
int n = 0;
|
||||
gr_complex s = 0;
|
||||
for (int k = i - beta; k <= i + beta; k++) {
|
||||
if ((k == 32) || (k < 6) || (k > 58)) {
|
||||
continue;
|
||||
}
|
||||
n++;
|
||||
s += H[k];
|
||||
}
|
||||
H_update[i] = s / gr_complex(n, 0);
|
||||
}
|
||||
|
||||
for(int i = 0; i < 64; i++) {
|
||||
if((i < 6) || ( i > 58)) {
|
||||
continue;
|
||||
}
|
||||
d_H[i] = gr_complex(1-alpha,0) * d_H[i] + gr_complex(alpha,0) * H_update[i];
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if ((i < 6) || (i > 58)) {
|
||||
continue;
|
||||
}
|
||||
d_H[i] =
|
||||
gr_complex(1 - alpha, 0) * d_H[i] + gr_complex(alpha, 0) * H_update[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
sta::get_snr() {
|
||||
return d_snr;
|
||||
}
|
||||
double sta::get_snr() { return d_snr; }
|
||||
|
||||
+12
-7
@@ -25,19 +25,24 @@ namespace gr {
|
||||
namespace ieee802_11 {
|
||||
namespace equalizer {
|
||||
|
||||
class sta: public base {
|
||||
class sta : public base
|
||||
{
|
||||
public:
|
||||
virtual void equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod);
|
||||
double get_snr();
|
||||
virtual void equalize(gr_complex* in,
|
||||
int n,
|
||||
gr_complex* symbols,
|
||||
uint8_t* bits,
|
||||
boost::shared_ptr<gr::digital::constellation> mod);
|
||||
double get_snr();
|
||||
|
||||
private:
|
||||
double d_snr;
|
||||
double d_snr;
|
||||
|
||||
const double alpha = 0.5;
|
||||
const int beta = 2;
|
||||
const double alpha = 0.5;
|
||||
const int beta = 2;
|
||||
};
|
||||
|
||||
} /* namespace channel_estimation */
|
||||
} // namespace equalizer
|
||||
} /* namespace ieee802_11 */
|
||||
} /* namespace gr */
|
||||
|
||||
|
||||
+84
-80
@@ -17,118 +17,122 @@
|
||||
#include "ether_encap_impl.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <gnuradio/block_detail.h>
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <string>
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
ether_encap_impl::ether_encap_impl(bool debug) :
|
||||
block("ether_encap",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(0, 0, 0)),
|
||||
d_debug(debug),
|
||||
d_last_seq(123) {
|
||||
ether_encap_impl::ether_encap_impl(bool debug)
|
||||
: block("ether_encap",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(0, 0, 0)),
|
||||
d_debug(debug),
|
||||
d_last_seq(123)
|
||||
{
|
||||
|
||||
message_port_register_out(pmt::mp("to tap"));
|
||||
message_port_register_out(pmt::mp("to wifi"));
|
||||
|
||||
message_port_register_in(pmt::mp("from tap"));
|
||||
set_msg_handler(pmt::mp("from tap"), boost::bind(ðer_encap_impl::from_tap, this, boost::placeholders::_1));
|
||||
set_msg_handler(
|
||||
pmt::mp("from tap"),
|
||||
boost::bind(ðer_encap_impl::from_tap, this, boost::placeholders::_1));
|
||||
message_port_register_in(pmt::mp("from wifi"));
|
||||
set_msg_handler(pmt::mp("from wifi"), boost::bind(ðer_encap_impl::from_wifi, this, boost::placeholders::_1));
|
||||
set_msg_handler(
|
||||
pmt::mp("from wifi"),
|
||||
boost::bind(ðer_encap_impl::from_wifi, this, boost::placeholders::_1));
|
||||
}
|
||||
|
||||
void
|
||||
ether_encap_impl::from_wifi(pmt::pmt_t msg) {
|
||||
void ether_encap_impl::from_wifi(pmt::pmt_t msg)
|
||||
{
|
||||
|
||||
msg = pmt::cdr(msg);
|
||||
msg = pmt::cdr(msg);
|
||||
|
||||
int data_len = pmt::blob_length(msg);
|
||||
const mac_header *mhdr = reinterpret_cast<const mac_header*>(pmt::blob_data(msg));
|
||||
int data_len = pmt::blob_length(msg);
|
||||
const mac_header* mhdr = reinterpret_cast<const mac_header*>(pmt::blob_data(msg));
|
||||
|
||||
if(d_last_seq == mhdr->seq_nr) {
|
||||
dout << "Ether Encap: frame already seen -- skipping" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (d_last_seq == mhdr->seq_nr) {
|
||||
dout << "Ether Encap: frame already seen -- skipping" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
d_last_seq = mhdr->seq_nr;
|
||||
d_last_seq = mhdr->seq_nr;
|
||||
|
||||
|
||||
if(data_len < 33) {
|
||||
dout << "Ether Encap: frame too short to parse (<33)" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (data_len < 33) {
|
||||
dout << "Ether Encap: frame too short to parse (<33)" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// this is more than needed
|
||||
char *buf = static_cast<char*>(std::malloc(data_len + sizeof(ethernet_header)));
|
||||
ethernet_header *ehdr = reinterpret_cast<ethernet_header*>(buf);
|
||||
// this is more than needed
|
||||
char* buf = static_cast<char*>(std::malloc(data_len + sizeof(ethernet_header)));
|
||||
ethernet_header* ehdr = reinterpret_cast<ethernet_header*>(buf);
|
||||
|
||||
if(((mhdr->frame_control >> 2) & 3) != 2) {
|
||||
dout << "this is not a data frame -- ignoring" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (((mhdr->frame_control >> 2) & 3) != 2) {
|
||||
dout << "this is not a data frame -- ignoring" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::memcpy(ehdr->dest, mhdr->addr1, 6);
|
||||
std::memcpy(ehdr->src, mhdr->addr2, 6);
|
||||
ehdr->type = 0x0008;
|
||||
std::memcpy(ehdr->dest, mhdr->addr1, 6);
|
||||
std::memcpy(ehdr->src, mhdr->addr2, 6);
|
||||
ehdr->type = 0x0008;
|
||||
|
||||
char *frame = (char*)pmt::blob_data(msg);
|
||||
char* frame = (char*)pmt::blob_data(msg);
|
||||
|
||||
// DATA
|
||||
if((((mhdr->frame_control) >> 2) & 63) == 2) {
|
||||
memcpy(buf + sizeof(ethernet_header), frame + 32, data_len - 32);
|
||||
pmt::pmt_t payload = pmt::make_blob(buf, data_len - 32 + 14);
|
||||
message_port_pub(pmt::mp("to tap"), pmt::cons(pmt::PMT_NIL, payload));
|
||||
// DATA
|
||||
if ((((mhdr->frame_control) >> 2) & 63) == 2) {
|
||||
memcpy(buf + sizeof(ethernet_header), frame + 32, data_len - 32);
|
||||
pmt::pmt_t payload = pmt::make_blob(buf, data_len - 32 + 14);
|
||||
message_port_pub(pmt::mp("to tap"), pmt::cons(pmt::PMT_NIL, payload));
|
||||
|
||||
// QoS Data
|
||||
} else if((((mhdr->frame_control) >> 2) & 63) == 34) {
|
||||
// QoS Data
|
||||
} else if ((((mhdr->frame_control) >> 2) & 63) == 34) {
|
||||
|
||||
memcpy(buf + sizeof(ethernet_header), frame + 34, data_len - 34);
|
||||
pmt::pmt_t payload = pmt::make_blob(buf, data_len - 34 + 14);
|
||||
message_port_pub(pmt::mp("to tap"), pmt::cons(pmt::PMT_NIL, payload));
|
||||
}
|
||||
memcpy(buf + sizeof(ethernet_header), frame + 34, data_len - 34);
|
||||
pmt::pmt_t payload = pmt::make_blob(buf, data_len - 34 + 14);
|
||||
message_port_pub(pmt::mp("to tap"), pmt::cons(pmt::PMT_NIL, payload));
|
||||
}
|
||||
|
||||
free(buf);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void
|
||||
ether_encap_impl::from_tap(pmt::pmt_t msg) {
|
||||
size_t len = pmt::blob_length(pmt::cdr(msg));
|
||||
const char* data = static_cast<const char*>(pmt::blob_data(pmt::cdr(msg)));
|
||||
void ether_encap_impl::from_tap(pmt::pmt_t msg)
|
||||
{
|
||||
size_t len = pmt::blob_length(pmt::cdr(msg));
|
||||
const char* data = static_cast<const char*>(pmt::blob_data(pmt::cdr(msg)));
|
||||
|
||||
const ethernet_header *ehdr = reinterpret_cast<const ethernet_header*>(data);
|
||||
const ethernet_header* ehdr = reinterpret_cast<const ethernet_header*>(data);
|
||||
|
||||
switch(ehdr->type) {
|
||||
case 0x0008: {
|
||||
std::cout << "ether type: IP" << std::endl;
|
||||
|
||||
char *buf = static_cast<char*>(malloc(len + 8 - sizeof(ethernet_header)));
|
||||
buf[0] = 0xaa;
|
||||
buf[1] = 0xaa;
|
||||
buf[2] = 0x03;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0x00;
|
||||
buf[5] = 0x00;
|
||||
buf[6] = 0x08;
|
||||
buf[7] = 0x00;
|
||||
std::memcpy(buf + 8, data + sizeof(ethernet_header), len - sizeof(ethernet_header));
|
||||
pmt::pmt_t blob = pmt::make_blob(buf, len + 8 - sizeof(ethernet_header));
|
||||
message_port_pub(pmt::mp("to wifi"), pmt::cons(pmt::PMT_NIL, blob));
|
||||
break;
|
||||
}
|
||||
case 0x0608:
|
||||
std::cout << "ether type: ARP " << std::endl;
|
||||
break;
|
||||
default:
|
||||
std::cout << "unknown ether type" << std::endl;
|
||||
break;
|
||||
}
|
||||
switch (ehdr->type) {
|
||||
case 0x0008: {
|
||||
std::cout << "ether type: IP" << std::endl;
|
||||
|
||||
char* buf = static_cast<char*>(malloc(len + 8 - sizeof(ethernet_header)));
|
||||
buf[0] = 0xaa;
|
||||
buf[1] = 0xaa;
|
||||
buf[2] = 0x03;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0x00;
|
||||
buf[5] = 0x00;
|
||||
buf[6] = 0x08;
|
||||
buf[7] = 0x00;
|
||||
std::memcpy(
|
||||
buf + 8, data + sizeof(ethernet_header), len - sizeof(ethernet_header));
|
||||
pmt::pmt_t blob = pmt::make_blob(buf, len + 8 - sizeof(ethernet_header));
|
||||
message_port_pub(pmt::mp("to wifi"), pmt::cons(pmt::PMT_NIL, blob));
|
||||
break;
|
||||
}
|
||||
case 0x0608:
|
||||
std::cout << "ether type: ARP " << std::endl;
|
||||
break;
|
||||
default:
|
||||
std::cout << "unknown ether type" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ether_encap::sptr
|
||||
ether_encap::make(bool debug) {
|
||||
return gnuradio::get_initial_sptr(new ether_encap_impl(debug));
|
||||
ether_encap::sptr ether_encap::make(bool debug)
|
||||
{
|
||||
return gnuradio::get_initial_sptr(new ether_encap_impl(debug));
|
||||
}
|
||||
|
||||
|
||||
+15
-15
@@ -22,27 +22,27 @@
|
||||
namespace gr {
|
||||
namespace ieee802_11 {
|
||||
|
||||
struct ethernet_header {
|
||||
uint8_t dest[6];
|
||||
uint8_t src[6];
|
||||
uint16_t type;
|
||||
}__attribute__((packed));
|
||||
struct ethernet_header {
|
||||
uint8_t dest[6];
|
||||
uint8_t src[6];
|
||||
uint16_t type;
|
||||
} __attribute__((packed));
|
||||
|
||||
class ether_encap_impl : public ether_encap {
|
||||
class ether_encap_impl : public ether_encap
|
||||
{
|
||||
|
||||
public:
|
||||
ether_encap_impl(bool debug);
|
||||
public:
|
||||
ether_encap_impl(bool debug);
|
||||
|
||||
private:
|
||||
void from_tap(pmt::pmt_t msg);
|
||||
void from_wifi(pmt::pmt_t msg);
|
||||
private:
|
||||
void from_tap(pmt::pmt_t msg);
|
||||
void from_wifi(pmt::pmt_t msg);
|
||||
|
||||
bool d_debug;
|
||||
uint16_t d_last_seq;
|
||||
};
|
||||
bool d_debug;
|
||||
uint16_t d_last_seq;
|
||||
};
|
||||
|
||||
} // namespace ieee802_11
|
||||
} // namespace gr
|
||||
|
||||
#endif /* INCLUDED_IEEE802_11_ETHER_ENCAP_IMPL_H */
|
||||
|
||||
|
||||
+30
-27
@@ -22,56 +22,59 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include "extract_csi_impl.h"
|
||||
#include <gnuradio/io_signature.h>
|
||||
|
||||
namespace gr {
|
||||
namespace ieee802_11 {
|
||||
|
||||
extract_csi::sptr extract_csi::make() {
|
||||
return gnuradio::get_initial_sptr(new extract_csi_impl());
|
||||
extract_csi::sptr extract_csi::make()
|
||||
{
|
||||
return gnuradio::get_initial_sptr(new extract_csi_impl());
|
||||
}
|
||||
|
||||
|
||||
extract_csi_impl::extract_csi_impl()
|
||||
: gr::sync_block("extract_csi", gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(1, 1, 52 * sizeof(gr_complex))) {
|
||||
message_port_register_in(pmt::mp("pdu in"));
|
||||
: gr::sync_block("extract_csi",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(1, 1, 52 * sizeof(gr_complex)))
|
||||
{
|
||||
message_port_register_in(pmt::mp("pdu in"));
|
||||
}
|
||||
|
||||
extract_csi_impl::~extract_csi_impl() {}
|
||||
|
||||
int extract_csi_impl::work(int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items) {
|
||||
pmt::pmt_t pdu(delete_head_nowait(pmt::mp("pdu in")));
|
||||
gr_vector_const_void_star& input_items,
|
||||
gr_vector_void_star& output_items)
|
||||
{
|
||||
pmt::pmt_t pdu(delete_head_nowait(pmt::mp("pdu in")));
|
||||
|
||||
if (pdu.get() == NULL)
|
||||
return 0;
|
||||
if (pdu.get() == NULL)
|
||||
return 0;
|
||||
|
||||
if (!pmt::is_pair(pdu) || !pmt::is_dict(pmt::car(pdu)))
|
||||
throw std::runtime_error("received a malformed pdu message");
|
||||
if (!pmt::is_pair(pdu) || !pmt::is_dict(pmt::car(pdu)))
|
||||
throw std::runtime_error("received a malformed pdu message");
|
||||
|
||||
d_meta = pmt::car(pdu);
|
||||
d_meta = pmt::car(pdu);
|
||||
|
||||
if (!pmt::dict_has_key(d_meta, pmt::mp("csi")))
|
||||
return 0;
|
||||
if (!pmt::dict_has_key(d_meta, pmt::mp("csi")))
|
||||
return 0;
|
||||
|
||||
d_csi = pmt::c32vector_elements(
|
||||
pmt::dict_ref(d_meta, pmt::mp("csi"), pmt::PMT_NIL));
|
||||
d_csi = pmt::c32vector_elements(pmt::dict_ref(d_meta, pmt::mp("csi"), pmt::PMT_NIL));
|
||||
|
||||
gr_complex *out = (gr_complex *)output_items[0];
|
||||
gr_complex* out = (gr_complex*)output_items[0];
|
||||
|
||||
std::copy(d_csi.begin(), d_csi.end(), out);
|
||||
std::copy(d_csi.begin(), d_csi.end(), out);
|
||||
|
||||
pmt::pmt_t keys(pmt::dict_keys(d_meta));
|
||||
for (int i = 0; i < pmt::length(keys); i++) {
|
||||
pmt::pmt_t k(pmt::nth(i, keys));
|
||||
pmt::pmt_t v(pmt::dict_ref(d_meta, k, pmt::PMT_NIL));
|
||||
add_item_tag(0, nitems_written(0), k, v, alias_pmt());
|
||||
}
|
||||
pmt::pmt_t keys(pmt::dict_keys(d_meta));
|
||||
for (int i = 0; i < pmt::length(keys); i++) {
|
||||
pmt::pmt_t k(pmt::nth(i, keys));
|
||||
pmt::pmt_t v(pmt::dict_ref(d_meta, k, pmt::PMT_NIL));
|
||||
add_item_tag(0, nitems_written(0), k, v, alias_pmt());
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
} /* namespace ieee802_11 */
|
||||
|
||||
@@ -26,17 +26,19 @@
|
||||
namespace gr {
|
||||
namespace ieee802_11 {
|
||||
|
||||
class extract_csi_impl : public extract_csi {
|
||||
class extract_csi_impl : public extract_csi
|
||||
{
|
||||
private:
|
||||
pmt::pmt_t d_meta;
|
||||
std::vector<gr_complex> d_csi;
|
||||
pmt::pmt_t d_meta;
|
||||
std::vector<gr_complex> d_csi;
|
||||
|
||||
public:
|
||||
extract_csi_impl();
|
||||
~extract_csi_impl();
|
||||
extract_csi_impl();
|
||||
~extract_csi_impl();
|
||||
|
||||
int work(int noutput_items, gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
int work(int noutput_items,
|
||||
gr_vector_const_void_star& input_items,
|
||||
gr_vector_void_star& output_items);
|
||||
};
|
||||
|
||||
} // namespace ieee802_11
|
||||
|
||||
+309
-297
@@ -15,12 +15,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 "frame_equalizer_impl.h"
|
||||
#include "utils.h"
|
||||
#include <gnuradio/io_signature.h>
|
||||
|
||||
@@ -28,330 +28,342 @@ 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::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),
|
||||
d_freq_offset_from_synclong(0.0) {
|
||||
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),
|
||||
d_freq_offset_from_synclong(0.0)
|
||||
{
|
||||
|
||||
message_port_register_out(pmt::mp("symbols"));
|
||||
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_bpsk = constellation_bpsk::make();
|
||||
d_qpsk = constellation_qpsk::make();
|
||||
d_16qam = constellation_16qam::make();
|
||||
d_64qam = constellation_64qam::make();
|
||||
|
||||
d_frame_mod = d_bpsk;
|
||||
d_frame_mod = d_bpsk;
|
||||
|
||||
set_tag_propagation_policy(block::TPP_DONT);
|
||||
set_algorithm(algo);
|
||||
set_tag_propagation_policy(block::TPP_DONT);
|
||||
set_algorithm(algo);
|
||||
}
|
||||
|
||||
frame_equalizer_impl::~frame_equalizer_impl() {
|
||||
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 << "STA" << std::endl;
|
||||
d_equalizer = new equalizer::sta();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Algorithm not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 << "STA" << 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_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::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;
|
||||
}
|
||||
|
||||
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_freq_offset_from_synclong =
|
||||
pmt::to_double(tags.front().value) * d_bw / (2 * M_PI);
|
||||
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];
|
||||
|
||||
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);
|
||||
|
||||
if (d_current_symbol < 2) {
|
||||
d_prev_pilots[0] = current_symbol[11];
|
||||
d_prev_pilots[1] = -current_symbol[25];
|
||||
d_prev_pilots[2] = current_symbol[39];
|
||||
d_prev_pilots[3] = current_symbol[53];
|
||||
} else {
|
||||
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)) {
|
||||
|
||||
pmt::pmt_t dict = pmt::make_dict();
|
||||
dict = pmt::dict_add(
|
||||
dict, pmt::mp("frame_bytes"), pmt::from_uint64(d_frame_bytes));
|
||||
dict = pmt::dict_add(
|
||||
dict, pmt::mp("encoding"), pmt::from_uint64(d_frame_encoding));
|
||||
dict = pmt::dict_add(
|
||||
dict, pmt::mp("snr"), pmt::from_double(d_equalizer->get_snr()));
|
||||
dict = pmt::dict_add(dict, pmt::mp("freq"), pmt::from_double(d_freq));
|
||||
dict = pmt::dict_add(dict,
|
||||
pmt::mp("freq_offset"),
|
||||
pmt::from_double(d_freq_offset_from_synclong));
|
||||
dict = pmt::dict_add(dict, pmt::mp("beta"), pmt::from_double(beta));
|
||||
|
||||
std::vector<gr_complex> csi = d_equalizer->get_csi();
|
||||
dict = pmt::dict_add(
|
||||
dict, pmt::mp("csi"), pmt::init_c32vector(csi.size(), csi));
|
||||
|
||||
add_item_tag(0,
|
||||
nitems_written(0) + o,
|
||||
pmt::string_to_symbol("wifi_start"),
|
||||
dict,
|
||||
pmt::string_to_symbol(alias()));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
bool frame_equalizer_impl::decode_signal_field(uint8_t* rx_bits)
|
||||
{
|
||||
|
||||
gr::thread::scoped_lock lock(d_mutex);
|
||||
static ofdm_param ofdm(BPSK_1_2);
|
||||
static frame_param frame(ofdm, 0);
|
||||
|
||||
const gr_complex *in = (const gr_complex *) input_items[0];
|
||||
uint8_t *out = (uint8_t *) output_items[0];
|
||||
deinterleave(rx_bits);
|
||||
uint8_t* decoded_bits = d_decoder.decode(&ofdm, &frame, d_deinterleaved);
|
||||
|
||||
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_freq_offset_from_synclong = pmt::to_double(tags.front().value) * d_bw / (2 * M_PI);
|
||||
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];
|
||||
|
||||
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);
|
||||
|
||||
if(d_current_symbol < 2) {
|
||||
d_prev_pilots[0] = current_symbol[11];
|
||||
d_prev_pilots[1] = -current_symbol[25];
|
||||
d_prev_pilots[2] = current_symbol[39];
|
||||
d_prev_pilots[3] = current_symbol[53];
|
||||
} else {
|
||||
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)) {
|
||||
|
||||
pmt::pmt_t dict = pmt::make_dict();
|
||||
dict = pmt::dict_add(dict, pmt::mp("frame_bytes"), pmt::from_uint64(d_frame_bytes));
|
||||
dict = pmt::dict_add(dict, pmt::mp("encoding"), pmt::from_uint64(d_frame_encoding));
|
||||
dict = pmt::dict_add(dict, pmt::mp("snr"), pmt::from_double(d_equalizer->get_snr()));
|
||||
dict = pmt::dict_add(dict, pmt::mp("freq"), pmt::from_double(d_freq));
|
||||
dict = pmt::dict_add(dict, pmt::mp("freq_offset"), pmt::from_double(d_freq_offset_from_synclong));
|
||||
dict = pmt::dict_add(dict, pmt::mp("beta"), pmt::from_double(beta));
|
||||
|
||||
std::vector<gr_complex> csi = d_equalizer->get_csi();
|
||||
dict = pmt::dict_add(dict, pmt::mp("csi"), pmt::init_c32vector(csi.size(), csi));
|
||||
|
||||
add_item_tag(0, nitems_written(0) + o,
|
||||
pmt::string_to_symbol("wifi_start"),
|
||||
dict,
|
||||
pmt::string_to_symbol(alias()));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
return parse_signal(decoded_bits);
|
||||
}
|
||||
|
||||
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]];
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
const 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};
|
||||
const 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 */
|
||||
|
||||
+40
-42
@@ -18,10 +18,10 @@
|
||||
#ifndef INCLUDED_IEEE802_11_FRAME_EQUALIZER_IMPL_H
|
||||
#define INCLUDED_IEEE802_11_FRAME_EQUALIZER_IMPL_H
|
||||
|
||||
#include <ieee802_11/frame_equalizer.h>
|
||||
#include <ieee802_11/constellations.h>
|
||||
#include "equalizer/base.h"
|
||||
#include "viterbi_decoder/viterbi_decoder.h"
|
||||
#include <ieee802_11/constellations.h>
|
||||
#include <ieee802_11/frame_equalizer.h>
|
||||
|
||||
namespace gr {
|
||||
namespace ieee802_11 {
|
||||
@@ -30,56 +30,54 @@ 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();
|
||||
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 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);
|
||||
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<gr::tag_t> tags;
|
||||
bool d_debug;
|
||||
bool d_log;
|
||||
int d_current_symbol;
|
||||
viterbi_decoder d_decoder;
|
||||
|
||||
bool parse_signal(uint8_t *signal);
|
||||
bool decode_signal_field(uint8_t *rx_bits);
|
||||
void deinterleave(uint8_t *rx_bits);
|
||||
// freq offset
|
||||
double d_freq; // Hz
|
||||
double d_freq_offset_from_synclong; // Hz, estimation from "sync_long" block
|
||||
double d_bw; // Hz
|
||||
double d_er;
|
||||
double d_epsilon0;
|
||||
gr_complex d_prev_pilots[4];
|
||||
|
||||
equalizer::base *d_equalizer;
|
||||
gr::thread::mutex d_mutex;
|
||||
std::vector<gr::tag_t> tags;
|
||||
bool d_debug;
|
||||
bool d_log;
|
||||
int d_current_symbol;
|
||||
viterbi_decoder d_decoder;
|
||||
int d_frame_bytes;
|
||||
int d_frame_symbols;
|
||||
int d_frame_encoding;
|
||||
|
||||
// freq offset
|
||||
double d_freq; // Hz
|
||||
double d_freq_offset_from_synclong; // Hz, estimation from "sync_long" block
|
||||
double d_bw; // Hz
|
||||
double d_er;
|
||||
double d_epsilon0;
|
||||
gr_complex d_prev_pilots[4];
|
||||
uint8_t d_deinterleaved[48];
|
||||
gr_complex symbols[48];
|
||||
|
||||
int d_frame_bytes;
|
||||
int d_frame_symbols;
|
||||
int d_frame_encoding;
|
||||
boost::shared_ptr<gr::digital::constellation> d_frame_mod;
|
||||
constellation_bpsk::sptr d_bpsk;
|
||||
constellation_qpsk::sptr d_qpsk;
|
||||
constellation_16qam::sptr d_16qam;
|
||||
constellation_64qam::sptr d_64qam;
|
||||
|
||||
uint8_t d_deinterleaved[48];
|
||||
gr_complex symbols[48];
|
||||
|
||||
boost::shared_ptr<gr::digital::constellation> d_frame_mod;
|
||||
constellation_bpsk::sptr d_bpsk;
|
||||
constellation_qpsk::sptr d_qpsk;
|
||||
constellation_16qam::sptr d_16qam;
|
||||
constellation_64qam::sptr d_64qam;
|
||||
|
||||
static const int interleaver_pattern[48];
|
||||
static const int interleaver_pattern[48];
|
||||
};
|
||||
|
||||
} // namespace ieee802_11
|
||||
|
||||
+120
-108
@@ -16,8 +16,8 @@
|
||||
*/
|
||||
#include <ieee802_11/mac.h>
|
||||
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <gnuradio/block_detail.h>
|
||||
#include <gnuradio/io_signature.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
@@ -34,145 +34,157 @@
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
class mac_impl : public mac {
|
||||
class mac_impl : public mac
|
||||
{
|
||||
|
||||
public:
|
||||
mac_impl(std::vector<uint8_t> src_mac,
|
||||
std::vector<uint8_t> dst_mac,
|
||||
std::vector<uint8_t> bss_mac)
|
||||
: block("mac", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)),
|
||||
d_seq_nr(0)
|
||||
{
|
||||
|
||||
mac_impl(std::vector<uint8_t> src_mac, std::vector<uint8_t> dst_mac, std::vector<uint8_t> bss_mac) :
|
||||
block("mac",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(0, 0, 0)),
|
||||
d_seq_nr(0) {
|
||||
message_port_register_out(pmt::mp("phy out"));
|
||||
message_port_register_out(pmt::mp("app out"));
|
||||
|
||||
message_port_register_out(pmt::mp("phy out"));
|
||||
message_port_register_out(pmt::mp("app out"));
|
||||
message_port_register_in(pmt::mp("app in"));
|
||||
set_msg_handler(pmt::mp("app in"),
|
||||
boost::bind(&mac_impl::app_in, this, boost::placeholders::_1));
|
||||
|
||||
message_port_register_in(pmt::mp("app in"));
|
||||
set_msg_handler(pmt::mp("app in"), boost::bind(&mac_impl::app_in, this, boost::placeholders::_1));
|
||||
message_port_register_in(pmt::mp("phy in"));
|
||||
set_msg_handler(pmt::mp("phy in"),
|
||||
boost::bind(&mac_impl::phy_in, this, boost::placeholders::_1));
|
||||
|
||||
message_port_register_in(pmt::mp("phy in"));
|
||||
set_msg_handler(pmt::mp("phy in"), boost::bind(&mac_impl::phy_in, this, boost::placeholders::_1));
|
||||
if (!check_mac(src_mac))
|
||||
throw std::invalid_argument("wrong mac address size");
|
||||
if (!check_mac(dst_mac))
|
||||
throw std::invalid_argument("wrong mac address size");
|
||||
if (!check_mac(bss_mac))
|
||||
throw std::invalid_argument("wrong mac address size");
|
||||
|
||||
if(!check_mac(src_mac)) throw std::invalid_argument("wrong mac address size");
|
||||
if(!check_mac(dst_mac)) throw std::invalid_argument("wrong mac address size");
|
||||
if(!check_mac(bss_mac)) throw std::invalid_argument("wrong mac address size");
|
||||
for (int i = 0; i < 6; i++) {
|
||||
d_src_mac[i] = src_mac[i];
|
||||
d_dst_mac[i] = dst_mac[i];
|
||||
d_bss_mac[i] = bss_mac[i];
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < 6; i++) {
|
||||
d_src_mac[i] = src_mac[i];
|
||||
d_dst_mac[i] = dst_mac[i];
|
||||
d_bss_mac[i] = bss_mac[i];
|
||||
}
|
||||
}
|
||||
void phy_in(pmt::pmt_t msg)
|
||||
{
|
||||
// this must be a pair
|
||||
if (!pmt::is_blob(pmt::cdr(msg))) {
|
||||
throw std::runtime_error("PMT must be blob");
|
||||
}
|
||||
|
||||
void phy_in (pmt::pmt_t msg) {
|
||||
// this must be a pair
|
||||
if (!pmt::is_blob(pmt::cdr(msg))) {
|
||||
throw std::runtime_error("PMT must be blob");
|
||||
}
|
||||
// strip MAC header
|
||||
// TODO: check for frame type to determine header size
|
||||
pmt::pmt_t blob(pmt::cdr(msg));
|
||||
const char* mpdu = reinterpret_cast<const char*>(pmt::blob_data(blob));
|
||||
std::cout << "pdu len " << pmt::blob_length(blob) << std::endl;
|
||||
pmt::pmt_t msdu = pmt::make_blob(mpdu + 24, pmt::blob_length(blob) - 24);
|
||||
|
||||
// strip MAC header
|
||||
// TODO: check for frame type to determine header size
|
||||
pmt::pmt_t blob(pmt::cdr(msg));
|
||||
const char *mpdu = reinterpret_cast<const char *>(pmt::blob_data(blob));
|
||||
std::cout << "pdu len " << pmt::blob_length(blob) << std::endl;
|
||||
pmt::pmt_t msdu = pmt::make_blob(mpdu + 24, pmt::blob_length(blob) - 24);
|
||||
message_port_pub(pmt::mp("app out"), pmt::cons(pmt::car(msg), msdu));
|
||||
}
|
||||
|
||||
message_port_pub(pmt::mp("app out"), pmt::cons(pmt::car(msg), msdu));
|
||||
}
|
||||
void app_in(pmt::pmt_t msg)
|
||||
{
|
||||
|
||||
void app_in (pmt::pmt_t msg) {
|
||||
size_t msg_len;
|
||||
const char* msdu;
|
||||
std::string str;
|
||||
|
||||
size_t msg_len;
|
||||
const char *msdu;
|
||||
std::string str;
|
||||
if (pmt::is_symbol(msg)) {
|
||||
|
||||
if(pmt::is_symbol(msg)) {
|
||||
str = pmt::symbol_to_string(msg);
|
||||
msg_len = str.length();
|
||||
msdu = str.data();
|
||||
|
||||
str = pmt::symbol_to_string(msg);
|
||||
msg_len = str.length();
|
||||
msdu = str.data();
|
||||
} else if (pmt::is_pair(msg)) {
|
||||
|
||||
} else if(pmt::is_pair(msg)) {
|
||||
msg_len = pmt::blob_length(pmt::cdr(msg));
|
||||
msdu = reinterpret_cast<const char*>(pmt::blob_data(pmt::cdr(msg)));
|
||||
|
||||
msg_len = pmt::blob_length(pmt::cdr(msg));
|
||||
msdu = reinterpret_cast<const char *>(pmt::blob_data(pmt::cdr(msg)));
|
||||
} else {
|
||||
throw std::invalid_argument("MAC expects PDUs or strings");
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
throw std::invalid_argument("MAC expects PDUs or strings");
|
||||
return;
|
||||
}
|
||||
if (msg_len > MAX_PAYLOAD_SIZE) {
|
||||
throw std::invalid_argument("Frame too large (> 1500)");
|
||||
}
|
||||
|
||||
if(msg_len > MAX_PAYLOAD_SIZE) {
|
||||
throw std::invalid_argument("Frame too large (> 1500)");
|
||||
}
|
||||
// make MAC frame
|
||||
int psdu_length;
|
||||
generate_mac_data_frame(msdu, msg_len, &psdu_length);
|
||||
|
||||
// make MAC frame
|
||||
int psdu_length;
|
||||
generate_mac_data_frame(msdu, msg_len, &psdu_length);
|
||||
// dict
|
||||
pmt::pmt_t dict = pmt::make_dict();
|
||||
dict = pmt::dict_add(dict, pmt::mp("crc_included"), pmt::PMT_T);
|
||||
|
||||
// dict
|
||||
pmt::pmt_t dict = pmt::make_dict();
|
||||
dict = pmt::dict_add(dict, pmt::mp("crc_included"), pmt::PMT_T);
|
||||
// blob
|
||||
pmt::pmt_t mac = pmt::make_blob(d_psdu, psdu_length);
|
||||
|
||||
// blob
|
||||
pmt::pmt_t mac = pmt::make_blob(d_psdu, psdu_length);
|
||||
// pdu
|
||||
message_port_pub(pmt::mp("phy out"), pmt::cons(dict, mac));
|
||||
}
|
||||
|
||||
// pdu
|
||||
message_port_pub(pmt::mp("phy out"), pmt::cons(dict, mac));
|
||||
}
|
||||
void generate_mac_data_frame(const char* msdu, int msdu_size, int* psdu_size)
|
||||
{
|
||||
|
||||
void generate_mac_data_frame(const char *msdu, int msdu_size, int *psdu_size) {
|
||||
// mac header
|
||||
mac_header header;
|
||||
header.frame_control = 0x0008;
|
||||
header.duration = 0x0000;
|
||||
|
||||
// mac header
|
||||
mac_header header;
|
||||
header.frame_control = 0x0008;
|
||||
header.duration = 0x0000;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
header.addr1[i] = d_dst_mac[i];
|
||||
header.addr2[i] = d_src_mac[i];
|
||||
header.addr3[i] = d_bss_mac[i];
|
||||
}
|
||||
|
||||
for(int i = 0; i < 6; i++) {
|
||||
header.addr1[i] = d_dst_mac[i];
|
||||
header.addr2[i] = d_src_mac[i];
|
||||
header.addr3[i] = d_bss_mac[i];
|
||||
}
|
||||
header.seq_nr = 0;
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if (d_seq_nr & (1 << i)) {
|
||||
header.seq_nr |= (1 << (i + 4));
|
||||
}
|
||||
}
|
||||
header.seq_nr = htole16(header.seq_nr);
|
||||
d_seq_nr++;
|
||||
|
||||
header.seq_nr = 0;
|
||||
for (int i = 0; i < 12; i++) {
|
||||
if(d_seq_nr & (1 << i)) {
|
||||
header.seq_nr |= (1 << (i + 4));
|
||||
}
|
||||
}
|
||||
header.seq_nr = htole16(header.seq_nr);
|
||||
d_seq_nr++;
|
||||
// header size is 24, plus 4 for FCS means 28 bytes
|
||||
*psdu_size = 28 + msdu_size;
|
||||
|
||||
//header size is 24, plus 4 for FCS means 28 bytes
|
||||
*psdu_size = 28 + msdu_size;
|
||||
// copy mac header into psdu
|
||||
std::memcpy(d_psdu, &header, 24);
|
||||
// copy msdu into psdu
|
||||
memcpy(d_psdu + 24, msdu, msdu_size);
|
||||
// compute and store fcs
|
||||
boost::crc_32_type result;
|
||||
result.process_bytes(d_psdu, msdu_size + 24);
|
||||
|
||||
//copy mac header into psdu
|
||||
std::memcpy(d_psdu, &header, 24);
|
||||
//copy msdu into psdu
|
||||
memcpy(d_psdu + 24, msdu, msdu_size);
|
||||
//compute and store fcs
|
||||
boost::crc_32_type result;
|
||||
result.process_bytes(d_psdu, msdu_size + 24);
|
||||
uint32_t fcs = result.checksum();
|
||||
memcpy(d_psdu + msdu_size + 24, &fcs, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
uint32_t fcs = result.checksum();
|
||||
memcpy(d_psdu + msdu_size + 24, &fcs, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
bool check_mac(std::vector<uint8_t> mac) {
|
||||
if(mac.size() != 6) return false;
|
||||
return true;
|
||||
}
|
||||
bool check_mac(std::vector<uint8_t> mac)
|
||||
{
|
||||
if (mac.size() != 6)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t d_seq_nr;
|
||||
uint8_t d_src_mac[6];
|
||||
uint8_t d_dst_mac[6];
|
||||
uint8_t d_bss_mac[6];
|
||||
uint8_t d_psdu[MAX_PSDU_SIZE];
|
||||
uint16_t d_seq_nr;
|
||||
uint8_t d_src_mac[6];
|
||||
uint8_t d_dst_mac[6];
|
||||
uint8_t d_bss_mac[6];
|
||||
uint8_t d_psdu[MAX_PSDU_SIZE];
|
||||
};
|
||||
|
||||
mac::sptr
|
||||
mac::make(std::vector<uint8_t> src_mac, std::vector<uint8_t> dst_mac, std::vector<uint8_t> bss_mac) {
|
||||
return gnuradio::get_initial_sptr(new mac_impl(src_mac, dst_mac, bss_mac));
|
||||
mac::sptr mac::make(std::vector<uint8_t> src_mac,
|
||||
std::vector<uint8_t> dst_mac,
|
||||
std::vector<uint8_t> bss_mac)
|
||||
{
|
||||
return gnuradio::get_initial_sptr(new mac_impl(src_mac, dst_mac, bss_mac));
|
||||
}
|
||||
|
||||
|
||||
+129
-123
@@ -14,174 +14,180 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <ieee802_11/mapper.h>
|
||||
#include "utils.h"
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <ieee802_11/mapper.h>
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
|
||||
class mapper_impl : public mapper {
|
||||
class mapper_impl : public mapper
|
||||
{
|
||||
public:
|
||||
static const int DATA_CARRIERS = 48;
|
||||
|
||||
static const int DATA_CARRIERS = 48;
|
||||
mapper_impl(Encoding e, bool debug)
|
||||
: block("mapper",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(1, 1, sizeof(char))),
|
||||
d_symbols_offset(0),
|
||||
d_symbols(NULL),
|
||||
d_debug(debug),
|
||||
d_scrambler(1),
|
||||
d_ofdm(e)
|
||||
{
|
||||
|
||||
mapper_impl(Encoding e, bool debug) :
|
||||
block ("mapper",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(1, 1, sizeof(char))),
|
||||
d_symbols_offset(0),
|
||||
d_symbols(NULL),
|
||||
d_debug(debug),
|
||||
d_scrambler(1),
|
||||
d_ofdm(e) {
|
||||
message_port_register_in(pmt::mp("in"));
|
||||
set_encoding(e);
|
||||
}
|
||||
|
||||
message_port_register_in(pmt::mp("in"));
|
||||
set_encoding(e);
|
||||
}
|
||||
~mapper_impl() { free(d_symbols); }
|
||||
|
||||
~mapper_impl() {
|
||||
free(d_symbols);
|
||||
}
|
||||
|
||||
void print_message(const char *msg, size_t len) {
|
||||
void print_message(const char* msg, size_t len)
|
||||
{
|
||||
|
||||
|
||||
dout << std::hex << "MAPPER input symbols" << std::endl
|
||||
<< "===========================" << std::endl;
|
||||
dout << std::hex << "MAPPER input symbols" << std::endl
|
||||
<< "===========================" << std::endl;
|
||||
|
||||
for(int i = 0; i < len; i++) {
|
||||
dout << std::hex << (int)msg[i] << " ";
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
dout << std::hex << (int)msg[i] << " ";
|
||||
}
|
||||
|
||||
dout << std::dec << std::endl;
|
||||
}
|
||||
dout << std::dec << std::endl;
|
||||
}
|
||||
|
||||
|
||||
int general_work(int noutput, gr_vector_int& ninput_items,
|
||||
gr_vector_const_void_star& input_items,
|
||||
gr_vector_void_star& output_items ) {
|
||||
int general_work(int noutput,
|
||||
gr_vector_int& ninput_items,
|
||||
gr_vector_const_void_star& input_items,
|
||||
gr_vector_void_star& output_items)
|
||||
{
|
||||
|
||||
unsigned char *out = (unsigned char*)output_items[0];
|
||||
dout << "MAPPER called offset: " << d_symbols_offset <<
|
||||
" length: " << d_symbols_len << std::endl;
|
||||
unsigned char* out = (unsigned char*)output_items[0];
|
||||
dout << "MAPPER called offset: " << d_symbols_offset
|
||||
<< " length: " << d_symbols_len << std::endl;
|
||||
|
||||
while(!d_symbols_offset) {
|
||||
pmt::pmt_t msg(delete_head_nowait(pmt::intern("in")));
|
||||
while (!d_symbols_offset) {
|
||||
pmt::pmt_t msg(delete_head_nowait(pmt::intern("in")));
|
||||
|
||||
if(!msg.get()) {
|
||||
return 0;
|
||||
}
|
||||
if (!msg.get()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(pmt::is_pair(msg)) {
|
||||
dout << "MAPPER: received new message" << std::endl;
|
||||
gr::thread::scoped_lock lock(d_mutex);
|
||||
if (pmt::is_pair(msg)) {
|
||||
dout << "MAPPER: received new message" << std::endl;
|
||||
gr::thread::scoped_lock lock(d_mutex);
|
||||
|
||||
int psdu_length = pmt::blob_length(pmt::cdr(msg));
|
||||
const char *psdu = static_cast<const char*>(pmt::blob_data(pmt::cdr(msg)));
|
||||
int psdu_length = pmt::blob_length(pmt::cdr(msg));
|
||||
const char* psdu =
|
||||
static_cast<const char*>(pmt::blob_data(pmt::cdr(msg)));
|
||||
|
||||
// ############ INSERT MAC STUFF
|
||||
frame_param frame(d_ofdm, psdu_length);
|
||||
if(frame.n_sym > MAX_SYM) {
|
||||
std::cout << "packet too large, maximum number of symbols is " << MAX_SYM << std::endl;
|
||||
return 0;
|
||||
}
|
||||
// ############ INSERT MAC STUFF
|
||||
frame_param frame(d_ofdm, psdu_length);
|
||||
if (frame.n_sym > MAX_SYM) {
|
||||
std::cout << "packet too large, maximum number of symbols is "
|
||||
<< MAX_SYM << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//alloc memory for modulation steps
|
||||
char *data_bits = (char*)calloc(frame.n_data_bits, sizeof(char));
|
||||
char *scrambled_data = (char*)calloc(frame.n_data_bits, sizeof(char));
|
||||
char *encoded_data = (char*)calloc(frame.n_data_bits * 2, sizeof(char));
|
||||
char *punctured_data = (char*)calloc(frame.n_encoded_bits, sizeof(char));
|
||||
char *interleaved_data = (char*)calloc(frame.n_encoded_bits, sizeof(char));
|
||||
char *symbols = (char*)calloc((frame.n_encoded_bits / d_ofdm.n_bpsc), sizeof(char));
|
||||
// alloc memory for modulation steps
|
||||
char* data_bits = (char*)calloc(frame.n_data_bits, sizeof(char));
|
||||
char* scrambled_data = (char*)calloc(frame.n_data_bits, sizeof(char));
|
||||
char* encoded_data = (char*)calloc(frame.n_data_bits * 2, sizeof(char));
|
||||
char* punctured_data = (char*)calloc(frame.n_encoded_bits, sizeof(char));
|
||||
char* interleaved_data =
|
||||
(char*)calloc(frame.n_encoded_bits, sizeof(char));
|
||||
char* symbols =
|
||||
(char*)calloc((frame.n_encoded_bits / d_ofdm.n_bpsc), sizeof(char));
|
||||
|
||||
//generate the WIFI data field, adding service field and pad bits
|
||||
generate_bits(psdu, data_bits, frame);
|
||||
// generate the WIFI data field, adding service field and pad bits
|
||||
generate_bits(psdu, data_bits, frame);
|
||||
|
||||
// scrambling
|
||||
scramble(data_bits, scrambled_data, frame, d_scrambler++);
|
||||
if(d_scrambler > 127) {
|
||||
d_scrambler = 1;
|
||||
}
|
||||
// scrambling
|
||||
scramble(data_bits, scrambled_data, frame, d_scrambler++);
|
||||
if (d_scrambler > 127) {
|
||||
d_scrambler = 1;
|
||||
}
|
||||
|
||||
// reset tail bits
|
||||
reset_tail_bits(scrambled_data, frame);
|
||||
// encoding
|
||||
convolutional_encoding(scrambled_data, encoded_data, frame);
|
||||
// puncturing
|
||||
puncturing(encoded_data, punctured_data, frame, d_ofdm);
|
||||
//std::cout << "punctured" << std::endl;
|
||||
// interleaving
|
||||
interleave(punctured_data, interleaved_data, frame, d_ofdm);
|
||||
//std::cout << "interleaved" << std::endl;
|
||||
// reset tail bits
|
||||
reset_tail_bits(scrambled_data, frame);
|
||||
// encoding
|
||||
convolutional_encoding(scrambled_data, encoded_data, frame);
|
||||
// puncturing
|
||||
puncturing(encoded_data, punctured_data, frame, d_ofdm);
|
||||
// std::cout << "punctured" << std::endl;
|
||||
// interleaving
|
||||
interleave(punctured_data, interleaved_data, frame, d_ofdm);
|
||||
// std::cout << "interleaved" << std::endl;
|
||||
|
||||
// one byte per symbol
|
||||
split_symbols(interleaved_data, symbols, frame, d_ofdm);
|
||||
// one byte per symbol
|
||||
split_symbols(interleaved_data, symbols, frame, d_ofdm);
|
||||
|
||||
d_symbols_len = frame.n_sym * 48;
|
||||
d_symbols_len = frame.n_sym * 48;
|
||||
|
||||
d_symbols = (char*)calloc(d_symbols_len, 1);
|
||||
std::memcpy(d_symbols, symbols, d_symbols_len);
|
||||
d_symbols = (char*)calloc(d_symbols_len, 1);
|
||||
std::memcpy(d_symbols, symbols, d_symbols_len);
|
||||
|
||||
|
||||
// add tags
|
||||
pmt::pmt_t key = pmt::string_to_symbol("packet_len");
|
||||
pmt::pmt_t value = pmt::from_long(d_symbols_len);
|
||||
pmt::pmt_t srcid = pmt::string_to_symbol(alias());
|
||||
add_item_tag(0, nitems_written(0), key, value, srcid);
|
||||
// add tags
|
||||
pmt::pmt_t key = pmt::string_to_symbol("packet_len");
|
||||
pmt::pmt_t value = pmt::from_long(d_symbols_len);
|
||||
pmt::pmt_t srcid = pmt::string_to_symbol(alias());
|
||||
add_item_tag(0, nitems_written(0), key, value, srcid);
|
||||
|
||||
pmt::pmt_t psdu_bytes = pmt::from_long(psdu_length);
|
||||
add_item_tag(0, nitems_written(0), pmt::mp("psdu_len"),
|
||||
psdu_bytes, srcid);
|
||||
pmt::pmt_t psdu_bytes = pmt::from_long(psdu_length);
|
||||
add_item_tag(
|
||||
0, nitems_written(0), pmt::mp("psdu_len"), psdu_bytes, srcid);
|
||||
|
||||
pmt::pmt_t encoding = pmt::from_long(d_ofdm.encoding);
|
||||
add_item_tag(0, nitems_written(0), pmt::mp("encoding"),
|
||||
encoding, srcid);
|
||||
pmt::pmt_t encoding = pmt::from_long(d_ofdm.encoding);
|
||||
add_item_tag(0, nitems_written(0), pmt::mp("encoding"), encoding, srcid);
|
||||
|
||||
|
||||
free(data_bits);
|
||||
free(scrambled_data);
|
||||
free(encoded_data);
|
||||
free(punctured_data);
|
||||
free(interleaved_data);
|
||||
free(symbols);
|
||||
free(data_bits);
|
||||
free(scrambled_data);
|
||||
free(encoded_data);
|
||||
free(punctured_data);
|
||||
free(interleaved_data);
|
||||
free(symbols);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int i = std::min(noutput, d_symbols_len - d_symbols_offset);
|
||||
std::memcpy(out, d_symbols + d_symbols_offset, i);
|
||||
d_symbols_offset += i;
|
||||
int i = std::min(noutput, d_symbols_len - d_symbols_offset);
|
||||
std::memcpy(out, d_symbols + d_symbols_offset, i);
|
||||
d_symbols_offset += i;
|
||||
|
||||
if(d_symbols_offset == d_symbols_len) {
|
||||
d_symbols_offset = 0;
|
||||
free(d_symbols);
|
||||
d_symbols = 0;
|
||||
}
|
||||
if (d_symbols_offset == d_symbols_len) {
|
||||
d_symbols_offset = 0;
|
||||
free(d_symbols);
|
||||
d_symbols = 0;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void set_encoding(Encoding encoding) {
|
||||
void set_encoding(Encoding encoding)
|
||||
{
|
||||
|
||||
std::cout << "MAPPER: encoding: " << encoding << std::endl;
|
||||
gr::thread::scoped_lock lock(d_mutex);
|
||||
std::cout << "MAPPER: encoding: " << encoding << std::endl;
|
||||
gr::thread::scoped_lock lock(d_mutex);
|
||||
|
||||
d_ofdm = ofdm_param(encoding);
|
||||
}
|
||||
d_ofdm = ofdm_param(encoding);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t d_scrambler;
|
||||
bool d_debug;
|
||||
char* d_symbols;
|
||||
int d_symbols_offset;
|
||||
int d_symbols_len;
|
||||
ofdm_param d_ofdm;
|
||||
gr::thread::mutex d_mutex;
|
||||
uint8_t d_scrambler;
|
||||
bool d_debug;
|
||||
char* d_symbols;
|
||||
int d_symbols_offset;
|
||||
int d_symbols_len;
|
||||
ofdm_param d_ofdm;
|
||||
gr::thread::mutex d_mutex;
|
||||
};
|
||||
|
||||
mapper::sptr
|
||||
mapper::make(Encoding mcs, bool debug) {
|
||||
return gnuradio::get_initial_sptr(new mapper_impl(mcs, debug));
|
||||
mapper::sptr mapper::make(Encoding mcs, bool debug)
|
||||
{
|
||||
return gnuradio::get_initial_sptr(new mapper_impl(mcs, debug));
|
||||
}
|
||||
|
||||
+374
-350
@@ -14,415 +14,439 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <ieee802_11/parse_mac.h>
|
||||
#include "utils.h"
|
||||
#include <ieee802_11/parse_mac.h>
|
||||
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <gnuradio/block_detail.h>
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <string>
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
class parse_mac_impl : public parse_mac {
|
||||
class parse_mac_impl : public parse_mac
|
||||
{
|
||||
|
||||
public:
|
||||
parse_mac_impl(bool log, bool debug)
|
||||
: block("parse_mac",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(0, 0, 0)),
|
||||
d_log(log),
|
||||
d_last_seq_no(-1),
|
||||
d_debug(debug)
|
||||
{
|
||||
|
||||
parse_mac_impl(bool log, bool debug) :
|
||||
block("parse_mac",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(0, 0, 0)),
|
||||
d_log(log), d_last_seq_no(-1),
|
||||
d_debug(debug) {
|
||||
message_port_register_in(pmt::mp("in"));
|
||||
set_msg_handler(
|
||||
pmt::mp("in"),
|
||||
boost::bind(&parse_mac_impl::parse, this, boost::placeholders::_1));
|
||||
|
||||
message_port_register_in(pmt::mp("in"));
|
||||
set_msg_handler(pmt::mp("in"), boost::bind(&parse_mac_impl::parse, this, boost::placeholders::_1));
|
||||
message_port_register_out(pmt::mp("out"));
|
||||
}
|
||||
|
||||
message_port_register_out(pmt::mp("out"));
|
||||
}
|
||||
~parse_mac_impl() {}
|
||||
|
||||
~parse_mac_impl() {
|
||||
void parse(pmt::pmt_t pdu)
|
||||
{
|
||||
|
||||
}
|
||||
if (pmt::is_eof_object(pdu)) {
|
||||
detail().get()->set_done(true);
|
||||
return;
|
||||
} else if (pmt::is_symbol(pdu)) {
|
||||
return;
|
||||
}
|
||||
|
||||
void parse(pmt::pmt_t pdu) {
|
||||
d_meta = pmt::car(pdu);
|
||||
d_msg = pmt::cdr(pdu);
|
||||
|
||||
if(pmt::is_eof_object(pdu)) {
|
||||
detail().get()->set_done(true);
|
||||
return;
|
||||
} else if(pmt::is_symbol(pdu)) {
|
||||
return;
|
||||
}
|
||||
int frame_len = pmt::blob_length(d_msg);
|
||||
mac_header* h = (mac_header*)pmt::blob_data(d_msg);
|
||||
|
||||
d_meta = pmt::car(pdu);
|
||||
d_msg = pmt::cdr(pdu);
|
||||
mylog(boost::format("length: %1%") % frame_len);
|
||||
|
||||
int frame_len = pmt::blob_length(d_msg);
|
||||
mac_header *h = (mac_header*)pmt::blob_data(d_msg);
|
||||
dout << std::endl << "new mac frame (length " << frame_len << ")" << std::endl;
|
||||
dout << "=========================================" << std::endl;
|
||||
if (frame_len < 20) {
|
||||
dout << "frame too short to parse (<20)" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
mylog(boost::format("length: %1%") % frame_len );
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Duration"), pmt::mp(h->duration));
|
||||
|
||||
dout << std::endl << "new mac frame (length " << frame_len << ")" << std::endl;
|
||||
dout << "=========================================" << std::endl;
|
||||
if(frame_len < 20) {
|
||||
dout << "frame too short to parse (<20)" << std::endl;
|
||||
return;
|
||||
}
|
||||
#define HEX(a) std::hex << std::setfill('0') << std::setw(2) << int(a) << std::dec
|
||||
dout << "duration: " << HEX(h->duration >> 8) << " " << HEX(h->duration & 0xff)
|
||||
<< std::endl;
|
||||
dout << "frame control: " << HEX(h->frame_control >> 8) << " "
|
||||
<< HEX(h->frame_control & 0xff);
|
||||
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Duration"), pmt::mp(h->duration));
|
||||
switch ((h->frame_control >> 2) & 3) {
|
||||
|
||||
#define HEX(a) std::hex << std::setfill('0') << std::setw(2) << int(a) << std::dec
|
||||
dout << "duration: " << HEX(h->duration >> 8) << " " << HEX(h->duration & 0xff) << std::endl;
|
||||
dout << "frame control: " << HEX(h->frame_control >> 8) << " " << HEX(h->frame_control & 0xff);
|
||||
case 0:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Type"), pmt::mp("Management"));
|
||||
dout << " (MANAGEMENT)" << std::endl;
|
||||
parse_management((char*)h, frame_len);
|
||||
break;
|
||||
case 1:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Type"), pmt::mp("Control"));
|
||||
dout << " (CONTROL)" << std::endl;
|
||||
parse_control((char*)h, frame_len);
|
||||
break;
|
||||
|
||||
switch((h->frame_control >> 2) & 3) {
|
||||
case 2:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Type"), pmt::mp("Data"));
|
||||
dout << " (DATA)" << std::endl;
|
||||
parse_data((char*)h, frame_len);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Type"), pmt::mp("Management"));
|
||||
dout << " (MANAGEMENT)" << std::endl;
|
||||
parse_management((char*)h, frame_len);
|
||||
break;
|
||||
case 1:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Type"), pmt::mp("Control"));
|
||||
dout << " (CONTROL)" << std::endl;
|
||||
parse_control((char*)h, frame_len);
|
||||
break;
|
||||
default:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Type"), pmt::mp("Unknown"));
|
||||
dout << " (unknown)" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Type"), pmt::mp("Data"));
|
||||
dout << " (DATA)" << std::endl;
|
||||
parse_data((char*)h, frame_len);
|
||||
break;
|
||||
char* frame = (char*)pmt::blob_data(d_msg);
|
||||
|
||||
default:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Type"), pmt::mp("Unknown"));
|
||||
dout << " (unknown)" << std::endl;
|
||||
break;
|
||||
}
|
||||
// DATA
|
||||
if ((((h->frame_control) >> 2) & 63) == 2) {
|
||||
print_ascii(frame + 24, frame_len - 24);
|
||||
// QoS Data
|
||||
} else if ((((h->frame_control) >> 2) & 63) == 34) {
|
||||
print_ascii(frame + 26, frame_len - 26);
|
||||
}
|
||||
|
||||
char *frame = (char*)pmt::blob_data(d_msg);
|
||||
message_port_pub(pmt::mp("out"), pmt::cons(d_meta, d_msg));
|
||||
}
|
||||
|
||||
// DATA
|
||||
if((((h->frame_control) >> 2) & 63) == 2) {
|
||||
print_ascii(frame + 24, frame_len - 24);
|
||||
// QoS Data
|
||||
} else if((((h->frame_control) >> 2) & 63) == 34) {
|
||||
print_ascii(frame + 26, frame_len - 26);
|
||||
}
|
||||
void parse_management(char* buf, int length)
|
||||
{
|
||||
mac_header* h = (mac_header*)buf;
|
||||
|
||||
message_port_pub(pmt::mp("out"), pmt::cons(d_meta, d_msg));
|
||||
}
|
||||
if (length < 24) {
|
||||
dout << "too short for a management frame" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
void parse_management(char *buf, int length) {
|
||||
mac_header* h = (mac_header*)buf;
|
||||
dout << "Subtype: ";
|
||||
switch (((h->frame_control) >> 4) & 0xf) {
|
||||
case 0:
|
||||
d_meta =
|
||||
pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Association Request"));
|
||||
dout << "Association Request";
|
||||
break;
|
||||
case 1:
|
||||
d_meta = pmt::dict_add(
|
||||
d_meta, pmt::mp("Subtype"), pmt::mp("Association Response"));
|
||||
dout << "Association Response";
|
||||
break;
|
||||
case 2:
|
||||
d_meta = pmt::dict_add(
|
||||
d_meta, pmt::mp("Subtype"), pmt::mp("Reassociation Request"));
|
||||
dout << "Reassociation Request";
|
||||
break;
|
||||
case 3:
|
||||
d_meta = pmt::dict_add(
|
||||
d_meta, pmt::mp("Subtype"), pmt::mp("Reassociation Response"));
|
||||
dout << "Reassociation Response";
|
||||
break;
|
||||
case 4:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Probe Request"));
|
||||
dout << "Probe Request";
|
||||
break;
|
||||
case 5:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Probe Response"));
|
||||
dout << "Probe Response";
|
||||
break;
|
||||
case 6:
|
||||
d_meta = pmt::dict_add(
|
||||
d_meta, pmt::mp("Subtype"), pmt::mp("Timing Advertisement"));
|
||||
dout << "Timing Advertisement";
|
||||
break;
|
||||
case 7:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Reserved"));
|
||||
dout << "Reserved";
|
||||
break;
|
||||
case 8:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Beacon"));
|
||||
dout << "Beacon" << std::endl;
|
||||
if (length < 38) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
uint8_t* len = (uint8_t*)(buf + 24 + 13);
|
||||
if (length < 38 + *len) {
|
||||
return;
|
||||
}
|
||||
std::string s(buf + 24 + 14, *len);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("SSID"), pmt::mp(s));
|
||||
dout << "SSID: " << s;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("ATIM"));
|
||||
dout << "ATIM";
|
||||
break;
|
||||
case 10:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Disassociation"));
|
||||
dout << "Disassociation";
|
||||
break;
|
||||
case 11:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Authentication"));
|
||||
dout << "Authentication";
|
||||
break;
|
||||
case 12:
|
||||
d_meta =
|
||||
pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Deauthentication"));
|
||||
dout << "Deauthentication";
|
||||
break;
|
||||
case 13:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Action"));
|
||||
dout << "Action";
|
||||
break;
|
||||
case 14:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Action No Ack"));
|
||||
dout << "Action No Ack";
|
||||
break;
|
||||
case 15:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Reserved"));
|
||||
dout << "Reserved";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dout << std::endl;
|
||||
|
||||
if(length < 24) {
|
||||
dout << "too short for a management frame" << std::endl;
|
||||
return;
|
||||
}
|
||||
int seq_no = int(h->seq_nr >> 4);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Sequence number"), pmt::mp(seq_no));
|
||||
dout << "seq nr: " << seq_no << std::endl;
|
||||
|
||||
dout << "Subtype: ";
|
||||
switch(((h->frame_control) >> 4) & 0xf) {
|
||||
case 0:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Association Request"));
|
||||
dout << "Association Request";
|
||||
break;
|
||||
case 1:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Association Response"));
|
||||
dout << "Association Response";
|
||||
break;
|
||||
case 2:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Reassociation Request"));
|
||||
dout << "Reassociation Request";
|
||||
break;
|
||||
case 3:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Reassociation Response"));
|
||||
dout << "Reassociation Response";
|
||||
break;
|
||||
case 4:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Probe Request"));
|
||||
dout << "Probe Request";
|
||||
break;
|
||||
case 5:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Probe Response"));
|
||||
dout << "Probe Response";
|
||||
break;
|
||||
case 6:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Timing Advertisement"));
|
||||
dout << "Timing Advertisement";
|
||||
break;
|
||||
case 7:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Reserved"));
|
||||
dout << "Reserved";
|
||||
break;
|
||||
case 8:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Beacon"));
|
||||
dout << "Beacon" << std::endl;
|
||||
if(length < 38) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
uint8_t* len = (uint8_t*) (buf + 24 + 13);
|
||||
if(length < 38 + *len) {
|
||||
return;
|
||||
}
|
||||
std::string s(buf + 24 + 14, *len);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("SSID"), pmt::mp(s));
|
||||
dout << "SSID: " << s;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("ATIM"));
|
||||
dout << "ATIM";
|
||||
break;
|
||||
case 10:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Disassociation"));
|
||||
dout << "Disassociation";
|
||||
break;
|
||||
case 11:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Authentication"));
|
||||
dout << "Authentication";
|
||||
break;
|
||||
case 12:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Deauthentication"));
|
||||
dout << "Deauthentication";
|
||||
break;
|
||||
case 13:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Action"));
|
||||
dout << "Action";
|
||||
break;
|
||||
case 14:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Action No Ack"));
|
||||
dout << "Action No Ack";
|
||||
break;
|
||||
case 15:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Reserved"));
|
||||
dout << "Reserved";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dout << std::endl;
|
||||
auto address = format_mac_address(h->addr1);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 1"), pmt::mp(address));
|
||||
dout << "address 1: " << address << std::endl;
|
||||
|
||||
int seq_no = int(h->seq_nr >> 4);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Sequence number"), pmt::mp(seq_no));
|
||||
dout << "seq nr: " << seq_no << std::endl;
|
||||
address = format_mac_address(h->addr2);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 2"), pmt::mp(address));
|
||||
dout << "address 2: " << address << std::endl;
|
||||
|
||||
auto address = format_mac_address(h->addr1);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 1"), pmt::mp(address));
|
||||
dout << "address 1: " << address << std::endl;
|
||||
|
||||
address = format_mac_address(h->addr2);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 2"), pmt::mp(address));
|
||||
dout << "address 2: "<< address << std::endl;
|
||||
|
||||
address = format_mac_address(h->addr3);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 3"), pmt::mp(address));
|
||||
dout << "address 3: "<< address << std::endl;
|
||||
}
|
||||
address = format_mac_address(h->addr3);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 3"), pmt::mp(address));
|
||||
dout << "address 3: " << address << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void parse_data(char *buf, int length) {
|
||||
mac_header* h = (mac_header*)buf;
|
||||
if(length < 24) {
|
||||
dout << "too short for a data frame" << std::endl;
|
||||
return;
|
||||
}
|
||||
void parse_data(char* buf, int length)
|
||||
{
|
||||
mac_header* h = (mac_header*)buf;
|
||||
if (length < 24) {
|
||||
dout << "too short for a data frame" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
dout << "Subtype: ";
|
||||
switch(((h->frame_control) >> 4) & 0xf) {
|
||||
case 0:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Data"));
|
||||
dout << "Data";
|
||||
break;
|
||||
case 1:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Data + CF-ACK"));
|
||||
dout << "Data + CF-ACK";
|
||||
break;
|
||||
case 2:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Data + CR-Poll"));
|
||||
dout << "Data + CR-Poll";
|
||||
break;
|
||||
case 3:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Data + CF-ACK + CF-Poll"));
|
||||
dout << "Data + CF-ACK + CF-Poll";
|
||||
break;
|
||||
case 4:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Null"));
|
||||
dout << "Null";
|
||||
break;
|
||||
case 5:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CF-ACK"));
|
||||
dout << "CF-ACK";
|
||||
break;
|
||||
case 6:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CF-Poll"));
|
||||
dout << "CF-Poll";
|
||||
break;
|
||||
case 7:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CF-ACK + CF-Poll"));
|
||||
dout << "CF-ACK + CF-Poll";
|
||||
break;
|
||||
case 8:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS Data"));
|
||||
dout << "QoS Data";
|
||||
break;
|
||||
case 9:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS Data + CF-ACK"));
|
||||
dout << "QoS Data + CF-ACK";
|
||||
break;
|
||||
case 10:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS Data + CF-Poll"));
|
||||
dout << "QoS Data + CF-Poll";
|
||||
break;
|
||||
case 11:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS Data + CF-ACK + CF-Poll"));
|
||||
dout << "QoS Data + CF-ACK + CF-Poll";
|
||||
break;
|
||||
case 12:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS Null"));
|
||||
dout << "QoS Null";
|
||||
break;
|
||||
case 13:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Reserved"));
|
||||
dout << "Reserved";
|
||||
break;
|
||||
case 14:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS CF-Poll"));
|
||||
dout << "QoS CF-Poll";
|
||||
break;
|
||||
case 15:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS CF-ACK + CF-Poll"));
|
||||
dout << "QoS CF-ACK + CF-Poll";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dout << std::endl;
|
||||
dout << "Subtype: ";
|
||||
switch (((h->frame_control) >> 4) & 0xf) {
|
||||
case 0:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Data"));
|
||||
dout << "Data";
|
||||
break;
|
||||
case 1:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Data + CF-ACK"));
|
||||
dout << "Data + CF-ACK";
|
||||
break;
|
||||
case 2:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Data + CR-Poll"));
|
||||
dout << "Data + CR-Poll";
|
||||
break;
|
||||
case 3:
|
||||
d_meta = pmt::dict_add(
|
||||
d_meta, pmt::mp("Subtype"), pmt::mp("Data + CF-ACK + CF-Poll"));
|
||||
dout << "Data + CF-ACK + CF-Poll";
|
||||
break;
|
||||
case 4:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Null"));
|
||||
dout << "Null";
|
||||
break;
|
||||
case 5:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CF-ACK"));
|
||||
dout << "CF-ACK";
|
||||
break;
|
||||
case 6:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CF-Poll"));
|
||||
dout << "CF-Poll";
|
||||
break;
|
||||
case 7:
|
||||
d_meta =
|
||||
pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CF-ACK + CF-Poll"));
|
||||
dout << "CF-ACK + CF-Poll";
|
||||
break;
|
||||
case 8:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS Data"));
|
||||
dout << "QoS Data";
|
||||
break;
|
||||
case 9:
|
||||
d_meta =
|
||||
pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS Data + CF-ACK"));
|
||||
dout << "QoS Data + CF-ACK";
|
||||
break;
|
||||
case 10:
|
||||
d_meta =
|
||||
pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS Data + CF-Poll"));
|
||||
dout << "QoS Data + CF-Poll";
|
||||
break;
|
||||
case 11:
|
||||
d_meta = pmt::dict_add(
|
||||
d_meta, pmt::mp("Subtype"), pmt::mp("QoS Data + CF-ACK + CF-Poll"));
|
||||
dout << "QoS Data + CF-ACK + CF-Poll";
|
||||
break;
|
||||
case 12:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS Null"));
|
||||
dout << "QoS Null";
|
||||
break;
|
||||
case 13:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Reserved"));
|
||||
dout << "Reserved";
|
||||
break;
|
||||
case 14:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("QoS CF-Poll"));
|
||||
dout << "QoS CF-Poll";
|
||||
break;
|
||||
case 15:
|
||||
d_meta = pmt::dict_add(
|
||||
d_meta, pmt::mp("Subtype"), pmt::mp("QoS CF-ACK + CF-Poll"));
|
||||
dout << "QoS CF-ACK + CF-Poll";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dout << std::endl;
|
||||
|
||||
|
||||
int seq_no = int(h->seq_nr >> 4);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Sequence number"), pmt::mp(seq_no));
|
||||
dout << "seq nr: " << seq_no << std::endl;
|
||||
int seq_no = int(h->seq_nr >> 4);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Sequence number"), pmt::mp(seq_no));
|
||||
dout << "seq nr: " << seq_no << std::endl;
|
||||
|
||||
auto address = format_mac_address(h->addr1);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 1"), pmt::mp(address));
|
||||
dout << "address 1: " << address << std::endl;
|
||||
auto address = format_mac_address(h->addr1);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 1"), pmt::mp(address));
|
||||
dout << "address 1: " << address << std::endl;
|
||||
|
||||
address = format_mac_address(h->addr2);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 2"), pmt::mp(address));
|
||||
dout << "address 2: "<< address << std::endl;
|
||||
address = format_mac_address(h->addr2);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 2"), pmt::mp(address));
|
||||
dout << "address 2: " << address << std::endl;
|
||||
|
||||
address = format_mac_address(h->addr3);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 3"), pmt::mp(address));
|
||||
dout << "address 3: "<< address << std::endl;
|
||||
address = format_mac_address(h->addr3);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Address 3"), pmt::mp(address));
|
||||
dout << "address 3: " << address << std::endl;
|
||||
|
||||
|
||||
float lost_frames = seq_no - d_last_seq_no - 1;
|
||||
if(lost_frames < 0)
|
||||
lost_frames += 1 << 12;
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Lost frames"), pmt::mp(lost_frames));
|
||||
float lost_frames = seq_no - d_last_seq_no - 1;
|
||||
if (lost_frames < 0)
|
||||
lost_frames += 1 << 12;
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Lost frames"), pmt::mp(lost_frames));
|
||||
|
||||
// calculate frame error rate
|
||||
float fer = lost_frames / (lost_frames + 1);
|
||||
dout << "instantaneous fer: " << fer << std::endl;
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Instantaneous FER"), pmt::mp(fer));
|
||||
// calculate frame error rate
|
||||
float fer = lost_frames / (lost_frames + 1);
|
||||
dout << "instantaneous fer: " << fer << std::endl;
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Instantaneous FER"), pmt::mp(fer));
|
||||
|
||||
// keep track of sequence numbers
|
||||
d_last_seq_no = seq_no;
|
||||
}
|
||||
// keep track of sequence numbers
|
||||
d_last_seq_no = seq_no;
|
||||
}
|
||||
|
||||
void parse_control(char *buf, int length) {
|
||||
mac_header* h = (mac_header*)buf;
|
||||
void parse_control(char* buf, int length)
|
||||
{
|
||||
mac_header* h = (mac_header*)buf;
|
||||
|
||||
dout << "Subtype: ";
|
||||
switch(((h->frame_control) >> 4) & 0xf) {
|
||||
case 7:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Control Wrapper"));
|
||||
dout << "Control Wrapper";
|
||||
break;
|
||||
case 8:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Block ACK Request"));
|
||||
dout << "Block ACK Request";
|
||||
break;
|
||||
case 9:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Block ACK"));
|
||||
dout << "Block ACK";
|
||||
break;
|
||||
case 10:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("PS Poll"));
|
||||
dout << "PS Poll";
|
||||
break;
|
||||
case 11:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("RTS"));
|
||||
dout << "RTS";
|
||||
break;
|
||||
case 12:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CTS"));
|
||||
dout << "CTS";
|
||||
break;
|
||||
case 13:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("ACK"));
|
||||
dout << "ACK";
|
||||
break;
|
||||
case 14:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CF-End"));
|
||||
dout << "CF-End";
|
||||
break;
|
||||
case 15:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CF-End + CF-ACK"));
|
||||
dout << "CF-End + CF-ACK";
|
||||
break;
|
||||
default:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Reserved"));
|
||||
dout << "Reserved";
|
||||
break;
|
||||
}
|
||||
dout << std::endl;
|
||||
dout << "Subtype: ";
|
||||
switch (((h->frame_control) >> 4) & 0xf) {
|
||||
case 7:
|
||||
d_meta =
|
||||
pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Control Wrapper"));
|
||||
dout << "Control Wrapper";
|
||||
break;
|
||||
case 8:
|
||||
d_meta =
|
||||
pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Block ACK Request"));
|
||||
dout << "Block ACK Request";
|
||||
break;
|
||||
case 9:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Block ACK"));
|
||||
dout << "Block ACK";
|
||||
break;
|
||||
case 10:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("PS Poll"));
|
||||
dout << "PS Poll";
|
||||
break;
|
||||
case 11:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("RTS"));
|
||||
dout << "RTS";
|
||||
break;
|
||||
case 12:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CTS"));
|
||||
dout << "CTS";
|
||||
break;
|
||||
case 13:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("ACK"));
|
||||
dout << "ACK";
|
||||
break;
|
||||
case 14:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CF-End"));
|
||||
dout << "CF-End";
|
||||
break;
|
||||
case 15:
|
||||
d_meta =
|
||||
pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("CF-End + CF-ACK"));
|
||||
dout << "CF-End + CF-ACK";
|
||||
break;
|
||||
default:
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("Subtype"), pmt::mp("Reserved"));
|
||||
dout << "Reserved";
|
||||
break;
|
||||
}
|
||||
dout << std::endl;
|
||||
|
||||
|
||||
auto address = format_mac_address(h->addr1);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("RA"), pmt::mp(address));
|
||||
dout << "RA: " << address << std::endl;
|
||||
auto address = format_mac_address(h->addr1);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("RA"), pmt::mp(address));
|
||||
dout << "RA: " << address << std::endl;
|
||||
|
||||
address = format_mac_address(h->addr2);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("TA"), pmt::mp(address));
|
||||
dout << "TA: "<< address << std::endl;
|
||||
}
|
||||
address = format_mac_address(h->addr2);
|
||||
d_meta = pmt::dict_add(d_meta, pmt::mp("TA"), pmt::mp(address));
|
||||
dout << "TA: " << address << std::endl;
|
||||
}
|
||||
|
||||
std::string format_mac_address(uint8_t *addr) {
|
||||
std::stringstream str;
|
||||
std::string format_mac_address(uint8_t* addr)
|
||||
{
|
||||
std::stringstream str;
|
||||
|
||||
str << std::setfill('0') << std::hex << std::setw(2) << (int)addr[0];
|
||||
str << std::setfill('0') << std::hex << std::setw(2) << (int)addr[0];
|
||||
|
||||
for(int i = 1; i < 6; i++) {
|
||||
str << ":" << (int)addr[i];
|
||||
}
|
||||
for (int i = 1; i < 6; i++) {
|
||||
str << ":" << (int)addr[i];
|
||||
}
|
||||
|
||||
return str.str();
|
||||
}
|
||||
return str.str();
|
||||
}
|
||||
|
||||
void print_ascii(char* buf, int length) {
|
||||
void print_ascii(char* buf, int length)
|
||||
{
|
||||
|
||||
for(int i = 0; i < length; i++) {
|
||||
if((buf[i] > 31) && (buf[i] < 127)) {
|
||||
dout << buf[i];
|
||||
} else {
|
||||
dout << ".";
|
||||
}
|
||||
}
|
||||
dout << std::endl;
|
||||
}
|
||||
for (int i = 0; i < length; i++) {
|
||||
if ((buf[i] > 31) && (buf[i] < 127)) {
|
||||
dout << buf[i];
|
||||
} else {
|
||||
dout << ".";
|
||||
}
|
||||
}
|
||||
dout << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
bool d_log;
|
||||
bool d_debug;
|
||||
int d_last_seq_no;
|
||||
pmt::pmt_t d_meta;
|
||||
pmt::pmt_t d_msg;
|
||||
bool d_log;
|
||||
bool d_debug;
|
||||
int d_last_seq_no;
|
||||
pmt::pmt_t d_meta;
|
||||
pmt::pmt_t d_msg;
|
||||
};
|
||||
|
||||
parse_mac::sptr
|
||||
parse_mac::make(bool log, bool debug) {
|
||||
return gnuradio::get_initial_sptr(new parse_mac_impl(log, debug));
|
||||
parse_mac::sptr parse_mac::make(bool log, bool debug)
|
||||
{
|
||||
return gnuradio::get_initial_sptr(new parse_mac_impl(log, debug));
|
||||
}
|
||||
|
||||
|
||||
+97
-94
@@ -21,12 +21,12 @@
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
signal_field::sptr
|
||||
signal_field::make() {
|
||||
return signal_field::sptr(new signal_field_impl());
|
||||
signal_field::sptr signal_field::make()
|
||||
{
|
||||
return signal_field::sptr(new signal_field_impl());
|
||||
}
|
||||
|
||||
signal_field::signal_field() : packet_header_default(48, "packet_len") {};
|
||||
signal_field::signal_field() : packet_header_default(48, "packet_len"){};
|
||||
|
||||
|
||||
signal_field_impl::signal_field_impl() : packet_header_default(48, "packet_len") {}
|
||||
@@ -35,105 +35,108 @@ signal_field_impl::signal_field_impl() : packet_header_default(48, "packet_len")
|
||||
signal_field_impl::~signal_field_impl() {}
|
||||
|
||||
|
||||
int signal_field_impl::get_bit(int b, int i) {
|
||||
return (b & (1 << i) ? 1 : 0);
|
||||
}
|
||||
int signal_field_impl::get_bit(int b, int i) { return (b & (1 << i) ? 1 : 0); }
|
||||
|
||||
|
||||
void signal_field_impl::generate_signal_field(char *out, frame_param &frame, ofdm_param &ofdm) {
|
||||
|
||||
//data bits of the signal header
|
||||
char *signal_header = (char *) malloc(sizeof(char) * 24);
|
||||
|
||||
//signal header after...
|
||||
//convolutional encoding
|
||||
char *encoded_signal_header = (char *) malloc(sizeof(char) * 48);
|
||||
//interleaving
|
||||
char *interleaved_signal_header = (char *) malloc(sizeof(char) * 48);
|
||||
|
||||
int length = frame.psdu_size;
|
||||
|
||||
// first 4 bits represent the modulation and coding scheme
|
||||
signal_header[ 0] = get_bit(ofdm.rate_field, 3);
|
||||
signal_header[ 1] = get_bit(ofdm.rate_field, 2);
|
||||
signal_header[ 2] = get_bit(ofdm.rate_field, 1);
|
||||
signal_header[ 3] = get_bit(ofdm.rate_field, 0);
|
||||
// 5th bit is reserved and must be set to 0
|
||||
signal_header[ 4] = 0;
|
||||
// then 12 bits represent the length
|
||||
signal_header[ 5] = get_bit(length, 0);
|
||||
signal_header[ 6] = get_bit(length, 1);
|
||||
signal_header[ 7] = get_bit(length, 2);
|
||||
signal_header[ 8] = get_bit(length, 3);
|
||||
signal_header[ 9] = get_bit(length, 4);
|
||||
signal_header[10] = get_bit(length, 5);
|
||||
signal_header[11] = get_bit(length, 6);
|
||||
signal_header[12] = get_bit(length, 7);
|
||||
signal_header[13] = get_bit(length, 8);
|
||||
signal_header[14] = get_bit(length, 9);
|
||||
signal_header[15] = get_bit(length, 10);
|
||||
signal_header[16] = get_bit(length, 11);
|
||||
//18-th bit is the parity bit for the first 17 bits
|
||||
int sum = 0;
|
||||
for(int i = 0; i < 17; i++) {
|
||||
if(signal_header[i]) {
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
signal_header[17] = sum % 2;
|
||||
|
||||
// last 6 bits must be set to 0
|
||||
for (int i = 0; i < 6; i++) {
|
||||
signal_header[18 + i] = 0;
|
||||
}
|
||||
|
||||
ofdm_param signal_ofdm(BPSK_1_2);
|
||||
frame_param signal_param(signal_ofdm, 0);
|
||||
|
||||
// convolutional encoding (scrambling is not needed)
|
||||
convolutional_encoding(signal_header, encoded_signal_header, signal_param);
|
||||
// interleaving
|
||||
interleave(encoded_signal_header, out, signal_param, signal_ofdm);
|
||||
|
||||
free(signal_header);
|
||||
free(encoded_signal_header);
|
||||
free(interleaved_signal_header);
|
||||
}
|
||||
|
||||
bool signal_field_impl::header_formatter(long packet_len, unsigned char *out, const std::vector<tag_t> &tags)
|
||||
void signal_field_impl::generate_signal_field(char* out,
|
||||
frame_param& frame,
|
||||
ofdm_param& ofdm)
|
||||
{
|
||||
|
||||
bool encoding_found = false;
|
||||
bool len_found = false;
|
||||
int encoding = 0;
|
||||
int len = 0;
|
||||
// data bits of the signal header
|
||||
char* signal_header = (char*)malloc(sizeof(char) * 24);
|
||||
|
||||
// read tags
|
||||
for(int i = 0; i < tags.size(); i++) {
|
||||
if(pmt::eq(tags[i].key, pmt::mp("encoding"))) {
|
||||
encoding_found = true;
|
||||
encoding = pmt::to_long(tags[i].value);
|
||||
} else if(pmt::eq(tags[i].key, pmt::mp("psdu_len"))) {
|
||||
len_found = true;
|
||||
len = pmt::to_long(tags[i].value);
|
||||
}
|
||||
}
|
||||
// signal header after...
|
||||
// convolutional encoding
|
||||
char* encoded_signal_header = (char*)malloc(sizeof(char) * 48);
|
||||
// interleaving
|
||||
char* interleaved_signal_header = (char*)malloc(sizeof(char) * 48);
|
||||
|
||||
// check if all tags are present
|
||||
if( (!encoding_found) || (!len_found)) {
|
||||
return false;
|
||||
}
|
||||
int length = frame.psdu_size;
|
||||
|
||||
ofdm_param ofdm((Encoding)encoding);
|
||||
frame_param frame(ofdm, len);
|
||||
// first 4 bits represent the modulation and coding scheme
|
||||
signal_header[0] = get_bit(ofdm.rate_field, 3);
|
||||
signal_header[1] = get_bit(ofdm.rate_field, 2);
|
||||
signal_header[2] = get_bit(ofdm.rate_field, 1);
|
||||
signal_header[3] = get_bit(ofdm.rate_field, 0);
|
||||
// 5th bit is reserved and must be set to 0
|
||||
signal_header[4] = 0;
|
||||
// then 12 bits represent the length
|
||||
signal_header[5] = get_bit(length, 0);
|
||||
signal_header[6] = get_bit(length, 1);
|
||||
signal_header[7] = get_bit(length, 2);
|
||||
signal_header[8] = get_bit(length, 3);
|
||||
signal_header[9] = get_bit(length, 4);
|
||||
signal_header[10] = get_bit(length, 5);
|
||||
signal_header[11] = get_bit(length, 6);
|
||||
signal_header[12] = get_bit(length, 7);
|
||||
signal_header[13] = get_bit(length, 8);
|
||||
signal_header[14] = get_bit(length, 9);
|
||||
signal_header[15] = get_bit(length, 10);
|
||||
signal_header[16] = get_bit(length, 11);
|
||||
// 18-th bit is the parity bit for the first 17 bits
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 17; i++) {
|
||||
if (signal_header[i]) {
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
signal_header[17] = sum % 2;
|
||||
|
||||
generate_signal_field((char*)out, frame, ofdm);
|
||||
return true;
|
||||
// last 6 bits must be set to 0
|
||||
for (int i = 0; i < 6; i++) {
|
||||
signal_header[18 + i] = 0;
|
||||
}
|
||||
|
||||
ofdm_param signal_ofdm(BPSK_1_2);
|
||||
frame_param signal_param(signal_ofdm, 0);
|
||||
|
||||
// convolutional encoding (scrambling is not needed)
|
||||
convolutional_encoding(signal_header, encoded_signal_header, signal_param);
|
||||
// interleaving
|
||||
interleave(encoded_signal_header, out, signal_param, signal_ofdm);
|
||||
|
||||
free(signal_header);
|
||||
free(encoded_signal_header);
|
||||
free(interleaved_signal_header);
|
||||
}
|
||||
|
||||
bool signal_field_impl::header_parser(
|
||||
const unsigned char *in, std::vector<tag_t> &tags) {
|
||||
bool signal_field_impl::header_formatter(long packet_len,
|
||||
unsigned char* out,
|
||||
const std::vector<tag_t>& tags)
|
||||
{
|
||||
|
||||
throw std::runtime_error("not implemented yet");
|
||||
return false;
|
||||
bool encoding_found = false;
|
||||
bool len_found = false;
|
||||
int encoding = 0;
|
||||
int len = 0;
|
||||
|
||||
// read tags
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
if (pmt::eq(tags[i].key, pmt::mp("encoding"))) {
|
||||
encoding_found = true;
|
||||
encoding = pmt::to_long(tags[i].value);
|
||||
} else if (pmt::eq(tags[i].key, pmt::mp("psdu_len"))) {
|
||||
len_found = true;
|
||||
len = pmt::to_long(tags[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
// check if all tags are present
|
||||
if ((!encoding_found) || (!len_found)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ofdm_param ofdm((Encoding)encoding);
|
||||
frame_param frame(ofdm, len);
|
||||
|
||||
generate_signal_field((char*)out, frame, ofdm);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool signal_field_impl::header_parser(const unsigned char* in, std::vector<tag_t>& tags)
|
||||
{
|
||||
|
||||
throw std::runtime_error("not implemented yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
+9
-10
@@ -18,8 +18,8 @@
|
||||
#ifndef INCLUDED_IEEE802_11_SIGNAL_FIELD_IMPL_H
|
||||
#define INCLUDED_IEEE802_11_SIGNAL_FIELD_IMPL_H
|
||||
|
||||
#include <ieee802_11/signal_field.h>
|
||||
#include "utils.h"
|
||||
#include <ieee802_11/signal_field.h>
|
||||
|
||||
namespace gr {
|
||||
namespace ieee802_11 {
|
||||
@@ -27,21 +27,20 @@ namespace ieee802_11 {
|
||||
class signal_field_impl : public signal_field
|
||||
{
|
||||
public:
|
||||
signal_field_impl();
|
||||
~signal_field_impl();
|
||||
signal_field_impl();
|
||||
~signal_field_impl();
|
||||
|
||||
bool header_formatter(long packet_len, unsigned char *out,
|
||||
const std::vector<tag_t> &tags);
|
||||
bool
|
||||
header_formatter(long packet_len, unsigned char* out, const std::vector<tag_t>& tags);
|
||||
|
||||
bool header_parser(const unsigned char* header, std::vector<tag_t>& tags);
|
||||
|
||||
bool header_parser(const unsigned char *header,
|
||||
std::vector<tag_t> &tags);
|
||||
private:
|
||||
int get_bit(int b, int i);
|
||||
void generate_signal_field(char *out, frame_param &frame, ofdm_param &ofdm);
|
||||
int get_bit(int b, int i);
|
||||
void generate_signal_field(char* out, frame_param& frame, ofdm_param& ofdm);
|
||||
};
|
||||
|
||||
} // namespace ieee802_11
|
||||
} // namespace gr
|
||||
|
||||
#endif /* INCLUDED_IEEE802_11_SIGNAL_FIELD_IMPL_H */
|
||||
|
||||
|
||||
+208
-184
@@ -14,11 +14,11 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <ieee802_11/sync_long.h>
|
||||
#include "utils.h"
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <gnuradio/filter/fir_filter.h>
|
||||
#include <gnuradio/fft/fft.h>
|
||||
#include <gnuradio/filter/fir_filter.h>
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <ieee802_11/sync_long.h>
|
||||
|
||||
#include <list>
|
||||
#include <tuple>
|
||||
@@ -27,239 +27,263 @@ using namespace gr::ieee802_11;
|
||||
using namespace std;
|
||||
|
||||
|
||||
bool compare_abs(const std::pair<gr_complex, int>& first, const std::pair<gr_complex, int>& second) {
|
||||
return abs(get<0>(first)) > abs(get<0>(second));
|
||||
bool compare_abs(const std::pair<gr_complex, int>& first,
|
||||
const std::pair<gr_complex, int>& second)
|
||||
{
|
||||
return abs(get<0>(first)) > abs(get<0>(second));
|
||||
}
|
||||
|
||||
class sync_long_impl : public sync_long {
|
||||
class sync_long_impl : public sync_long
|
||||
{
|
||||
|
||||
public:
|
||||
sync_long_impl(unsigned int sync_length, bool log, bool debug) : block("sync_long",
|
||||
gr::io_signature::make2(2, 2, sizeof(gr_complex), sizeof(gr_complex)),
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex))),
|
||||
d_fir(gr::filter::kernel::fir_filter_ccc(1, LONG)),
|
||||
d_log(log),
|
||||
d_debug(debug),
|
||||
d_offset(0),
|
||||
d_state(SYNC),
|
||||
SYNC_LENGTH(sync_length) {
|
||||
sync_long_impl(unsigned int sync_length, bool log, bool debug)
|
||||
: block("sync_long",
|
||||
gr::io_signature::make2(2, 2, sizeof(gr_complex), sizeof(gr_complex)),
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex))),
|
||||
d_fir(gr::filter::kernel::fir_filter_ccc(1, LONG)),
|
||||
d_log(log),
|
||||
d_debug(debug),
|
||||
d_offset(0),
|
||||
d_state(SYNC),
|
||||
SYNC_LENGTH(sync_length)
|
||||
{
|
||||
|
||||
set_tag_propagation_policy(block::TPP_DONT);
|
||||
d_correlation = gr::fft::malloc_complex(8192);
|
||||
}
|
||||
set_tag_propagation_policy(block::TPP_DONT);
|
||||
d_correlation = gr::fft::malloc_complex(8192);
|
||||
}
|
||||
|
||||
~sync_long_impl(){
|
||||
gr::fft::free(d_correlation);
|
||||
}
|
||||
~sync_long_impl() { gr::fft::free(d_correlation); }
|
||||
|
||||
int general_work (int noutput, gr_vector_int& ninput_items,
|
||||
gr_vector_const_void_star& input_items,
|
||||
gr_vector_void_star& output_items) {
|
||||
int general_work(int noutput,
|
||||
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];
|
||||
const gr_complex *in_delayed = (const gr_complex*)input_items[1];
|
||||
gr_complex *out = (gr_complex*)output_items[0];
|
||||
const gr_complex* in = (const gr_complex*)input_items[0];
|
||||
const gr_complex* in_delayed = (const gr_complex*)input_items[1];
|
||||
gr_complex* out = (gr_complex*)output_items[0];
|
||||
|
||||
dout << "LONG ninput[0] " << ninput_items[0] << " ninput[1] " <<
|
||||
ninput_items[1] << " noutput " << noutput <<
|
||||
" state " << d_state << std::endl;
|
||||
dout << "LONG ninput[0] " << ninput_items[0] << " ninput[1] " << ninput_items[1]
|
||||
<< " noutput " << noutput << " state " << d_state << std::endl;
|
||||
|
||||
int ninput = std::min(std::min(ninput_items[0], ninput_items[1]), 8192);
|
||||
int ninput = std::min(std::min(ninput_items[0], ninput_items[1]), 8192);
|
||||
|
||||
const uint64_t nread = nitems_read(0);
|
||||
get_tags_in_range(d_tags, 0, nread, nread + ninput);
|
||||
if (d_tags.size()) {
|
||||
std::sort(d_tags.begin(), d_tags.end(), gr::tag_t::offset_compare);
|
||||
const uint64_t nread = nitems_read(0);
|
||||
get_tags_in_range(d_tags, 0, nread, nread + ninput);
|
||||
if (d_tags.size()) {
|
||||
std::sort(d_tags.begin(), d_tags.end(), gr::tag_t::offset_compare);
|
||||
|
||||
const uint64_t offset = d_tags.front().offset;
|
||||
const uint64_t offset = d_tags.front().offset;
|
||||
|
||||
if(offset > nread) {
|
||||
ninput = offset - nread;
|
||||
} else {
|
||||
if(d_offset && (d_state == SYNC)) {
|
||||
throw std::runtime_error("wtf");
|
||||
}
|
||||
if(d_state == COPY) {
|
||||
d_state = RESET;
|
||||
}
|
||||
d_freq_offset_short = pmt::to_double(d_tags.front().value);
|
||||
}
|
||||
}
|
||||
if (offset > nread) {
|
||||
ninput = offset - nread;
|
||||
} else {
|
||||
if (d_offset && (d_state == SYNC)) {
|
||||
throw std::runtime_error("wtf");
|
||||
}
|
||||
if (d_state == COPY) {
|
||||
d_state = RESET;
|
||||
}
|
||||
d_freq_offset_short = pmt::to_double(d_tags.front().value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int i = 0;
|
||||
int o = 0;
|
||||
int i = 0;
|
||||
int o = 0;
|
||||
|
||||
switch(d_state) {
|
||||
switch (d_state) {
|
||||
|
||||
case SYNC:
|
||||
d_fir.filterN(d_correlation, in, std::min(SYNC_LENGTH, std::max(ninput - 63, 0)));
|
||||
case SYNC:
|
||||
d_fir.filterN(
|
||||
d_correlation, in, std::min(SYNC_LENGTH, std::max(ninput - 63, 0)));
|
||||
|
||||
while(i + 63 < ninput) {
|
||||
while (i + 63 < ninput) {
|
||||
|
||||
d_cor.push_back(pair<gr_complex, int>(d_correlation[i], d_offset));
|
||||
d_cor.push_back(pair<gr_complex, int>(d_correlation[i], d_offset));
|
||||
|
||||
i++;
|
||||
d_offset++;
|
||||
i++;
|
||||
d_offset++;
|
||||
|
||||
if(d_offset == SYNC_LENGTH) {
|
||||
search_frame_start();
|
||||
mylog(boost::format("LONG: frame start at %1%") % d_frame_start);
|
||||
d_offset = 0;
|
||||
d_count = 0;
|
||||
d_state = COPY;
|
||||
if (d_offset == SYNC_LENGTH) {
|
||||
search_frame_start();
|
||||
mylog(boost::format("LONG: frame start at %1%") % d_frame_start);
|
||||
d_offset = 0;
|
||||
d_count = 0;
|
||||
d_state = COPY;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case COPY:
|
||||
while(i < ninput && o < noutput) {
|
||||
case COPY:
|
||||
while (i < ninput && o < noutput) {
|
||||
|
||||
int rel = d_offset - d_frame_start;
|
||||
int rel = d_offset - d_frame_start;
|
||||
|
||||
if(!rel) {
|
||||
add_item_tag(0, nitems_written(0),
|
||||
pmt::string_to_symbol("wifi_start"),
|
||||
pmt::from_double(d_freq_offset_short - d_freq_offset),
|
||||
pmt::string_to_symbol(name()));
|
||||
}
|
||||
if (!rel) {
|
||||
add_item_tag(0,
|
||||
nitems_written(0),
|
||||
pmt::string_to_symbol("wifi_start"),
|
||||
pmt::from_double(d_freq_offset_short - d_freq_offset),
|
||||
pmt::string_to_symbol(name()));
|
||||
}
|
||||
|
||||
if(rel >= 0 && (rel < 128 || ((rel - 128) % 80) > 15)) {
|
||||
out[o] = in_delayed[i] * exp(gr_complex(0, d_offset * d_freq_offset));
|
||||
o++;
|
||||
}
|
||||
if (rel >= 0 && (rel < 128 || ((rel - 128) % 80) > 15)) {
|
||||
out[o] = in_delayed[i] * exp(gr_complex(0, d_offset * d_freq_offset));
|
||||
o++;
|
||||
}
|
||||
|
||||
i++;
|
||||
d_offset++;
|
||||
}
|
||||
i++;
|
||||
d_offset++;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case RESET: {
|
||||
while(o < noutput) {
|
||||
if(((d_count + o) % 64) == 0) {
|
||||
d_offset = 0;
|
||||
d_state = SYNC;
|
||||
break;
|
||||
} else {
|
||||
out[o] = 0;
|
||||
o++;
|
||||
}
|
||||
}
|
||||
case RESET: {
|
||||
while (o < noutput) {
|
||||
if (((d_count + o) % 64) == 0) {
|
||||
d_offset = 0;
|
||||
d_state = SYNC;
|
||||
break;
|
||||
} else {
|
||||
out[o] = 0;
|
||||
o++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dout << "produced : " << o << " consumed: " << i << std::endl;
|
||||
dout << "produced : " << o << " consumed: " << i << std::endl;
|
||||
|
||||
d_count += o;
|
||||
consume(0, i);
|
||||
consume(1, i);
|
||||
return o;
|
||||
}
|
||||
d_count += o;
|
||||
consume(0, i);
|
||||
consume(1, i);
|
||||
return o;
|
||||
}
|
||||
|
||||
void forecast (int noutput_items, gr_vector_int &ninput_items_required) {
|
||||
void forecast(int noutput_items, gr_vector_int& ninput_items_required)
|
||||
{
|
||||
|
||||
// in sync state we need at least a symbol to correlate
|
||||
// with the pattern
|
||||
if(d_state == SYNC) {
|
||||
ninput_items_required[0] = 64;
|
||||
ninput_items_required[1] = 64;
|
||||
// in sync state we need at least a symbol to correlate
|
||||
// with the pattern
|
||||
if (d_state == SYNC) {
|
||||
ninput_items_required[0] = 64;
|
||||
ninput_items_required[1] = 64;
|
||||
|
||||
} else {
|
||||
ninput_items_required[0] = noutput_items;
|
||||
ninput_items_required[1] = noutput_items;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ninput_items_required[0] = noutput_items;
|
||||
ninput_items_required[1] = noutput_items;
|
||||
}
|
||||
}
|
||||
|
||||
void search_frame_start() {
|
||||
void search_frame_start()
|
||||
{
|
||||
|
||||
// sort list (highest correlation first)
|
||||
assert(d_cor.size() == SYNC_LENGTH);
|
||||
d_cor.sort(compare_abs);
|
||||
// sort list (highest correlation first)
|
||||
assert(d_cor.size() == SYNC_LENGTH);
|
||||
d_cor.sort(compare_abs);
|
||||
|
||||
// copy list in vector for nicer access
|
||||
vector<pair<gr_complex, int> > vec(d_cor.begin(), d_cor.end());
|
||||
d_cor.clear();
|
||||
// copy list in vector for nicer access
|
||||
vector<pair<gr_complex, int>> vec(d_cor.begin(), d_cor.end());
|
||||
d_cor.clear();
|
||||
|
||||
// in case we don't find anything use SYNC_LENGTH
|
||||
d_frame_start = SYNC_LENGTH;
|
||||
// in case we don't find anything use SYNC_LENGTH
|
||||
d_frame_start = SYNC_LENGTH;
|
||||
|
||||
for(int i = 0; i < 3; i++) {
|
||||
for(int k = i + 1; k < 4; k++) {
|
||||
gr_complex first;
|
||||
gr_complex second;
|
||||
if(get<1>(vec[i]) > get<1>(vec[k])) {
|
||||
first = get<0>(vec[k]);
|
||||
second = get<0>(vec[i]);
|
||||
} else {
|
||||
first = get<0>(vec[i]);
|
||||
second = get<0>(vec[k]);
|
||||
}
|
||||
int diff = abs(get<1>(vec[i]) - get<1>(vec[k]));
|
||||
if(diff == 64) {
|
||||
d_frame_start = min(get<1>(vec[i]), get<1>(vec[k]));
|
||||
d_freq_offset = arg(first * conj(second)) / 64;
|
||||
// nice match found, return immediately
|
||||
return;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int k = i + 1; k < 4; k++) {
|
||||
gr_complex first;
|
||||
gr_complex second;
|
||||
if (get<1>(vec[i]) > get<1>(vec[k])) {
|
||||
first = get<0>(vec[k]);
|
||||
second = get<0>(vec[i]);
|
||||
} else {
|
||||
first = get<0>(vec[i]);
|
||||
second = get<0>(vec[k]);
|
||||
}
|
||||
int diff = abs(get<1>(vec[i]) - get<1>(vec[k]));
|
||||
if (diff == 64) {
|
||||
d_frame_start = min(get<1>(vec[i]), get<1>(vec[k]));
|
||||
d_freq_offset = arg(first * conj(second)) / 64;
|
||||
// nice match found, return immediately
|
||||
return;
|
||||
|
||||
} else if(diff == 63) {
|
||||
d_frame_start = min(get<1>(vec[i]), get<1>(vec[k]));
|
||||
d_freq_offset = arg(first * conj(second)) / 63;
|
||||
} else if(diff == 65) {
|
||||
d_frame_start = min(get<1>(vec[i]), get<1>(vec[k]));
|
||||
d_freq_offset = arg(first * conj(second)) / 65;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (diff == 63) {
|
||||
d_frame_start = min(get<1>(vec[i]), get<1>(vec[k]));
|
||||
d_freq_offset = arg(first * conj(second)) / 63;
|
||||
} else if (diff == 65) {
|
||||
d_frame_start = min(get<1>(vec[i]), get<1>(vec[k]));
|
||||
d_freq_offset = arg(first * conj(second)) / 65;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
enum {SYNC, COPY, RESET} d_state;
|
||||
int d_count;
|
||||
int d_offset;
|
||||
int d_frame_start;
|
||||
float d_freq_offset;
|
||||
double d_freq_offset_short;
|
||||
enum { SYNC, COPY, RESET } d_state;
|
||||
int d_count;
|
||||
int d_offset;
|
||||
int d_frame_start;
|
||||
float d_freq_offset;
|
||||
double d_freq_offset_short;
|
||||
|
||||
gr_complex *d_correlation;
|
||||
list<pair<gr_complex, int> > d_cor;
|
||||
std::vector<gr::tag_t> d_tags;
|
||||
gr::filter::kernel::fir_filter_ccc d_fir;
|
||||
gr_complex* d_correlation;
|
||||
list<pair<gr_complex, int>> d_cor;
|
||||
std::vector<gr::tag_t> d_tags;
|
||||
gr::filter::kernel::fir_filter_ccc d_fir;
|
||||
|
||||
const bool d_log;
|
||||
const bool d_debug;
|
||||
const int SYNC_LENGTH;
|
||||
const bool d_log;
|
||||
const bool d_debug;
|
||||
const int SYNC_LENGTH;
|
||||
|
||||
static const std::vector<gr_complex> LONG;
|
||||
static const std::vector<gr_complex> LONG;
|
||||
};
|
||||
|
||||
sync_long::sptr
|
||||
sync_long::make(unsigned int sync_length, bool log, bool debug) {
|
||||
return gnuradio::get_initial_sptr(new sync_long_impl(sync_length, log, debug));
|
||||
sync_long::sptr sync_long::make(unsigned int sync_length, bool log, bool debug)
|
||||
{
|
||||
return gnuradio::get_initial_sptr(new sync_long_impl(sync_length, log, debug));
|
||||
}
|
||||
|
||||
const std::vector<gr_complex> sync_long_impl::LONG = {
|
||||
|
||||
gr_complex(-0.0455, -1.0679), gr_complex( 0.3528, -0.9865), gr_complex( 0.8594, 0.7348), gr_complex( 0.1874, 0.2475),
|
||||
gr_complex( 0.5309, -0.7784), gr_complex(-1.0218, -0.4897), gr_complex(-0.3401, -0.9423), gr_complex( 0.8657, -0.2298),
|
||||
gr_complex( 0.4734, 0.0362), gr_complex( 0.0088, -1.0207), gr_complex(-1.2142, -0.4205), gr_complex( 0.2172, -0.5195),
|
||||
gr_complex( 0.5207, -0.1326), gr_complex(-0.1995, 1.4259), gr_complex( 1.0583, -0.0363), gr_complex( 0.5547, -0.5547),
|
||||
gr_complex( 0.3277, 0.8728), gr_complex(-0.5077, 0.3488), gr_complex(-1.1650, 0.5789), gr_complex( 0.7297, 0.8197),
|
||||
gr_complex( 0.6173, 0.1253), gr_complex(-0.5353, 0.7214), gr_complex(-0.5011, -0.1935), gr_complex(-0.3110, -1.3392),
|
||||
gr_complex(-1.0818, -0.1470), gr_complex(-1.1300, -0.1820), gr_complex( 0.6663, -0.6571), gr_complex(-0.0249, 0.4773),
|
||||
gr_complex(-0.8155, 1.0218), gr_complex( 0.8140, 0.9396), gr_complex( 0.1090, 0.8662), gr_complex(-1.3868, -0.0000),
|
||||
gr_complex( 0.1090, -0.8662), gr_complex( 0.8140, -0.9396), gr_complex(-0.8155, -1.0218), gr_complex(-0.0249, -0.4773),
|
||||
gr_complex( 0.6663, 0.6571), gr_complex(-1.1300, 0.1820), gr_complex(-1.0818, 0.1470), gr_complex(-0.3110, 1.3392),
|
||||
gr_complex(-0.5011, 0.1935), gr_complex(-0.5353, -0.7214), gr_complex( 0.6173, -0.1253), gr_complex( 0.7297, -0.8197),
|
||||
gr_complex(-1.1650, -0.5789), gr_complex(-0.5077, -0.3488), gr_complex( 0.3277, -0.8728), gr_complex( 0.5547, 0.5547),
|
||||
gr_complex( 1.0583, 0.0363), gr_complex(-0.1995, -1.4259), gr_complex( 0.5207, 0.1326), gr_complex( 0.2172, 0.5195),
|
||||
gr_complex(-1.2142, 0.4205), gr_complex( 0.0088, 1.0207), gr_complex( 0.4734, -0.0362), gr_complex( 0.8657, 0.2298),
|
||||
gr_complex(-0.3401, 0.9423), gr_complex(-1.0218, 0.4897), gr_complex( 0.5309, 0.7784), gr_complex( 0.1874, -0.2475),
|
||||
gr_complex( 0.8594, -0.7348), gr_complex( 0.3528, 0.9865), gr_complex(-0.0455, 1.0679), gr_complex( 1.3868, -0.0000),
|
||||
gr_complex(-0.0455, -1.0679), gr_complex(0.3528, -0.9865),
|
||||
gr_complex(0.8594, 0.7348), gr_complex(0.1874, 0.2475),
|
||||
gr_complex(0.5309, -0.7784), gr_complex(-1.0218, -0.4897),
|
||||
gr_complex(-0.3401, -0.9423), gr_complex(0.8657, -0.2298),
|
||||
gr_complex(0.4734, 0.0362), gr_complex(0.0088, -1.0207),
|
||||
gr_complex(-1.2142, -0.4205), gr_complex(0.2172, -0.5195),
|
||||
gr_complex(0.5207, -0.1326), gr_complex(-0.1995, 1.4259),
|
||||
gr_complex(1.0583, -0.0363), gr_complex(0.5547, -0.5547),
|
||||
gr_complex(0.3277, 0.8728), gr_complex(-0.5077, 0.3488),
|
||||
gr_complex(-1.1650, 0.5789), gr_complex(0.7297, 0.8197),
|
||||
gr_complex(0.6173, 0.1253), gr_complex(-0.5353, 0.7214),
|
||||
gr_complex(-0.5011, -0.1935), gr_complex(-0.3110, -1.3392),
|
||||
gr_complex(-1.0818, -0.1470), gr_complex(-1.1300, -0.1820),
|
||||
gr_complex(0.6663, -0.6571), gr_complex(-0.0249, 0.4773),
|
||||
gr_complex(-0.8155, 1.0218), gr_complex(0.8140, 0.9396),
|
||||
gr_complex(0.1090, 0.8662), gr_complex(-1.3868, -0.0000),
|
||||
gr_complex(0.1090, -0.8662), gr_complex(0.8140, -0.9396),
|
||||
gr_complex(-0.8155, -1.0218), gr_complex(-0.0249, -0.4773),
|
||||
gr_complex(0.6663, 0.6571), gr_complex(-1.1300, 0.1820),
|
||||
gr_complex(-1.0818, 0.1470), gr_complex(-0.3110, 1.3392),
|
||||
gr_complex(-0.5011, 0.1935), gr_complex(-0.5353, -0.7214),
|
||||
gr_complex(0.6173, -0.1253), gr_complex(0.7297, -0.8197),
|
||||
gr_complex(-1.1650, -0.5789), gr_complex(-0.5077, -0.3488),
|
||||
gr_complex(0.3277, -0.8728), gr_complex(0.5547, 0.5547),
|
||||
gr_complex(1.0583, 0.0363), gr_complex(-0.1995, -1.4259),
|
||||
gr_complex(0.5207, 0.1326), gr_complex(0.2172, 0.5195),
|
||||
gr_complex(-1.2142, 0.4205), gr_complex(0.0088, 1.0207),
|
||||
gr_complex(0.4734, -0.0362), gr_complex(0.8657, 0.2298),
|
||||
gr_complex(-0.3401, 0.9423), gr_complex(-1.0218, 0.4897),
|
||||
gr_complex(0.5309, 0.7784), gr_complex(0.1874, -0.2475),
|
||||
gr_complex(0.8594, -0.7348), gr_complex(0.3528, 0.9865),
|
||||
gr_complex(-0.0455, 1.0679), gr_complex(1.3868, -0.0000),
|
||||
|
||||
};
|
||||
|
||||
+111
-100
@@ -14,9 +14,9 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <ieee802_11/sync_short.h>
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include "utils.h"
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include <ieee802_11/sync_short.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
@@ -25,130 +25,141 @@ using namespace gr::ieee802_11;
|
||||
static const int MIN_GAP = 480;
|
||||
static const int MAX_SAMPLES = 540 * 80;
|
||||
|
||||
class sync_short_impl : public sync_short {
|
||||
class sync_short_impl : public sync_short
|
||||
{
|
||||
|
||||
public:
|
||||
sync_short_impl(double threshold, unsigned int min_plateau, bool log, bool debug) :
|
||||
block("sync_short",
|
||||
gr::io_signature::make3(3, 3, sizeof(gr_complex), sizeof(gr_complex), sizeof(float)),
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex))),
|
||||
d_log(log),
|
||||
d_debug(debug),
|
||||
d_state(SEARCH),
|
||||
d_plateau(0),
|
||||
d_freq_offset(0),
|
||||
d_copied(0),
|
||||
MIN_PLATEAU(min_plateau),
|
||||
d_threshold(threshold) {
|
||||
sync_short_impl(double threshold, unsigned int min_plateau, bool log, bool debug)
|
||||
: block("sync_short",
|
||||
gr::io_signature::make3(
|
||||
3, 3, sizeof(gr_complex), sizeof(gr_complex), sizeof(float)),
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex))),
|
||||
d_log(log),
|
||||
d_debug(debug),
|
||||
d_state(SEARCH),
|
||||
d_plateau(0),
|
||||
d_freq_offset(0),
|
||||
d_copied(0),
|
||||
MIN_PLATEAU(min_plateau),
|
||||
d_threshold(threshold)
|
||||
{
|
||||
|
||||
set_tag_propagation_policy(block::TPP_DONT);
|
||||
}
|
||||
set_tag_propagation_policy(block::TPP_DONT);
|
||||
}
|
||||
|
||||
int general_work (int noutput_items, gr_vector_int& ninput_items,
|
||||
gr_vector_const_void_star& input_items,
|
||||
gr_vector_void_star& output_items) {
|
||||
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];
|
||||
const gr_complex *in_abs = (const gr_complex*)input_items[1];
|
||||
const float *in_cor = (const float*)input_items[2];
|
||||
gr_complex *out = (gr_complex*)output_items[0];
|
||||
const gr_complex* in = (const gr_complex*)input_items[0];
|
||||
const gr_complex* in_abs = (const gr_complex*)input_items[1];
|
||||
const float* in_cor = (const float*)input_items[2];
|
||||
gr_complex* out = (gr_complex*)output_items[0];
|
||||
|
||||
int noutput = noutput_items;
|
||||
int ninput = std::min(std::min(ninput_items[0], ninput_items[1]), ninput_items[2]);
|
||||
int noutput = noutput_items;
|
||||
int ninput =
|
||||
std::min(std::min(ninput_items[0], ninput_items[1]), ninput_items[2]);
|
||||
|
||||
// dout << "SHORT noutput : " << noutput << " ninput: " << ninput_items[0] << std::endl;
|
||||
// dout << "SHORT noutput : " << noutput << " ninput: " << ninput_items[0] <<
|
||||
// std::endl;
|
||||
|
||||
switch(d_state) {
|
||||
switch (d_state) {
|
||||
|
||||
case SEARCH: {
|
||||
int i;
|
||||
case SEARCH: {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ninput; i++) {
|
||||
if(in_cor[i] > d_threshold) {
|
||||
if(d_plateau < MIN_PLATEAU) {
|
||||
d_plateau++;
|
||||
for (i = 0; i < ninput; i++) {
|
||||
if (in_cor[i] > d_threshold) {
|
||||
if (d_plateau < MIN_PLATEAU) {
|
||||
d_plateau++;
|
||||
|
||||
} else {
|
||||
d_state = COPY;
|
||||
d_copied = 0;
|
||||
d_freq_offset = arg(in_abs[i]) / 16;
|
||||
d_plateau = 0;
|
||||
insert_tag(nitems_written(0), d_freq_offset, nitems_read(0) + i);
|
||||
dout << "SHORT Frame!" << std::endl;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
d_plateau = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
d_state = COPY;
|
||||
d_copied = 0;
|
||||
d_freq_offset = arg(in_abs[i]) / 16;
|
||||
d_plateau = 0;
|
||||
insert_tag(nitems_written(0), d_freq_offset, nitems_read(0) + i);
|
||||
dout << "SHORT Frame!" << std::endl;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
d_plateau = 0;
|
||||
}
|
||||
}
|
||||
|
||||
consume_each(i);
|
||||
return 0;
|
||||
}
|
||||
consume_each(i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case COPY: {
|
||||
case COPY: {
|
||||
|
||||
int o = 0;
|
||||
while( o < ninput && o < noutput && d_copied < MAX_SAMPLES) {
|
||||
if(in_cor[o] > d_threshold) {
|
||||
if(d_plateau < MIN_PLATEAU) {
|
||||
d_plateau++;
|
||||
int o = 0;
|
||||
while (o < ninput && o < noutput && d_copied < MAX_SAMPLES) {
|
||||
if (in_cor[o] > d_threshold) {
|
||||
if (d_plateau < MIN_PLATEAU) {
|
||||
d_plateau++;
|
||||
|
||||
// there's another frame
|
||||
} else if(d_copied > MIN_GAP) {
|
||||
d_copied = 0;
|
||||
d_plateau = 0;
|
||||
d_freq_offset = arg(in_abs[o]) / 16;
|
||||
insert_tag(nitems_written(0) + o, d_freq_offset, nitems_read(0) + o);
|
||||
dout << "SHORT Frame!" << std::endl;
|
||||
break;
|
||||
}
|
||||
// there's another frame
|
||||
} else if (d_copied > MIN_GAP) {
|
||||
d_copied = 0;
|
||||
d_plateau = 0;
|
||||
d_freq_offset = arg(in_abs[o]) / 16;
|
||||
insert_tag(
|
||||
nitems_written(0) + o, d_freq_offset, nitems_read(0) + o);
|
||||
dout << "SHORT Frame!" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
d_plateau = 0;
|
||||
}
|
||||
} else {
|
||||
d_plateau = 0;
|
||||
}
|
||||
|
||||
out[o] = in[o] * exp(gr_complex(0, -d_freq_offset * d_copied));
|
||||
o++;
|
||||
d_copied++;
|
||||
}
|
||||
out[o] = in[o] * exp(gr_complex(0, -d_freq_offset * d_copied));
|
||||
o++;
|
||||
d_copied++;
|
||||
}
|
||||
|
||||
if(d_copied == MAX_SAMPLES) {
|
||||
d_state = SEARCH;
|
||||
}
|
||||
if (d_copied == MAX_SAMPLES) {
|
||||
d_state = SEARCH;
|
||||
}
|
||||
|
||||
dout << "SHORT copied " << o << std::endl;
|
||||
dout << "SHORT copied " << o << std::endl;
|
||||
|
||||
consume_each(o);
|
||||
return o;
|
||||
}
|
||||
}
|
||||
consume_each(o);
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("sync short: unknown state");
|
||||
return 0;
|
||||
}
|
||||
throw std::runtime_error("sync short: unknown state");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void insert_tag(uint64_t item, double freq_offset, uint64_t input_item) {
|
||||
mylog(boost::format("frame start at in: %2% out: %1%") % item % input_item);
|
||||
void insert_tag(uint64_t item, double freq_offset, uint64_t input_item)
|
||||
{
|
||||
mylog(boost::format("frame start at in: %2% out: %1%") % item % input_item);
|
||||
|
||||
const pmt::pmt_t key = pmt::string_to_symbol("wifi_start");
|
||||
const pmt::pmt_t value = pmt::from_double(freq_offset);
|
||||
const pmt::pmt_t srcid = pmt::string_to_symbol(name());
|
||||
add_item_tag(0, item, key, value, srcid);
|
||||
}
|
||||
const pmt::pmt_t key = pmt::string_to_symbol("wifi_start");
|
||||
const pmt::pmt_t value = pmt::from_double(freq_offset);
|
||||
const pmt::pmt_t srcid = pmt::string_to_symbol(name());
|
||||
add_item_tag(0, item, key, value, srcid);
|
||||
}
|
||||
|
||||
private:
|
||||
enum {SEARCH, COPY} d_state;
|
||||
int d_copied;
|
||||
int d_plateau;
|
||||
float d_freq_offset;
|
||||
const double d_threshold;
|
||||
const bool d_log;
|
||||
const bool d_debug;
|
||||
const unsigned int MIN_PLATEAU;
|
||||
enum { SEARCH, COPY } d_state;
|
||||
int d_copied;
|
||||
int d_plateau;
|
||||
float d_freq_offset;
|
||||
const double d_threshold;
|
||||
const bool d_log;
|
||||
const bool d_debug;
|
||||
const unsigned int MIN_PLATEAU;
|
||||
};
|
||||
|
||||
sync_short::sptr
|
||||
sync_short::make(double threshold, unsigned int min_plateau, bool log, bool debug) {
|
||||
return gnuradio::get_initial_sptr(new sync_short_impl(threshold, min_plateau, log, debug));
|
||||
sync_short::make(double threshold, unsigned int min_plateau, bool log, bool debug)
|
||||
{
|
||||
return gnuradio::get_initial_sptr(
|
||||
new sync_short_impl(threshold, min_plateau, log, debug));
|
||||
}
|
||||
|
||||
+183
-172
@@ -16,244 +16,255 @@
|
||||
*/
|
||||
#include "utils.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <math.h>
|
||||
|
||||
ofdm_param::ofdm_param(Encoding e) {
|
||||
encoding = e;
|
||||
ofdm_param::ofdm_param(Encoding e)
|
||||
{
|
||||
encoding = e;
|
||||
|
||||
switch(e) {
|
||||
case BPSK_1_2:
|
||||
n_bpsc = 1;
|
||||
n_cbps = 48;
|
||||
n_dbps = 24;
|
||||
rate_field = 0x0D; // 0b00001101
|
||||
break;
|
||||
switch (e) {
|
||||
case BPSK_1_2:
|
||||
n_bpsc = 1;
|
||||
n_cbps = 48;
|
||||
n_dbps = 24;
|
||||
rate_field = 0x0D; // 0b00001101
|
||||
break;
|
||||
|
||||
case BPSK_3_4:
|
||||
n_bpsc = 1;
|
||||
n_cbps = 48;
|
||||
n_dbps = 36;
|
||||
rate_field = 0x0F; // 0b00001111
|
||||
break;
|
||||
case BPSK_3_4:
|
||||
n_bpsc = 1;
|
||||
n_cbps = 48;
|
||||
n_dbps = 36;
|
||||
rate_field = 0x0F; // 0b00001111
|
||||
break;
|
||||
|
||||
case QPSK_1_2:
|
||||
n_bpsc = 2;
|
||||
n_cbps = 96;
|
||||
n_dbps = 48;
|
||||
rate_field = 0x05; // 0b00000101
|
||||
break;
|
||||
case QPSK_1_2:
|
||||
n_bpsc = 2;
|
||||
n_cbps = 96;
|
||||
n_dbps = 48;
|
||||
rate_field = 0x05; // 0b00000101
|
||||
break;
|
||||
|
||||
case QPSK_3_4:
|
||||
n_bpsc = 2;
|
||||
n_cbps = 96;
|
||||
n_dbps = 72;
|
||||
rate_field = 0x07; // 0b00000111
|
||||
break;
|
||||
case QPSK_3_4:
|
||||
n_bpsc = 2;
|
||||
n_cbps = 96;
|
||||
n_dbps = 72;
|
||||
rate_field = 0x07; // 0b00000111
|
||||
break;
|
||||
|
||||
case QAM16_1_2:
|
||||
n_bpsc = 4;
|
||||
n_cbps = 192;
|
||||
n_dbps = 96;
|
||||
rate_field = 0x09; // 0b00001001
|
||||
break;
|
||||
case QAM16_1_2:
|
||||
n_bpsc = 4;
|
||||
n_cbps = 192;
|
||||
n_dbps = 96;
|
||||
rate_field = 0x09; // 0b00001001
|
||||
break;
|
||||
|
||||
case QAM16_3_4:
|
||||
n_bpsc = 4;
|
||||
n_cbps = 192;
|
||||
n_dbps = 144;
|
||||
rate_field = 0x0B; // 0b00001011
|
||||
break;
|
||||
case QAM16_3_4:
|
||||
n_bpsc = 4;
|
||||
n_cbps = 192;
|
||||
n_dbps = 144;
|
||||
rate_field = 0x0B; // 0b00001011
|
||||
break;
|
||||
|
||||
case QAM64_2_3:
|
||||
n_bpsc = 6;
|
||||
n_cbps = 288;
|
||||
n_dbps = 192;
|
||||
rate_field = 0x01; // 0b00000001
|
||||
break;
|
||||
case QAM64_2_3:
|
||||
n_bpsc = 6;
|
||||
n_cbps = 288;
|
||||
n_dbps = 192;
|
||||
rate_field = 0x01; // 0b00000001
|
||||
break;
|
||||
|
||||
case QAM64_3_4:
|
||||
n_bpsc = 6;
|
||||
n_cbps = 288;
|
||||
n_dbps = 216;
|
||||
rate_field = 0x03; // 0b00000011
|
||||
break;
|
||||
defaut:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
case QAM64_3_4:
|
||||
n_bpsc = 6;
|
||||
n_cbps = 288;
|
||||
n_dbps = 216;
|
||||
rate_field = 0x03; // 0b00000011
|
||||
break;
|
||||
defaut:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ofdm_param::print() {
|
||||
std::cout << "OFDM Parameters:" << std::endl;
|
||||
std::cout << "endcoding :" << encoding << std::endl;
|
||||
std::cout << "rate_field :" << (int)rate_field << std::endl;
|
||||
std::cout << "n_bpsc :" << n_bpsc << std::endl;
|
||||
std::cout << "n_cbps :" << n_cbps << std::endl;
|
||||
std::cout << "n_dbps :" << n_dbps << std::endl;
|
||||
void ofdm_param::print()
|
||||
{
|
||||
std::cout << "OFDM Parameters:" << std::endl;
|
||||
std::cout << "endcoding :" << encoding << std::endl;
|
||||
std::cout << "rate_field :" << (int)rate_field << std::endl;
|
||||
std::cout << "n_bpsc :" << n_bpsc << std::endl;
|
||||
std::cout << "n_cbps :" << n_cbps << std::endl;
|
||||
std::cout << "n_dbps :" << n_dbps << std::endl;
|
||||
}
|
||||
|
||||
|
||||
frame_param::frame_param(ofdm_param &ofdm, int psdu_length) {
|
||||
frame_param::frame_param(ofdm_param& ofdm, int psdu_length)
|
||||
{
|
||||
|
||||
psdu_size = psdu_length;
|
||||
psdu_size = psdu_length;
|
||||
|
||||
// number of symbols (17-11)
|
||||
n_sym = (int) ceil((16 + 8 * psdu_size + 6) / (double) ofdm.n_dbps);
|
||||
// number of symbols (17-11)
|
||||
n_sym = (int)ceil((16 + 8 * psdu_size + 6) / (double)ofdm.n_dbps);
|
||||
|
||||
n_data_bits = n_sym * ofdm.n_dbps;
|
||||
n_data_bits = n_sym * ofdm.n_dbps;
|
||||
|
||||
// number of padding bits (17-13)
|
||||
n_pad = n_data_bits - (16 + 8 * psdu_size + 6);
|
||||
// number of padding bits (17-13)
|
||||
n_pad = n_data_bits - (16 + 8 * psdu_size + 6);
|
||||
|
||||
n_encoded_bits = n_sym * ofdm.n_cbps;
|
||||
n_encoded_bits = n_sym * ofdm.n_cbps;
|
||||
}
|
||||
void
|
||||
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_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;
|
||||
void 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_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;
|
||||
}
|
||||
|
||||
|
||||
void scramble(const char *in, char *out, frame_param &frame, char initial_state) {
|
||||
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_bits; i++) {
|
||||
|
||||
feedback = (!!(state & 64)) ^ (!!(state & 8));
|
||||
out[i] = feedback ^ in[i];
|
||||
state = ((state << 1) & 0x7e) | feedback;
|
||||
feedback = (!!(state & 64)) ^ (!!(state & 8));
|
||||
out[i] = feedback ^ in[i];
|
||||
state = ((state << 1) & 0x7e) | feedback;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reset_tail_bits(char *scrambled_data, frame_param &frame) {
|
||||
memset(scrambled_data + frame.n_data_bits - frame.n_pad - 6, 0, 6 * sizeof(char));
|
||||
void reset_tail_bits(char* scrambled_data, frame_param& frame)
|
||||
{
|
||||
memset(scrambled_data + frame.n_data_bits - frame.n_pad - 6, 0, 6 * sizeof(char));
|
||||
}
|
||||
|
||||
|
||||
int ones(int n) {
|
||||
int sum = 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(n & (1 << i)) {
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
int ones(int n)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (n & (1 << i)) {
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
void convolutional_encoding(const char *in, char *out, frame_param &frame) {
|
||||
void convolutional_encoding(const char* in, char* out, frame_param& frame)
|
||||
{
|
||||
|
||||
int state = 0;
|
||||
int state = 0;
|
||||
|
||||
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;
|
||||
out[i * 2 + 1] = ones(state & 0117) % 2;
|
||||
}
|
||||
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;
|
||||
out[i * 2 + 1] = ones(state & 0117) % 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void puncturing(const char *in, char *out, frame_param &frame, ofdm_param &ofdm) {
|
||||
void puncturing(const char* in, char* out, frame_param& frame, ofdm_param& ofdm)
|
||||
{
|
||||
|
||||
int mod;
|
||||
int mod;
|
||||
|
||||
for (int i = 0; i < frame.n_data_bits * 2; i++) {
|
||||
switch(ofdm.encoding) {
|
||||
case BPSK_1_2:
|
||||
case QPSK_1_2:
|
||||
case QAM16_1_2:
|
||||
*out = in[i];
|
||||
out++;
|
||||
break;
|
||||
for (int i = 0; i < frame.n_data_bits * 2; i++) {
|
||||
switch (ofdm.encoding) {
|
||||
case BPSK_1_2:
|
||||
case QPSK_1_2:
|
||||
case QAM16_1_2:
|
||||
*out = in[i];
|
||||
out++;
|
||||
break;
|
||||
|
||||
case QAM64_2_3:
|
||||
if (i % 4 != 3) {
|
||||
*out = in[i];
|
||||
out++;
|
||||
}
|
||||
break;
|
||||
case QAM64_2_3:
|
||||
if (i % 4 != 3) {
|
||||
*out = in[i];
|
||||
out++;
|
||||
}
|
||||
break;
|
||||
|
||||
case BPSK_3_4:
|
||||
case QPSK_3_4:
|
||||
case QAM16_3_4:
|
||||
case QAM64_3_4:
|
||||
mod = i % 6;
|
||||
if (!(mod == 3 || mod == 4)) {
|
||||
*out = in[i];
|
||||
out++;
|
||||
}
|
||||
break;
|
||||
defaut:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case BPSK_3_4:
|
||||
case QPSK_3_4:
|
||||
case QAM16_3_4:
|
||||
case QAM64_3_4:
|
||||
mod = i % 6;
|
||||
if (!(mod == 3 || mod == 4)) {
|
||||
*out = in[i];
|
||||
out++;
|
||||
}
|
||||
break;
|
||||
defaut:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void interleave(const char *in, char *out, frame_param &frame, ofdm_param &ofdm, bool reverse) {
|
||||
void interleave(
|
||||
const char* in, char* 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);
|
||||
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 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 < 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]]];
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
void split_symbols(const char* in, char* out, frame_param& frame, ofdm_param& ofdm)
|
||||
{
|
||||
|
||||
int symbols = frame.n_sym * 48;
|
||||
int symbols = frame.n_sym * 48;
|
||||
|
||||
for (int i = 0; i < symbols; i++) {
|
||||
out[i] = 0;
|
||||
for(int k = 0; k < ofdm.n_bpsc; k++) {
|
||||
assert(*in == 1 || *in == 0);
|
||||
out[i] |= (*in << k);
|
||||
in++;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < symbols; i++) {
|
||||
out[i] = 0;
|
||||
for (int k = 0; k < ofdm.n_bpsc; k++) {
|
||||
assert(*in == 1 || *in == 0);
|
||||
out[i] |= (*in << k);
|
||||
in++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void generate_bits(const char *psdu, char *data_bits, frame_param &frame) {
|
||||
void generate_bits(const char* psdu, char* data_bits, frame_param& frame)
|
||||
{
|
||||
|
||||
// first 16 bits are zero (SERVICE/DATA field)
|
||||
memset(data_bits, 0, 16);
|
||||
data_bits += 16;
|
||||
// first 16 bits are zero (SERVICE/DATA field)
|
||||
memset(data_bits, 0, 16);
|
||||
data_bits += 16;
|
||||
|
||||
for(int i = 0; i < frame.psdu_size; i++) {
|
||||
for(int b = 0; b < 8; b++) {
|
||||
data_bits[i * 8 + b] = !!(psdu[i] & (1 << b));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < frame.psdu_size; i++) {
|
||||
for (int b = 0; b < 8; b++) {
|
||||
data_bits[i * 8 + b] = !!(psdu[i] & (1 << b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+56
-44
@@ -17,9 +17,9 @@
|
||||
#ifndef INCLUDED_IEEE802_11_UTILS_H
|
||||
#define INCLUDED_IEEE802_11_UTILS_H
|
||||
|
||||
#include <gnuradio/config.h>
|
||||
#include <ieee802_11/api.h>
|
||||
#include <ieee802_11/mapper.h>
|
||||
#include <gnuradio/config.h>
|
||||
#include <cinttypes>
|
||||
#include <iostream>
|
||||
|
||||
@@ -28,57 +28,64 @@
|
||||
#define MAX_SYM (((16 + 8 * MAX_PSDU_SIZE + 6) / 24) + 1)
|
||||
#define MAX_ENCODED_BITS ((16 + 8 * MAX_PSDU_SIZE + 6) * 2 + 288)
|
||||
|
||||
#define dout d_debug && std::cout
|
||||
#define mylog(msg) do { if(d_log) { GR_LOG_INFO(d_logger, msg); }} while(0);
|
||||
#define dout d_debug&& std::cout
|
||||
#define mylog(msg) \
|
||||
do { \
|
||||
if (d_log) { \
|
||||
GR_LOG_INFO(d_logger, msg); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
struct mac_header {
|
||||
//protocol version, type, subtype, to_ds, from_ds, ...
|
||||
uint16_t frame_control;
|
||||
uint16_t duration;
|
||||
uint8_t addr1[6];
|
||||
uint8_t addr2[6];
|
||||
uint8_t addr3[6];
|
||||
uint16_t seq_nr;
|
||||
}__attribute__((packed));
|
||||
// protocol version, type, subtype, to_ds, from_ds, ...
|
||||
uint16_t frame_control;
|
||||
uint16_t duration;
|
||||
uint8_t addr1[6];
|
||||
uint8_t addr2[6];
|
||||
uint8_t addr3[6];
|
||||
uint16_t seq_nr;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* WIFI parameters
|
||||
*/
|
||||
class ofdm_param {
|
||||
class ofdm_param
|
||||
{
|
||||
public:
|
||||
ofdm_param(Encoding e);
|
||||
ofdm_param(Encoding e);
|
||||
|
||||
// data rate
|
||||
Encoding encoding;
|
||||
// rate field of the SIGNAL header
|
||||
char rate_field;
|
||||
// number of coded bits per sub carrier
|
||||
int n_bpsc;
|
||||
// number of coded bits per OFDM symbol
|
||||
int n_cbps;
|
||||
// number of data bits per OFDM symbol
|
||||
int n_dbps;
|
||||
// data rate
|
||||
Encoding encoding;
|
||||
// rate field of the SIGNAL header
|
||||
char rate_field;
|
||||
// number of coded bits per sub carrier
|
||||
int n_bpsc;
|
||||
// number of coded bits per OFDM symbol
|
||||
int n_cbps;
|
||||
// number of data bits per OFDM symbol
|
||||
int n_dbps;
|
||||
|
||||
void print();
|
||||
void print();
|
||||
};
|
||||
|
||||
/**
|
||||
* packet specific parameters
|
||||
*/
|
||||
class frame_param {
|
||||
class frame_param
|
||||
{
|
||||
public:
|
||||
frame_param(ofdm_param &ofdm, int psdu_length);
|
||||
// PSDU size in bytes
|
||||
int psdu_size;
|
||||
// number of OFDM symbols (17-11)
|
||||
int n_sym;
|
||||
// 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;
|
||||
frame_param(ofdm_param& ofdm, int psdu_length);
|
||||
// PSDU size in bytes
|
||||
int psdu_size;
|
||||
// number of OFDM symbols (17-11)
|
||||
int n_sym;
|
||||
// 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();
|
||||
void print();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -93,20 +100,25 @@ public:
|
||||
* will be stored
|
||||
* \param seq sequence number of the frame
|
||||
*/
|
||||
void generate_mac_data_frame(const char *msdu, int msdu_size, char **psdu, int *psdu_size, char seq);
|
||||
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 scramble(const char* input, char* out, frame_param& frame, char initial_state);
|
||||
|
||||
void reset_tail_bits(char *scrambled_data, frame_param &frame);
|
||||
void reset_tail_bits(char* scrambled_data, frame_param& frame);
|
||||
|
||||
void convolutional_encoding(const char *input, char *out, frame_param &frame);
|
||||
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 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 char* input,
|
||||
char* out,
|
||||
frame_param& frame,
|
||||
ofdm_param& ofdm,
|
||||
bool reverse = false);
|
||||
|
||||
void split_symbols(const char *input, char *out, frame_param &frame, ofdm_param &ofdm);
|
||||
void split_symbols(const char* input, char* out, frame_param& frame, ofdm_param& ofdm);
|
||||
|
||||
void generate_bits(const char *psdu, char *data_bits, frame_param &frame);
|
||||
void generate_bits(const char* psdu, char* data_bits, frame_param& frame);
|
||||
|
||||
#endif /* INCLUDED_IEEE802_11_UTILS_H */
|
||||
|
||||
+42
-68
@@ -21,85 +21,59 @@
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
base::base() :
|
||||
d_store_pos(0) {
|
||||
}
|
||||
base::base() : d_store_pos(0) {}
|
||||
|
||||
base::~base() {
|
||||
}
|
||||
base::~base() {}
|
||||
|
||||
uint8_t*
|
||||
base::depuncture(uint8_t *in) {
|
||||
uint8_t* base::depuncture(uint8_t* in)
|
||||
{
|
||||
|
||||
int count;
|
||||
int n_cbps = d_ofdm->n_cbps;
|
||||
uint8_t *depunctured;
|
||||
int count;
|
||||
int n_cbps = d_ofdm->n_cbps;
|
||||
uint8_t* depunctured;
|
||||
|
||||
if (d_ntraceback == 5) {
|
||||
count = d_frame->n_sym * n_cbps;
|
||||
depunctured = in;
|
||||
if (d_ntraceback == 5) {
|
||||
count = d_frame->n_sym * n_cbps;
|
||||
depunctured = in;
|
||||
|
||||
} else {
|
||||
depunctured = d_depunctured;
|
||||
count = 0;
|
||||
for(int i = 0; i < d_frame->n_sym; i++) {
|
||||
for(int k = 0; k < n_cbps; k++) {
|
||||
while (d_depuncture_pattern[count % (2 * d_k)] == 0) {
|
||||
depunctured[count] = 2;
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
depunctured = d_depunctured;
|
||||
count = 0;
|
||||
for (int i = 0; i < d_frame->n_sym; i++) {
|
||||
for (int k = 0; k < n_cbps; k++) {
|
||||
while (d_depuncture_pattern[count % (2 * d_k)] == 0) {
|
||||
depunctured[count] = 2;
|
||||
count++;
|
||||
}
|
||||
|
||||
// Insert received bits
|
||||
depunctured[count] = in[i * n_cbps + k];
|
||||
count++;
|
||||
// Insert received bits
|
||||
depunctured[count] = in[i * n_cbps + k];
|
||||
count++;
|
||||
|
||||
while (d_depuncture_pattern[count % (2 * d_k)] == 0) {
|
||||
depunctured[count] = 2;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (d_depuncture_pattern[count % (2 * d_k)] == 0) {
|
||||
depunctured[count] = 2;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return depunctured;
|
||||
return depunctured;
|
||||
}
|
||||
|
||||
/* Parity lookup table */
|
||||
const unsigned char base::PARTAB[256] = {
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1,
|
||||
0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0,
|
||||
0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0,
|
||||
1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0,
|
||||
1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1,
|
||||
1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0,
|
||||
1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
||||
};
|
||||
|
||||
const unsigned char base::PUNCTURE_1_2[2] = {1, 1};
|
||||
const unsigned char base::PUNCTURE_2_3[4] = {1, 1, 1, 0};
|
||||
const unsigned char base::PUNCTURE_3_4[6] = {1, 1, 1, 0, 0, 1};
|
||||
const unsigned char base::PUNCTURE_1_2[2] = { 1, 1 };
|
||||
const unsigned char base::PUNCTURE_2_3[4] = { 1, 1, 1, 0 };
|
||||
const unsigned char base::PUNCTURE_3_4[6] = { 1, 1, 1, 0, 0, 1 };
|
||||
|
||||
+22
-23
@@ -33,35 +33,34 @@ namespace ieee802_11 {
|
||||
class base
|
||||
{
|
||||
public:
|
||||
|
||||
base();
|
||||
~base();
|
||||
virtual uint8_t* decode(ofdm_param *ofdm, frame_param *frame, uint8_t *in) = 0;
|
||||
base();
|
||||
~base();
|
||||
virtual uint8_t* decode(ofdm_param* ofdm, frame_param* frame, uint8_t* in) = 0;
|
||||
|
||||
protected:
|
||||
// Position in circular buffer where the current decoded byte is stored
|
||||
int d_store_pos;
|
||||
// Metrics for each state
|
||||
unsigned char d_mmresult[64] __attribute__((aligned(16)));
|
||||
// Paths for each state
|
||||
unsigned char d_ppresult[TRACEBACK_MAX][64] __attribute__((aligned(16)));
|
||||
// Position in circular buffer where the current decoded byte is stored
|
||||
int d_store_pos;
|
||||
// Metrics for each state
|
||||
unsigned char d_mmresult[64] __attribute__((aligned(16)));
|
||||
// Paths for each state
|
||||
unsigned char d_ppresult[TRACEBACK_MAX][64] __attribute__((aligned(16)));
|
||||
|
||||
int d_ntraceback;
|
||||
int d_k;
|
||||
ofdm_param *d_ofdm;
|
||||
frame_param *d_frame;
|
||||
const unsigned char *d_depuncture_pattern;
|
||||
int d_ntraceback;
|
||||
int d_k;
|
||||
ofdm_param* d_ofdm;
|
||||
frame_param* d_frame;
|
||||
const unsigned char* d_depuncture_pattern;
|
||||
|
||||
uint8_t d_depunctured[MAX_ENCODED_BITS];
|
||||
uint8_t d_decoded[MAX_ENCODED_BITS * 3 / 4];
|
||||
uint8_t d_depunctured[MAX_ENCODED_BITS];
|
||||
uint8_t d_decoded[MAX_ENCODED_BITS * 3 / 4];
|
||||
|
||||
static const unsigned char PARTAB[256];
|
||||
static const unsigned char PUNCTURE_1_2[2];
|
||||
static const unsigned char PUNCTURE_2_3[4];
|
||||
static const unsigned char PUNCTURE_3_4[6];
|
||||
static const unsigned char PARTAB[256];
|
||||
static const unsigned char PUNCTURE_1_2[2];
|
||||
static const unsigned char PUNCTURE_2_3[4];
|
||||
static const unsigned char PUNCTURE_3_4[6];
|
||||
|
||||
virtual void reset() = 0;
|
||||
uint8_t* depuncture(uint8_t *in);
|
||||
virtual void reset() = 0;
|
||||
uint8_t* depuncture(uint8_t* in);
|
||||
};
|
||||
|
||||
} // namespace ieee802_11
|
||||
|
||||
@@ -56,371 +56,381 @@
|
||||
* would spill over into memory.
|
||||
*/
|
||||
|
||||
#define BUTTERFLY(i,sym) { \
|
||||
int m0,m1,m2,m3; \
|
||||
/* ACS for 0 branch */ \
|
||||
m0 = state[i].metric + mets[sym]; /* 2*i */ \
|
||||
m1 = state[i+32].metric + mets[3 ^ sym]; /* 2*i + 64 */ \
|
||||
if(m0 > m1){ \
|
||||
next[2*i].metric = m0; \
|
||||
next[2*i].path = state[i].path << 1; \
|
||||
} else { \
|
||||
next[2*i].metric = m1; \
|
||||
next[2*i].path = (state[i+32].path << 1)|1; \
|
||||
} \
|
||||
/* ACS for 1 branch */ \
|
||||
m2 = state[i].metric + mets[3 ^ sym]; /* 2*i + 1 */ \
|
||||
m3 = state[i+32].metric + mets[sym]; /* 2*i + 65 */ \
|
||||
if(m2 > m3){ \
|
||||
next[2*i+1].metric = m2; \
|
||||
next[2*i+1].path = state[i].path << 1; \
|
||||
} else { \
|
||||
next[2*i+1].metric = m3; \
|
||||
next[2*i+1].path = (state[i+32].path << 1)|1; \
|
||||
} \
|
||||
}
|
||||
#define BUTTERFLY(i, sym) \
|
||||
{ \
|
||||
int m0, m1, m2, m3; \
|
||||
/* ACS for 0 branch */ \
|
||||
m0 = state[i].metric + mets[sym]; /* 2*i */ \
|
||||
m1 = state[i + 32].metric + mets[3 ^ sym]; /* 2*i + 64 */ \
|
||||
if (m0 > m1) { \
|
||||
next[2 * i].metric = m0; \
|
||||
next[2 * i].path = state[i].path << 1; \
|
||||
} else { \
|
||||
next[2 * i].metric = m1; \
|
||||
next[2 * i].path = (state[i + 32].path << 1) | 1; \
|
||||
} \
|
||||
/* ACS for 1 branch */ \
|
||||
m2 = state[i].metric + mets[3 ^ sym]; /* 2*i + 1 */ \
|
||||
m3 = state[i + 32].metric + mets[sym]; /* 2*i + 65 */ \
|
||||
if (m2 > m3) { \
|
||||
next[2 * i + 1].metric = m2; \
|
||||
next[2 * i + 1].path = state[i].path << 1; \
|
||||
} else { \
|
||||
next[2 * i + 1].metric = m3; \
|
||||
next[2 * i + 1].path = (state[i + 32].path << 1) | 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
|
||||
void
|
||||
viterbi_decoder::viterbi_butterfly2_generic(unsigned char *symbols,
|
||||
unsigned char *mm0, unsigned char *mm1, unsigned char *pp0,
|
||||
unsigned char *pp1)
|
||||
void viterbi_decoder::viterbi_butterfly2_generic(unsigned char* symbols,
|
||||
unsigned char* mm0,
|
||||
unsigned char* mm1,
|
||||
unsigned char* pp0,
|
||||
unsigned char* pp1)
|
||||
{
|
||||
int i, j, k;
|
||||
int i, j, k;
|
||||
|
||||
unsigned char *metric0, *metric1;
|
||||
unsigned char *path0, *path1;
|
||||
unsigned char *metric0, *metric1;
|
||||
unsigned char *path0, *path1;
|
||||
|
||||
metric0 = mm0;
|
||||
path0 = pp0;
|
||||
metric1 = mm1;
|
||||
path1 = pp1;
|
||||
metric0 = mm0;
|
||||
path0 = pp0;
|
||||
metric1 = mm1;
|
||||
path1 = pp1;
|
||||
|
||||
// Operate on 4 symbols (2 bits) at a time
|
||||
// Operate on 4 symbols (2 bits) at a time
|
||||
|
||||
unsigned char m0[16], m1[16], m2[16], m3[16], decision0[16], decision1[16], survivor0[16], survivor1[16];
|
||||
unsigned char metsv[16], metsvm[16];
|
||||
unsigned char shift0[16], shift1[16];
|
||||
unsigned char tmp0[16], tmp1[16];
|
||||
unsigned char sym0v[16], sym1v[16];
|
||||
unsigned short simd_epi16;
|
||||
unsigned char m0[16], m1[16], m2[16], m3[16], decision0[16], decision1[16],
|
||||
survivor0[16], survivor1[16];
|
||||
unsigned char metsv[16], metsvm[16];
|
||||
unsigned char shift0[16], shift1[16];
|
||||
unsigned char tmp0[16], tmp1[16];
|
||||
unsigned char sym0v[16], sym1v[16];
|
||||
unsigned short simd_epi16;
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
sym0v[j] = symbols[0];
|
||||
sym1v[j] = symbols[1];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
sym0v[j] = symbols[0];
|
||||
sym1v[j] = symbols[1];
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (symbols[0] == 2) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = d_branchtab27_generic[1].c[(i*16) + j] ^ sym1v[j];
|
||||
metsv[j] = 1 - metsvm[j];
|
||||
}
|
||||
}
|
||||
else if (symbols[1] == 2) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = d_branchtab27_generic[0].c[(i*16) + j] ^ sym0v[j];
|
||||
metsv[j] = 1 - metsvm[j];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = (d_branchtab27_generic[0].c[(i*16) + j] ^ sym0v[j]) + (d_branchtab27_generic[1].c[(i*16) + j] ^ sym1v[j]);
|
||||
metsv[j] = 2 - metsvm[j];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (symbols[0] == 2) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = d_branchtab27_generic[1].c[(i * 16) + j] ^ sym1v[j];
|
||||
metsv[j] = 1 - metsvm[j];
|
||||
}
|
||||
} else if (symbols[1] == 2) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = d_branchtab27_generic[0].c[(i * 16) + j] ^ sym0v[j];
|
||||
metsv[j] = 1 - metsvm[j];
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = (d_branchtab27_generic[0].c[(i * 16) + j] ^ sym0v[j]) +
|
||||
(d_branchtab27_generic[1].c[(i * 16) + j] ^ sym1v[j]);
|
||||
metsv[j] = 2 - metsvm[j];
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
m0[j] = metric0[(i*16) + j] + metsv[j];
|
||||
m1[j] = metric0[((i+2)*16) + j] + metsvm[j];
|
||||
m2[j] = metric0[(i*16) + j] + metsvm[j];
|
||||
m3[j] = metric0[((i+2)*16) + j] + metsv[j];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
m0[j] = metric0[(i * 16) + j] + metsv[j];
|
||||
m1[j] = metric0[((i + 2) * 16) + j] + metsvm[j];
|
||||
m2[j] = metric0[(i * 16) + j] + metsvm[j];
|
||||
m3[j] = metric0[((i + 2) * 16) + j] + metsv[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
decision0[j] = ((m0[j] - m1[j]) > 0) ? 0xff : 0x0;
|
||||
decision1[j] = ((m2[j] - m3[j]) > 0) ? 0xff : 0x0;
|
||||
survivor0[j] = (decision0[j] & m0[j]) | ((~decision0[j]) & m1[j]);
|
||||
survivor1[j] = (decision1[j] & m2[j]) | ((~decision1[j]) & m3[j]);
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
decision0[j] = ((m0[j] - m1[j]) > 0) ? 0xff : 0x0;
|
||||
decision1[j] = ((m2[j] - m3[j]) > 0) ? 0xff : 0x0;
|
||||
survivor0[j] = (decision0[j] & m0[j]) | ((~decision0[j]) & m1[j]);
|
||||
survivor1[j] = (decision1[j] & m2[j]) | ((~decision1[j]) & m3[j]);
|
||||
}
|
||||
|
||||
for (j = 0; j < 16; j += 2) {
|
||||
simd_epi16 = path0[(i*16) + j];
|
||||
simd_epi16 |= path0[(i*16) + (j+1)] << 8;
|
||||
simd_epi16 <<= 1;
|
||||
shift0[j] = simd_epi16;
|
||||
shift0[j+1] = simd_epi16 >> 8;
|
||||
for (j = 0; j < 16; j += 2) {
|
||||
simd_epi16 = path0[(i * 16) + j];
|
||||
simd_epi16 |= path0[(i * 16) + (j + 1)] << 8;
|
||||
simd_epi16 <<= 1;
|
||||
shift0[j] = simd_epi16;
|
||||
shift0[j + 1] = simd_epi16 >> 8;
|
||||
|
||||
simd_epi16 = path0[((i+2)*16) + j];
|
||||
simd_epi16 |= path0[((i+2)*16) + (j+1)] << 8;
|
||||
simd_epi16 <<= 1;
|
||||
shift1[j] = simd_epi16;
|
||||
shift1[j+1] = simd_epi16 >> 8;
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
shift1[j] = shift1[j] + 1;
|
||||
}
|
||||
simd_epi16 = path0[((i + 2) * 16) + j];
|
||||
simd_epi16 |= path0[((i + 2) * 16) + (j + 1)] << 8;
|
||||
simd_epi16 <<= 1;
|
||||
shift1[j] = simd_epi16;
|
||||
shift1[j + 1] = simd_epi16 >> 8;
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
shift1[j] = shift1[j] + 1;
|
||||
}
|
||||
|
||||
for (j = 0, k = 0; j < 16; j += 2, k++) {
|
||||
metric1[(2*i*16) + j] = survivor0[k];
|
||||
metric1[(2*i*16) + (j+1)] = survivor1[k];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
tmp0[j] = (decision0[j] & shift0[j]) | ((~decision0[j]) & shift1[j]);
|
||||
}
|
||||
for (j = 0, k = 0; j < 16; j += 2, k++) {
|
||||
metric1[(2 * i * 16) + j] = survivor0[k];
|
||||
metric1[(2 * i * 16) + (j + 1)] = survivor1[k];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
tmp0[j] = (decision0[j] & shift0[j]) | ((~decision0[j]) & shift1[j]);
|
||||
}
|
||||
|
||||
for (j = 0, k = 8; j < 16; j += 2, k++) {
|
||||
metric1[((2*i+1)*16) + j] = survivor0[k];
|
||||
metric1[((2*i+1)*16) + (j+1)] = survivor1[k];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
tmp1[j] = (decision1[j] & shift0[j]) | ((~decision1[j]) & shift1[j]);
|
||||
}
|
||||
for (j = 0, k = 8; j < 16; j += 2, k++) {
|
||||
metric1[((2 * i + 1) * 16) + j] = survivor0[k];
|
||||
metric1[((2 * i + 1) * 16) + (j + 1)] = survivor1[k];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
tmp1[j] = (decision1[j] & shift0[j]) | ((~decision1[j]) & shift1[j]);
|
||||
}
|
||||
|
||||
for (j = 0, k = 0; j < 16; j += 2, k++) {
|
||||
path1[(2*i*16) + j] = tmp0[k];
|
||||
path1[(2*i*16) + (j+1)] = tmp1[k];
|
||||
}
|
||||
for (j = 0, k = 8; j < 16; j += 2, k++) {
|
||||
path1[((2*i+1)*16) + j] = tmp0[k];
|
||||
path1[((2*i+1)*16) + (j+1)] = tmp1[k];
|
||||
}
|
||||
}
|
||||
for (j = 0, k = 0; j < 16; j += 2, k++) {
|
||||
path1[(2 * i * 16) + j] = tmp0[k];
|
||||
path1[(2 * i * 16) + (j + 1)] = tmp1[k];
|
||||
}
|
||||
for (j = 0, k = 8; j < 16; j += 2, k++) {
|
||||
path1[((2 * i + 1) * 16) + j] = tmp0[k];
|
||||
path1[((2 * i + 1) * 16) + (j + 1)] = tmp1[k];
|
||||
}
|
||||
}
|
||||
|
||||
metric0 = mm1;
|
||||
path0 = pp1;
|
||||
metric1 = mm0;
|
||||
path1 = pp0;
|
||||
metric0 = mm1;
|
||||
path0 = pp1;
|
||||
metric1 = mm0;
|
||||
path1 = pp0;
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
sym0v[j] = symbols[2];
|
||||
sym1v[j] = symbols[3];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
sym0v[j] = symbols[2];
|
||||
sym1v[j] = symbols[3];
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (symbols[2] == 2) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = d_branchtab27_generic[1].c[(i*16) + j] ^ sym1v[j];
|
||||
metsv[j] = 1 - metsvm[j];
|
||||
}
|
||||
}
|
||||
else if (symbols[3] == 2) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = d_branchtab27_generic[0].c[(i*16) + j] ^ sym0v[j];
|
||||
metsv[j] = 1 - metsvm[j];
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = (d_branchtab27_generic[0].c[(i*16) + j] ^ sym0v[j]) + (d_branchtab27_generic[1].c[(i*16) + j] ^ sym1v[j]);
|
||||
metsv[j] = 2 - metsvm[j];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (symbols[2] == 2) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = d_branchtab27_generic[1].c[(i * 16) + j] ^ sym1v[j];
|
||||
metsv[j] = 1 - metsvm[j];
|
||||
}
|
||||
} else if (symbols[3] == 2) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = d_branchtab27_generic[0].c[(i * 16) + j] ^ sym0v[j];
|
||||
metsv[j] = 1 - metsvm[j];
|
||||
}
|
||||
} else {
|
||||
for (j = 0; j < 16; j++) {
|
||||
metsvm[j] = (d_branchtab27_generic[0].c[(i * 16) + j] ^ sym0v[j]) +
|
||||
(d_branchtab27_generic[1].c[(i * 16) + j] ^ sym1v[j]);
|
||||
metsv[j] = 2 - metsvm[j];
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
m0[j] = metric0[(i*16) + j] + metsv[j];
|
||||
m1[j] = metric0[((i+2)*16) + j] + metsvm[j];
|
||||
m2[j] = metric0[(i*16) + j] + metsvm[j];
|
||||
m3[j] = metric0[((i+2)*16) + j] + metsv[j];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
m0[j] = metric0[(i * 16) + j] + metsv[j];
|
||||
m1[j] = metric0[((i + 2) * 16) + j] + metsvm[j];
|
||||
m2[j] = metric0[(i * 16) + j] + metsvm[j];
|
||||
m3[j] = metric0[((i + 2) * 16) + j] + metsv[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
decision0[j] = ((m0[j] - m1[j]) > 0) ? 0xff : 0x0;
|
||||
decision1[j] = ((m2[j] - m3[j]) > 0) ? 0xff : 0x0;
|
||||
survivor0[j] = (decision0[j] & m0[j]) | ((~decision0[j]) & m1[j]);
|
||||
survivor1[j] = (decision1[j] & m2[j]) | ((~decision1[j]) & m3[j]);
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
decision0[j] = ((m0[j] - m1[j]) > 0) ? 0xff : 0x0;
|
||||
decision1[j] = ((m2[j] - m3[j]) > 0) ? 0xff : 0x0;
|
||||
survivor0[j] = (decision0[j] & m0[j]) | ((~decision0[j]) & m1[j]);
|
||||
survivor1[j] = (decision1[j] & m2[j]) | ((~decision1[j]) & m3[j]);
|
||||
}
|
||||
|
||||
for (j = 0; j < 16; j += 2) {
|
||||
simd_epi16 = path0[(i*16) + j];
|
||||
simd_epi16 |= path0[(i*16) + (j+1)] << 8;
|
||||
simd_epi16 <<= 1;
|
||||
shift0[j] = simd_epi16;
|
||||
shift0[j+1] = simd_epi16 >> 8;
|
||||
for (j = 0; j < 16; j += 2) {
|
||||
simd_epi16 = path0[(i * 16) + j];
|
||||
simd_epi16 |= path0[(i * 16) + (j + 1)] << 8;
|
||||
simd_epi16 <<= 1;
|
||||
shift0[j] = simd_epi16;
|
||||
shift0[j + 1] = simd_epi16 >> 8;
|
||||
|
||||
simd_epi16 = path0[((i+2)*16) + j];
|
||||
simd_epi16 |= path0[((i+2)*16) + (j+1)] << 8;
|
||||
simd_epi16 <<= 1;
|
||||
shift1[j] = simd_epi16;
|
||||
shift1[j+1] = simd_epi16 >> 8;
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
shift1[j] = shift1[j] + 1;
|
||||
}
|
||||
simd_epi16 = path0[((i + 2) * 16) + j];
|
||||
simd_epi16 |= path0[((i + 2) * 16) + (j + 1)] << 8;
|
||||
simd_epi16 <<= 1;
|
||||
shift1[j] = simd_epi16;
|
||||
shift1[j + 1] = simd_epi16 >> 8;
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
shift1[j] = shift1[j] + 1;
|
||||
}
|
||||
|
||||
for (j = 0, k = 0; j < 16; j += 2, k++) {
|
||||
metric1[(2*i*16) + j] = survivor0[k];
|
||||
metric1[(2*i*16) + (j+1)] = survivor1[k];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
tmp0[j] = (decision0[j] & shift0[j]) | ((~decision0[j]) & shift1[j]);
|
||||
}
|
||||
for (j = 0, k = 0; j < 16; j += 2, k++) {
|
||||
metric1[(2 * i * 16) + j] = survivor0[k];
|
||||
metric1[(2 * i * 16) + (j + 1)] = survivor1[k];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
tmp0[j] = (decision0[j] & shift0[j]) | ((~decision0[j]) & shift1[j]);
|
||||
}
|
||||
|
||||
for (j = 0, k = 8; j < 16; j += 2, k++) {
|
||||
metric1[((2*i+1)*16) + j] = survivor0[k];
|
||||
metric1[((2*i+1)*16) + (j+1)] = survivor1[k];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
tmp1[j] = (decision1[j] & shift0[j]) | ((~decision1[j]) & shift1[j]);
|
||||
}
|
||||
for (j = 0, k = 8; j < 16; j += 2, k++) {
|
||||
metric1[((2 * i + 1) * 16) + j] = survivor0[k];
|
||||
metric1[((2 * i + 1) * 16) + (j + 1)] = survivor1[k];
|
||||
}
|
||||
for (j = 0; j < 16; j++) {
|
||||
tmp1[j] = (decision1[j] & shift0[j]) | ((~decision1[j]) & shift1[j]);
|
||||
}
|
||||
|
||||
for (j = 0, k = 0; j < 16; j += 2, k++) {
|
||||
path1[(2*i*16) + j] = tmp0[k];
|
||||
path1[(2*i*16) + (j+1)] = tmp1[k];
|
||||
}
|
||||
for (j = 0, k = 8; j < 16; j += 2, k++) {
|
||||
path1[((2*i+1)*16) + j] = tmp0[k];
|
||||
path1[((2*i+1)*16) + (j+1)] = tmp1[k];
|
||||
}
|
||||
}
|
||||
for (j = 0, k = 0; j < 16; j += 2, k++) {
|
||||
path1[(2 * i * 16) + j] = tmp0[k];
|
||||
path1[(2 * i * 16) + (j + 1)] = tmp1[k];
|
||||
}
|
||||
for (j = 0, k = 8; j < 16; j += 2, k++) {
|
||||
path1[((2 * i + 1) * 16) + j] = tmp0[k];
|
||||
path1[((2 * i + 1) * 16) + (j + 1)] = tmp1[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find current best path
|
||||
unsigned char
|
||||
viterbi_decoder::viterbi_get_output_generic(unsigned char *mm0,
|
||||
unsigned char *pp0, int ntraceback, unsigned char *outbuf) {
|
||||
int i;
|
||||
int bestmetric, minmetric;
|
||||
int beststate = 0;
|
||||
int pos = 0;
|
||||
int j;
|
||||
unsigned char viterbi_decoder::viterbi_get_output_generic(unsigned char* mm0,
|
||||
unsigned char* pp0,
|
||||
int ntraceback,
|
||||
unsigned char* outbuf)
|
||||
{
|
||||
int i;
|
||||
int bestmetric, minmetric;
|
||||
int beststate = 0;
|
||||
int pos = 0;
|
||||
int j;
|
||||
|
||||
// circular buffer with the last ntraceback paths
|
||||
d_store_pos = (d_store_pos + 1) % ntraceback;
|
||||
// circular buffer with the last ntraceback paths
|
||||
d_store_pos = (d_store_pos + 1) % ntraceback;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
d_mmresult[(i*16) + j] = mm0[(i*16) + j];
|
||||
d_ppresult[d_store_pos][(i*16) + j] = pp0[(i*16) + j];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
d_mmresult[(i * 16) + j] = mm0[(i * 16) + j];
|
||||
d_ppresult[d_store_pos][(i * 16) + j] = pp0[(i * 16) + j];
|
||||
}
|
||||
}
|
||||
|
||||
// Find out the best final state
|
||||
bestmetric = d_mmresult[beststate];
|
||||
minmetric = d_mmresult[beststate];
|
||||
// Find out the best final state
|
||||
bestmetric = d_mmresult[beststate];
|
||||
minmetric = d_mmresult[beststate];
|
||||
|
||||
for (i = 1; i < 64; i++) {
|
||||
if (d_mmresult[i] > bestmetric) {
|
||||
bestmetric = d_mmresult[i];
|
||||
beststate = i;
|
||||
}
|
||||
if (d_mmresult[i] < minmetric) {
|
||||
minmetric = d_mmresult[i];
|
||||
}
|
||||
}
|
||||
for (i = 1; i < 64; i++) {
|
||||
if (d_mmresult[i] > bestmetric) {
|
||||
bestmetric = d_mmresult[i];
|
||||
beststate = i;
|
||||
}
|
||||
if (d_mmresult[i] < minmetric) {
|
||||
minmetric = d_mmresult[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Trace back
|
||||
for (i = 0, pos = d_store_pos; i < (ntraceback - 1); i++) {
|
||||
// Obtain the state from the output bits
|
||||
// by clocking in the output bits in reverse order.
|
||||
// The state has only 6 bits
|
||||
beststate = d_ppresult[pos][beststate] >> 2;
|
||||
pos = (pos - 1 + ntraceback) % ntraceback;
|
||||
}
|
||||
// Trace back
|
||||
for (i = 0, pos = d_store_pos; i < (ntraceback - 1); i++) {
|
||||
// Obtain the state from the output bits
|
||||
// by clocking in the output bits in reverse order.
|
||||
// The state has only 6 bits
|
||||
beststate = d_ppresult[pos][beststate] >> 2;
|
||||
pos = (pos - 1 + ntraceback) % ntraceback;
|
||||
}
|
||||
|
||||
// Store output byte
|
||||
*outbuf = d_ppresult[pos][beststate];
|
||||
// Store output byte
|
||||
*outbuf = d_ppresult[pos][beststate];
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
pp0[(i*16) + j] = 0;
|
||||
mm0[(i*16) + j] = mm0[(i*16) + j] - minmetric;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 16; j++) {
|
||||
pp0[(i * 16) + j] = 0;
|
||||
mm0[(i * 16) + j] = mm0[(i * 16) + j] - minmetric;
|
||||
}
|
||||
}
|
||||
|
||||
return bestmetric;
|
||||
return bestmetric;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
viterbi_decoder::decode(ofdm_param *ofdm, frame_param *frame, uint8_t *in) {
|
||||
uint8_t* viterbi_decoder::decode(ofdm_param* ofdm, frame_param* frame, uint8_t* in)
|
||||
{
|
||||
|
||||
d_ofdm = ofdm;
|
||||
d_frame = frame;
|
||||
d_ofdm = ofdm;
|
||||
d_frame = frame;
|
||||
|
||||
reset();
|
||||
uint8_t *depunctured = depuncture(in);
|
||||
reset();
|
||||
uint8_t* depunctured = depuncture(in);
|
||||
|
||||
int in_count = 0;
|
||||
int out_count = 0;
|
||||
int n_decoded = 0;
|
||||
int in_count = 0;
|
||||
int out_count = 0;
|
||||
int n_decoded = 0;
|
||||
|
||||
while(n_decoded < d_frame->n_data_bits) {
|
||||
while (n_decoded < d_frame->n_data_bits) {
|
||||
|
||||
if ((in_count % 4) == 0) { //0 or 3
|
||||
viterbi_butterfly2_generic(&depunctured[in_count & 0xfffffffc], d_metric0_generic, d_metric1_generic,
|
||||
d_path0_generic, d_path1_generic);
|
||||
if ((in_count % 4) == 0) { // 0 or 3
|
||||
viterbi_butterfly2_generic(&depunctured[in_count & 0xfffffffc],
|
||||
d_metric0_generic,
|
||||
d_metric1_generic,
|
||||
d_path0_generic,
|
||||
d_path1_generic);
|
||||
|
||||
if ((in_count > 0) && (in_count % 16) == 8) { // 8 or 11
|
||||
unsigned char c;
|
||||
if ((in_count > 0) && (in_count % 16) == 8) { // 8 or 11
|
||||
unsigned char c;
|
||||
|
||||
viterbi_get_output_generic(d_metric0_generic, d_path0_generic, d_ntraceback, &c);
|
||||
viterbi_get_output_generic(
|
||||
d_metric0_generic, d_path0_generic, d_ntraceback, &c);
|
||||
|
||||
if (out_count >= d_ntraceback) {
|
||||
for (int i= 0; i < 8; i++) {
|
||||
d_decoded[(out_count - d_ntraceback) * 8 + i] = (c >> (7 - i)) & 0x1;
|
||||
n_decoded++;
|
||||
}
|
||||
}
|
||||
out_count++;
|
||||
}
|
||||
}
|
||||
in_count++;
|
||||
}
|
||||
if (out_count >= d_ntraceback) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
d_decoded[(out_count - d_ntraceback) * 8 + i] =
|
||||
(c >> (7 - i)) & 0x1;
|
||||
n_decoded++;
|
||||
}
|
||||
}
|
||||
out_count++;
|
||||
}
|
||||
}
|
||||
in_count++;
|
||||
}
|
||||
|
||||
return d_decoded;
|
||||
return d_decoded;
|
||||
}
|
||||
|
||||
void
|
||||
viterbi_decoder::reset() {
|
||||
void viterbi_decoder::reset()
|
||||
{
|
||||
|
||||
viterbi_chunks_init_generic();
|
||||
viterbi_chunks_init_generic();
|
||||
|
||||
switch(d_ofdm->encoding) {
|
||||
case BPSK_1_2:
|
||||
case QPSK_1_2:
|
||||
case QAM16_1_2:
|
||||
d_ntraceback = 5;
|
||||
d_depuncture_pattern = PUNCTURE_1_2;
|
||||
d_k = 1;
|
||||
break;
|
||||
case QAM64_2_3:
|
||||
d_ntraceback = 9;
|
||||
d_depuncture_pattern = PUNCTURE_2_3;
|
||||
d_k = 2;
|
||||
break;
|
||||
case BPSK_3_4:
|
||||
case QPSK_3_4:
|
||||
case QAM16_3_4:
|
||||
case QAM64_3_4:
|
||||
d_ntraceback = 10;
|
||||
d_depuncture_pattern = PUNCTURE_3_4;
|
||||
d_k = 3;
|
||||
break;
|
||||
}
|
||||
switch (d_ofdm->encoding) {
|
||||
case BPSK_1_2:
|
||||
case QPSK_1_2:
|
||||
case QAM16_1_2:
|
||||
d_ntraceback = 5;
|
||||
d_depuncture_pattern = PUNCTURE_1_2;
|
||||
d_k = 1;
|
||||
break;
|
||||
case QAM64_2_3:
|
||||
d_ntraceback = 9;
|
||||
d_depuncture_pattern = PUNCTURE_2_3;
|
||||
d_k = 2;
|
||||
break;
|
||||
case BPSK_3_4:
|
||||
case QPSK_3_4:
|
||||
case QAM16_3_4:
|
||||
case QAM64_3_4:
|
||||
d_ntraceback = 10;
|
||||
d_depuncture_pattern = PUNCTURE_3_4;
|
||||
d_k = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize starting metrics to prefer 0 state
|
||||
void
|
||||
viterbi_decoder::viterbi_chunks_init_generic() {
|
||||
int i, j;
|
||||
void viterbi_decoder::viterbi_chunks_init_generic()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
d_metric0_generic[i] = 0;
|
||||
d_path0_generic[i] = 0;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
d_metric0_generic[i] = 0;
|
||||
d_path0_generic[i] = 0;
|
||||
}
|
||||
|
||||
int polys[2] = { 0x6d, 0x4f };
|
||||
for(i=0; i < 32; i++) {
|
||||
d_branchtab27_generic[0].c[i] = (polys[0] < 0) ^ PARTAB[(2*i) & abs(polys[0])] ? 1 : 0;
|
||||
d_branchtab27_generic[1].c[i] = (polys[1] < 0) ^ PARTAB[(2*i) & abs(polys[1])] ? 1 : 0;
|
||||
}
|
||||
int polys[2] = { 0x6d, 0x4f };
|
||||
for (i = 0; i < 32; i++) {
|
||||
d_branchtab27_generic[0].c[i] =
|
||||
(polys[0] < 0) ^ PARTAB[(2 * i) & abs(polys[0])] ? 1 : 0;
|
||||
d_branchtab27_generic[1].c[i] =
|
||||
(polys[1] < 0) ^ PARTAB[(2 * i) & abs(polys[1])] ? 1 : 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
d_mmresult[i] = 0;
|
||||
for (j = 0; j < TRACEBACK_MAX; j++) {
|
||||
d_ppresult[j][i] = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 64; i++) {
|
||||
d_mmresult[i] = 0;
|
||||
for (j = 0; j < TRACEBACK_MAX; j++) {
|
||||
d_ppresult[j][i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,28 +30,30 @@ namespace ieee802_11 {
|
||||
class viterbi_decoder : public base
|
||||
{
|
||||
public:
|
||||
|
||||
virtual uint8_t* decode(ofdm_param *ofdm, frame_param *frame, uint8_t *in);
|
||||
virtual uint8_t* decode(ofdm_param* ofdm, frame_param* frame, uint8_t* in);
|
||||
|
||||
private:
|
||||
union branchtab27 {
|
||||
unsigned char c[32];
|
||||
} d_branchtab27_generic[2];
|
||||
|
||||
union branchtab27 {
|
||||
unsigned char c[32];
|
||||
} d_branchtab27_generic[2];
|
||||
unsigned char d_metric0_generic[64] __attribute__((aligned(16)));
|
||||
unsigned char d_metric1_generic[64] __attribute__((aligned(16)));
|
||||
unsigned char d_path0_generic[64] __attribute__((aligned(16)));
|
||||
unsigned char d_path1_generic[64] __attribute__((aligned(16)));
|
||||
|
||||
unsigned char d_metric0_generic[64] __attribute__ ((aligned(16)));
|
||||
unsigned char d_metric1_generic[64] __attribute__ ((aligned(16)));
|
||||
unsigned char d_path0_generic[64] __attribute__ ((aligned(16)));
|
||||
unsigned char d_path1_generic[64] __attribute__ ((aligned(16)));
|
||||
void reset();
|
||||
|
||||
void reset();
|
||||
|
||||
void viterbi_chunks_init_generic();
|
||||
void viterbi_butterfly2_generic(unsigned char *symbols,
|
||||
unsigned char m0[], unsigned char m1[], unsigned char p0[],
|
||||
unsigned char p1[]);
|
||||
unsigned char viterbi_get_output_generic(unsigned char *mm0,
|
||||
unsigned char *pp0, int ntraceback, unsigned char *outbuf);
|
||||
void viterbi_chunks_init_generic();
|
||||
void viterbi_butterfly2_generic(unsigned char* symbols,
|
||||
unsigned char m0[],
|
||||
unsigned char m1[],
|
||||
unsigned char p0[],
|
||||
unsigned char p1[]);
|
||||
unsigned char viterbi_get_output_generic(unsigned char* mm0,
|
||||
unsigned char* pp0,
|
||||
int ntraceback,
|
||||
unsigned char* outbuf);
|
||||
};
|
||||
|
||||
} // namespace ieee802_11
|
||||
|
||||
@@ -56,280 +56,300 @@
|
||||
* would spill over into memory.
|
||||
*/
|
||||
|
||||
#define BUTTERFLY(i,sym) { \
|
||||
int m0,m1,m2,m3; \
|
||||
/* ACS for 0 branch */ \
|
||||
m0 = state[i].metric + mets[sym]; /* 2*i */ \
|
||||
m1 = state[i+32].metric + mets[3 ^ sym]; /* 2*i + 64 */ \
|
||||
if(m0 > m1){ \
|
||||
next[2*i].metric = m0; \
|
||||
next[2*i].path = state[i].path << 1; \
|
||||
} else { \
|
||||
next[2*i].metric = m1; \
|
||||
next[2*i].path = (state[i+32].path << 1)|1; \
|
||||
} \
|
||||
/* ACS for 1 branch */ \
|
||||
m2 = state[i].metric + mets[3 ^ sym]; /* 2*i + 1 */ \
|
||||
m3 = state[i+32].metric + mets[sym]; /* 2*i + 65 */ \
|
||||
if(m2 > m3){ \
|
||||
next[2*i+1].metric = m2; \
|
||||
next[2*i+1].path = state[i].path << 1; \
|
||||
} else { \
|
||||
next[2*i+1].metric = m3; \
|
||||
next[2*i+1].path = (state[i+32].path << 1)|1; \
|
||||
} \
|
||||
}
|
||||
#define BUTTERFLY(i, sym) \
|
||||
{ \
|
||||
int m0, m1, m2, m3; \
|
||||
/* ACS for 0 branch */ \
|
||||
m0 = state[i].metric + mets[sym]; /* 2*i */ \
|
||||
m1 = state[i + 32].metric + mets[3 ^ sym]; /* 2*i + 64 */ \
|
||||
if (m0 > m1) { \
|
||||
next[2 * i].metric = m0; \
|
||||
next[2 * i].path = state[i].path << 1; \
|
||||
} else { \
|
||||
next[2 * i].metric = m1; \
|
||||
next[2 * i].path = (state[i + 32].path << 1) | 1; \
|
||||
} \
|
||||
/* ACS for 1 branch */ \
|
||||
m2 = state[i].metric + mets[3 ^ sym]; /* 2*i + 1 */ \
|
||||
m3 = state[i + 32].metric + mets[sym]; /* 2*i + 65 */ \
|
||||
if (m2 > m3) { \
|
||||
next[2 * i + 1].metric = m2; \
|
||||
next[2 * i + 1].path = state[i].path << 1; \
|
||||
} else { \
|
||||
next[2 * i + 1].metric = m3; \
|
||||
next[2 * i + 1].path = (state[i + 32].path << 1) | 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
using namespace gr::ieee802_11;
|
||||
|
||||
void
|
||||
viterbi_decoder::viterbi_butterfly2_sse2(unsigned char *symbols,
|
||||
__m128i *mm0, __m128i *mm1, __m128i *pp0, __m128i *pp1) {
|
||||
int i;
|
||||
void viterbi_decoder::viterbi_butterfly2_sse2(
|
||||
unsigned char* symbols, __m128i* mm0, __m128i* mm1, __m128i* pp0, __m128i* pp1)
|
||||
{
|
||||
int i;
|
||||
|
||||
__m128i *metric0, *metric1;
|
||||
__m128i *path0, *path1;
|
||||
__m128i *metric0, *metric1;
|
||||
__m128i *path0, *path1;
|
||||
|
||||
metric0 = mm0;
|
||||
path0 = pp0;
|
||||
metric1 = mm1;
|
||||
path1 = pp1;
|
||||
metric0 = mm0;
|
||||
path0 = pp0;
|
||||
metric1 = mm1;
|
||||
path1 = pp1;
|
||||
|
||||
// Operate on 4 symbols (2 bits) at a time
|
||||
// Operate on 4 symbols (2 bits) at a time
|
||||
|
||||
__m128i m0, m1, m2, m3, decision0, decision1, survivor0, survivor1;
|
||||
__m128i metsv, metsvm;
|
||||
__m128i shift0, shift1;
|
||||
__m128i tmp0, tmp1;
|
||||
__m128i sym0v, sym1v;
|
||||
__m128i m0, m1, m2, m3, decision0, decision1, survivor0, survivor1;
|
||||
__m128i metsv, metsvm;
|
||||
__m128i shift0, shift1;
|
||||
__m128i tmp0, tmp1;
|
||||
__m128i sym0v, sym1v;
|
||||
|
||||
sym0v = _mm_set1_epi8(symbols[0]);
|
||||
sym1v = _mm_set1_epi8(symbols[1]);
|
||||
sym0v = _mm_set1_epi8(symbols[0]);
|
||||
sym1v = _mm_set1_epi8(symbols[1]);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (symbols[0] == 2) {
|
||||
metsvm = _mm_xor_si128(d_branchtab27_sse2[1].v[i],sym1v);
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm);
|
||||
} else if (symbols[1] == 2) {
|
||||
metsvm = _mm_xor_si128(d_branchtab27_sse2[0].v[i],sym0v);
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm);
|
||||
} else {
|
||||
metsvm = _mm_add_epi8(_mm_xor_si128(d_branchtab27_sse2[0].v[i],sym0v),_mm_xor_si128(d_branchtab27_sse2[1].v[i],sym1v));
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(2),metsvm);
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (symbols[0] == 2) {
|
||||
metsvm = _mm_xor_si128(d_branchtab27_sse2[1].v[i], sym1v);
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(1), metsvm);
|
||||
} else if (symbols[1] == 2) {
|
||||
metsvm = _mm_xor_si128(d_branchtab27_sse2[0].v[i], sym0v);
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(1), metsvm);
|
||||
} else {
|
||||
metsvm = _mm_add_epi8(_mm_xor_si128(d_branchtab27_sse2[0].v[i], sym0v),
|
||||
_mm_xor_si128(d_branchtab27_sse2[1].v[i], sym1v));
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(2), metsvm);
|
||||
}
|
||||
|
||||
m0 = _mm_add_epi8(metric0[i], metsv);
|
||||
m1 = _mm_add_epi8(metric0[i+2], metsvm);
|
||||
m2 = _mm_add_epi8(metric0[i], metsvm);
|
||||
m3 = _mm_add_epi8(metric0[i+2], metsv);
|
||||
m0 = _mm_add_epi8(metric0[i], metsv);
|
||||
m1 = _mm_add_epi8(metric0[i + 2], metsvm);
|
||||
m2 = _mm_add_epi8(metric0[i], metsvm);
|
||||
m3 = _mm_add_epi8(metric0[i + 2], metsv);
|
||||
|
||||
decision0 = _mm_cmpgt_epi8(_mm_sub_epi8(m0,m1),_mm_setzero_si128());
|
||||
decision1 = _mm_cmpgt_epi8(_mm_sub_epi8(m2,m3),_mm_setzero_si128());
|
||||
survivor0 = _mm_or_si128(_mm_and_si128(decision0,m0),_mm_andnot_si128(decision0,m1));
|
||||
survivor1 = _mm_or_si128(_mm_and_si128(decision1,m2),_mm_andnot_si128(decision1,m3));
|
||||
decision0 = _mm_cmpgt_epi8(_mm_sub_epi8(m0, m1), _mm_setzero_si128());
|
||||
decision1 = _mm_cmpgt_epi8(_mm_sub_epi8(m2, m3), _mm_setzero_si128());
|
||||
survivor0 =
|
||||
_mm_or_si128(_mm_and_si128(decision0, m0), _mm_andnot_si128(decision0, m1));
|
||||
survivor1 =
|
||||
_mm_or_si128(_mm_and_si128(decision1, m2), _mm_andnot_si128(decision1, m3));
|
||||
|
||||
shift0 = _mm_slli_epi16(path0[i], 1);
|
||||
shift1 = _mm_slli_epi16(path0[2+i], 1);
|
||||
shift1 = _mm_add_epi8(shift1, _mm_set1_epi8(1));
|
||||
shift0 = _mm_slli_epi16(path0[i], 1);
|
||||
shift1 = _mm_slli_epi16(path0[2 + i], 1);
|
||||
shift1 = _mm_add_epi8(shift1, _mm_set1_epi8(1));
|
||||
|
||||
metric1[2*i] = _mm_unpacklo_epi8(survivor0,survivor1);
|
||||
tmp0 = _mm_or_si128(_mm_and_si128(decision0,shift0),_mm_andnot_si128(decision0,shift1));
|
||||
metric1[2 * i] = _mm_unpacklo_epi8(survivor0, survivor1);
|
||||
tmp0 = _mm_or_si128(_mm_and_si128(decision0, shift0),
|
||||
_mm_andnot_si128(decision0, shift1));
|
||||
|
||||
metric1[2*i+1] = _mm_unpackhi_epi8(survivor0,survivor1);
|
||||
tmp1 = _mm_or_si128(_mm_and_si128(decision1,shift0),_mm_andnot_si128(decision1,shift1));
|
||||
metric1[2 * i + 1] = _mm_unpackhi_epi8(survivor0, survivor1);
|
||||
tmp1 = _mm_or_si128(_mm_and_si128(decision1, shift0),
|
||||
_mm_andnot_si128(decision1, shift1));
|
||||
|
||||
path1[2*i] = _mm_unpacklo_epi8(tmp0, tmp1);
|
||||
path1[2*i+1] = _mm_unpackhi_epi8(tmp0, tmp1);
|
||||
}
|
||||
path1[2 * i] = _mm_unpacklo_epi8(tmp0, tmp1);
|
||||
path1[2 * i + 1] = _mm_unpackhi_epi8(tmp0, tmp1);
|
||||
}
|
||||
|
||||
metric0 = mm1;
|
||||
path0 = pp1;
|
||||
metric1 = mm0;
|
||||
path1 = pp0;
|
||||
metric0 = mm1;
|
||||
path0 = pp1;
|
||||
metric1 = mm0;
|
||||
path1 = pp0;
|
||||
|
||||
sym0v = _mm_set1_epi8(symbols[2]);
|
||||
sym1v = _mm_set1_epi8(symbols[3]);
|
||||
sym0v = _mm_set1_epi8(symbols[2]);
|
||||
sym1v = _mm_set1_epi8(symbols[3]);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (symbols[2] == 2) {
|
||||
metsvm = _mm_xor_si128(d_branchtab27_sse2[1].v[i],sym1v);
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm);
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (symbols[2] == 2) {
|
||||
metsvm = _mm_xor_si128(d_branchtab27_sse2[1].v[i], sym1v);
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(1), metsvm);
|
||||
|
||||
} else if (symbols[3] == 2) {
|
||||
metsvm = _mm_xor_si128(d_branchtab27_sse2[0].v[i],sym0v);
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm);
|
||||
} else if (symbols[3] == 2) {
|
||||
metsvm = _mm_xor_si128(d_branchtab27_sse2[0].v[i], sym0v);
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(1), metsvm);
|
||||
|
||||
} else {
|
||||
metsvm = _mm_add_epi8(_mm_xor_si128(d_branchtab27_sse2[0].v[i],sym0v),_mm_xor_si128(d_branchtab27_sse2[1].v[i],sym1v));
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(2),metsvm);
|
||||
}
|
||||
} else {
|
||||
metsvm = _mm_add_epi8(_mm_xor_si128(d_branchtab27_sse2[0].v[i], sym0v),
|
||||
_mm_xor_si128(d_branchtab27_sse2[1].v[i], sym1v));
|
||||
metsv = _mm_sub_epi8(_mm_set1_epi8(2), metsvm);
|
||||
}
|
||||
|
||||
m0 = _mm_add_epi8(metric0[i], metsv);
|
||||
m1 = _mm_add_epi8(metric0[i+2], metsvm);
|
||||
m2 = _mm_add_epi8(metric0[i], metsvm);
|
||||
m3 = _mm_add_epi8(metric0[i+2], metsv);
|
||||
m0 = _mm_add_epi8(metric0[i], metsv);
|
||||
m1 = _mm_add_epi8(metric0[i + 2], metsvm);
|
||||
m2 = _mm_add_epi8(metric0[i], metsvm);
|
||||
m3 = _mm_add_epi8(metric0[i + 2], metsv);
|
||||
|
||||
decision0 = _mm_cmpgt_epi8(_mm_sub_epi8(m0,m1),_mm_setzero_si128());
|
||||
decision1 = _mm_cmpgt_epi8(_mm_sub_epi8(m2,m3),_mm_setzero_si128());
|
||||
survivor0 = _mm_or_si128(_mm_and_si128(decision0,m0),_mm_andnot_si128(decision0,m1));
|
||||
survivor1 = _mm_or_si128(_mm_and_si128(decision1,m2),_mm_andnot_si128(decision1,m3));
|
||||
decision0 = _mm_cmpgt_epi8(_mm_sub_epi8(m0, m1), _mm_setzero_si128());
|
||||
decision1 = _mm_cmpgt_epi8(_mm_sub_epi8(m2, m3), _mm_setzero_si128());
|
||||
survivor0 =
|
||||
_mm_or_si128(_mm_and_si128(decision0, m0), _mm_andnot_si128(decision0, m1));
|
||||
survivor1 =
|
||||
_mm_or_si128(_mm_and_si128(decision1, m2), _mm_andnot_si128(decision1, m3));
|
||||
|
||||
shift0 = _mm_slli_epi16(path0[i], 1);
|
||||
shift1 = _mm_slli_epi16(path0[2+i], 1);
|
||||
shift1 = _mm_add_epi8(shift1, _mm_set1_epi8(1));
|
||||
shift0 = _mm_slli_epi16(path0[i], 1);
|
||||
shift1 = _mm_slli_epi16(path0[2 + i], 1);
|
||||
shift1 = _mm_add_epi8(shift1, _mm_set1_epi8(1));
|
||||
|
||||
metric1[2*i] = _mm_unpacklo_epi8(survivor0,survivor1);
|
||||
tmp0 = _mm_or_si128(_mm_and_si128(decision0,shift0),_mm_andnot_si128(decision0,shift1));
|
||||
metric1[2 * i] = _mm_unpacklo_epi8(survivor0, survivor1);
|
||||
tmp0 = _mm_or_si128(_mm_and_si128(decision0, shift0),
|
||||
_mm_andnot_si128(decision0, shift1));
|
||||
|
||||
metric1[2*i+1] = _mm_unpackhi_epi8(survivor0,survivor1);
|
||||
tmp1 = _mm_or_si128(_mm_and_si128(decision1,shift0),_mm_andnot_si128(decision1,shift1));
|
||||
metric1[2 * i + 1] = _mm_unpackhi_epi8(survivor0, survivor1);
|
||||
tmp1 = _mm_or_si128(_mm_and_si128(decision1, shift0),
|
||||
_mm_andnot_si128(decision1, shift1));
|
||||
|
||||
path1[2*i] = _mm_unpacklo_epi8(tmp0, tmp1);
|
||||
path1[2*i+1] = _mm_unpackhi_epi8(tmp0, tmp1);
|
||||
}
|
||||
path1[2 * i] = _mm_unpacklo_epi8(tmp0, tmp1);
|
||||
path1[2 * i + 1] = _mm_unpackhi_epi8(tmp0, tmp1);
|
||||
}
|
||||
}
|
||||
|
||||
// Find current best path
|
||||
unsigned char
|
||||
viterbi_decoder::viterbi_get_output_sse2(__m128i *mm0, __m128i *pp0,
|
||||
int ntraceback, unsigned char *outbuf) {
|
||||
int i;
|
||||
int bestmetric, minmetric;
|
||||
int beststate = 0;
|
||||
int pos = 0;
|
||||
unsigned char viterbi_decoder::viterbi_get_output_sse2(__m128i* mm0,
|
||||
__m128i* pp0,
|
||||
int ntraceback,
|
||||
unsigned char* outbuf)
|
||||
{
|
||||
int i;
|
||||
int bestmetric, minmetric;
|
||||
int beststate = 0;
|
||||
int pos = 0;
|
||||
|
||||
// circular buffer with the last ntraceback paths
|
||||
d_store_pos = (d_store_pos + 1) % ntraceback;
|
||||
// circular buffer with the last ntraceback paths
|
||||
d_store_pos = (d_store_pos + 1) % ntraceback;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
_mm_store_si128((__m128i *) &d_mmresult[i*16], mm0[i]);
|
||||
_mm_store_si128((__m128i *) &d_ppresult[d_store_pos][i*16], pp0[i]);
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
_mm_store_si128((__m128i*)&d_mmresult[i * 16], mm0[i]);
|
||||
_mm_store_si128((__m128i*)&d_ppresult[d_store_pos][i * 16], pp0[i]);
|
||||
}
|
||||
|
||||
// Find out the best final state
|
||||
bestmetric = d_mmresult[beststate];
|
||||
minmetric = d_mmresult[beststate];
|
||||
// Find out the best final state
|
||||
bestmetric = d_mmresult[beststate];
|
||||
minmetric = d_mmresult[beststate];
|
||||
|
||||
for (i = 1; i < 64; i++) {
|
||||
if (d_mmresult[i] > bestmetric) {
|
||||
bestmetric = d_mmresult[i];
|
||||
beststate = i;
|
||||
}
|
||||
if (d_mmresult[i] < minmetric) {
|
||||
minmetric = d_mmresult[i];
|
||||
}
|
||||
}
|
||||
for (i = 1; i < 64; i++) {
|
||||
if (d_mmresult[i] > bestmetric) {
|
||||
bestmetric = d_mmresult[i];
|
||||
beststate = i;
|
||||
}
|
||||
if (d_mmresult[i] < minmetric) {
|
||||
minmetric = d_mmresult[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Trace back
|
||||
for (i = 0, pos = d_store_pos; i < (ntraceback - 1); i++) {
|
||||
// Obtain the state from the output bits
|
||||
// by clocking in the output bits in reverse order.
|
||||
// The state has only 6 bits
|
||||
beststate = d_ppresult[pos][beststate] >> 2;
|
||||
pos = (pos - 1 + ntraceback) % ntraceback;
|
||||
}
|
||||
// Trace back
|
||||
for (i = 0, pos = d_store_pos; i < (ntraceback - 1); i++) {
|
||||
// Obtain the state from the output bits
|
||||
// by clocking in the output bits in reverse order.
|
||||
// The state has only 6 bits
|
||||
beststate = d_ppresult[pos][beststate] >> 2;
|
||||
pos = (pos - 1 + ntraceback) % ntraceback;
|
||||
}
|
||||
|
||||
// Store output byte
|
||||
*outbuf = d_ppresult[pos][beststate];
|
||||
// Store output byte
|
||||
*outbuf = d_ppresult[pos][beststate];
|
||||
|
||||
// Zero out the path variable
|
||||
// and prevent metric overflow
|
||||
for (i = 0; i < 4; i++) {
|
||||
pp0[i] = _mm_setzero_si128();
|
||||
mm0[i] = _mm_sub_epi8(mm0[i], _mm_set1_epi8(minmetric));
|
||||
}
|
||||
// Zero out the path variable
|
||||
// and prevent metric overflow
|
||||
for (i = 0; i < 4; i++) {
|
||||
pp0[i] = _mm_setzero_si128();
|
||||
mm0[i] = _mm_sub_epi8(mm0[i], _mm_set1_epi8(minmetric));
|
||||
}
|
||||
|
||||
return bestmetric;
|
||||
return bestmetric;
|
||||
}
|
||||
|
||||
|
||||
uint8_t*
|
||||
viterbi_decoder::decode(ofdm_param *ofdm, frame_param *frame, uint8_t *in) {
|
||||
uint8_t* viterbi_decoder::decode(ofdm_param* ofdm, frame_param* frame, uint8_t* in)
|
||||
{
|
||||
|
||||
d_ofdm = ofdm;
|
||||
d_frame = frame;
|
||||
d_ofdm = ofdm;
|
||||
d_frame = frame;
|
||||
|
||||
reset();
|
||||
uint8_t *depunctured = depuncture(in);
|
||||
reset();
|
||||
uint8_t* depunctured = depuncture(in);
|
||||
|
||||
int in_count = 0;
|
||||
int out_count = 0;
|
||||
int n_decoded = 0;
|
||||
int in_count = 0;
|
||||
int out_count = 0;
|
||||
int n_decoded = 0;
|
||||
|
||||
while(n_decoded < d_frame->n_data_bits) {
|
||||
while (n_decoded < d_frame->n_data_bits) {
|
||||
|
||||
if ((in_count % 4) == 0) { //0 or 3
|
||||
viterbi_butterfly2_sse2(&depunctured[in_count & 0xfffffffc], d_metric0, d_metric1, d_path0, d_path1);
|
||||
if ((in_count % 4) == 0) { // 0 or 3
|
||||
viterbi_butterfly2_sse2(&depunctured[in_count & 0xfffffffc],
|
||||
d_metric0,
|
||||
d_metric1,
|
||||
d_path0,
|
||||
d_path1);
|
||||
|
||||
if ((in_count > 0) && (in_count % 16) == 8) { // 8 or 11
|
||||
unsigned char c;
|
||||
if ((in_count > 0) && (in_count % 16) == 8) { // 8 or 11
|
||||
unsigned char c;
|
||||
|
||||
viterbi_get_output_sse2(d_metric0, d_path0, d_ntraceback, &c);
|
||||
viterbi_get_output_sse2(d_metric0, d_path0, d_ntraceback, &c);
|
||||
|
||||
if (out_count >= d_ntraceback) {
|
||||
for (int i= 0; i < 8; i++) {
|
||||
d_decoded[(out_count - d_ntraceback) * 8 + i] = (c >> (7 - i)) & 0x1;
|
||||
n_decoded++;
|
||||
}
|
||||
}
|
||||
out_count++;
|
||||
}
|
||||
}
|
||||
in_count++;
|
||||
}
|
||||
if (out_count >= d_ntraceback) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
d_decoded[(out_count - d_ntraceback) * 8 + i] =
|
||||
(c >> (7 - i)) & 0x1;
|
||||
n_decoded++;
|
||||
}
|
||||
}
|
||||
out_count++;
|
||||
}
|
||||
}
|
||||
in_count++;
|
||||
}
|
||||
|
||||
return d_decoded;
|
||||
return d_decoded;
|
||||
}
|
||||
|
||||
void
|
||||
viterbi_decoder::reset() {
|
||||
void viterbi_decoder::reset()
|
||||
{
|
||||
|
||||
viterbi_chunks_init_sse2();
|
||||
viterbi_chunks_init_sse2();
|
||||
|
||||
switch(d_ofdm->encoding) {
|
||||
case BPSK_1_2:
|
||||
case QPSK_1_2:
|
||||
case QAM16_1_2:
|
||||
d_ntraceback = 5;
|
||||
d_depuncture_pattern = PUNCTURE_1_2;
|
||||
d_k = 1;
|
||||
break;
|
||||
case QAM64_2_3:
|
||||
d_ntraceback = 9;
|
||||
d_depuncture_pattern = PUNCTURE_2_3;
|
||||
d_k = 2;
|
||||
break;
|
||||
case BPSK_3_4:
|
||||
case QPSK_3_4:
|
||||
case QAM16_3_4:
|
||||
case QAM64_3_4:
|
||||
d_ntraceback = 10;
|
||||
d_depuncture_pattern = PUNCTURE_3_4;
|
||||
d_k = 3;
|
||||
break;
|
||||
}
|
||||
switch (d_ofdm->encoding) {
|
||||
case BPSK_1_2:
|
||||
case QPSK_1_2:
|
||||
case QAM16_1_2:
|
||||
d_ntraceback = 5;
|
||||
d_depuncture_pattern = PUNCTURE_1_2;
|
||||
d_k = 1;
|
||||
break;
|
||||
case QAM64_2_3:
|
||||
d_ntraceback = 9;
|
||||
d_depuncture_pattern = PUNCTURE_2_3;
|
||||
d_k = 2;
|
||||
break;
|
||||
case BPSK_3_4:
|
||||
case QPSK_3_4:
|
||||
case QAM16_3_4:
|
||||
case QAM64_3_4:
|
||||
d_ntraceback = 10;
|
||||
d_depuncture_pattern = PUNCTURE_3_4;
|
||||
d_k = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize starting metrics to prefer 0 state
|
||||
void
|
||||
viterbi_decoder::viterbi_chunks_init_sse2() {
|
||||
int i, j;
|
||||
void viterbi_decoder::viterbi_chunks_init_sse2()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
d_metric0[i] = _mm_setzero_si128();
|
||||
d_path0[i] = _mm_setzero_si128();
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
d_metric0[i] = _mm_setzero_si128();
|
||||
d_path0[i] = _mm_setzero_si128();
|
||||
}
|
||||
|
||||
int polys[2] = { 0x6d, 0x4f };
|
||||
for(i=0; i < 32; i++) {
|
||||
d_branchtab27_sse2[0].c[i] = (polys[0] < 0) ^ PARTAB[(2*i) & abs(polys[0])] ? 1 : 0;
|
||||
d_branchtab27_sse2[1].c[i] = (polys[1] < 0) ^ PARTAB[(2*i) & abs(polys[1])] ? 1 : 0;
|
||||
}
|
||||
int polys[2] = { 0x6d, 0x4f };
|
||||
for (i = 0; i < 32; i++) {
|
||||
d_branchtab27_sse2[0].c[i] =
|
||||
(polys[0] < 0) ^ PARTAB[(2 * i) & abs(polys[0])] ? 1 : 0;
|
||||
d_branchtab27_sse2[1].c[i] =
|
||||
(polys[1] < 0) ^ PARTAB[(2 * i) & abs(polys[1])] ? 1 : 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
d_mmresult[i] = 0;
|
||||
for (j = 0; j < TRACEBACK_MAX; j++) {
|
||||
d_ppresult[j][i] = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 64; i++) {
|
||||
d_mmresult[i] = 0;
|
||||
for (j = 0; j < TRACEBACK_MAX; j++) {
|
||||
d_ppresult[j][i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#ifndef INCLUDED_IEEE802_11_VITERBI_DECODER_X86_H
|
||||
#define INCLUDED_IEEE802_11_VITERBI_DECODER_X86_H
|
||||
|
||||
#include <xmmintrin.h>
|
||||
#include "base.h"
|
||||
#include <xmmintrin.h>
|
||||
|
||||
namespace gr {
|
||||
namespace ieee802_11 {
|
||||
@@ -31,28 +31,28 @@ namespace ieee802_11 {
|
||||
class viterbi_decoder : public base
|
||||
{
|
||||
public:
|
||||
|
||||
virtual uint8_t* decode(ofdm_param *ofdm, frame_param *frame, uint8_t *in);
|
||||
virtual uint8_t* decode(ofdm_param* ofdm, frame_param* frame, uint8_t* in);
|
||||
|
||||
private:
|
||||
union branchtab27 {
|
||||
unsigned char c[32];
|
||||
__m128i v[2];
|
||||
} d_branchtab27_sse2[2];
|
||||
|
||||
union branchtab27 {
|
||||
unsigned char c[32];
|
||||
__m128i v[2];
|
||||
} d_branchtab27_sse2[2];
|
||||
__m128i d_metric0[4] __attribute__((aligned(16)));
|
||||
__m128i d_metric1[4] __attribute__((aligned(16)));
|
||||
__m128i d_path0[4] __attribute__((aligned(16)));
|
||||
__m128i d_path1[4] __attribute__((aligned(16)));
|
||||
|
||||
__m128i d_metric0[4] __attribute__ ((aligned(16)));
|
||||
__m128i d_metric1[4] __attribute__ ((aligned(16)));
|
||||
__m128i d_path0[4] __attribute__ ((aligned(16)));
|
||||
__m128i d_path1[4] __attribute__ ((aligned(16)));
|
||||
virtual void reset();
|
||||
|
||||
virtual void reset();
|
||||
|
||||
void viterbi_chunks_init_sse2();
|
||||
void viterbi_butterfly2_sse2(unsigned char *symbols,
|
||||
__m128i m0[], __m128i m1[], __m128i p0[], __m128i p1[]);
|
||||
unsigned char viterbi_get_output_sse2(__m128i *mm0,
|
||||
__m128i *pp0, int ntraceback, unsigned char *outbuf);
|
||||
void viterbi_chunks_init_sse2();
|
||||
void viterbi_butterfly2_sse2(
|
||||
unsigned char* symbols, __m128i m0[], __m128i m1[], __m128i p0[], __m128i p1[]);
|
||||
unsigned char viterbi_get_output_sse2(__m128i* mm0,
|
||||
__m128i* pp0,
|
||||
int ntraceback,
|
||||
unsigned char* outbuf);
|
||||
};
|
||||
|
||||
} // namespace ieee802_11
|
||||
|
||||
Reference in New Issue
Block a user