All tags, all the time. Still some weirdness with set_history() that requires using the check widths in the framer & slicer.

This commit is contained in:
Nick Foster 2010-11-20 17:06:48 -08:00
parent cd394e1863
commit f8966f0d10
5 changed files with 203 additions and 206 deletions

View File

@ -40,7 +40,7 @@ air_modes_framer_sptr air_make_modes_framer(int channel_rate)
air_modes_framer::air_modes_framer(int channel_rate) : air_modes_framer::air_modes_framer(int channel_rate) :
gr_sync_block ("modes_framer", 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)), //stream 0 is received data
gr_make_io_signature (1, 1, sizeof(unsigned char))) //output is [0, 1, 2]: [no frame, short frame, long frame] gr_make_io_signature (1, 1, sizeof(float))) //raw samples passed back out
{ {
//initialize private data here //initialize private data here
d_chip_rate = 2000000; //2Mchips per second d_chip_rate = 2000000; //2Mchips per second
@ -49,6 +49,11 @@ air_modes_framer::air_modes_framer(int channel_rate) :
d_check_width = 120 * d_samples_per_symbol; //gotta be able to look at two long frame lengths at a time 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 //in the event that FRUIT occurs near the end of the first frame
//set_history(d_check_width*2); //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, int air_modes_framer::work(int noutput_items,
@ -57,8 +62,8 @@ int air_modes_framer::work(int noutput_items,
{ {
//do things! //do things!
const float *inraw = (const float *) input_items[0]; const float *inraw = (const float *) input_items[0];
//float *outraw = (float *) output_items[0]; float *outraw = (float *) output_items[0];
unsigned char *outattrib = (unsigned char *) output_items[0]; //unsigned char *outattrib = (unsigned char *) output_items[0];
int size = noutput_items - d_check_width*2; int size = noutput_items - d_check_width*2;
float reference_level; float reference_level;
framer_packet_type packet_attrib; framer_packet_type packet_attrib;
@ -68,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")); 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; std::vector<pmt::pmt_t>::iterator tag_iter;
memset(outattrib, 0x00, size * sizeof(unsigned char)); memcpy(outraw, inraw, size * sizeof(float));
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 = gr_tags::get_nitems(*tag_iter) - abs_sample_cnt; uint64_t i = gr_tags::get_nitems(*tag_iter) - abs_sample_cnt;
@ -106,7 +111,13 @@ int air_modes_framer::work(int noutput_items,
get_tags_in_range(fruit_tags, 0, abs_sample_cnt+i+1, abs_sample_cnt+i+lookahead, pmt::pmt_string_to_symbol("preamble_found")); 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; if(fruit_tags.size() > 0) packet_attrib = Fruited_Packet;
outattrib[i] = packet_attrib; //insert tag here
add_item_tag(0, //stream ID
nitems_written(0)+i, //sample
d_key, //preamble_found
pmt::pmt_from_long((long)packet_attrib),
d_me //block src id
);
} }
return size; return size;

View File

@ -44,6 +44,7 @@ private:
int d_chip_rate; int d_chip_rate;
int d_samples_per_chip; int d_samples_per_chip;
int d_samples_per_symbol; int d_samples_per_symbol;
pmt::pmt_t d_me, d_key;
public: public:
int work (int noutput_items, int work (int noutput_items,

View File

@ -51,7 +51,7 @@ air_modes_preamble::air_modes_preamble(int channel_rate, float threshold_db) :
str << name() << unique_id(); str << name() << unique_id();
d_me = pmt::pmt_string_to_symbol(str.str()); d_me = pmt::pmt_string_to_symbol(str.str());
d_key = pmt::pmt_string_to_symbol("preamble_found"); d_key = pmt::pmt_string_to_symbol("preamble_found");
//set_history(d_check_width); set_history(d_check_width);
} }
int air_modes_preamble::work(int noutput_items, int air_modes_preamble::work(int noutput_items,
@ -64,7 +64,7 @@ int air_modes_preamble::work(int noutput_items,
float *outraw = (float *) output_items[0]; float *outraw = (float *) output_items[0];
int size = noutput_items - d_check_width; int size = noutput_items;// - d_check_width;
int pulse_offsets[4]; int pulse_offsets[4];
float bit_energies[4]; float bit_energies[4];

View File

@ -46,7 +46,7 @@ air_modes_slicer_sptr air_make_modes_slicer(int channel_rate, gr_msg_queue_sptr
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_make_io_signature2 (2, 2, sizeof(float), sizeof(unsigned char)), //stream 0 is received data, stream 1 is binary preamble detector output gr_make_io_signature (1, 1, sizeof(float)), //stream 0 is received data, stream 1 is binary preamble detector output
gr_make_io_signature (0, 0, 0) ) gr_make_io_signature (0, 0, 0) )
{ {
//initialize private data here //initialize private data here
@ -74,222 +74,222 @@ int air_modes_slicer::work(int noutput_items,
{ {
//do things! //do things!
const float *inraw = (const float *) input_items[0]; const float *inraw = (const float *) input_items[0];
const unsigned char *inattrib = (const unsigned char *) input_items[1];
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
int i; int i;
for(i = 0; i < size; i++) { std::vector<pmt::pmt_t> tags;
if(inattrib[i] == framer_packet_type(Short_Packet) || inattrib[i] == framer_packet_type(Long_Packet)) { //if there's a packet starting here.... uint64_t abs_sample_cnt = nitems_read(0);
modes_packet rx_packet; get_tags_in_range(tags, 0, abs_sample_cnt, abs_sample_cnt + size, pmt::pmt_string_to_symbol("frame_info"));
std::vector<pmt::pmt_t>::iterator tag_iter;
int packet_length = 112; for(tag_iter = tags.begin(); tag_iter != tags.end(); tag_iter++) {
if(inattrib[i] == framer_packet_type(Short_Packet)) packet_length = 56; 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)));
rx_packet.type = framer_packet_type(inattrib[i]); int packet_length;
memset(&rx_packet.data, 0x00, 14 * sizeof(unsigned char)); packet_length = packet_type == framer_packet_type(Short_Packet) ? 56 : 112;
memset(&rx_packet.lowconfbits, 0x00, 24 * sizeof(unsigned char));
rx_packet.numlowconf = 0; 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 //let's use the preamble marker to get a reference level for the packet
rx_packet.reference_level = (bit_energy(&inraw[i], d_samples_per_chip) rx_packet.reference_level = (bit_energy(&inraw[i], d_samples_per_chip)
+ bit_energy(&inraw[i+int(1.0*d_samples_per_symbol)], d_samples_per_chip) + bit_energy(&inraw[i+int(1.0*d_samples_per_symbol)], d_samples_per_chip)
+ bit_energy(&inraw[i+int(3.5*d_samples_per_symbol)], d_samples_per_chip) + bit_energy(&inraw[i+int(3.5*d_samples_per_symbol)], d_samples_per_chip)
+ bit_energy(&inraw[i+int(4.5*d_samples_per_symbol)], d_samples_per_chip)) / 4; + bit_energy(&inraw[i+int(4.5*d_samples_per_symbol)], d_samples_per_chip)) / 4;
i += 8 * d_samples_per_symbol; //move to the center of the first bit of the data i += 8 * d_samples_per_symbol; //move to the center of the first bit of the data
//here we calculate the total energy contained in each chip of the symbol //here we calculate the total energy contained in each chip of the symbol
for(int j = 0; j < packet_length; j++) { for(int j = 0; j < packet_length; j++) {
int firstchip = i+j*d_samples_per_symbol; int firstchip = i+j*d_samples_per_symbol;
int secondchip = firstchip + d_samples_per_chip; int secondchip = firstchip + d_samples_per_chip;
bool slice, confidence; bool slice, confidence;
float firstchip_energy=0, secondchip_energy=0; float firstchip_energy=0, secondchip_energy=0;
firstchip_energy = bit_energy(&inraw[firstchip], d_samples_per_chip); firstchip_energy = bit_energy(&inraw[firstchip], d_samples_per_chip);
secondchip_energy = bit_energy(&inraw[secondchip], d_samples_per_chip); secondchip_energy = bit_energy(&inraw[secondchip], d_samples_per_chip);
//3dB limits for bit slicing and confidence measurement //3dB limits for bit slicing and confidence measurement
float highlimit=rx_packet.reference_level*2; float highlimit=rx_packet.reference_level*2;
float lowlimit=rx_packet.reference_level*0.5; float lowlimit=rx_packet.reference_level*0.5;
bool firstchip_inref = ((firstchip_energy > lowlimit) && (firstchip_energy < highlimit)); bool firstchip_inref = ((firstchip_energy > lowlimit) && (firstchip_energy < highlimit));
bool secondchip_inref = ((secondchip_energy > lowlimit) && (secondchip_energy < highlimit)); bool secondchip_inref = ((secondchip_energy > lowlimit) && (secondchip_energy < highlimit));
//these two lines for a super simple naive slicer. //these two lines for a super simple naive slicer.
// slice = firstchip_energy > secondchip_energy; // slice = firstchip_energy > secondchip_energy;
// confidence = bool(int(firstchip_inref) + int(secondchip_inref)); //one and only one chip in the reference zone // 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. //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 //see http://adsb.tc.faa.gov/WG3_Meetings/Meeting8/Squitter-Lon.pdf
if(firstchip_inref && !secondchip_inref) { if(firstchip_inref && !secondchip_inref) {
slice = 1; slice = 1;
confidence = 1; confidence = 1;
} }
else if(secondchip_inref && !firstchip_inref) { else if(secondchip_inref && !firstchip_inref) {
slice = 0; slice = 0;
confidence = 1; confidence = 1;
} }
else if(firstchip_inref && secondchip_inref) { else if(firstchip_inref && secondchip_inref) {
slice = firstchip_energy > secondchip_energy; slice = firstchip_energy > secondchip_energy;
confidence = 0; 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. 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; 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
if(slice) { if(slice) {
rx_packet.data[j/8] += 1 << (7-(j%8)); if(secondchip_energy < lowlimit * 0.5) confidence = 1;
} else confidence = 0;
//put the confidence decision into the packet
if(confidence) {
//rx_packet.confidence[j/8] += 1 << (7-(j%8));
} else { } else {
if(rx_packet.numlowconf < 24) rx_packet.lowconfbits[rx_packet.numlowconf++] = j; if(firstchip_energy < lowlimit * 0.5) confidence = 1;
else confidence = 0;
} }
} }
//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) {
//rx_packet.confidence[j/8] += 1 << (7-(j%8));
} else {
if(rx_packet.numlowconf < 24) rx_packet.lowconfbits[rx_packet.numlowconf++] = j;
}
}
/******************** BEGIN TIMESTAMP BS ******************/ /******************** BEGIN TIMESTAMP BS ******************/
rx_packet.timestamp_secs = 0; rx_packet.timestamp_secs = 0;
rx_packet.timestamp_frac = 0; rx_packet.timestamp_frac = 0;
uint64_t abs_sample_cnt = nitems_read(0); uint64_t abs_sample_cnt = nitems_read(0);
std::vector<pmt::pmt_t> tags; std::vector<pmt::pmt_t> tags;
uint64_t timestamp_secs, timestamp_sample, timestamp_delta; uint64_t timestamp_secs, timestamp_sample, timestamp_delta;
double timestamp_frac; double timestamp_frac;
pmt::pmt_t timestamp; pmt::pmt_t timestamp;
get_tags_in_range(tags, 0, abs_sample_cnt, abs_sample_cnt + i, pmt::pmt_string_to_symbol("packet_time_stamp")); get_tags_in_range(tags, 0, abs_sample_cnt, abs_sample_cnt + i, pmt::pmt_string_to_symbol("packet_time_stamp"));
//tags.back() is the most recent timestamp, then. //tags.back() is the most recent timestamp, then.
if(tags.size() > 0) { if(tags.size() > 0) {
//if nobody but the USRP is producing timestamps this isn't necessary //if nobody but the USRP is producing timestamps this isn't necessary
//std::sort(tags.begin(), tags.end(), pmtcompare); //std::sort(tags.begin(), tags.end(), pmtcompare);
timestamp = tags.back(); timestamp = tags.back();
timestamp_secs = pmt_to_uint64(pmt_tuple_ref(gr_tags::get_value(timestamp), 0)); timestamp_secs = pmt_to_uint64(pmt_tuple_ref(gr_tags::get_value(timestamp), 0));
timestamp_frac = pmt_to_double(pmt_tuple_ref(gr_tags::get_value(timestamp), 1)); timestamp_frac = pmt_to_double(pmt_tuple_ref(gr_tags::get_value(timestamp), 1));
timestamp_sample = gr_tags::get_nitems(timestamp); timestamp_sample = gr_tags::get_nitems(timestamp);
//now we have to offset the timestamp based on the current sample number //now we have to offset the timestamp based on the current sample number
timestamp_delta = (abs_sample_cnt + i) - timestamp_sample; timestamp_delta = (abs_sample_cnt + i) - timestamp_sample;
timestamp_frac += timestamp_delta * d_secs_per_sample; timestamp_frac += timestamp_delta * d_secs_per_sample;
if(timestamp_frac > 1.0) { if(timestamp_frac > 1.0) {
timestamp_frac -= 1.0; timestamp_frac -= 1.0;
timestamp_secs++; timestamp_secs++;
}
rx_packet.timestamp_secs = timestamp_secs;
rx_packet.timestamp_frac = timestamp_frac;
} }
/******************* END TIMESTAMP BS *********************/ rx_packet.timestamp_secs = timestamp_secs;
rx_packet.timestamp_frac = timestamp_frac;
}
//increment for the next round /******************* END TIMESTAMP BS *********************/
i += packet_length * d_samples_per_symbol;
//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. //increment for the next round
bool zeroes = 1;
for(int m = 0; m < 14; m++) { //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.
if(rx_packet.data[m]) zeroes = 0; bool zeroes = 1;
for(int m = 0; m < 14; m++) {
if(rx_packet.data[m]) zeroes = 0;
}
if(zeroes) continue; //toss it
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
//we note that short packets other than type 11 CANNOT be reliably decoded, since the a/c address is encoded with the parity bits.
//mode S in production ATC use relies on the fact that these short packets are reply squitters to transponder requests,
//and so the radar should already know the expected a/c reply address. so, error-correction makes no sense on short packets (other than type 11)
//this means two things: first, we will DROP short packets (other than type 11) with ANY low-confidence bits, since we can't be confident that we're seeing real data
//second, we will only perform error correction on LONG type S packets.
//the limitation on short packets means in practice a short packet has to be at least 6dB above the noise floor in order to be output. long packets can theoretically
//be decoded at the 3dB SNR point. below that and the preamble detector won't fire.
//in practice, this limitation causes you to see a HUGE number of type 11 packets which pass CRC through random luck.
//these packets necessarily have large numbers of low-confidence bits, so we toss them with an arbitrary limit of 10.
//that's a pretty dang low threshold so i don't think we'll drop many legit packets
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 >= 10) continue;
//if(rx_packet.numlowconf >= 24) continue; //don't even try, this is the maximum number of errors ECC could possibly correct
//the above line should be part of ECC, and only checked if the message has parity errors
rx_packet.parity = modes_check_parity(rx_packet.data, packet_length);
if(rx_packet.parity && rx_packet.type == Long_Packet) {
// long before = rx_packet.parity;
bruteResultTypeDef bruteResult = modes_ec_brute(rx_packet);
if(bruteResult == No_Solution) {
//printf("No solution!\n");
continue;
} else if(bruteResult == Multiple_Solutions) {
// printf("Multiple solutions!\n");
continue;
} else if(bruteResult == Too_Many_LCBs) {
//printf("Too many LCBs (%i)!\n", rx_packet.numlowconf);
continue;
} else if(bruteResult == No_Error) {
// printf("No error!\n");
} else if(bruteResult == Solution_Found) {
// printf("Solution found for %i LCBs!\n", rx_packet.numlowconf);
} }
if(zeroes) continue; //toss it // rx_packet.parity = modes_check_parity(rx_packet.data, packet_length);
// if(rx_packet.parity) printf("Error: packet fails parity check after correction, was %x, now %x\n", before, rx_packet.parity);
}
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.parity && rx_packet.type == Long_Packet) printf("Error! Bad packet forwarded to the queue.\n");
//now we have a complete packet with confidence data, let's print it to the message queue
//here, rather than send the entire packet, since we've already done parity checking and ECC in C++, we'll
//send just the data (no confidence bits), separated into fields for easier parsing.
//we'll replicate some data by sending the message type as the first field, followed by the first 8+24=32 bits of the packet, followed by
//56 long packet data bits if applicable (zero-padded if not), followed by parity
//we note that short packets other than type 11 CANNOT be reliably decoded, since the a/c address is encoded with the parity bits. d_payload.str("");
//mode S in production ATC use relies on the fact that these short packets are reply squitters to transponder requests,
//and so the radar should already know the expected a/c reply address. so, error-correction makes no sense on short packets (other than type 11)
//this means two things: first, we will DROP short packets (other than type 11) with ANY low-confidence bits, since we can't be confident that we're seeing real data
//second, we will only perform error correction on LONG type S packets.
//the limitation on short packets means in practice a short packet has to be at least 6dB above the noise floor in order to be output. long packets can theoretically d_payload << std::dec << std::setw(2) << std::setfill('0') << rx_packet.message_type << std::hex << " ";
//be decoded at the 3dB SNR point. below that and the preamble detector won't fire.
//in practice, this limitation causes you to see a HUGE number of type 11 packets which pass CRC through random luck. for(int m = 0; m < 4; m++) {
//these packets necessarily have large numbers of low-confidence bits, so we toss them with an arbitrary limit of 10. d_payload << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]);
//that's a pretty dang low threshold so i don't think we'll drop many legit packets }
d_payload << " ";
if(rx_packet.type == Short_Packet && rx_packet.message_type != 11 && rx_packet.numlowconf != 0) continue; if(packet_length == 112) {
if(rx_packet.type == Short_Packet && rx_packet.message_type == 11 && rx_packet.numlowconf >= 10) continue; for(int m = 4; m < 11; m++) {
//if(rx_packet.numlowconf >= 24) continue; //don't even try, this is the maximum number of errors ECC could possibly correct
//the above line should be part of ECC, and only checked if the message has parity errors
rx_packet.parity = modes_check_parity(rx_packet.data, packet_length);
if(rx_packet.parity && rx_packet.type == Long_Packet) {
// long before = rx_packet.parity;
bruteResultTypeDef bruteResult = modes_ec_brute(rx_packet);
if(bruteResult == No_Solution) {
//printf("No solution!\n");
continue;
} else if(bruteResult == Multiple_Solutions) {
// printf("Multiple solutions!\n");
continue;
} else if(bruteResult == Too_Many_LCBs) {
//printf("Too many LCBs (%i)!\n", rx_packet.numlowconf);
continue;
} else if(bruteResult == No_Error) {
// printf("No error!\n");
} else if(bruteResult == Solution_Found) {
// printf("Solution found for %i LCBs!\n", rx_packet.numlowconf);
}
// rx_packet.parity = modes_check_parity(rx_packet.data, packet_length);
// if(rx_packet.parity) printf("Error: packet fails parity check after correction, was %x, now %x\n", before, rx_packet.parity);
}
// if(rx_packet.parity && rx_packet.type == Long_Packet) printf("Error! Bad packet forwarded to the queue.\n");
//now we have a complete packet with confidence data, let's print it to the message queue
//here, rather than send the entire packet, since we've already done parity checking and ECC in C++, we'll
//send just the data (no confidence bits), separated into fields for easier parsing.
//we'll replicate some data by sending the message type as the first field, followed by the first 8+24=32 bits of the packet, followed by
//56 long packet data bits if applicable (zero-padded if not), followed by parity
d_payload.str("");
d_payload << std::dec << std::setw(2) << std::setfill('0') << rx_packet.message_type << std::hex << " ";
for(int m = 0; m < 4; m++) {
d_payload << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]); d_payload << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]);
} }
d_payload << " "; d_payload << " ";
if(packet_length == 112) { for(int m = 11; m < 14; m++) {
for(int m = 4; m < 11; m++) { d_payload << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]);
d_payload << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]); }
} } else {
d_payload << " "; for(int m = 4; m < 11; m++) {
for(int m = 11; m < 14; m++) { d_payload << std::setw(2) << std::setfill('0') << unsigned(0);
d_payload << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]); }
} d_payload << " ";
} else { for(int m = 4; m < 7; m++) {
for(int m = 4; m < 11; m++) { d_payload << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]);
d_payload << std::setw(2) << std::setfill('0') << unsigned(0);
}
d_payload << " ";
for(int m = 4; m < 7; m++) {
d_payload << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]);
}
} }
d_payload << " " << std::setw(6) << rx_packet.parity << " " << std::dec << rx_packet.reference_level
<< " " << rx_packet.timestamp_secs
<< " " << std::setprecision(10) << std::setw(10) << rx_packet.timestamp_frac;
gr_message_sptr msg = gr_make_message_from_string(std::string(d_payload.str()));
d_queue->handle(msg);
} }
d_payload << " " << std::setw(6) << rx_packet.parity << " " << std::dec << rx_packet.reference_level
<< " " << rx_packet.timestamp_secs
<< " " << std::setprecision(10) << std::setw(10) << rx_packet.timestamp_frac;
gr_message_sptr msg = gr_make_message_from_string(std::string(d_payload.str()));
d_queue->handle(msg);
} }
return size; return size;

View File

@ -97,27 +97,12 @@ class adsb_rx_block (gr.top_block):
self.framer = air.modes_framer(rate) self.framer = air.modes_framer(rate)
self.slicer = air.modes_slicer(rate, queue) self.slicer = air.modes_slicer(rate, queue)
#self.nullsink = gr.file_sink(gr.sizeof_gr_complex, "/dev/null")
#self.connect(self.u, self.nullsink)
# self.connect(self.u, self.demod, self.filter)
# self.connect(self.filter, self.avg)
# self.connect(self.filter, (self.preamble, 0))
# self.connect(self.avg, (self.preamble, 1))
# self.connect(self.filter, (self.framer, 0))
# self.connect(self.preamble, (self.framer, 1))
# self.connect(self.filter, (self.slicer, 0))
# self.connect(self.framer, (self.slicer, 1))
#use this flowgraph instead to omit the filter
self.connect(self.u, self.demod) self.connect(self.u, self.demod)
self.connect(self.demod, self.avg) self.connect(self.demod, self.avg)
self.connect(self.demod, (self.preamble, 0)) self.connect(self.demod, (self.preamble, 0))
self.connect(self.avg, (self.preamble, 1)) self.connect(self.avg, (self.preamble, 1))
self.connect((self.preamble, 0), (self.framer, 0)) self.connect((self.preamble, 0), (self.framer, 0))
self.connect(self.demod, (self.slicer, 0)) self.connect(self.framer, self.slicer)
self.connect(self.framer, (self.slicer, 1))
def tune(self, freq): def tune(self, freq):
result = self.u.set_center_freq(freq, 0) result = self.u.set_center_freq(freq, 0)