Statistics
| Branch: | Tag: | Revision:

root / gnuradio-core / src / lib / io / gr_tagged_file_sink.cc @ 9217bbca

History | View | Annotate | Download (6 kB)

1
/* -*- c++ -*- */
2
/*
3
 * Copyright 2010 Free Software Foundation, Inc.
4
 * 
5
 * This file is part of GNU Radio
6
 * 
7
 * GNU Radio is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3, or (at your option)
10
 * any later version.
11
 * 
12
 * GNU Radio is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 * 
17
 * You should have received a copy of the GNU General Public License
18
 * along with GNU Radio; see the file COPYING.  If not, write to
19
 * the Free Software Foundation, Inc., 51 Franklin Street,
20
 * Boston, MA 02110-1301, USA.
21
 */
22
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26
27
#include <gr_tagged_file_sink.h>
28
#include <gr_io_signature.h>
29
#include <cstdio>
30
#include <errno.h>
31
#include <sys/types.h>
32
#include <sys/stat.h>
33
#include <fcntl.h>
34
#include <stdexcept>
35
#include <iostream>
36
#include <gr_tag_info.h>
37
38
#ifdef O_BINARY
39
#define        OUR_O_BINARY O_BINARY
40
#else
41
#define        OUR_O_BINARY 0
42
#endif
43
44
// should be handled via configure
45
#ifdef O_LARGEFILE
46
#define        OUR_O_LARGEFILE        O_LARGEFILE
47
#else
48
#define        OUR_O_LARGEFILE 0
49
#endif
50
51
52
gr_tagged_file_sink::gr_tagged_file_sink (size_t itemsize, double samp_rate)
53
  : gr_sync_block ("tagged_file_sink",
54
                   gr_make_io_signature (1, 1, itemsize),
55
                   gr_make_io_signature (0, 0, 0)),
56
    d_itemsize (itemsize), d_n(0), d_sample_rate(samp_rate)
57
{
58
  d_state = NOT_IN_BURST;
59
  d_last_N = 0;
60
  d_timeval = 0;
61
}
62
63
gr_tagged_file_sink_sptr
64
gr_make_tagged_file_sink (size_t itemsize, double samp_rate)
65
{
66
  return gnuradio::get_initial_sptr(new gr_tagged_file_sink (itemsize, samp_rate));
67
}
68
69
gr_tagged_file_sink::~gr_tagged_file_sink ()
70
{
71
}
72
73
int 
74
gr_tagged_file_sink::work (int noutput_items,
75
                           gr_vector_const_void_star &input_items,
76
                           gr_vector_void_star &output_items)
77
{
78
  char *inbuf = (char *) input_items[0];
79
80
  uint64_t start_N = nitems_read(0);
81
  uint64_t end_N = start_N + (uint64_t)(noutput_items);
82
  pmt::pmt_t bkey = pmt::pmt_string_to_symbol("burst");
83
  //pmt::pmt_t tkey = pmt::pmt_string_to_symbol("time"); // use gr_tags::key_time
84
85
  std::vector<pmt::pmt_t> all_tags;
86
  get_tags_in_range(all_tags, 0, start_N, end_N);
87
88
  std::sort(all_tags.begin(), all_tags.end(), gr_tags::nitems_compare);
89
90
  std::vector<pmt::pmt_t>::iterator vitr = all_tags.begin();
91
92
  int idx = 0, idx_stop = 0;
93
  while(idx < noutput_items) {
94
    if(d_state == NOT_IN_BURST) {
95
      while(vitr != all_tags.end()) {
96
        if((pmt::pmt_eqv(gr_tags::get_key(*vitr), bkey)) &&
97
           pmt::pmt_is_true(gr_tags::get_value(*vitr))) {
98
99
          uint64_t N = gr_tags::get_nitems(*vitr);
100
          idx = (int)(N - start_N);
101
102
          std::cout << std::endl << "Found start of burst: "
103
                    << idx << ", " << N << std::endl;
104
105
          // Find time burst occurred by getting latest time tag and extrapolating
106
          // to new time based on sample rate of this block.
107
          std::vector<pmt::pmt_t> time_tags;
108
          get_tags_in_range(time_tags, 0, d_last_N, N, gr_tags::key_time);
109
          if(time_tags.size() > 0) {
110
            pmt::pmt_t tag = time_tags[time_tags.size()-1];
111
            
112
            uint64_t time_nitems = gr_tags::get_nitems(tag);
113
114
            // Get time based on last time tag from USRP
115
            pmt::pmt_t time = gr_tags::get_value(tag);
116
            int tsecs = pmt::pmt_to_long(pmt::pmt_tuple_ref(time, 0));
117
            double tfrac = pmt::pmt_to_double(pmt::pmt_tuple_ref(time, 1));
118
119
            // Get new time from last time tag + difference in time to when
120
            // burst tag occured based on the sample rate
121
            double delta = (double)(N - time_nitems) / d_sample_rate;
122
            d_timeval = (double)tsecs + tfrac + delta;
123
124
            std::cout.setf(std::ios::fixed, std::ios::floatfield);
125
            std::cout.precision(8);
126
            std::cout << "Time found: " << (double)tsecs + tfrac << std::endl;
127
            std::cout << "   time: " << d_timeval << std::endl;
128
            std::cout << "   time at N = " << time_nitems << " burst N = " << N << std::endl;
129
          }
130
          else {
131
            // if no time tag, use last seen tag and update time based on
132
            // sample rate of the block
133
            d_timeval += (double)(N - d_last_N) / d_sample_rate;
134
            std::cout << "Time not found" << std::endl;
135
            std::cout << "   time: " << d_timeval << std::endl;
136
          }
137
          d_last_N = N;
138
          
139
          std::stringstream filename;
140
          filename.setf(std::ios::fixed, std::ios::floatfield);
141
          filename.precision(8);
142
          filename << "file" << d_n << "_" << d_timeval << ".dat";
143
          d_n++;
144
          
145
          int fd;
146
          if ((fd = ::open (filename.str().c_str(),
147
                            O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY,
148
                            0664)) < 0){
149
            perror (filename.str().c_str());
150
            return -1;
151
          }
152
          
153
          // FIXME:
154
          //if ((d_handle = fdopen (fd, d_is_binary ? "wb" : "w")) == NULL){
155
          if ((d_handle = fdopen (fd, "wb")) == NULL){
156
            perror (filename.str().c_str());
157
            ::close(fd);                // don't leak file descriptor if fdopen fails.
158
          }
159
160
          std::cout << "Created new file: " << filename.str() << std::endl;
161
162
          d_state = IN_BURST;
163
          break;
164
        }
165
        
166
        vitr++;
167
      }
168
      if(d_state == NOT_IN_BURST)
169
        return noutput_items;
170
    }
171
    else {  // In burst
172
      while(vitr != all_tags.end()) {
173
        if((pmt::pmt_eqv(gr_tags::get_key(*vitr), bkey)) &&
174
           pmt::pmt_is_false(gr_tags::get_value(*vitr))) {
175
          uint64_t N = gr_tags::get_nitems(*vitr);
176
          idx_stop = (int)N - start_N;
177
178
          std::cout << "Found end of burst: "
179
                    << idx_stop << ", " << N << std::endl;
180
181
          int count = fwrite (&inbuf[d_itemsize*idx], d_itemsize, idx_stop-idx, d_handle);
182
          if (count == 0) {
183
            if(ferror(d_handle)) {
184
              perror("gr_tagged_file_sink: error writing file");
185
            }
186
          }
187
          idx = idx_stop;
188
          d_state = NOT_IN_BURST;
189
          vitr++;
190
          fclose(d_handle);
191
          break;
192
        }
193
        else {
194
          vitr++;
195
        }
196
      }
197
      if(d_state == IN_BURST) {
198
        int count = fwrite (&inbuf[idx], d_itemsize, noutput_items-idx, d_handle);
199
        if (count == 0) {
200
          if(ferror(d_handle)) {
201
            perror("gr_tagged_file_sink: error writing file");
202
          }
203
        }
204
        idx = noutput_items;
205
      }
206
    }
207
  }
208
209
  return noutput_items;
210
}