pull the framer out, remove the brute forcer
This commit is contained in:
parent
87444eb980
commit
08730769dc
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
@ -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 */
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user