Everything changed.
* Rewrote preamble detector. Uses integrate-and-dump along with correlator to perform optimal receive. * No longer using framer. Determining packet length via header. Missing some anti-FRUIT stuff. * Pulled out the slicer logic into its own function. Lots of todos and fixmes.
This commit is contained in:
parent
c8dce82b75
commit
8b1c1791c7
@ -60,8 +60,8 @@ int air_modes_framer::work(int noutput_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
//do things!
|
||||
const float *inraw = (const float *) input_items[0];
|
||||
float *outraw = (float *) output_items[0];
|
||||
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;
|
||||
@ -73,7 +73,7 @@ int air_modes_framer::work(int noutput_items,
|
||||
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(outraw, inraw, size * sizeof(float));
|
||||
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;
|
||||
@ -81,18 +81,18 @@ int air_modes_framer::work(int noutput_items,
|
||||
packet_attrib = Long_Packet;
|
||||
|
||||
//let's use the preamble marker to get a reference level for the packet
|
||||
reference_level = (inraw[i]
|
||||
+ inraw[i+int(1.0*d_samples_per_symbol)]
|
||||
+ inraw[i+int(3.5*d_samples_per_symbol)]
|
||||
+ inraw[i+int(4.5*d_samples_per_symbol)]) / 4;
|
||||
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(inraw[i+j],
|
||||
inraw[i+j+d_samples_per_chip]
|
||||
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;
|
||||
}
|
||||
@ -114,7 +114,7 @@ int air_modes_framer::work(int noutput_items,
|
||||
//insert tag here
|
||||
add_item_tag(0, //stream ID
|
||||
nitems_written(0)+i, //sample
|
||||
d_key, //preamble_found
|
||||
d_key, //frame_info
|
||||
pmt::pmt_from_long((long)packet_attrib),
|
||||
d_me //block src id
|
||||
);
|
||||
|
@ -35,17 +35,19 @@ air_modes_preamble_sptr air_make_modes_preamble(int channel_rate, float threshol
|
||||
}
|
||||
|
||||
air_modes_preamble::air_modes_preamble(int channel_rate, float threshold_db) :
|
||||
gr_sync_block ("modes_preamble",
|
||||
gr_block ("modes_preamble",
|
||||
gr_make_io_signature2 (2, 2, sizeof(float), sizeof(float)), //stream 0 is received data, stream 1 is moving average for reference
|
||||
gr_make_io_signature (1, 1, sizeof(float))) //the original data. we pass it out in order to use tags.
|
||||
gr_make_io_signature (1, 1, sizeof(float))) //the output packets
|
||||
{
|
||||
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 = 7.5 * d_samples_per_symbol; //only search to this far from the end of the stream buffer
|
||||
d_check_width = 120 * d_samples_per_symbol; //only search to this far from the end of the stream buffer
|
||||
d_threshold_db = threshold_db;
|
||||
d_threshold = powf(10., threshold_db/10.); //the level that the sample must be above the moving average in order to qualify as a pulse
|
||||
|
||||
set_output_multiple(1+d_check_width*2);
|
||||
|
||||
std::stringstream str;
|
||||
str << name() << unique_id();
|
||||
d_me = pmt::pmt_string_to_symbol(str.str());
|
||||
@ -59,111 +61,110 @@ static int early_late(const float *data) {
|
||||
else return 0;
|
||||
}
|
||||
|
||||
int air_modes_preamble::work(int noutput_items,
|
||||
static void integrate_and_dump(float *out, const float *in, int chips, int samps_per_chip) {
|
||||
for(int i=0; i<chips; i++) {
|
||||
float acc = 0;
|
||||
for(int j=0; j<samps_per_chip; j++) {
|
||||
acc += in[i*samps_per_chip+j];
|
||||
}
|
||||
out[i] = acc/samps_per_chip;
|
||||
}
|
||||
}
|
||||
|
||||
//the preamble pattern in bits
|
||||
//fixme goes in .h
|
||||
static const bool preamble_bits[] = {1, 0, 1, 0, 0, 0, 0, 1, 0, 1};
|
||||
static double correlate_preamble(const float *in, int samples_per_chip) {
|
||||
double corr = 0.0;
|
||||
for(int i=0; i<10; i++) {
|
||||
for(int j=0; j<samples_per_chip;j++)
|
||||
if(preamble_bits[i]) corr += in[i*samples_per_chip+j];
|
||||
}
|
||||
return corr;
|
||||
}
|
||||
|
||||
int air_modes_preamble::general_work(int noutput_items,
|
||||
gr_vector_int &ninput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
//do things!
|
||||
const float *in = (const float *) input_items[0];
|
||||
const float *inavg = (const float *) input_items[1];
|
||||
|
||||
const int ninputs = std::min(ninput_items[0], ninput_items[1]); //just in case
|
||||
float *out = (float *) output_items[0];
|
||||
|
||||
int size = noutput_items;
|
||||
//fixme move into .h
|
||||
const int pulse_offsets[4] = {0,
|
||||
int(1.0 * d_samples_per_symbol),
|
||||
int(3.5 * d_samples_per_symbol),
|
||||
int(4.5 * d_samples_per_symbol)
|
||||
};
|
||||
|
||||
float preamble_pulses[4];
|
||||
|
||||
memcpy(out, in, size * sizeof(float));
|
||||
|
||||
uint64_t abs_out_sample_cnt = nitems_written(0);
|
||||
|
||||
for(int i = d_samples_per_chip; i < size; i++) {
|
||||
for(int i=0; i < ninputs; i++) {
|
||||
float pulse_threshold = inavg[i] * d_threshold;
|
||||
bool valid_preamble = false;
|
||||
float gate_sum_now = 0, gate_sum_early = 0, gate_sum_late = 0;
|
||||
if(in[i] > pulse_threshold) { //hey we got a candidate
|
||||
if(in[i+1] > in[i]) continue; //wait for the peak
|
||||
//check to see the rest of the pulses are there
|
||||
if( in[i+pulse_offsets[1]] < pulse_threshold ) continue;
|
||||
if( in[i+pulse_offsets[2]] < pulse_threshold ) continue;
|
||||
if( in[i+pulse_offsets[3]] < pulse_threshold ) continue;
|
||||
|
||||
if(in[i] > pulse_threshold) { //if the sample is greater than the reference level by the specified amount
|
||||
int gate_sum = early_late(&in[i]);
|
||||
if(gate_sum != 0) continue; //if either the early gate or the late gate had greater energy, keep moving.
|
||||
//the packets are so short we choose not to do any sort of closed-loop synchronization after this simple gating.
|
||||
//if we get a good center sample, the drift should be negligible.
|
||||
preamble_pulses[0] = in[i+pulse_offsets[0]];
|
||||
preamble_pulses[1] = in[i+pulse_offsets[1]];
|
||||
preamble_pulses[2] = in[i+pulse_offsets[2]];
|
||||
preamble_pulses[3] = in[i+pulse_offsets[3]];
|
||||
|
||||
//search for the rest of the pulses at their expected positions
|
||||
if( preamble_pulses[1] < pulse_threshold ) continue;
|
||||
if( preamble_pulses[2] < pulse_threshold ) continue;
|
||||
if( preamble_pulses[3] < pulse_threshold ) continue;
|
||||
|
||||
valid_preamble = true; //this gets falsified by the following statements to disqualify a preamble
|
||||
|
||||
float avgpeak = (preamble_pulses[0] + preamble_pulses[1] + preamble_pulses[2] + preamble_pulses[3]) / 4;
|
||||
|
||||
//set the threshold requirement for spaces (0 chips) to
|
||||
//threshold dB below the current peak
|
||||
float space_threshold = preamble_pulses[0] / d_threshold;
|
||||
//search between pulses and all the way out to 8.0us to make
|
||||
//sure there are no pulses inside the "0" chips. make sure
|
||||
//all the samples are <= (in[peak] * d_threshold).
|
||||
//so 0.5us has to be < space_threshold, as does (1.5-3), 4, (5-7.5) in order to qualify.
|
||||
for(int j = 1.5 * d_samples_per_symbol; j <= 3 * d_samples_per_symbol; j+=d_samples_per_chip)
|
||||
if(in[i+j] > space_threshold) valid_preamble = false;
|
||||
for(int j = 5 * d_samples_per_symbol; j <= 7.5 * d_samples_per_symbol; j+=d_samples_per_chip)
|
||||
if(in[i+j] > space_threshold) valid_preamble = false;
|
||||
|
||||
//make sure all four peaks are within 3dB of each other
|
||||
float minpeak = avgpeak * 0.5;//-3db, was 0.631; //-2db
|
||||
float maxpeak = avgpeak * 2.0;//3db, was 1.585; //2db
|
||||
|
||||
if(preamble_pulses[0] < minpeak || preamble_pulses[0] > maxpeak) continue;
|
||||
if(preamble_pulses[1] < minpeak || preamble_pulses[1] > maxpeak) continue;
|
||||
if(preamble_pulses[2] < minpeak || preamble_pulses[2] > maxpeak) continue;
|
||||
if(preamble_pulses[3] < minpeak || preamble_pulses[3] > maxpeak) continue;
|
||||
}
|
||||
|
||||
if(valid_preamble) {
|
||||
//get a more accurate chip center by finding the energy peak across all four preamble peaks
|
||||
//there's some weirdness in the early part, so i ripped it out.
|
||||
bool early, late;
|
||||
//get a more accurate bit center by finding the correlation peak across all four preamble bits
|
||||
bool late = false;
|
||||
do {
|
||||
early = late = false;
|
||||
//gate_sum_early= in[i+pulse_offsets[0]-1]
|
||||
// + in[i+pulse_offsets[1]-1]
|
||||
// + in[i+pulse_offsets[2]-1]
|
||||
// + in[i+pulse_offsets[3]-1];
|
||||
|
||||
gate_sum_now = in[i+pulse_offsets[0]]
|
||||
+ in[i+pulse_offsets[1]]
|
||||
+ in[i+pulse_offsets[2]]
|
||||
+ in[i+pulse_offsets[3]];
|
||||
|
||||
gate_sum_late = in[i+pulse_offsets[0]+1]
|
||||
+ in[i+pulse_offsets[1]+1]
|
||||
+ in[i+pulse_offsets[2]+1]
|
||||
+ in[i+pulse_offsets[3]+1];
|
||||
|
||||
early = (gate_sum_early > gate_sum_now);
|
||||
late = (gate_sum_late > gate_sum_now);
|
||||
double now_corr = correlate_preamble(in+i, d_samples_per_chip);
|
||||
double late_corr = correlate_preamble(in+i+1, d_samples_per_chip);
|
||||
late = (late_corr > now_corr);
|
||||
if(late) i++;
|
||||
//else if(early) i--;
|
||||
//if(early && late) early = late = false;
|
||||
} while(late);
|
||||
|
||||
//finally after all this, let's post the preamble!
|
||||
//now check to see that the rest of the chips in the preamble
|
||||
//are below the peaks by threshold dB
|
||||
float avgpeak = ( in[i+pulse_offsets[0]]
|
||||
+ in[i+pulse_offsets[1]]
|
||||
+ in[i+pulse_offsets[2]]
|
||||
+ in[i+pulse_offsets[3]]) / 4.0;
|
||||
|
||||
float space_threshold = inavg[i] + (avgpeak - inavg[i])/d_threshold;
|
||||
bool valid_preamble = true; //f'in c++
|
||||
for( int j=1.5*d_samples_per_symbol; j<=3*d_samples_per_symbol; j++)
|
||||
if(in[i+j] > space_threshold) valid_preamble = false;
|
||||
for( int j=5*d_samples_per_symbol; j<=7.5*d_samples_per_symbol; j++)
|
||||
if(in[i+j] > space_threshold) valid_preamble = false;
|
||||
if(!valid_preamble) continue;
|
||||
|
||||
//be sure we've got enough room in the input buffer to copy out a whole packet
|
||||
if(ninputs-i < 240*d_samples_per_chip) {
|
||||
consume_each(i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//all right i'm prepared to call this a preamble
|
||||
//let's integrate and dump the output
|
||||
i -= d_samples_per_chip-1;
|
||||
integrate_and_dump(out, &in[i], 240, d_samples_per_chip);
|
||||
// out[0] = 1.0; //for debug
|
||||
// out[1] = out[2] = out[3] = out[4] = avgpeak;
|
||||
// out[5] = out[6] = out[7] = out[8] = space_threshold;
|
||||
// out[9] = 0.0;
|
||||
|
||||
//now tag the preamble
|
||||
add_item_tag(0, //stream ID
|
||||
nitems_written(0)+i, //sample
|
||||
d_key, //preamble_found
|
||||
pmt::PMT_T, //meaningless for us
|
||||
d_me //block src id
|
||||
);
|
||||
nitems_written(0), //sample
|
||||
d_key, //frame_info
|
||||
pmt::pmt_from_double((double) space_threshold),
|
||||
d_me //block src id
|
||||
);
|
||||
|
||||
//produce only one output per work call
|
||||
consume_each(i+240*d_samples_per_chip);
|
||||
return 240; //fixme debug should be 240
|
||||
}
|
||||
}
|
||||
return size;
|
||||
|
||||
//didn't get anything this time
|
||||
consume_each(ninputs);
|
||||
return 0;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
#ifndef INCLUDED_AIR_MODES_PREAMBLE_H
|
||||
#define INCLUDED_AIR_MODES_PREAMBLE_H
|
||||
|
||||
#include <gr_sync_block.h>
|
||||
#include <gr_block.h>
|
||||
|
||||
class air_modes_preamble;
|
||||
typedef boost::shared_ptr<air_modes_preamble> air_modes_preamble_sptr;
|
||||
@ -34,7 +34,7 @@ air_modes_preamble_sptr air_make_modes_preamble(int channel_rate, float threshol
|
||||
* \brief mode select preamble detection
|
||||
* \ingroup block
|
||||
*/
|
||||
class air_modes_preamble : public gr_sync_block
|
||||
class air_modes_preamble : public gr_block
|
||||
{
|
||||
private:
|
||||
friend air_modes_preamble_sptr air_make_modes_preamble(int channel_rate, float threshold_db);
|
||||
@ -50,7 +50,8 @@ private:
|
||||
pmt::pmt_t d_me, d_key;
|
||||
|
||||
public:
|
||||
int work (int noutput_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);
|
||||
};
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <iomanip>
|
||||
#include <modes_parity.h>
|
||||
#include <gr_tag_info.h>
|
||||
#include <iostream>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@ -50,7 +51,7 @@ air_modes_slicer::air_modes_slicer(int channel_rate, gr_msg_queue_sptr queue) :
|
||||
{
|
||||
//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_chip = 2;//FIXME this is constant now channel_rate / d_chip_rate;
|
||||
d_samples_per_symbol = d_samples_per_chip * 2;
|
||||
d_check_width = 120 * d_samples_per_symbol; //how far you will have to look ahead
|
||||
d_queue = queue;
|
||||
@ -66,6 +67,44 @@ static bool pmtcompare(pmt::pmt_t x, pmt::pmt_t y)
|
||||
t_y = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(y, 0));
|
||||
return t_x < t_y;
|
||||
}
|
||||
|
||||
//this slicer is courtesy of Lincoln Labs. supposedly it is more resistant to mode A/C FRUIT.
|
||||
//see http://adsb.tc.faa.gov/WG3_Meetings/Meeting8/Squitter-Lon.pdf
|
||||
static bool slicer(const float bit0, const float bit1, const float ref) {
|
||||
bool slice, confidence;
|
||||
|
||||
//3dB limits for bit slicing and confidence measurement
|
||||
float highlimit=ref*2;
|
||||
float lowlimit=ref*0.5;
|
||||
|
||||
bool firstchip_inref = ((bit0 > lowlimit) && (bit0 < highlimit));
|
||||
bool secondchip_inref = ((bit1 > lowlimit) && (bit1 < highlimit));
|
||||
|
||||
if(firstchip_inref && !secondchip_inref) {
|
||||
slice = 1;
|
||||
confidence = 1;
|
||||
}
|
||||
else if(secondchip_inref && !firstchip_inref) {
|
||||
slice = 0;
|
||||
confidence = 1;
|
||||
}
|
||||
else if(firstchip_inref && secondchip_inref) {
|
||||
slice = bit0 > bit1;
|
||||
confidence = 0;
|
||||
}
|
||||
else if(!firstchip_inref && !secondchip_inref) { //in this case, we determine the bit by whichever is larger, and we determine high confidence if the low chip is 6dB below reference.
|
||||
slice = bit0 > bit1;
|
||||
if(slice) {
|
||||
if(bit1 < lowlimit * 0.5) confidence = 1;
|
||||
else confidence = 0;
|
||||
} else {
|
||||
if(bit0 < lowlimit * 0.5) confidence = 1;
|
||||
else confidence = 0;
|
||||
}
|
||||
}
|
||||
return slice;
|
||||
}
|
||||
|
||||
/*
|
||||
static double pmt_to_timestamp(pmt::pmt_t tstamp, uint64_t sample_cnt, double secs_per_sample) {
|
||||
double frac;
|
||||
@ -85,92 +124,63 @@ int air_modes_slicer::work(int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
//do things!
|
||||
const float *inraw = (const float *) input_items[0];
|
||||
const float *in = (const float *) input_items[0];
|
||||
int size = noutput_items - d_check_width; //since it's a sync block, i assume that it runs with ninput_items = noutput_items
|
||||
|
||||
int i;
|
||||
|
||||
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("frame_info"));
|
||||
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;
|
||||
|
||||
for(tag_iter = tags.begin(); tag_iter != tags.end(); tag_iter++) {
|
||||
uint64_t i = gr_tags::get_nitems(*tag_iter) - abs_sample_cnt;
|
||||
modes_packet rx_packet;
|
||||
framer_packet_type packet_type = framer_packet_type(pmt::pmt_to_long(gr_tags::get_value(*tag_iter)));
|
||||
|
||||
int packet_length;
|
||||
packet_length = packet_type == framer_packet_type(Short_Packet) ? 56 : 112;
|
||||
|
||||
rx_packet.type = packet_type;
|
||||
memset(&rx_packet.data, 0x00, 14 * sizeof(unsigned char));
|
||||
memset(&rx_packet.lowconfbits, 0x00, 24 * sizeof(unsigned char));
|
||||
rx_packet.numlowconf = 0;
|
||||
|
||||
//let's use the preamble marker to get a reference level for the packet
|
||||
rx_packet.reference_level = (inraw[i]
|
||||
+ inraw[i+int(1.0*d_samples_per_symbol)]
|
||||
+ inraw[i+int(3.5*d_samples_per_symbol)]
|
||||
+ inraw[i+int(4.5*d_samples_per_symbol)]) / 4;
|
||||
//let's use the preamble to get a reference level for the packet
|
||||
//fixme: a better thing to do is create a bi-level avg 1 and avg 0
|
||||
//through simple statistics, then take the median for your slice level
|
||||
//this won't improve decoding but will improve confidence
|
||||
rx_packet.reference_level = (in[i]
|
||||
+ in[i+2]
|
||||
+ in[i+7]
|
||||
+ in[i+9]) / 4.0;
|
||||
|
||||
i += 8 * d_samples_per_symbol; //move to the center of the first bit of the data
|
||||
i += 16; //move on up to the first bit of the packet data
|
||||
//now let's slice the header so we can determine if it's a short pkt or a long pkt
|
||||
unsigned char pkt_hdr = 0;
|
||||
for(int j=0; j < 5; j++) {
|
||||
bool slice = slicer(in[i+j*2], in[i+j*2+1], rx_packet.reference_level);
|
||||
if(slice) pkt_hdr += 1 << (4-j);
|
||||
}
|
||||
//std::cout << "SLICER: TYPE " << int(pkt_hdr) << std::endl;
|
||||
|
||||
//here we calculate the total energy contained in each chip of the symbol
|
||||
if(pkt_hdr == 17) rx_packet.type = Long_Packet;
|
||||
else rx_packet.type = Short_Packet;
|
||||
|
||||
int packet_length;
|
||||
packet_length = (rx_packet.type == framer_packet_type(Short_Packet)) ? 56 : 112;
|
||||
|
||||
//it's slice time!
|
||||
//TODO: don't repeat your work here, you already have the first 5 bits
|
||||
for(int j = 0; j < packet_length; j++) {
|
||||
int firstchip = i+j*d_samples_per_symbol;
|
||||
int secondchip = firstchip + d_samples_per_chip;
|
||||
bool slice, confidence;
|
||||
float firstchip_energy=0, secondchip_energy=0;
|
||||
bool slice = slicer(in[i+j*2], in[i+j*2+1], rx_packet.reference_level);
|
||||
|
||||
firstchip_energy = inraw[firstchip];
|
||||
secondchip_energy = inraw[secondchip];
|
||||
|
||||
//3dB limits for bit slicing and confidence measurement
|
||||
float highlimit=rx_packet.reference_level*2;
|
||||
float lowlimit=rx_packet.reference_level*0.5;
|
||||
bool firstchip_inref = ((firstchip_energy > lowlimit) && (firstchip_energy < highlimit));
|
||||
bool secondchip_inref = ((secondchip_energy > lowlimit) && (secondchip_energy < highlimit));
|
||||
|
||||
//these two lines for a super simple naive slicer.
|
||||
// slice = firstchip_energy > secondchip_energy;
|
||||
// confidence = bool(int(firstchip_inref) + int(secondchip_inref)); //one and only one chip in the reference zone
|
||||
|
||||
//below is the Lincoln Labs slicer. it may produce greater bit errors. supposedly it is more resistant to mode A/C FRUIT.
|
||||
//see http://adsb.tc.faa.gov/WG3_Meetings/Meeting8/Squitter-Lon.pdf
|
||||
if(firstchip_inref && !secondchip_inref) {
|
||||
slice = 1;
|
||||
confidence = 1;
|
||||
}
|
||||
else if(secondchip_inref && !firstchip_inref) {
|
||||
slice = 0;
|
||||
confidence = 1;
|
||||
}
|
||||
else if(firstchip_inref && secondchip_inref) {
|
||||
slice = firstchip_energy > secondchip_energy;
|
||||
confidence = 0;
|
||||
}
|
||||
else if(!firstchip_inref && !secondchip_inref) { //in this case, we determine the bit by whichever is larger, and we determine high confidence if the low chip is 6dB below reference.
|
||||
slice = firstchip_energy > secondchip_energy;
|
||||
if(slice) {
|
||||
if(secondchip_energy < lowlimit * 0.5) confidence = 1;
|
||||
else confidence = 0;
|
||||
} else {
|
||||
if(firstchip_energy < lowlimit * 0.5) confidence = 1;
|
||||
else confidence = 0;
|
||||
}
|
||||
}
|
||||
//put the data into the packet
|
||||
//put the data into the packet
|
||||
if(slice) {
|
||||
rx_packet.data[j/8] += 1 << (7-(j%8));
|
||||
}
|
||||
//put the confidence decision into the packet
|
||||
if(confidence) {
|
||||
// if(confidence) {
|
||||
//rx_packet.confidence[j/8] += 1 << (7-(j%8));
|
||||
} else {
|
||||
if(rx_packet.numlowconf < 24) rx_packet.lowconfbits[rx_packet.numlowconf++] = j;
|
||||
}
|
||||
// } else {
|
||||
// if(rx_packet.numlowconf < 24) rx_packet.lowconfbits[rx_packet.numlowconf++] = j;
|
||||
// }
|
||||
}
|
||||
|
||||
/******************** BEGIN TIMESTAMP BS ******************/
|
||||
|
@ -19,9 +19,9 @@
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
#my_position = [37.76225, -122.44254]
|
||||
my_position = [37.76225, -122.44254]
|
||||
#my_position = [37.409066,-122.077836]
|
||||
my_position = None
|
||||
#my_position = None
|
||||
|
||||
from gnuradio import gr, gru, optfir, eng_notation, blks2, air
|
||||
from gnuradio import uhd
|
||||
@ -92,32 +92,21 @@ class adsb_rx_block (gr.top_block):
|
||||
|
||||
#the DBSRX especially tends to be spur-prone; the LPF keeps out the
|
||||
#spur multiple that shows up at 2MHz
|
||||
# self.filtcoeffs = gr.firdes.low_pass(1, rate, 1.8e6, 200e3)
|
||||
# self.filter = gr.fir_filter_fff(1, self.filtcoeffs)
|
||||
#self.lpfiltcoeffs = gr.firdes.low_pass(1, rate, 1.8e6, 200e3)
|
||||
#self.lpfilter = gr.fir_filter_fff(1, self.lpfiltcoeffs)
|
||||
|
||||
#this is an integrate-and-dump filter to act as a matched filter
|
||||
#for the essentially rectangular Mode S pulses.
|
||||
#if a particular Mode S transponder is using a pulse shaping filter,
|
||||
#this will not be optimal.
|
||||
self.filtcoeffs = list()
|
||||
for i in range(int(rate/4e6)):
|
||||
self.filtcoeffs.append(1.0 / (rate/4e6))
|
||||
|
||||
#i think downstream blocks can therefore process at 2Msps -- try this
|
||||
#self.filter = gr.fir_filter_fff(int(rate/2e6), self.filtcoeffs)
|
||||
self.filter = gr.fir_filter_fff(1, self.filtcoeffs)
|
||||
#rate = int(2e6)
|
||||
|
||||
self.preamble = air.modes_preamble(rate, options.threshold)
|
||||
self.framer = air.modes_framer(rate)
|
||||
#self.framer = air.modes_framer(rate)
|
||||
self.slicer = air.modes_slicer(rate, queue)
|
||||
|
||||
self.connect(self.u, self.demod, self.filter)
|
||||
self.connect(self.filter, self.avg)
|
||||
self.connect(self.filter, (self.preamble, 0))
|
||||
self.connect(self.u, self.demod)
|
||||
self.connect(self.demod, self.avg)
|
||||
self.connect(self.demod, (self.preamble, 0))
|
||||
self.connect(self.avg, (self.preamble, 1))
|
||||
self.connect((self.preamble, 0), (self.framer, 0))
|
||||
self.connect(self.framer, self.slicer)
|
||||
self.connect((self.preamble, 0), (self.slicer, 0))
|
||||
|
||||
def tune(self, freq):
|
||||
result = self.u.set_center_freq(freq, 0)
|
||||
|
Loading…
Reference in New Issue
Block a user