diff --git a/grc/ieee802_11_decode_mac.xml b/grc/ieee802_11_decode_mac.xml index 28b950d..c89b5a3 100644 --- a/grc/ieee802_11_decode_mac.xml +++ b/grc/ieee802_11_decode_mac.xml @@ -41,9 +41,8 @@ in - complex + byte 48 - 1 diff --git a/lib/decode_mac.cc b/lib/decode_mac.cc index 9d23f4e..448378e 100644 --- a/lib/decode_mac.cc +++ b/lib/decode_mac.cc @@ -17,58 +17,35 @@ #include #include "utils.h" +#include "viterbi_decoder.h" #include #include -#include -#include using namespace gr::ieee802_11; -using namespace itpp; 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 * sizeof(gr_complex)), +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_ofdm(BPSK_1_2), - d_frame(d_ofdm, 0), - d_frame_complete(true) { + d_log(log), + d_debug(debug), + d_snr(0), + d_ofdm(BPSK_1_2), + d_frame(d_ofdm, 0), + d_frame_complete(true) { message_port_register_out(pmt::mp("out")); - - // bpsk - int bpsk_bits[] = {0, 1}; - bpsk.set(cvec(BPSK_D, 2), ivec(bpsk_bits, 2)); - - // qpsk - int qpsk_bits[] = {0, 1, 2, 3}; - qpsk.set(cvec(QPSK_D, 4), ivec(qpsk_bits, 4)); - - // qam16 - int qam16_bits[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - qam16.set(cvec(QAM16_D, 16), ivec(qam16_bits, 16)); - - // qam64 - int qam64_bits[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63}; - qam64.set(cvec(QAM64_D, 64), ivec(qam64_bits, 64)); } 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 uint8_t *in = (const uint8_t*)input_items[0]; int i = 0; @@ -90,14 +67,15 @@ int general_work (int noutput_items, gr_vector_int& ninput_items, d_frame_complete = false; pmt::pmt_t tuple = tags[0].value; - int len_data = pmt::to_uint64(pmt::car(tuple)); - int encoding = pmt::to_uint64(pmt::cdr(tuple)); + int len_data = pmt::to_uint64(pmt::tuple_ref(tuple, 0)); + int encoding = pmt::to_uint64(pmt::tuple_ref(tuple, 1)); + d_snr = pmt::to_double(pmt::tuple_ref(tuple, 2)); ofdm_param ofdm = ofdm_param((Encoding)encoding); frame_param frame = frame_param(ofdm, len_data); - // sanity check, more than MAX_SYM may indicate garbage - if(frame.n_sym <= MAX_SYM && frame.n_encoded_bits <= MAX_BITS) { + // check for maximum frame size + if(frame.n_sym <= MAX_SYM && frame.psdu_size <= MAX_FRAME_SIZE) { d_ofdm = ofdm; d_frame = frame; copied = 0; @@ -111,7 +89,7 @@ int general_work (int noutput_items, gr_vector_int& ninput_items, if(copied < d_frame.n_sym) { dout << "copy one symbol, copied " << copied << " out of " << d_frame.n_sym << std::endl; - std::memcpy(sym + (copied * 48), in, 48 * sizeof(gr_complex)); + std::memcpy(d_rx_symbols + (copied * 48), in, 48); copied++; if(copied == d_frame.n_sym) { @@ -133,10 +111,16 @@ int general_work (int noutput_items, gr_vector_int& ninput_items, } void decode() { - demodulate(); + + 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(); - decode_conv(); - descramble(); + uint8_t *decoded = d_decoder.decode(&d_ofdm, &d_frame, d_deinterleaved_bits); + descramble(decoded); print_output(); // skip service field @@ -155,44 +139,10 @@ void decode() { 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)); message_port_pub(pmt::mp("out"), pmt::cons(dict, blob)); } -void demodulate() { - - cvec symbols; - symbols.set_length(d_frame.n_sym * 48); - for(int i = 0; i < d_frame.n_sym * 48; i++) { - symbols[i] = std::complex(sym[i]); - } - - switch(d_ofdm.encoding) { - case BPSK_1_2: - case BPSK_3_4: - - bits = to_vec(bpsk.demodulate_bits(symbols)); - break; - - case QPSK_1_2: - case QPSK_3_4: - - bits = to_vec(qpsk.demodulate_bits(symbols)); - break; - - case QAM16_1_2: - case QAM16_3_4: - bits = to_vec(qam16.demodulate_bits(symbols)); - break; - case QAM64_2_3: - case QAM64_3_4: - bits = to_vec(qam64.demodulate_bits(symbols)); - break; - } - - // I hate the guy who wrote itpp - bits = bits * (-2) + 1; -} - void deinterleave() { int n_cbps = d_ofdm.n_cbps; @@ -208,93 +158,50 @@ void deinterleave() { 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++) { - deinter[i * n_cbps + second[first[k]]] = bits[i * n_cbps + k]; + d_deinterleaved_bits[i * n_cbps + second[first[k]]] = d_rx_bits[i * n_cbps + k]; } } } -void decode_conv() { - Punctured_Convolutional_Code code; - ivec generator(2); - generator(0)=0133; - generator(1)=0171; - code.set_generator_polynomials(generator, 7); - bmat puncture_matrix; - switch(d_ofdm.encoding) { - case BPSK_1_2: - case QPSK_1_2: - case QAM16_1_2: - puncture_matrix = "1 1; 1 1"; - break; - case BPSK_3_4: - case QPSK_3_4: - case QAM16_3_4: - case QAM64_3_4: - puncture_matrix = "1 1 0; 1 0 1;"; - break; - case QAM64_2_3: - puncture_matrix = "1 1 1 1 1 1; 1 0 1 0 1 0;"; - break; - } - code.set_puncture_matrix(puncture_matrix); - code.set_truncation_length(30); +void descramble (uint8_t *decoded_bits) { - dout << "coding rate " << code.get_rate() << std::endl; - dout << d_frame.n_encoded_bits << std::endl; - - vec rx_signal(deinter, d_frame.n_encoded_bits); - - code.reset(); - decoded_bits.set_length(d_frame.n_encoded_bits); - code.decode_tail(rx_signal, decoded_bits); - - //dout << "length decoded " << decoded_bits.size() << std::endl; - //std::cout << decoded_bits << std::endl; -} - -void descramble () { int state = 0; + std::memset(out_bytes, 0, d_frame.n_data_bits/8 + 1); + for(int i = 0; i < 7; i++) { - if(decoded_bits(i)) { + if(decoded_bits[i]) { state |= 1 << (6 - i); } } + out_bytes[0] = state; int feedback; + int bit; - for(int i = 7; i < decoded_bits.size(); i++) { + for(int i = 7; i < d_frame.n_data_bits; i++) { feedback = ((!!(state & 64))) ^ (!!(state & 8)); - out_bits[i] = feedback ^ (int)decoded_bits(i); + bit = feedback ^ (decoded_bits[i] & 0x1); + out_bytes[i/8] |= bit << (i%8); state = ((state << 1) & 0x7e) | feedback; } - - for(int i = 0; i < decoded_bits.size(); i++) { - int bit = i % 8; - int byte = i / 8; - if(bit == 0) { - out_bytes[byte] = 0; - } - - if(out_bits[i]) { - out_bytes[byte] |= (1 << bit); - } - } } void print_output() { dout << std::endl; - for(int i = 0; i < decoded_bits.size() / 8; i++) { + dout << "psdu size" << d_frame.n_data_bits / 8 << std::endl; + for(int i = 0; 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 = 0; i < decoded_bits.size() / 8; i++) { + for(int i = 0; i < d_frame.n_data_bits / 8; i++) { if((out_bytes[i] > 31) && (out_bytes[i] < 127)) { dout << ((char) out_bytes[i]); } else { @@ -305,28 +212,24 @@ void print_output() { } private: - gr_complex sym[1000 * 48 * 100]; - vec bits; - double deinter[1000 * 48]; - char out_bits[40000]; - char out_bytes[40000]; - bvec decoded_bits; - bool d_debug; bool d_log; + frame_param d_frame; ofdm_param d_ofdm; + double d_snr; + 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_FRAME_SIZE]; + int copied; bool d_frame_complete; - - Modulator > bpsk; - Modulator > qpsk; - Modulator > qam16; - Modulator > qam64; }; decode_mac::sptr decode_mac::make(bool log, bool debug) { return gnuradio::get_initial_sptr(new decode_mac_impl(log, debug)); } - diff --git a/lib/mac.cc b/lib/mac.cc index 22359de..4cea55a 100644 --- a/lib/mac.cc +++ b/lib/mac.cc @@ -66,8 +66,9 @@ mac_impl(std::vector src_mac, std::vector dst_mac, std::vector void phy_in (pmt::pmt_t msg) { // this must be a pair - if (!pmt::is_blob(pmt::cdr(msg))) + 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 @@ -85,12 +86,7 @@ void app_in (pmt::pmt_t msg) { const char *msdu; std::string str; - if(pmt::is_eof_object(msg)) { - message_port_pub(pmt::mp("phy out"), pmt::PMT_EOF); - detail().get()->set_done(true); - return; - - } else if(pmt::is_symbol(msg)) { + if(pmt::is_symbol(msg)) { str = pmt::symbol_to_string(msg); msg_len = str.length(); @@ -103,10 +99,10 @@ void app_in (pmt::pmt_t msg) { } else { throw std::invalid_argument("MAC expects PDUs or strings"); - return; + return; } - if(msg_len > 1500) { + if(msg_len >= MAX_FRAME_SIZE - 32) { throw std::invalid_argument("Frame too large (> 1500)"); } diff --git a/lib/mapper.cc b/lib/mapper.cc index dc5c4b3..73b1c42 100644 --- a/lib/mapper.cc +++ b/lib/mapper.cc @@ -66,12 +66,11 @@ int general_work(int noutput, gr_vector_int& ninput_items, " length: " << d_symbols_len << std::endl; while(!d_symbols_offset) { - pmt::pmt_t msg(delete_head_blocking(pmt::intern("in"))); + pmt::pmt_t msg(delete_head_nowait(pmt::intern("in"))); - if(pmt::is_eof_object(msg)) { - dout << "MAPPER: exiting" << std::endl; - return -1; - } + if(!msg.get()) { + return 0; + } if(pmt::is_pair(msg)) { dout << "MAPPER: received new message" << std::endl; @@ -88,16 +87,15 @@ int general_work(int noutput, gr_vector_int& ninput_items, } //alloc memory for modulation steps - char *data_bits = (char*)calloc(frame.n_data, sizeof(char)); - char *scrambled_data = (char*)calloc(frame.n_data, sizeof(char)); - char *encoded_data = (char*)calloc(frame.n_data * 2, sizeof(char)); + 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); - //print_hex_array(data_bits, frame.n_data); // scrambling static uint8_t scrambler = 1; @@ -106,13 +104,10 @@ int general_work(int noutput, gr_vector_int& ninput_items, scrambler = 1; } - //print_hex_array(scrambled_data, frame.n_data); // reset tail bits reset_tail_bits(scrambled_data, frame); - //print_hex_array(scrambled_data, frame.n_data); // encoding convolutional_encoding(scrambled_data, encoded_data, frame); - //print_hex_array(encoded_data, frame.n_data * 2); // puncturing puncturing(encoded_data, punctured_data, frame, d_ofdm); //std::cout << "punctured" << std::endl; @@ -120,7 +115,7 @@ int general_work(int noutput, gr_vector_int& ninput_items, interleave(punctured_data, interleaved_data, frame, d_ofdm); //std::cout << "interleaved" << std::endl; - // one byte per symbol + // one byte per symbol split_symbols(interleaved_data, symbols, frame, d_ofdm); d_symbols_len = frame.n_sym * 48; diff --git a/lib/signal_field_impl.cc b/lib/signal_field_impl.cc index 92270dc..78d4c6b 100644 --- a/lib/signal_field_impl.cc +++ b/lib/signal_field_impl.cc @@ -88,14 +88,11 @@ void signal_field_impl::generate_signal_field(char *out, frame_param &frame, ofd } ofdm_param signal_ofdm(BPSK_1_2); - frame_param signal_param(signal_ofdm, 3); - signal_param.n_data = 24; - signal_param.n_sym = 1; + 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, interleaved_signal_header, signal_param, signal_ofdm); interleave(encoded_signal_header, out, signal_param, signal_ofdm); free(signal_header);