diff --git a/include/gr_air_modes/preamble.h b/include/gr_air_modes/preamble.h index a07022c..a86aba0 100644 --- a/include/gr_air_modes/preamble.h +++ b/include/gr_air_modes/preamble.h @@ -37,11 +37,11 @@ class AIR_MODES_API preamble : virtual public gr::block { public: typedef boost::shared_ptr sptr; - static sptr make(int channel_rate, float threshold_db); + static sptr make(float channel_rate, float threshold_db); - virtual void set_rate(int channel_rate) = 0; + virtual void set_rate(float channel_rate) = 0; virtual void set_threshold(float threshold_db) = 0; - virtual int get_rate(void) = 0; + virtual float get_rate(void) = 0; virtual float get_threshold(void) = 0; }; diff --git a/lib/preamble_impl.cc b/lib/preamble_impl.cc index d367c98..af8644d 100644 --- a/lib/preamble_impl.cc +++ b/lib/preamble_impl.cc @@ -34,11 +34,11 @@ namespace gr { -air_modes::preamble::sptr air_modes::preamble::make(int channel_rate, float threshold_db) { +air_modes::preamble::sptr air_modes::preamble::make(float channel_rate, float threshold_db) { return gnuradio::get_initial_sptr(new air_modes::preamble_impl(channel_rate, threshold_db)); } -air_modes::preamble_impl::preamble_impl(int channel_rate, float threshold_db) : +air_modes::preamble_impl::preamble_impl(float channel_rate, float threshold_db) : gr::block ("preamble", gr::io_signature::make2 (2, 2, sizeof(float), sizeof(float)), //stream 0 is received data, stream 1 is moving average for reference gr::io_signature::make (1, 1, sizeof(float))) //the output soft symbols @@ -53,11 +53,11 @@ air_modes::preamble_impl::preamble_impl(int channel_rate, float threshold_db) : d_key = pmt::string_to_symbol("preamble_found"); } -void air_modes::preamble_impl::set_rate(int channel_rate) { +void air_modes::preamble_impl::set_rate(float channel_rate) { d_samples_per_chip = channel_rate / d_chip_rate; d_samples_per_symbol = d_samples_per_chip * 2; d_check_width = 120 * d_samples_per_symbol; - d_secs_per_sample = 1.0/channel_rate; + d_sample_rate = channel_rate; set_output_multiple(1+d_check_width*2); set_history(d_samples_per_symbol); } @@ -71,8 +71,8 @@ float air_modes::preamble_impl::get_threshold(void) { return d_threshold_db; } -int air_modes::preamble_impl::get_rate(void) { - return d_samples_per_chip * d_chip_rate; +float air_modes::preamble_impl::get_rate(void) { + return d_sample_rate; } static void integrate_and_dump(float *out, const float *in, int chips, int samps_per_chip) { @@ -97,19 +97,34 @@ static double correlate_preamble(const float *in, int samples_per_chip) { return corr; } -//todo: make it return a pair of some kind, otherwise you can lose precision -static double tag_to_timestamp(gr::tag_t tstamp, uint64_t abs_sample_cnt, double secs_per_sample) { - uint64_t ts_sample, last_whole_stamp; - double last_frac_stamp; - +static pmt::pmt_t tag_to_timestamp(gr::tag_t tstamp, uint64_t abs_sample_cnt, int rate) { if(tstamp.key == NULL || pmt::symbol_to_string(tstamp.key) != "rx_time") return 0; - last_whole_stamp = pmt::to_uint64(pmt::tuple_ref(tstamp.value, 0)); - last_frac_stamp = pmt::to_double(pmt::tuple_ref(tstamp.value, 1)); - ts_sample = tstamp.offset; + //the timestamp tag has tstamp.offset, the sample index of the timestamp tag + //also tstamp.value, a pmt pair with (uint64, double) representing int and + //fractional timestamp, respectively. + //this function also gets an abs_sample_cnt which represents the sample count to + //find a timestamp for. sps is obviously samples per second. + // + //so (abs_sample_cnt - tstamp.offset) is the delay we apply to the tag + // int((abs_sample_cnt - tstamp.offset)/sps) is the integer offset + // (abs_sample_cnt - tstamp.offset)/sps is the fractional offset + + uint64_t last_whole_stamp = pmt::to_uint64(pmt::tuple_ref(tstamp.value, 0)); + double last_frac_stamp = pmt::to_double(pmt::tuple_ref(tstamp.value, 1)); + std::cout << "Rate: " << rate << std::endl; + uint64_t int_offset = int(abs_sample_cnt - tstamp.offset)/rate; + double frac_offset = ((abs_sample_cnt - tstamp.offset) % rate) / double(rate); + + uint64_t abs_whole = last_whole_stamp + int_offset; + double abs_frac = last_frac_stamp + frac_offset; + if(abs_frac > 1.0f) { + abs_frac -= 1.0f; + abs_whole += 1.0f; + } + + pmt::pmt_t tstime = pmt::make_tuple(pmt::from_uint64(abs_whole), pmt::from_double(abs_frac)); - double tstime = double(abs_sample_cnt * secs_per_sample) + last_whole_stamp + last_frac_stamp; - if(0) std::cout << "HEY WE GOT A STAMP AT " << tstime << " TICKS AT SAMPLE " << ts_sample << " ABS SAMPLE CNT IS " << abs_sample_cnt << std::endl; return tstime; } @@ -124,7 +139,7 @@ int air_modes::preamble_impl::general_work(int noutput_items, int mininputs = std::min(ninput_items[0], ninput_items[1]); //they should be matched but let's be safe //round number of input samples down to nearest d_samples_per_chip //we also subtract off d_samples_per_chip to allow the bit center finder some leeway - const int ninputs = std::max(mininputs - (mininputs % d_samples_per_chip) - d_samples_per_chip, 0); + const int ninputs = std::max(mininputs - (mininputs % int(d_samples_per_chip)) - int(d_samples_per_chip), 0); if (ninputs <= 0) { consume_each(0); return 0; } float *out = (float *) output_items[0]; @@ -194,22 +209,20 @@ int air_modes::preamble_impl::general_work(int noutput_items, //all right i'm prepared to call this a preamble for(int j=0; j<240; j++) { - out[j] = in[i+j*d_samples_per_chip] - inavg[i]; + out[j] = in[i+int(j*d_samples_per_chip)] - inavg[i]; } //get the timestamp of the preamble - double tstamp = tag_to_timestamp(d_timestamp, abs_sample_cnt + i, d_secs_per_sample); + pmt::pmt_t tstamp = tag_to_timestamp(d_timestamp, abs_sample_cnt + i, d_sample_rate); //now tag the preamble add_item_tag(0, //stream ID nitems_written(0), //sample d_key, //frame_info - pmt::from_double(tstamp), + tstamp, d_me //block src id ); - //std::cout << "PREAMBLE" << std::endl; - //produce only one output per work call -- TODO this should probably change if(0) std::cout << "Preamble consumed " << i+240*d_samples_per_chip << "with i=" << i << ", returned 240" << std::endl; diff --git a/lib/preamble_impl.h b/lib/preamble_impl.h index 482b46a..6d6509f 100644 --- a/lib/preamble_impl.h +++ b/lib/preamble_impl.h @@ -15,26 +15,26 @@ private: int d_check_width; int d_chip_rate; float d_preamble_length_us; - int d_samples_per_chip; - int d_samples_per_symbol; + float d_samples_per_chip; + float d_samples_per_symbol; float d_threshold_db; float d_threshold; - pmt::pmt_t d_me, d_key; gr::tag_t d_timestamp; - double d_secs_per_sample; + pmt::pmt_t d_me, d_key; + int d_sample_rate; public: - preamble_impl(int channel_rate, float threshold_db); + preamble_impl(float channel_rate, float threshold_db); int general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); - void set_rate(int channel_rate); + void set_rate(float channel_rate); void set_threshold(float threshold_db); float get_threshold(void); - int get_rate(void); + float get_rate(void); }; } //namespace air_modes diff --git a/lib/slicer_impl.cc b/lib/slicer_impl.cc index c34e9e4..565f691 100644 --- a/lib/slicer_impl.cc +++ b/lib/slicer_impl.cc @@ -158,8 +158,6 @@ int air_modes::slicer_impl::work(int noutput_items, } } - rx_packet.timestamp = pmt::to_double(tag_iter->value); - //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; for(int m = 0; m < 14; m++) { @@ -183,13 +181,15 @@ int air_modes::slicer_impl::work(int noutput_items, //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;} + pmt::pmt_t tstamp = tag_iter->value; + d_payload.str(""); 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::setw(6) << rx_packet.crc << " " << std::dec << rx_packet.reference_level - << " " << std::setprecision(10) << std::setw(10) << rx_packet.timestamp; + << " " << pmt::to_uint64(pmt::tuple_ref(tstamp, 0)) << " " << std::setprecision(10) << pmt::to_double(pmt::tuple_ref(tstamp, 1)); gr::message::sptr msg = gr::message::make_from_string(std::string(d_payload.str())); d_queue->handle(msg); } diff --git a/lib/slicer_impl.h b/lib/slicer_impl.h index bfdf3de..f4914ea 100644 --- a/lib/slicer_impl.h +++ b/lib/slicer_impl.h @@ -38,6 +38,7 @@ private: int d_chip_rate; int d_samples_per_chip; int d_samples_per_symbol; + gr::tag_t d_timestamp; gr::msg_queue::sptr d_queue; std::ostringstream d_payload; diff --git a/python/parse.py b/python/parse.py index 7fe3297..2fb5398 100644 --- a/python/parse.py +++ b/python/parse.py @@ -423,12 +423,12 @@ def parse_TCAS_CRM(data): def make_parser(pub): publisher = pub def publish(message): - [data, ecc, reference, timestamp] = message.split() + [data, ecc, reference, int_timestamp, frac_timestamp] = message.split() try: ret = air_modes.modes_report(modes_reply(int(data, 16)), int(ecc, 16), 10.0*math.log10(max(1e-8,float(reference))), - air_modes.stamp(0, float(timestamp))) + air_modes.stamp(int(int_timestamp), float(frac_timestamp))) pub["modes_dl"] = ret pub["type%i_dl" % ret.data.get_type()] = ret except ADSBError: