blob: 68fa207dfc04cb6c2caf5258b208a32dcf412008 [file] [log] [blame]
piotr4089c1a2014-08-06 14:10:56 +02001/* -*- c++ -*- */
ptrkrysik529895b2014-12-02 18:07:38 +01002/*
3 * @file
4 * @author Piotr Krysik <ptrkrysik@gmail.com>
5 * @section LICENSE
6 *
7 * Gr-gsm is free software; you can redistribute it and/or modify
piotr4089c1a2014-08-06 14:10:56 +02008 * 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.
ptrkrysik529895b2014-12-02 18:07:38 +010011 *
12 * Gr-gsm is distributed in the hope that it will be useful,
piotr4089c1a2014-08-06 14:10:56 +020013 * 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.
ptrkrysik529895b2014-12-02 18:07:38 +010016 *
piotr4089c1a2014-08-06 14:10:56 +020017 * You should have received a copy of the GNU General Public License
ptrkrysik529895b2014-12-02 18:07:38 +010018 * along with gr-gsm; see the file COPYING. If not, write to
piotr4089c1a2014-08-06 14:10:56 +020019 * 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 <gnuradio/io_signature.h>
28#include "controlled_rotator_cc_impl.h"
piotr4089c1a2014-08-06 14:10:56 +020029#include <math.h>
30
31namespace gr {
32 namespace gsm {
33
34 controlled_rotator_cc::sptr
35 controlled_rotator_cc::make(double phase_inc, double samp_rate)
36 {
37 return gnuradio::get_initial_sptr
38 (new controlled_rotator_cc_impl(phase_inc, samp_rate));
39 }
40
41 /*
42 * The private constructor
43 */
44 controlled_rotator_cc_impl::controlled_rotator_cc_impl(double phase_inc, double samp_rate)
45 : gr::sync_block("controlled_rotator_cc",
46 gr::io_signature::make2(1, 2, sizeof(gr_complex), sizeof(float)),
47 gr::io_signature::make(1, 1, sizeof(gr_complex)))
48 {
49 set_phase_inc(phase_inc);
50 set_samp_rate(samp_rate);
51 }
52
53 /*
54 * Our virtual destructor.
55 */
56 controlled_rotator_cc_impl::~controlled_rotator_cc_impl()
57 {
58 }
59
60 void
61 controlled_rotator_cc_impl::set_phase_inc(double phase_inc)
62 {
63 d_phase_inc = phase_inc;
64 d_r.set_phase_incr( exp(gr_complex(0, (double)phase_inc)) );
65 }
66
67 void
68 controlled_rotator_cc_impl::set_samp_rate(double samp_rate)
69 {
70 d_samp_rate = samp_rate;
71 }
72
73 int
74 controlled_rotator_cc_impl::work(int noutput_items,
75 gr_vector_const_void_star &input_items,
76 gr_vector_void_star &output_items)
Piotr Krysik74c4f2c2016-07-15 13:12:46 +020077 {
78 //process phase_inc input
piotr4089c1a2014-08-06 14:10:56 +020079 if(input_items.size() == 2) {
80 int ii=0;
81 const float *pp = (const float *)input_items[1];
82
83 while(ii < noutput_items){
84 //look for different values on phase increment control input
85 if(d_phase_inc != (*pp)){
Piotr K66bb3cd2014-08-13 19:04:57 +020086
piotr4089c1a2014-08-06 14:10:56 +020087 set_phase_inc(*(pp)); //set new value of phase increment
88
89 float freq_offset_setting = (*(pp) / (2*M_PI)) * d_samp_rate; //send stream tag with a new value of the frequency offset
Piotr K66bb3cd2014-08-13 19:04:57 +020090
91 uint64_t offset = nitems_written(0);
piotr4089c1a2014-08-06 14:10:56 +020092 pmt::pmt_t key = pmt::string_to_symbol("setting_freq_offset");
93 pmt::pmt_t value = pmt::from_double(freq_offset_setting);
94 add_item_tag(0,offset, key, value);
Piotr K66bb3cd2014-08-13 19:04:57 +020095
piotr4089c1a2014-08-06 14:10:56 +020096 break;
97 }
98 pp++;
99 ii++;
100 }
101 }
Piotr Krysik74c4f2c2016-07-15 13:12:46 +0200102
103 //get complex input and output
104 const gr_complex *in = (const gr_complex *)input_items[0];
105 gr_complex *out = (gr_complex *)output_items[0];
106 //get tags
piotr4089c1a2014-08-06 14:10:56 +0200107
Piotr Krysik74c4f2c2016-07-15 13:12:46 +0200108 uint64_t processed_in = 0;
109 uint64_t produced_out = 0;
110
111 std::vector<tag_t> set_phase_inc_tags;
112
113 pmt::pmt_t key = pmt::string_to_symbol("set_phase_inc");
114 get_tags_in_window(set_phase_inc_tags, 0, 0, noutput_items, key);
115
116 for(std::vector<tag_t>::iterator i_tag = set_phase_inc_tags.begin(); i_tag < set_phase_inc_tags.end(); i_tag++){
117 uint64_t tag_offset_rel = i_tag->offset-nitems_read(0);
118 set_phase_inc(pmt::to_double(i_tag->value));
119 uint64_t samples_to_process = tag_offset_rel-processed_in;
120 d_r.rotateN((out+produced_out), const_cast<gr_complex *>(in+processed_in), samples_to_process);
121 processed_in = processed_in + samples_to_process;
122 produced_out = produced_out + samples_to_process;
123// std::cout << "Rotator, phase inc: " << pmt::to_double(i_tag->value) << std::endl;
124
125 float freq_offset_setting = (pmt::to_double(i_tag->value) / (2*M_PI)) * d_samp_rate; //send stream tag with a new value of the frequency offset
126 pmt::pmt_t key = pmt::string_to_symbol("setting_freq_offset");
127 pmt::pmt_t value = pmt::from_double(freq_offset_setting);
128 add_item_tag(0,i_tag->offset, key, value);
129 }
130
131 d_r.rotateN((out+produced_out), const_cast<gr_complex *>(in+processed_in), (noutput_items-produced_out)); //const_cast<gr_complex *> is workaround old implementation of rotateN that is still present in ubuntu 14.04 packages
132 return noutput_items;
133 }
piotr4089c1a2014-08-06 14:10:56 +0200134 } /* namespace gsm */
135} /* namespace gr */
136