pull the framer out, remove the brute forcer

This commit is contained in:
Nick Foster 2011-06-12 00:59:41 -07:00
parent 87444eb980
commit 08730769dc
6 changed files with 1 additions and 275 deletions

View File

@ -24,7 +24,6 @@ include $(top_srcdir)/Makefile.common
# C/C++ headers get installed in ${prefix}/include/gnuradio
grinclude_HEADERS = \
air_modes_preamble.h \
air_modes_framer.h \
air_modes_slicer.h \
air_modes_types.h \
modes_parity.h
@ -49,7 +48,6 @@ air_pythondir_category = \
# additional sources for the SWIG-generated library
air_la_swig_sources = \
air_modes_preamble.cc \
air_modes_framer.cc \
air_modes_slicer.cc \
modes_parity.cc

View File

@ -4,7 +4,6 @@
%{
#include "air_modes_preamble.h"
#include "air_modes_framer.h"
#include "air_modes_slicer.h"
#include <gr_msg_queue.h>
%}
@ -28,16 +27,6 @@ private:
air_modes_preamble (int channel_rate, float threshold_db);
};
GR_SWIG_BLOCK_MAGIC(air,modes_framer);
air_modes_framer_sptr air_make_modes_framer (int channel_rate);
class air_modes_framer : public gr_sync_block
{
private:
air_modes_framer (int channel_rate);
};
GR_SWIG_BLOCK_MAGIC(air,modes_slicer);
air_modes_slicer_sptr air_make_modes_slicer (int channel_rate, gr_msg_queue_sptr queue);

View File

@ -1,124 +0,0 @@
/*
# Copyright 2010 Nick Foster
#
# This file is part of gr-air-modes
#
# gr-air-modes is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# gr-air-modes is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gr-air-modes; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <air_modes_framer.h>
#include <gr_io_signature.h>
#include <air_modes_types.h>
#include <gr_tag_info.h>
#include <iostream>
#include <string.h>
air_modes_framer_sptr air_make_modes_framer(int channel_rate)
{
return air_modes_framer_sptr (new air_modes_framer(channel_rate));
}
air_modes_framer::air_modes_framer(int channel_rate) :
gr_sync_block ("modes_framer",
gr_make_io_signature (1, 1, sizeof(float)), //stream 0 is received data
gr_make_io_signature (1, 1, sizeof(float))) //raw samples passed back out
{
//initialize private data here
d_chip_rate = 2000000; //2Mchips per second
d_samples_per_chip = channel_rate / d_chip_rate; //must be integer number of samples per chip to work
d_samples_per_symbol = d_samples_per_chip * 2;
d_check_width = 120 * d_samples_per_symbol; //gotta be able to look at two long frame lengths at a time
//in the event that FRUIT occurs near the end of the first frame
//set_history(d_check_width*2);
std::stringstream str;
str << name() << unique_id();
d_me = pmt::pmt_string_to_symbol(str.str());
d_key = pmt::pmt_string_to_symbol("frame_info");
}
int air_modes_framer::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
//do things!
const float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];
//unsigned char *outattrib = (unsigned char *) output_items[0];
int size = noutput_items - d_check_width*2;
if(size < 0) return 0;
float reference_level;
framer_packet_type packet_attrib;
std::vector<pmt::pmt_t> tags;
uint64_t abs_sample_cnt = nitems_read(0);
get_tags_in_range(tags, 0, abs_sample_cnt, abs_sample_cnt + size, pmt::pmt_string_to_symbol("preamble_found"));
std::vector<pmt::pmt_t>::iterator tag_iter;
memcpy(out, in, size * sizeof(float));
for(tag_iter = tags.begin(); tag_iter != tags.end(); tag_iter++) {
uint64_t i = gr_tags::get_nitems(*tag_iter) - abs_sample_cnt;
//first, assume we have a long packet
packet_attrib = Long_Packet;
//let's use the preamble marker to get a reference level for the packet
reference_level = (in[i]
+ in[i+2]
+ in[i+7]
+ in[i+9]) / 4.0;
//armed with our reference level, let's look for marks within 3dB of the reference level in bits 57-62 (65-70, see above)
//if bits 57-62 have marks in either chip, we've got a long packet
//otherwise we have a short packet
//NOTE: you can change the default here to be short packet, and then check for a long packet. don't know which way is better.
for(int j = (65 * d_samples_per_symbol); j < (70 * d_samples_per_symbol); j += d_samples_per_symbol) {
float t_max = std::max(in[i+j],
in[i+j+d_samples_per_chip]
);
if(t_max < (reference_level / 2.0)) packet_attrib = Short_Packet;
}
//BUT: we must also loop through the entire packet to make sure it is clear of additional preamble markers!
//if it has another preamble marker, it's been FRUITed, and we must only
//mark the new packet (i.e., just continue).
int lookahead;
if(packet_attrib == Long_Packet) lookahead = 112 * d_samples_per_symbol;
else lookahead = 56 * d_samples_per_symbol;
//ok we have to re-do lookahead for this tagged version.
//we can do this by looking for tags that fall within that window
std::vector<pmt::pmt_t> fruit_tags;
get_tags_in_range(fruit_tags, 0, abs_sample_cnt+i+1, abs_sample_cnt+i+lookahead, pmt::pmt_string_to_symbol("preamble_found"));
if(fruit_tags.size() > 0) packet_attrib = Fruited_Packet;
//insert tag here
add_item_tag(0, //stream ID
nitems_written(0)+i, //sample
d_key, //frame_info
pmt::pmt_from_long((long)packet_attrib),
d_me //block src id
);
}
return size;
}

View File

@ -1,56 +0,0 @@
/*
# Copyright 2010 Nick Foster
#
# This file is part of gr-air-modes
#
# gr-air-modes is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
#
# gr-air-modes is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gr-air-modes; see the file COPYING. If not, write to
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
#
*/
#ifndef INCLUDED_AIR_MODES_FRAMER_H
#define INCLUDED_AIR_MODES_FRAMER_H
#include <gr_sync_block.h>
class air_modes_framer;
typedef boost::shared_ptr<air_modes_framer> air_modes_framer_sptr;
air_modes_framer_sptr air_make_modes_framer(int channel_rate);
/*!
* \brief mode select framer detection
* \ingroup block
*/
class air_modes_framer : public gr_sync_block
{
private:
friend air_modes_framer_sptr air_make_modes_framer(int channel_rate);
air_modes_framer(int channel_rate);
int d_check_width;
int d_chip_rate;
int d_samples_per_chip;
int d_samples_per_symbol;
pmt::pmt_t d_me, d_key;
public:
int work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
#endif /* INCLUDED_AIR_MODES_framer_H */

View File

@ -212,7 +212,7 @@ int air_modes_slicer::work(int noutput_items,
rx_packet.message_type = (rx_packet.data[0] >> 3) & 0x1F; //get the message type for the parser to conveniently use, and to make decisions on ECC methods
if(rx_packet.type == Short_Packet && rx_packet.message_type != 11 && rx_packet.numlowconf > 2) {n_loconf++; continue;}
if(rx_packet.type == Short_Packet && rx_packet.message_type != 11 && rx_packet.numlowconf > 0) {n_loconf++; continue;}
if(rx_packet.message_type == 11 && rx_packet.numlowconf >= 10) {n_loconf++; continue;}
rx_packet.parity = modes_check_parity(rx_packet.data, packet_length);

View File

@ -176,84 +176,3 @@ int modes_check_parity(unsigned char data[], int length)
else return short_crc;
}
bruteResultTypeDef modes_ec_brute(modes_packet &err_packet)
{
//here we basically crib EC's air_ms_ec_brute algorithm, because wherever he got it, it's perfect, and that comparison thing is fast to boot.
//we assume that the syndrome result has already been calculated
//how many bits shall we attempt to flip? let's say a max of 8 bits, to start. remember we're only going after long packets here.
//well, in practice, you almost never successfully recover a packet with more than 4 LCBs. so let's put the limit there to save wasting CPU time
//on hopeless packets.
//want to speed things up? instead of going through the "search codes" in numeric order, let's find a way to order them probablistically.
//that is, right now, EC's algorithm uses a "search order" which starts with ALL possible low-confidence bits flipped, and goes down counting in binary.
//statistically it's far more likely that a single bit was flipped somewhere, so we should go through those codes first. THEN we move on to two bits flipped, and so on.
if(err_packet.parity == 0) return No_Error;
if(err_packet.numlowconf > 4) return Too_Many_LCBs;
if(err_packet.type != Long_Packet) return No_Solution;
unsigned crc;
unsigned answer;
unsigned found = 0;
//so in order for this to work, we need the positions of the LCBs. should we be calculating these as we go? ok, done.
unsigned lastone = (1 << err_packet.numlowconf) - 1;
// int numflipped; //for debugging
//here it would be a little faster if we ran through the parity table looking for single-bit errors. then we could start
//the loop at i=2 instead.
for(int i = 1; i <= err_packet.numlowconf; i++) {
unsigned j = (1 << i) - 1;
while(j < lastone) {
crc = 0;
//calc syndrome
for(int k = 0; k < err_packet.numlowconf; k++) {
if((j >> k) & 1) crc ^= modes_parity_table[err_packet.lowconfbits[k]];
}
//then test
if(crc == err_packet.parity) {
answer = j;
found++;
if(found > 1) break;
}
//then increment
j = next_set_of_n_elements(j);
}
if(found > 1) break;
}
if(found > 1) return Multiple_Solutions;
else if(found == 1) {
//fix the packet, verify the CRC, and return
//the bits that need to be flipped are in answer.
// numflipped=0; //just for debugging, so i can see
for(int i = 0; i < err_packet.numlowconf; i++) {
if( (answer >> i) & 1) {
// numflipped++;
unsigned mask = 1 << (7 - (err_packet.lowconfbits[i] % 8)); //create a bitmask
err_packet.data[err_packet.lowconfbits[i]/8] ^= mask; //flip the bit
}
}
//printf("Flipped %i bits\n", numflipped);
err_packet.parity = 0; //since you found it
return Solution_Found;
} else return No_Solution;
}
//from hackersdelight. given a number with x bits set, gives you the next number in that set.
unsigned next_set_of_n_elements(unsigned x)
{
unsigned smallest, ripple, new_smallest, ones;
if (x == 0) return 0;
smallest = (x & -x);
ripple = x + smallest;
new_smallest = (ripple & -ripple);
ones = ((new_smallest/smallest) >> 1) - 1;
return ripple | ones;
}