Statistics
| Branch: | Tag: | Revision:

gnuradio / gr-uhd / examples / c++ / tag_source_demo.h @ master

History | View | Annotate | Download (5.97 KB)

1
/*
2
 * Copyright 2011 Free Software Foundation, Inc.
3
 *
4
 * This file is part of GNU Radio
5
 *
6
 * GNU Radio is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3, or (at your option)
9
 * any later version.
10
 *
11
 * GNU Radio is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with GNU Radio; see the file COPYING.  If not, write to
18
 * the Free Software Foundation, Inc., 51 Franklin Street,
19
 * Boston, MA 02110-1301, USA.
20
 */
21

22
#include <gnuradio/sync_block.h>
23
#include <gnuradio/io_signature.h>
24
#include <boost/foreach.hpp>
25
#include <boost/format.hpp>
26
#include <iostream>
27
#include <complex>
28

29
class tag_source_demo : public gr::sync_block
30
{
31
public:
32

33
    tag_source_demo(
34
        const uint64_t start_secs,
35
        const double start_fracs,
36
        const double samp_rate,
37
        const double idle_duration,
38
        const double burst_duration,
39
        const std::string &length_tag_name = ""
40
    ):
41
        sync_block(
42
            "uhd tag source demo",
43
            gr::io_signature::make(0, 0, 0),
44
            gr::io_signature::make(1, 1, sizeof(std::complex<float>))
45
        ),
46
        _time_secs(start_secs),
47
        _time_fracs(start_fracs),
48
        _samp_rate(samp_rate),
49
        _samps_per_burst(samp_rate*burst_duration),
50
        _cycle_duration(idle_duration + burst_duration),
51
        _samps_left_in_burst(1), //immediate EOB
52
        _do_new_burst(false),
53
        _firstrun(not length_tag_name.empty()),
54
        _length_tag_key(length_tag_name.empty() ? pmt::PMT_NIL : pmt::string_to_symbol(length_tag_name))
55
    {
56
        //NOP
57
    }
58

59
    void make_time_tag(const uint64_t tag_count)
60
    {
61
        const pmt::pmt_t key = pmt::string_to_symbol("tx_time");
62
        const pmt::pmt_t value = pmt::make_tuple(
63
            pmt::from_uint64(_time_secs),
64
            pmt::from_double(_time_fracs)
65
        );
66
        const pmt::pmt_t srcid = pmt::string_to_symbol(this->name());
67
        this->add_item_tag(0/*chan0*/, tag_count, key, value, srcid);
68
    }
69

70
    void make_sob_tag(const uint64_t tag_count)
71
    {
72
        const pmt::pmt_t key = pmt::string_to_symbol("tx_sob");
73
        const pmt::pmt_t value = pmt::PMT_T;
74
        const pmt::pmt_t srcid = pmt::string_to_symbol(this->name());
75
        this->add_item_tag(0/*chan0*/, tag_count, key, value, srcid);
76
    }
77

78
    void make_eob_tag(const uint64_t tag_count)
79
    {
80
        const pmt::pmt_t key = pmt::string_to_symbol("tx_eob");
81
        const pmt::pmt_t value = pmt::PMT_T;
82
        const pmt::pmt_t srcid = pmt::string_to_symbol(this->name());
83
        this->add_item_tag(0/*chan0*/, tag_count, key, value, srcid);
84
    }
85

86
    void make_length_tag(const uint64_t tag_count, const uint64_t burst_len)
87
    {
88
        if (pmt::is_null(_length_tag_key)) {
89
            //no length_tag was specified at initialization; make a tx_sob tag instead
90
            this->make_sob_tag(tag_count);
91
            return;
92
        }
93
        const pmt::pmt_t key = _length_tag_key;
94
        const pmt::pmt_t value = pmt::from_long((long)burst_len);
95
        const pmt::pmt_t srcid = pmt::string_to_symbol(this->name());
96
        this->add_item_tag(0/*chan0*/, tag_count, key, value, srcid);
97
    }
98

99
    int work(
100
        int noutput_items,
101
        gr_vector_const_void_star &input_items,
102
        gr_vector_void_star &output_items)
103
    {
104
        //load the output with a constant
105
        std::complex<float> *output = reinterpret_cast<std::complex<float> *>(output_items[0]);
106
        for (size_t i = 0; i < size_t(noutput_items); i++) {
107
            output[i] = std::complex<float>(0.7, 0.7);
108
        }
109

110
        //Handle the start of burst condition.
111
        //Tag a start of burst and timestamp.
112
        //Increment the time for the next burst.
113
        if (_do_new_burst) {
114
            _do_new_burst = false;
115
            _samps_left_in_burst = _samps_per_burst;
116

117
            if (pmt::is_null(_length_tag_key))
118
                this->make_sob_tag(this->nitems_written(0));
119
            else
120
#if 1
121
                this->make_length_tag(this->nitems_written(0), _samps_left_in_burst);
122
#else
123
                //Test usrp_sink's ability to cancel remainder of burst if new length_tag is found early
124
                //sets burst time to 10% greater than the cycle duration to guarantee early length_tag
125
                //In a real implementation the user should guard against this so that the number of
126
                //samples promised by the length_tag are actually processed by the usrp_sink.
127
                this->make_length_tag(this->nitems_written(0), uint64_t(1.1 * _samp_rate * _cycle_duration));
128
#endif
129
            this->make_time_tag(this->nitems_written(0));
130

131
            _time_fracs += _cycle_duration;
132
            double intpart; //normalize
133
            _time_fracs = std::modf(_time_fracs, &intpart);
134
            _time_secs += uint64_t(intpart);
135
        }
136

137
        //Handle the end of burst condition.
138
        //Tag an end of burst and return early.
139
        //the next work call will be a start of burst.
140
        if (_samps_left_in_burst < size_t(noutput_items)){
141
            if (pmt::is_null(_length_tag_key))
142
                this->make_eob_tag(this->nitems_written(0) + _samps_left_in_burst - 1);
143
            else if (_firstrun){
144
                _firstrun = false;
145
                this->make_length_tag(this->nitems_written(0), 1);
146
            }
147
            _do_new_burst = true;
148
            noutput_items = _samps_left_in_burst;
149
        }
150

151
        _samps_left_in_burst -= noutput_items;
152
        return noutput_items;
153
    }
154

155
private:
156
    uint64_t _time_secs;
157
    double _time_fracs;
158
    const double _samp_rate;
159
    const uint64_t _samps_per_burst;
160
    const double _cycle_duration;
161
    uint64_t _samps_left_in_burst;
162
    bool _do_new_burst;
163
    bool _firstrun;
164
    const pmt::pmt_t _length_tag_key;
165

166
};