Re-tab air_modes_slicer.cc
This commit is contained in:
parent
640b13e62d
commit
e52e4039c0
@ -43,155 +43,155 @@ extern "C"
|
|||||||
|
|
||||||
air_modes_slicer_sptr air_make_modes_slicer(int channel_rate, gr::msg_queue::sptr queue)
|
air_modes_slicer_sptr air_make_modes_slicer(int channel_rate, gr::msg_queue::sptr queue)
|
||||||
{
|
{
|
||||||
return air_modes_slicer_sptr (new air_modes_slicer(channel_rate, queue));
|
return air_modes_slicer_sptr (new air_modes_slicer(channel_rate, queue));
|
||||||
}
|
}
|
||||||
|
|
||||||
air_modes_slicer::air_modes_slicer(int channel_rate, gr::msg_queue::sptr queue) :
|
air_modes_slicer::air_modes_slicer(int channel_rate, gr::msg_queue::sptr queue) :
|
||||||
gr::sync_block ("modes_slicer",
|
gr::sync_block ("modes_slicer",
|
||||||
gr::io_signature::make (1, 1, sizeof(float)), //stream 0 is received data, stream 1 is binary preamble detector output
|
gr::io_signature::make (1, 1, sizeof(float)), //stream 0 is received data, stream 1 is binary preamble detector output
|
||||||
gr::io_signature::make (0, 0, 0) )
|
gr::io_signature::make (0, 0, 0) )
|
||||||
{
|
{
|
||||||
//initialize private data here
|
//initialize private data here
|
||||||
d_chip_rate = 2000000; //2Mchips per second
|
d_chip_rate = 2000000; //2Mchips per second
|
||||||
d_samples_per_chip = 2;//FIXME this is constant now channel_rate / d_chip_rate;
|
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_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_check_width = 120 * d_samples_per_symbol; //how far you will have to look ahead
|
||||||
d_queue = queue;
|
d_queue = queue;
|
||||||
|
|
||||||
set_output_multiple(d_check_width*2); //how do you specify buffer size for sinks?
|
set_output_multiple(d_check_width*2); //how do you specify buffer size for sinks?
|
||||||
}
|
}
|
||||||
|
|
||||||
//this slicer is courtesy of Lincoln Labs. supposedly it is more resistant to mode A/C FRUIT.
|
//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
|
//see http://adsb.tc.faa.gov/WG3_Meetings/Meeting8/Squitter-Lon.pdf
|
||||||
static slice_result_t slicer(const float bit0, const float bit1, const float ref) {
|
static slice_result_t slicer(const float bit0, const float bit1, const float ref) {
|
||||||
slice_result_t result;
|
slice_result_t result;
|
||||||
|
|
||||||
//3dB limits for bit slicing and confidence measurement
|
//3dB limits for bit slicing and confidence measurement
|
||||||
float highlimit=ref*1.414;
|
float highlimit=ref*1.414;
|
||||||
float lowlimit=ref*0.707;
|
float lowlimit=ref*0.707;
|
||||||
|
|
||||||
bool firstchip_inref = ((bit0 > lowlimit) && (bit0 < highlimit));
|
bool firstchip_inref = ((bit0 > lowlimit) && (bit0 < highlimit));
|
||||||
bool secondchip_inref = ((bit1 > lowlimit) && (bit1 < highlimit));
|
bool secondchip_inref = ((bit1 > lowlimit) && (bit1 < highlimit));
|
||||||
|
|
||||||
if(firstchip_inref && !secondchip_inref) {
|
if(firstchip_inref && !secondchip_inref) {
|
||||||
result.decision = 1;
|
result.decision = 1;
|
||||||
result.confidence = 1;
|
result.confidence = 1;
|
||||||
}
|
}
|
||||||
else if(secondchip_inref && !firstchip_inref) {
|
else if(secondchip_inref && !firstchip_inref) {
|
||||||
result.decision = 0;
|
result.decision = 0;
|
||||||
result.confidence = 1;
|
result.confidence = 1;
|
||||||
}
|
}
|
||||||
else if(firstchip_inref && secondchip_inref) {
|
else if(firstchip_inref && secondchip_inref) {
|
||||||
result.decision = bit0 > bit1;
|
result.decision = bit0 > bit1;
|
||||||
result.confidence = 0;
|
result.confidence = 0;
|
||||||
}
|
}
|
||||||
else {//if(!firstchip_inref && !secondchip_inref) {
|
else {//if(!firstchip_inref && !secondchip_inref) {
|
||||||
result.decision = bit0 > bit1;
|
result.decision = bit0 > bit1;
|
||||||
if(result.decision) {
|
if(result.decision) {
|
||||||
if(bit1 < lowlimit * 0.5) result.confidence = 1;
|
if(bit1 < lowlimit * 0.5) result.confidence = 1;
|
||||||
else result.confidence = 0;
|
else result.confidence = 0;
|
||||||
} else {
|
} else {
|
||||||
if(bit0 < lowlimit * 0.5) result.confidence = 1;
|
if(bit0 < lowlimit * 0.5) result.confidence = 1;
|
||||||
else result.confidence = 0;
|
else result.confidence = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int air_modes_slicer::work(int noutput_items,
|
int air_modes_slicer::work(int noutput_items,
|
||||||
gr_vector_const_void_star &input_items,
|
gr_vector_const_void_star &input_items,
|
||||||
gr_vector_void_star &output_items)
|
gr_vector_void_star &output_items)
|
||||||
{
|
{
|
||||||
const float *in = (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 size = noutput_items - d_check_width; //since it's a sync block, i assume that it runs with ninput_items = noutput_items
|
||||||
|
|
||||||
if(0) std::cout << "Slicer called with " << size << " samples" << std::endl;
|
if(0) std::cout << "Slicer called with " << size << " samples" << std::endl;
|
||||||
|
|
||||||
std::vector<gr::tag_t> tags;
|
std::vector<gr::tag_t> tags;
|
||||||
uint64_t abs_sample_cnt = nitems_read(0);
|
uint64_t abs_sample_cnt = nitems_read(0);
|
||||||
get_tags_in_range(tags, 0, abs_sample_cnt, abs_sample_cnt + size, pmt::string_to_symbol("preamble_found"));
|
get_tags_in_range(tags, 0, abs_sample_cnt, abs_sample_cnt + size, pmt::string_to_symbol("preamble_found"));
|
||||||
std::vector<gr::tag_t>::iterator tag_iter;
|
std::vector<gr::tag_t>::iterator tag_iter;
|
||||||
|
|
||||||
for(tag_iter = tags.begin(); tag_iter != tags.end(); tag_iter++) {
|
for(tag_iter = tags.begin(); tag_iter != tags.end(); tag_iter++) {
|
||||||
uint64_t i = tag_iter->offset - abs_sample_cnt;
|
uint64_t i = tag_iter->offset - abs_sample_cnt;
|
||||||
modes_packet rx_packet;
|
modes_packet rx_packet;
|
||||||
|
|
||||||
memset(&rx_packet.data, 0x00, 14 * sizeof(unsigned char));
|
memset(&rx_packet.data, 0x00, 14 * sizeof(unsigned char));
|
||||||
memset(&rx_packet.lowconfbits, 0x00, 24 * sizeof(unsigned char));
|
memset(&rx_packet.lowconfbits, 0x00, 24 * sizeof(unsigned char));
|
||||||
rx_packet.numlowconf = 0;
|
rx_packet.numlowconf = 0;
|
||||||
|
|
||||||
//let's use the preamble to get a reference level for the packet
|
//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
|
//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
|
//through simple statistics, then take the median for your slice level
|
||||||
//this won't improve decoding but will improve confidence
|
//this won't improve decoding but will improve confidence
|
||||||
rx_packet.reference_level = (in[i]
|
rx_packet.reference_level = (in[i]
|
||||||
+ in[i+2]
|
+ in[i+2]
|
||||||
+ in[i+7]
|
+ in[i+7]
|
||||||
+ in[i+9]) / 4.0;
|
+ in[i+9]) / 4.0;
|
||||||
|
|
||||||
i += 16; //move on up to the first bit of the packet 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
|
//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;
|
unsigned char pkt_hdr = 0;
|
||||||
for(int j=0; j < 5; j++) {
|
for(int j=0; j < 5; j++) {
|
||||||
slice_result_t slice_result = slicer(in[i+j*2], in[i+j*2+1], rx_packet.reference_level);
|
slice_result_t slice_result = slicer(in[i+j*2], in[i+j*2+1], rx_packet.reference_level);
|
||||||
if(slice_result.decision) pkt_hdr += 1 << (4-j);
|
if(slice_result.decision) pkt_hdr += 1 << (4-j);
|
||||||
}
|
}
|
||||||
if(pkt_hdr == 16 or pkt_hdr == 17 or pkt_hdr == 20 or pkt_hdr == 21) rx_packet.type = Long_Packet;
|
if(pkt_hdr == 16 or pkt_hdr == 17 or pkt_hdr == 20 or pkt_hdr == 21) rx_packet.type = Long_Packet;
|
||||||
else rx_packet.type = Short_Packet;
|
else rx_packet.type = Short_Packet;
|
||||||
int packet_length = (rx_packet.type == framer_packet_type(Short_Packet)) ? 56 : 112;
|
int packet_length = (rx_packet.type == framer_packet_type(Short_Packet)) ? 56 : 112;
|
||||||
|
|
||||||
//it's slice time!
|
//it's slice time!
|
||||||
//TODO: don't repeat your work here, you already have the first 5 bits
|
//TODO: don't repeat your work here, you already have the first 5 bits
|
||||||
for(int j = 0; j < packet_length; j++) {
|
for(int j = 0; j < packet_length; j++) {
|
||||||
slice_result_t slice_result = slicer(in[i+j*2], in[i+j*2+1], rx_packet.reference_level);
|
slice_result_t slice_result = slicer(in[i+j*2], in[i+j*2+1], rx_packet.reference_level);
|
||||||
|
|
||||||
//put the data into the packet
|
//put the data into the packet
|
||||||
if(slice_result.decision) {
|
if(slice_result.decision) {
|
||||||
rx_packet.data[j/8] += 1 << (7-(j%8));
|
rx_packet.data[j/8] += 1 << (7-(j%8));
|
||||||
}
|
}
|
||||||
//put the confidence decision into the packet
|
//put the confidence decision into the packet
|
||||||
if(slice_result.confidence) {
|
if(slice_result.confidence) {
|
||||||
//rx_packet.confidence[j/8] += 1 << (7-(j%8));
|
//rx_packet.confidence[j/8] += 1 << (7-(j%8));
|
||||||
} else {
|
} else {
|
||||||
if(rx_packet.numlowconf < 24) rx_packet.lowconfbits[rx_packet.numlowconf++] = j;
|
if(rx_packet.numlowconf < 24) rx_packet.lowconfbits[rx_packet.numlowconf++] = j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************** BEGIN TIMESTAMP BS ******************/
|
/******************** BEGIN TIMESTAMP BS ******************/
|
||||||
rx_packet.timestamp = pmt::to_double(tag_iter->value);
|
rx_packet.timestamp = pmt::to_double(tag_iter->value);
|
||||||
/******************* END TIMESTAMP BS *********************/
|
/******************* END TIMESTAMP BS *********************/
|
||||||
|
|
||||||
//increment for the next round
|
//increment for the next round
|
||||||
|
|
||||||
//here you might want to traverse the whole packet and if you find all 0's, just toss it. don't know why these packets turn up, but they pass ECC.
|
//here you might want to traverse the whole packet and if you find all 0's, just toss it. don't know why these packets turn up, but they pass ECC.
|
||||||
bool zeroes = 1;
|
bool zeroes = 1;
|
||||||
for(int m = 0; m < 14; m++) {
|
for(int m = 0; m < 14; m++) {
|
||||||
if(rx_packet.data[m]) zeroes = 0;
|
if(rx_packet.data[m]) zeroes = 0;
|
||||||
}
|
}
|
||||||
if(zeroes) {continue;} //toss it
|
if(zeroes) {continue;} //toss it
|
||||||
|
|
||||||
rx_packet.message_type = (rx_packet.data[0] >> 3) & 0x1F; //get the message type to make decisions on ECC methods
|
rx_packet.message_type = (rx_packet.data[0] >> 3) & 0x1F; //get the message type to make decisions on ECC methods
|
||||||
|
|
||||||
if(rx_packet.type == Short_Packet && rx_packet.message_type != 11 && rx_packet.numlowconf > 0) {continue;}
|
if(rx_packet.type == Short_Packet && rx_packet.message_type != 11 && rx_packet.numlowconf > 0) {continue;}
|
||||||
if(rx_packet.message_type == 11 && rx_packet.numlowconf >= 10) {continue;}
|
if(rx_packet.message_type == 11 && rx_packet.numlowconf >= 10) {continue;}
|
||||||
|
|
||||||
rx_packet.crc = modes_check_crc(rx_packet.data, packet_length);
|
rx_packet.crc = modes_check_crc(rx_packet.data, packet_length);
|
||||||
|
|
||||||
//crc for packets that aren't type 11 or type 17 is encoded with the transponder ID, which we don't know
|
//crc for packets that aren't type 11 or type 17 is encoded with the transponder ID, which we don't know
|
||||||
//therefore we toss 'em if there's syndrome
|
//therefore we toss 'em if there's syndrome
|
||||||
//crc for the other short packets is usually nonzero, so they can't really be trusted that far
|
//crc for the other short packets is usually nonzero, so they can't really be trusted that far
|
||||||
if(rx_packet.crc && (rx_packet.message_type == 11 || rx_packet.message_type == 17)) {continue;}
|
if(rx_packet.crc && (rx_packet.message_type == 11 || rx_packet.message_type == 17)) {continue;}
|
||||||
|
|
||||||
d_payload.str("");
|
d_payload.str("");
|
||||||
for(int m = 0; m < packet_length/8; m++) {
|
for(int m = 0; m < packet_length/8; m++) {
|
||||||
d_payload << std::hex << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]);
|
d_payload << std::hex << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]);
|
||||||
}
|
}
|
||||||
|
|
||||||
d_payload << " " << std::setw(6) << rx_packet.crc << " " << std::dec << rx_packet.reference_level
|
d_payload << " " << std::setw(6) << rx_packet.crc << " " << std::dec << rx_packet.reference_level
|
||||||
<< " " << std::setprecision(10) << std::setw(10) << rx_packet.timestamp;
|
<< " " << std::setprecision(10) << std::setw(10) << rx_packet.timestamp;
|
||||||
gr::message::sptr msg = gr::message::make_from_string(std::string(d_payload.str()));
|
gr::message::sptr msg = gr::message::make_from_string(std::string(d_payload.str()));
|
||||||
d_queue->handle(msg);
|
d_queue->handle(msg);
|
||||||
}
|
}
|
||||||
if(0) std::cout << "Slicer consumed " << size << ", returned " << size << std::endl;
|
if(0) std::cout << "Slicer consumed " << size << ", returned " << size << std::endl;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user