The timestamp in gr-uhd is useful because a USRP can provide the exact start/restart time of a sample stream, based on a GPSDO. A system timestamp at the call to work() is not quite as useful. I'd suggest that a "timestamp first sample" block would do the same thing, and would be usable for sources other than gr-soapy, too.
Our workflow uses pull requests on Github. A short diff like this in email is fine as a question, but submitting a PR works better for us. On Mon, Oct 18, 2021 at 6:33 PM Bailey, Josh <j...@vandervecken.com> wrote: > Hi all, > > The gr-uhd driver, tags samples when center frequency changes and some > other events): > > > https://github.com/gnuradio/gnuradio/blob/8b23f906844c9784c784934ae06dfdfe10d31a1f/gr-uhd/lib/usrp_source_impl.cc#L619 > > I've been able to make a minimal patch to the soapy driver (see > following), that does the same thing for all other SDRs supported by soapy > (the patch is for proof of concept/illustrative purposes only - I > appreciate that it isn't compatible with the contribution guidelines). > > My question - would a suitable patch that provides these tags, be > acceptable to the maintainers? I can appreciate that it's possible that > there are flow graphs that just happen to use these same tags perhaps for > other purposes - perhaps I could then add a flag to make them optional? In > any case, the gr-uhd driver appears to always send them, already. > > Thanks, > > diff --git a/gr-soapy/lib/block_impl.h b/gr-soapy/lib/block_impl.h > index a1e95fdd0..74b2beffe 100644 > --- a/gr-soapy/lib/block_impl.h > +++ b/gr-soapy/lib/block_impl.h > @@ -90,6 +90,7 @@ protected: > public: > bool start() override; > bool stop() override; > + bool _tag_now; > > /*** Begin public API implementation ***/ > > diff --git a/gr-soapy/lib/source_impl.cc b/gr-soapy/lib/source_impl.cc > index f76d4437f..93aa06bb2 100644 > --- a/gr-soapy/lib/source_impl.cc > +++ b/gr-soapy/lib/source_impl.cc > @@ -47,6 +47,10 @@ source_impl::source_impl(const std::string& device, > { > } > > +static const pmt::pmt_t TIME_KEY = pmt::string_to_symbol("rx_time"); > +static const pmt::pmt_t FREQ_KEY = pmt::string_to_symbol("rx_freq"); > +static const pmt::pmt_t RATE_KEY = pmt::string_to_symbol("rx_rate"); > + > int source_impl::general_work(int noutput_items, > __GR_ATTR_UNUSED gr_vector_int& > ninput_items, > __GR_ATTR_UNUSED gr_vector_const_void_star& > input_items, > @@ -57,6 +61,11 @@ int source_impl::general_work(int noutput_items, > const long timeout_us = 500000; // 0.5 sec > int nout = 0; > > + std::stringstream str; > + str << name() << unique_id(); > + pmt::pmt_t _id = pmt::string_to_symbol(str.str()); > + std::time_t time_now = std::time(nullptr); > + > for (;;) { > > // No command handlers while reading > @@ -66,6 +75,25 @@ int source_impl::general_work(int noutput_items, > result = d_device->readStream( > d_stream, output_items.data(), noutput_items, flags, > time_ns, timeout_us); > } > + if (_tag_now) { > + _tag_now = false; > + // create a timestamp pmt for the first sample > + // TODO: use timestamp from radio hardware, and < 1s > granularity? > + const pmt::pmt_t val = > + pmt::make_tuple(pmt::from_uint64(time_now), > + pmt::from_double(0)); > + // create a tag set for each channel > + for (size_t i = 0; i < 1; i++) { // TODO: get actual number > of channels. > + this->add_item_tag(i, nitems_written(0), TIME_KEY, val, > _id); > + this->add_item_tag( > + i, nitems_written(0), RATE_KEY, > pmt::from_double(this->get_sample_rate(i)), _id); > + this->add_item_tag(i, > + nitems_written(0), > + FREQ_KEY, > + > pmt::from_double(this->get_frequency(i)), > + _id); > + } > + } > > if (result >= 0) { > nout = result; > > >