/*! * \file gnss_sdr_sample_counter.cc * \brief Simple block to report the current receiver time based on the output of the tracking or telemetry blocks * \author Javier Arribas 2018. jarribas(at)cttc.es * * * ----------------------------------------------------------------------------- * * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- */ #include "gnss_sdr_sample_counter.h" #include "gnss_synchro.h" #include "gnss_time.h" #include #include // for from_double #include // for mp #include // for round #include // for operator<< #include #include // for string #include #if PMT_USES_BOOST_ANY #include namespace wht = boost; #else #include namespace wht = std; #endif gnss_sdr_sample_counter::gnss_sdr_sample_counter( double _fs, int32_t _interval_ms, size_t _size) : gr::sync_decimator("sample_counter", gr::io_signature::make(1, 1, _size), gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)), static_cast(std::round(_fs * static_cast(_interval_ms) / 1e3))), fs(_fs), current_T_rx_ms(0), sample_counter(0), interval_ms(_interval_ms), report_interval_ms(1000), // default reporting 1 second samples_per_output(std::round(fs * static_cast(interval_ms) / 1e3)), current_s(0), current_m(0), current_h(0), current_days(0), flag_m(false), flag_h(false), flag_days(false), flag_enable_send_msg(false) // enable it for reporting time with asynchronous message { message_port_register_out(pmt::mp("sample_counter")); set_max_noutput_items(1); set_tag_propagation_policy(TPP_DONT); // no tag propagation, the time tag will be adjusted and regenerated in work() } gnss_sdr_sample_counter_sptr gnss_sdr_make_sample_counter(double _fs, int32_t _interval_ms, size_t _size) { gnss_sdr_sample_counter_sptr sample_counter_(new gnss_sdr_sample_counter(_fs, _interval_ms, _size)); return sample_counter_; } int64_t gnss_sdr_sample_counter::uint64diff(uint64_t first, uint64_t second) { uint64_t abs_diff = (first > second) ? (first - second) : (second - first); assert(abs_diff <= INT64_MAX); return (first > second) ? (int64_t)abs_diff : -(int64_t)abs_diff; } int gnss_sdr_sample_counter::work(int noutput_items __attribute__((unused)), gr_vector_const_void_star &input_items __attribute__((unused)), gr_vector_void_star &output_items) { auto *out = reinterpret_cast(output_items[0]); out[0] = Gnss_Synchro(); out[0].Flag_valid_symbol_output = false; out[0].Flag_valid_word = false; out[0].Channel_ID = -1; out[0].fs = fs; if ((current_T_rx_ms % report_interval_ms) == 0) { current_s++; if ((current_s % 60) == 0) { current_s = 0; current_m++; flag_m = true; if ((current_m % 60) == 0) { current_m = 0; current_h++; flag_h = true; if ((current_h % 24) == 0) { current_h = 0; current_days++; flag_days = true; } } } if (flag_days) { std::string day; if (current_days == 1) { day = " day "; } else { day = " days "; } std::cout << "Current receiver time: " << current_days << day << current_h << " h " << current_m << " min " << current_s << " s\n"; } else { if (flag_h) { std::cout << "Current receiver time: " << current_h << " h " << current_m << " min " << current_s << " s\n"; } else { if (flag_m) { std::cout << "Current receiver time: " << current_m << " min " << current_s << " s\n"; } else { std::cout << "Current receiver time: " << current_s << " s\n"; } } } if (flag_enable_send_msg) { message_port_pub(pmt::mp("receiver_time"), pmt::from_double(static_cast(current_T_rx_ms) / 1000.0)); } } sample_counter += samples_per_output; out[0].Tracking_sample_counter = sample_counter; current_T_rx_ms += interval_ms; // *************** time tags **************** std::vector tags_vec; // notice that nitems_read is updated in decimation blocks after leaving work() with return 1, equivalent to call consume_each this->get_tags_in_range(tags_vec, 0, this->nitems_read(0), this->nitems_read(0) + samples_per_output); for (const auto &it : tags_vec) { try { if (pmt::any_ref(it.value).type().hash_code() == typeid(const std::shared_ptr).hash_code()) { // recompute timestamp to match the last sample in the consumed samples in this batch int64_t diff_samplecount = uint64diff(out[0].Tracking_sample_counter, it.offset); const auto last_timetag = wht::any_cast>(pmt::any_ref(it.value)); double intpart; last_timetag->tow_ms_fraction += modf(1000.0 * static_cast(diff_samplecount) / fs, &intpart); last_timetag->tow_ms = last_timetag->tow_ms + static_cast(intpart); last_timetag->rx_time = static_cast(out[0].Tracking_sample_counter) / fs; add_item_tag(0, this->nitems_written(0) + 1, pmt::mp("timetag"), pmt::make_any(last_timetag)); // std::cout << "COUNTER TAG: this->nitems_read(0):" << this->nitems_read(0) << " sample_counter:" << sample_counter // << " it->offset:" << it->offset << " diff:" << diff_samplecount << "\n"; // getchar(); } else { std::cout << "hash code not match\n"; } } catch (const wht::bad_any_cast &e) { std::cout << "msg Bad any_cast: " << e.what(); } catch (const std::exception &ee) { return 1; } } // ************ end time tags ************** return 1; }