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:
Nick Foster 2010-11-18 14:25:07 -08:00
parent d23530615f
commit eb18bdc308
4 changed files with 87 additions and 29 deletions

View File

@ -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);

View File

@ -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

View File

@ -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):

View File

@ -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__':