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.u, self.nullsink)
self.connect(self.avg, (self.preamble, 1))
self.connect(self.filter, (self.framer, 0)) # self.connect(self.u, self.demod, self.filter)
self.connect(self.preamble, (self.framer, 1)) # self.connect(self.filter, self.avg)
self.connect(self.filter, (self.slicer, 0)) # self.connect(self.filter, (self.preamble, 0))
self.connect(self.framer, (self.slicer, 1)) # 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 #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.demod, (self.framer, 0)) self.connect(self.demod, (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.demod, (self.slicer, 0))
# self.connect(self.framer, (self.slicer, 1)) 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__':