First stab at tagged timestamps using TR's tagging branch. Currently segfaults due to some oddness in the tag subsystem.
This commit is contained in:
parent
d23530615f
commit
eb18bdc308
@ -31,6 +31,7 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <modes_parity.h>
|
#include <modes_parity.h>
|
||||||
#include <modes_energy.h>
|
#include <modes_energy.h>
|
||||||
|
#include <gr_tag_info.h>
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -58,6 +59,14 @@ air_modes_slicer::air_modes_slicer(int channel_rate, gr_msg_queue_sptr queue) :
|
|||||||
set_output_multiple(1+d_check_width * 2); //how do you specify buffer size for sinks?
|
set_output_multiple(1+d_check_width * 2); //how do you specify buffer size for sinks?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool pmtcompare(pmt::pmt_t x, pmt::pmt_t y)
|
||||||
|
{
|
||||||
|
uint64_t t_x, t_y;
|
||||||
|
t_x = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(x, 0));
|
||||||
|
t_y = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(y, 0));
|
||||||
|
return t_x < t_y;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
@ -146,8 +155,48 @@ int air_modes_slicer::work(int noutput_items,
|
|||||||
} 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 ******************/
|
||||||
|
uint64_t abs_sample_cnt = nitems_read(0);
|
||||||
|
std::vector<pmt::pmt_t> tags;
|
||||||
|
|
||||||
|
//printf("nitems_read: %i", abs_sample_cnt);
|
||||||
|
pmt::pmt_t timestamp = pmt::mp(pmt::mp(0), pmt::mp(0)); //so we don't barf if there isn't one
|
||||||
|
|
||||||
|
get_tags_in_range(tags, 0, abs_sample_cnt, abs_sample_cnt + i);
|
||||||
|
//tags.back() is the most recent timestamp, then.
|
||||||
|
if(tags.size() > 0) {
|
||||||
|
std::sort(tags.begin(), tags.end(), pmtcompare);
|
||||||
|
|
||||||
|
do {
|
||||||
|
timestamp = tags.back();
|
||||||
|
tags.pop_back();
|
||||||
|
} while(!pmt::pmt_eqv(gr_tags::get_key(timestamp), pmt::pmt_string_to_symbol("time"))); //only interested in timestamps
|
||||||
|
|
||||||
|
uint64_t timestamp_secs = pmt_to_uint64(pmt_tuple_ref(timestamp, 0));
|
||||||
|
double timestamp_frac = pmt_to_double(pmt_tuple_ref(timestamp, 1));
|
||||||
|
uint64_t timestamp_sample = gr_tags::get_nitems(timestamp);
|
||||||
|
//now we have to offset the timestamp based on the current sample number
|
||||||
|
uint64_t timestamp_delta = (abs_sample_cnt + i) - timestamp_sample;
|
||||||
|
|
||||||
|
timestamp_frac += timestamp_delta * (1.0 / (d_samples_per_chip * d_chip_rate));
|
||||||
|
if(timestamp_frac > 1.0) {
|
||||||
|
timestamp_frac -= 1.0;
|
||||||
|
timestamp_secs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rx_packet.timestamp_secs = timestamp_secs;
|
||||||
|
rx_packet.timestamp_frac = timestamp_frac;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rx_packet.timestamp_secs = 0;
|
||||||
|
rx_packet.timestamp_frac = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************* END TIMESTAMP BS *********************/
|
||||||
|
|
||||||
|
//increment for the next round
|
||||||
i += packet_length * d_samples_per_symbol;
|
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.
|
//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.
|
||||||
@ -237,7 +286,8 @@ int air_modes_slicer::work(int noutput_items,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d_payload << " " << std::setw(6) << rx_packet.parity << " " << std::dec << rx_packet.reference_level;
|
d_payload << " " << std::setw(6) << rx_packet.parity << " " << std::dec << rx_packet.reference_level
|
||||||
|
<< " " << rx_packet.timestamp_secs << " " << rx_packet.timestamp_frac;
|
||||||
|
|
||||||
gr_message_sptr msg = gr_make_message_from_string(std::string(d_payload.str()));
|
gr_message_sptr msg = gr_make_message_from_string(std::string(d_payload.str()));
|
||||||
d_queue->handle(msg);
|
d_queue->handle(msg);
|
||||||
|
@ -36,6 +36,8 @@ struct modes_packet {
|
|||||||
framer_packet_type type; //what length packet are we
|
framer_packet_type type; //what length packet are we
|
||||||
unsigned int message_type;
|
unsigned int message_type;
|
||||||
float reference_level;
|
float reference_level;
|
||||||
|
unsigned long timestamp_secs; //timestamp from tags
|
||||||
|
double timestamp_frac;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,7 +30,9 @@ class modes_output_print(modes_parse.modes_parse):
|
|||||||
modes_parse.modes_parse.__init__(self, mypos)
|
modes_parse.modes_parse.__init__(self, mypos)
|
||||||
|
|
||||||
def parse(self, message):
|
def parse(self, message):
|
||||||
[msgtype, shortdata, longdata, parity, ecc, reference] = message.split()
|
[msgtype, shortdata, longdata, parity, ecc, reference, time_secs, time_frac] = message.split()
|
||||||
|
time_secs = long(time_secs)
|
||||||
|
time_frac = float(time_frac)
|
||||||
|
|
||||||
shortdata = long(shortdata, 16)
|
shortdata = long(shortdata, 16)
|
||||||
longdata = long(longdata, 16)
|
longdata = long(longdata, 16)
|
||||||
@ -53,7 +55,7 @@ class modes_output_print(modes_parse.modes_parse):
|
|||||||
elif msgtype == 17:
|
elif msgtype == 17:
|
||||||
output = self.print17(shortdata, longdata, parity, ecc)
|
output = self.print17(shortdata, longdata, parity, ecc)
|
||||||
else:
|
else:
|
||||||
output = "No handler for message type " + str(msgtype) + " from " + str(ecc)
|
output = "No handler for message type " + str(msgtype) + " from %x" % ecc
|
||||||
|
|
||||||
if reference == 0.0:
|
if reference == 0.0:
|
||||||
refdb = 0.0
|
refdb = 0.0
|
||||||
@ -61,7 +63,7 @@ class modes_output_print(modes_parse.modes_parse):
|
|||||||
refdb = 10.0*math.log10(reference)
|
refdb = 10.0*math.log10(reference)
|
||||||
|
|
||||||
if output is not None:
|
if output is not None:
|
||||||
output = "(%.0f) " % (refdb) + output
|
output = "(%.0f %u %f) " % (refdb, time_secs, time_frac) + output
|
||||||
print output
|
print output
|
||||||
|
|
||||||
def print0(self, shortdata, parity, ecc):
|
def print0(self, shortdata, parity, ecc):
|
||||||
|
@ -54,11 +54,11 @@ class adsb_rx_block (gr.top_block):
|
|||||||
self.args = args
|
self.args = args
|
||||||
|
|
||||||
if options.filename is None:
|
if options.filename is None:
|
||||||
self.u = uhd.simple_source("", uhd.io_type_t.COMPLEX_FLOAT32)
|
self.u = uhd.single_usrp_source("", uhd.io_type_t.COMPLEX_FLOAT32)
|
||||||
|
|
||||||
if(options.rx_subdev_spec is None):
|
#if(options.rx_subdev_spec is None):
|
||||||
options.rx_subdev_spec = ""
|
# options.rx_subdev_spec = ""
|
||||||
self.u.set_subdev_spec(options.rx_subdev_spec)
|
#self.u.set_subdev_spec(options.rx_subdev_spec)
|
||||||
|
|
||||||
rate = options.rate
|
rate = options.rate
|
||||||
self.u.set_samp_rate(rate)
|
self.u.set_samp_rate(rate)
|
||||||
@ -66,7 +66,7 @@ class adsb_rx_block (gr.top_block):
|
|||||||
|
|
||||||
if options.gain is None: #set to halfway
|
if options.gain is None: #set to halfway
|
||||||
g = self.u.get_gain_range()
|
g = self.u.get_gain_range()
|
||||||
options.gain = (g.min+g.max) / 2.0
|
options.gain = (g.start()+g.stop()) / 2.0
|
||||||
|
|
||||||
if not(self.tune(options.freq)):
|
if not(self.tune(options.freq)):
|
||||||
print "Failed to set initial frequency"
|
print "Failed to set initial frequency"
|
||||||
@ -89,34 +89,38 @@ class adsb_rx_block (gr.top_block):
|
|||||||
|
|
||||||
#the DBSRX especially tends to be spur-prone; the LPF keeps out the
|
#the DBSRX especially tends to be spur-prone; the LPF keeps out the
|
||||||
#spur multiple that shows up at 2MHz
|
#spur multiple that shows up at 2MHz
|
||||||
self.filtcoeffs = gr.firdes.low_pass(1, rate, 1.8e6, 200e3)
|
# self.filtcoeffs = gr.firdes.low_pass(1, rate, 1.8e6, 200e3)
|
||||||
self.filter = gr.fir_filter_fff(1, self.filtcoeffs)
|
# self.filter = gr.fir_filter_fff(1, self.filtcoeffs)
|
||||||
|
|
||||||
self.preamble = air.modes_preamble(rate, options.threshold)
|
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.slicer = air.modes_slicer(rate, queue)
|
||||||
|
|
||||||
self.connect(self.u, self.demod, self.filter)
|
#self.nullsink = gr.file_sink(gr.sizeof_gr_complex, "/dev/null")
|
||||||
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.nullsink)
|
||||||
# self.connect(self.u, self.demod)
|
|
||||||
# self.connect(self.demod, self.avg)
|
# self.connect(self.u, self.demod, self.filter)
|
||||||
# self.connect(self.demod, (self.preamble, 0))
|
# self.connect(self.filter, self.avg)
|
||||||
|
# self.connect(self.filter, (self.preamble, 0))
|
||||||
# self.connect(self.avg, (self.preamble, 1))
|
# self.connect(self.avg, (self.preamble, 1))
|
||||||
# self.connect(self.demod, (self.framer, 0))
|
# self.connect(self.filter, (self.framer, 0))
|
||||||
# self.connect(self.preamble, (self.framer, 1))
|
# self.connect(self.preamble, (self.framer, 1))
|
||||||
# self.connect(self.demod, (self.slicer, 0))
|
# self.connect(self.filter, (self.slicer, 0))
|
||||||
# self.connect(self.framer, (self.slicer, 1))
|
# self.connect(self.framer, (self.slicer, 1))
|
||||||
|
|
||||||
|
#use this flowgraph instead to omit the filter
|
||||||
|
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.demod, (self.framer, 0))
|
||||||
|
self.connect(self.preamble, (self.framer, 1))
|
||||||
|
self.connect(self.demod, (self.slicer, 0))
|
||||||
|
self.connect(self.framer, (self.slicer, 1))
|
||||||
|
|
||||||
def tune(self, freq):
|
def tune(self, freq):
|
||||||
result = self.u.set_center_freq(freq)
|
result = self.u.set_center_freq(freq, 0)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
Reference in New Issue
Block a user