GNU Radio 3.6.3 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2004,2007,2009,2010 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #ifndef INCLUDED_GR_BLOCK_H 00024 #define INCLUDED_GR_BLOCK_H 00025 00026 #include <gr_core_api.h> 00027 #include <gr_basic_block.h> 00028 #include <gr_tags.h> 00029 00030 /*! 00031 * \brief The abstract base class for all 'terminal' processing blocks. 00032 * \ingroup base_blk 00033 * 00034 * A signal processing flow is constructed by creating a tree of 00035 * hierarchical blocks, which at any level may also contain terminal nodes 00036 * that actually implement signal processing functions. This is the base 00037 * class for all such leaf nodes. 00038 00039 * Blocks have a set of input streams and output streams. The 00040 * input_signature and output_signature define the number of input 00041 * streams and output streams respectively, and the type of the data 00042 * items in each stream. 00043 * 00044 * Although blocks may consume data on each input stream at a 00045 * different rate, all outputs streams must produce data at the same 00046 * rate. That rate may be different from any of the input rates. 00047 * 00048 * User derived blocks override two methods, forecast and general_work, 00049 * to implement their signal processing behavior. forecast is called 00050 * by the system scheduler to determine how many items are required on 00051 * each input stream in order to produce a given number of output 00052 * items. 00053 * 00054 * general_work is called to perform the signal processing in the block. 00055 * It reads the input items and writes the output items. 00056 */ 00057 00058 class GR_CORE_API gr_block : public gr_basic_block { 00059 00060 public: 00061 00062 //! Magic return values from general_work 00063 enum { 00064 WORK_CALLED_PRODUCE = -2, 00065 WORK_DONE = -1 00066 }; 00067 00068 enum tag_propagation_policy_t { 00069 TPP_DONT = 0, 00070 TPP_ALL_TO_ALL = 1, 00071 TPP_ONE_TO_ONE = 2 00072 }; 00073 00074 virtual ~gr_block (); 00075 00076 /*! 00077 * Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...) 00078 * History is the number of x_i's that are examined to produce one y_i. 00079 * This comes in handy for FIR filters, where we use history to 00080 * ensure that our input contains the appropriate "history" for the 00081 * filter. History should be equal to the number of filter taps. 00082 */ 00083 unsigned history () const { return d_history; } 00084 void set_history (unsigned history) { d_history = history; } 00085 00086 /*! 00087 * \brief Return true if this block has a fixed input to output rate. 00088 * 00089 * If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called. 00090 */ 00091 bool fixed_rate() const { return d_fixed_rate; } 00092 00093 // ---------------------------------------------------------------- 00094 // override these to define your behavior 00095 // ---------------------------------------------------------------- 00096 00097 /*! 00098 * \brief Estimate input requirements given output request 00099 * 00100 * \param noutput_items number of output items to produce 00101 * \param ninput_items_required number of input items required on each input stream 00102 * 00103 * Given a request to product \p noutput_items, estimate the number of 00104 * data items required on each input stream. The estimate doesn't have 00105 * to be exact, but should be close. 00106 */ 00107 virtual void forecast (int noutput_items, 00108 gr_vector_int &ninput_items_required); 00109 00110 /*! 00111 * \brief compute output items from input items 00112 * 00113 * \param noutput_items number of output items to write on each output stream 00114 * \param ninput_items number of input items available on each input stream 00115 * \param input_items vector of pointers to the input items, one entry per input stream 00116 * \param output_items vector of pointers to the output items, one entry per output stream 00117 * 00118 * \returns number of items actually written to each output stream, or -1 on EOF. 00119 * It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items 00120 * 00121 * general_work must call consume or consume_each to indicate how many items 00122 * were consumed on each input stream. 00123 */ 00124 virtual int general_work (int noutput_items, 00125 gr_vector_int &ninput_items, 00126 gr_vector_const_void_star &input_items, 00127 gr_vector_void_star &output_items); 00128 00129 /*! 00130 * \brief Called to enable drivers, etc for i/o devices. 00131 * 00132 * This allows a block to enable an associated driver to begin 00133 * transfering data just before we start to execute the scheduler. 00134 * The end result is that this reduces latency in the pipeline when 00135 * dealing with audio devices, usrps, etc. 00136 */ 00137 virtual bool start(); 00138 00139 /*! 00140 * \brief Called to disable drivers, etc for i/o devices. 00141 */ 00142 virtual bool stop(); 00143 00144 // ---------------------------------------------------------------- 00145 00146 /*! 00147 * \brief Constrain the noutput_items argument passed to forecast and general_work 00148 * 00149 * set_output_multiple causes the scheduler to ensure that the noutput_items 00150 * argument passed to forecast and general_work will be an integer multiple 00151 * of \param multiple The default value of output multiple is 1. 00152 */ 00153 void set_output_multiple (int multiple); 00154 int output_multiple () const { return d_output_multiple; } 00155 bool output_multiple_set () const { return d_output_multiple_set; } 00156 00157 /*! 00158 * \brief Constrains buffers to work on a set item alignment (for SIMD) 00159 * 00160 * set_alignment_multiple causes the scheduler to ensure that the noutput_items 00161 * argument passed to forecast and general_work will be an integer multiple 00162 * of \param multiple The default value is 1. 00163 * 00164 * This control is similar to the output_multiple setting, except 00165 * that if the number of items passed to the block is less than the 00166 * output_multiple, this value is ignored and the block can produce 00167 * like normal. The d_unaligned value is set to the number of items 00168 * the block is off by. In the next call to general_work, the 00169 * noutput_items is set to d_unaligned or less until 00170 * d_unaligned==0. The buffers are now aligned again and the aligned 00171 * calls can be performed again. 00172 */ 00173 void set_alignment (int multiple); 00174 int alignment () const { return d_output_multiple; } 00175 00176 void set_unaligned (int na); 00177 int unaligned () const { return d_unaligned; } 00178 void set_is_unaligned (bool u); 00179 bool is_unaligned () const { return d_is_unaligned; } 00180 00181 /*! 00182 * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed. 00183 */ 00184 void consume (int which_input, int how_many_items); 00185 00186 /*! 00187 * \brief Tell the scheduler \p how_many_items were consumed on each input stream. 00188 */ 00189 void consume_each (int how_many_items); 00190 00191 /*! 00192 * \brief Tell the scheduler \p how_many_items were produced on output stream \p which_output. 00193 * 00194 * If the block's general_work method calls produce, \p general_work must return WORK_CALLED_PRODUCE. 00195 */ 00196 void produce (int which_output, int how_many_items); 00197 00198 /*! 00199 * \brief Set the approximate output rate / input rate 00200 * 00201 * Provide a hint to the buffer allocator and scheduler. 00202 * The default relative_rate is 1.0 00203 * 00204 * decimators have relative_rates < 1.0 00205 * interpolators have relative_rates > 1.0 00206 */ 00207 void set_relative_rate (double relative_rate); 00208 00209 /*! 00210 * \brief return the approximate output rate / input rate 00211 */ 00212 double relative_rate () const { return d_relative_rate; } 00213 00214 /* 00215 * The following two methods provide special case info to the 00216 * scheduler in the event that a block has a fixed input to output 00217 * ratio. gr_sync_block, gr_sync_decimator and gr_sync_interpolator 00218 * override these. If you're fixed rate, subclass one of those. 00219 */ 00220 /*! 00221 * \brief Given ninput samples, return number of output samples that will be produced. 00222 * N.B. this is only defined if fixed_rate returns true. 00223 * Generally speaking, you don't need to override this. 00224 */ 00225 virtual int fixed_rate_ninput_to_noutput(int ninput); 00226 00227 /*! 00228 * \brief Given noutput samples, return number of input samples required to produce noutput. 00229 * N.B. this is only defined if fixed_rate returns true. 00230 * Generally speaking, you don't need to override this. 00231 */ 00232 virtual int fixed_rate_noutput_to_ninput(int noutput); 00233 00234 /*! 00235 * \brief Return the number of items read on input stream which_input 00236 */ 00237 uint64_t nitems_read(unsigned int which_input); 00238 00239 /*! 00240 * \brief Return the number of items written on output stream which_output 00241 */ 00242 uint64_t nitems_written(unsigned int which_output); 00243 00244 /*! 00245 * \brief Asks for the policy used by the scheduler to moved tags downstream. 00246 */ 00247 tag_propagation_policy_t tag_propagation_policy(); 00248 00249 /*! 00250 * \brief Set the policy by the scheduler to determine how tags are moved downstream. 00251 */ 00252 void set_tag_propagation_policy(tag_propagation_policy_t p); 00253 00254 /*! 00255 * \brief Return the maximum number of output items this block will 00256 * handle during a call to work. 00257 */ 00258 int max_noutput_items(); 00259 00260 /*! 00261 * \brief Set the maximum number of ouput items htis block will 00262 * handle during a call to work. 00263 * 00264 * \param m the maximum noutput_items this block will handle. 00265 */ 00266 void set_max_noutput_items(int m); 00267 00268 /*! 00269 * \brief Clear the switch for using the max_noutput_items value of this block. 00270 * 00271 * When is_set_max_noutput_items() returns 'true', the scheduler 00272 * will use the value returned by max_noutput_items() to limit the 00273 * size of the number of items possible for this block's work 00274 * function. If is_set_max_notput_items() returns 'false', then the 00275 * scheduler ignores the internal value and uses the value set 00276 * globally in the top_block. 00277 * 00278 * Use this value to clear the 'is_set' flag so the scheduler will 00279 * ignore this. Use the set_max_noutput_items(m) call to both set a 00280 * new value for max_noutput_items and to reenable its use in the 00281 * scheduler. 00282 */ 00283 void unset_max_noutput_items(); 00284 00285 /*! 00286 * \brief Ask the block if the flag is or is not set to use the 00287 * internal value of max_noutput_items during a call to work. 00288 */ 00289 bool is_set_max_noutput_items(); 00290 00291 /* 00292 * Used to expand the vectors that hold the min/max buffer sizes. 00293 * 00294 * Specifically, when -1 is used, the vectors are just initialized 00295 * with 1 value; this is used by the flat_flowgraph to expand when 00296 * required to add a new value for new ports on these blocks. 00297 */ 00298 void expand_minmax_buffer(int port) { 00299 if((size_t)port >= d_max_output_buffer.size()) 00300 set_max_output_buffer(port, -1); 00301 if((size_t)port >= d_min_output_buffer.size()) 00302 set_min_output_buffer(port, -1); 00303 } 00304 00305 /*! 00306 * \brief Returns max buffer size on output port \p i. 00307 */ 00308 long max_output_buffer(size_t i) { 00309 if(i >= d_max_output_buffer.size()) 00310 throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range."); 00311 return d_max_output_buffer[i]; 00312 } 00313 00314 /*! 00315 * \brief Sets max buffer size on all output ports. 00316 */ 00317 void set_max_output_buffer(long max_output_buffer) { 00318 for(int i = 0; i < output_signature()->max_streams(); i++) { 00319 set_max_output_buffer(i, max_output_buffer); 00320 } 00321 } 00322 00323 /*! 00324 * \brief Sets max buffer size on output port \p port. 00325 */ 00326 void set_max_output_buffer(int port, long max_output_buffer) { 00327 if((size_t)port >= d_max_output_buffer.size()) 00328 d_max_output_buffer.push_back(max_output_buffer); 00329 else 00330 d_max_output_buffer[port] = max_output_buffer; 00331 } 00332 00333 /*! 00334 * \brief Returns min buffer size on output port \p i. 00335 */ 00336 long min_output_buffer(size_t i) { 00337 if(i >= d_min_output_buffer.size()) 00338 throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range."); 00339 return d_min_output_buffer[i]; 00340 } 00341 00342 /*! 00343 * \brief Sets min buffer size on all output ports. 00344 */ 00345 void set_min_output_buffer(long min_output_buffer) { 00346 for(int i=0; i<output_signature()->max_streams(); i++) { 00347 set_min_output_buffer(i, min_output_buffer); 00348 } 00349 } 00350 00351 /*! 00352 * \brief Sets min buffer size on output port \p port. 00353 */ 00354 void set_min_output_buffer(int port, long min_output_buffer) { 00355 if((size_t)port >= d_min_output_buffer.size()) 00356 d_min_output_buffer.push_back(min_output_buffer); 00357 else 00358 d_min_output_buffer[port] = min_output_buffer; 00359 } 00360 00361 // ---------------------------------------------------------------------------- 00362 00363 private: 00364 00365 int d_output_multiple; 00366 bool d_output_multiple_set; 00367 int d_unaligned; 00368 bool d_is_unaligned; 00369 double d_relative_rate; // approx output_rate / input_rate 00370 gr_block_detail_sptr d_detail; // implementation details 00371 unsigned d_history; 00372 bool d_fixed_rate; 00373 bool d_max_noutput_items_set; // if d_max_noutput_items is valid 00374 int d_max_noutput_items; // value of max_noutput_items for this block 00375 tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream 00376 00377 protected: 00378 gr_block (void){} //allows pure virtual interface sub-classes 00379 gr_block (const std::string &name, 00380 gr_io_signature_sptr input_signature, 00381 gr_io_signature_sptr output_signature); 00382 00383 void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; } 00384 00385 00386 /*! 00387 * \brief Adds a new tag onto the given output buffer. 00388 * 00389 * \param which_output an integer of which output stream to attach the tag 00390 * \param abs_offset a uint64 number of the absolute item number 00391 * assicated with the tag. Can get from nitems_written. 00392 * \param key the tag key as a PMT symbol 00393 * \param value any PMT holding any value for the given key 00394 * \param srcid optional source ID specifier; defaults to PMT_F 00395 */ 00396 inline void add_item_tag(unsigned int which_output, 00397 uint64_t abs_offset, 00398 const pmt::pmt_t &key, 00399 const pmt::pmt_t &value, 00400 const pmt::pmt_t &srcid=pmt::PMT_F) 00401 { 00402 gr_tag_t tag; 00403 tag.offset = abs_offset; 00404 tag.key = key; 00405 tag.value = value; 00406 tag.srcid = srcid; 00407 this->add_item_tag(which_output, tag); 00408 } 00409 00410 /*! 00411 * \brief Adds a new tag onto the given output buffer. 00412 * 00413 * \param which_output an integer of which output stream to attach the tag 00414 * \param tag the tag object to add 00415 */ 00416 void add_item_tag(unsigned int which_output, const gr_tag_t &tag); 00417 00418 /*! 00419 * \brief Given a [start,end), returns a vector of all tags in the range. 00420 * 00421 * Range of counts is from start to end-1. 00422 * 00423 * Tags are tuples of: 00424 * (item count, source id, key, value) 00425 * 00426 * \param v a vector reference to return tags into 00427 * \param which_input an integer of which input stream to pull from 00428 * \param abs_start a uint64 count of the start of the range of interest 00429 * \param abs_end a uint64 count of the end of the range of interest 00430 */ 00431 void get_tags_in_range(std::vector<gr_tag_t> &v, 00432 unsigned int which_input, 00433 uint64_t abs_start, 00434 uint64_t abs_end); 00435 00436 /*! 00437 * \brief Given a [start,end), returns a vector of all tags in the range 00438 * with a given key. 00439 * 00440 * Range of counts is from start to end-1. 00441 * 00442 * Tags are tuples of: 00443 * (item count, source id, key, value) 00444 * 00445 * \param v a vector reference to return tags into 00446 * \param which_input an integer of which input stream to pull from 00447 * \param abs_start a uint64 count of the start of the range of interest 00448 * \param abs_end a uint64 count of the end of the range of interest 00449 * \param key a PMT symbol key to filter only tags of this key 00450 */ 00451 void get_tags_in_range(std::vector<gr_tag_t> &v, 00452 unsigned int which_input, 00453 uint64_t abs_start, 00454 uint64_t abs_end, 00455 const pmt::pmt_t &key); 00456 00457 std::vector<long> d_max_output_buffer; 00458 std::vector<long> d_min_output_buffer; 00459 00460 00461 // These are really only for internal use, but leaving them public avoids 00462 // having to work up an ever-varying list of friend GR_CORE_APIs 00463 00464 public: 00465 gr_block_detail_sptr detail () const { return d_detail; } 00466 void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } 00467 }; 00468 00469 typedef std::vector<gr_block_sptr> gr_block_vector_t; 00470 typedef std::vector<gr_block_sptr>::iterator gr_block_viter_t; 00471 00472 inline gr_block_sptr cast_to_block_sptr(gr_basic_block_sptr p) 00473 { 00474 return boost::dynamic_pointer_cast<gr_block, gr_basic_block>(p); 00475 } 00476 00477 00478 std::ostream& 00479 operator << (std::ostream& os, const gr_block *m); 00480 00481 #endif /* INCLUDED_GR_BLOCK_H */