| 1 | /**************************************************************************** |
|---|
| 2 | |
|---|
| 3 | Copyright 2005,2006 Virginia Polytechnic Institute and State University |
|---|
| 4 | |
|---|
| 5 | This file is part of the OSSIE Decimator. |
|---|
| 6 | |
|---|
| 7 | OSSIE Decimator 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 2 of the License, or |
|---|
| 10 | (at your option) any later version. |
|---|
| 11 | |
|---|
| 12 | OSSIE Decimator 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 OSSIE Decimator; if not, write to the Free Software |
|---|
| 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 20 | |
|---|
| 21 | |
|---|
| 22 | ****************************************************************************/ |
|---|
| 23 | |
|---|
| 24 | #include <iostream> |
|---|
| 25 | |
|---|
| 26 | #include <string.h> |
|---|
| 27 | #include <math.h> // For energy debugging routine |
|---|
| 28 | #include "ossie/cf.h" |
|---|
| 29 | |
|---|
| 30 | #include "Decimator.h" |
|---|
| 31 | |
|---|
| 32 | //#define PRINT_ENERGY 1 |
|---|
| 33 | |
|---|
| 34 | Decimator_i::Decimator_i(const char *uuid, omni_condition *condition) : |
|---|
| 35 | Resource_impl(uuid), |
|---|
| 36 | component_running(condition), |
|---|
| 37 | calculateFilterCoefficients(true), |
|---|
| 38 | M(1), |
|---|
| 39 | sample_count(0), |
|---|
| 40 | previous_length(0){ |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | // Create the port for output data |
|---|
| 44 | dataOut = new standardInterfaces_i::complexShort_u("outData"); |
|---|
| 45 | |
|---|
| 46 | // Create port for input Data |
|---|
| 47 | dataIn = new standardInterfaces_i::complexShort_p("inData"); |
|---|
| 48 | |
|---|
| 49 | // Start the run_decimation thread |
|---|
| 50 | processing_thread = new omni_thread(do_run_decimation, (void *) this); |
|---|
| 51 | processing_thread->start(); |
|---|
| 52 | |
|---|
| 53 | filter_type=FIR; |
|---|
| 54 | // Filter length is L |
|---|
| 55 | len_h = 1; |
|---|
| 56 | h = new float[len_h]; |
|---|
| 57 | |
|---|
| 58 | h[0] = 1.0; |
|---|
| 59 | |
|---|
| 60 | fir_i_filter = new SigProc::fir_filter(h, len_h); |
|---|
| 61 | fir_q_filter = new SigProc::fir_filter(h, len_h); |
|---|
| 62 | iir_i_filter = NULL; |
|---|
| 63 | iir_q_filter = NULL; |
|---|
| 64 | |
|---|
| 65 | //outFile = new std::ofstream("decimator_out.dat"); |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | void Decimator_i::start() throw (CF::Resource::StartError, CORBA::SystemException) |
|---|
| 69 | |
|---|
| 70 | { |
|---|
| 71 | std::cout << "Start Decimator called" << std::endl; |
|---|
| 72 | |
|---|
| 73 | } |
|---|
| 74 | |
|---|
| 75 | void Decimator_i::stop() throw (CF::Resource::StopError, CORBA::SystemException) |
|---|
| 76 | |
|---|
| 77 | { |
|---|
| 78 | std::cout << "Stop decimator called" << std::endl; |
|---|
| 79 | |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | CORBA::Object_ptr Decimator_i::getPort(const char* portName) throw(CF::PortSupplier::UnknownPort, CORBA::SystemException) |
|---|
| 83 | |
|---|
| 84 | { |
|---|
| 85 | std::cout << "Decimator getPort called with : " << portName << std::endl; |
|---|
| 86 | |
|---|
| 87 | CORBA::Object_var p; |
|---|
| 88 | |
|---|
| 89 | p = dataOut->getPort(portName); |
|---|
| 90 | |
|---|
| 91 | if (!CORBA::is_nil(p)) |
|---|
| 92 | return p._retn(); |
|---|
| 93 | |
|---|
| 94 | p = dataIn->getPort(portName); |
|---|
| 95 | |
|---|
| 96 | if (!CORBA::is_nil(p)) |
|---|
| 97 | return p._retn(); |
|---|
| 98 | |
|---|
| 99 | throw CF::PortSupplier::UnknownPort(); |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | void Decimator_i::initialize() throw (CF::LifeCycle::InitializeError, CORBA::SystemException) |
|---|
| 103 | |
|---|
| 104 | { |
|---|
| 105 | std::cout << "Decimator Initialize called" << std::endl; |
|---|
| 106 | |
|---|
| 107 | } |
|---|
| 108 | |
|---|
| 109 | void Decimator_i::configure(const CF::Properties& props) throw (CORBA::SystemException, CF::PropertySet::InvalidConfiguration, CF::PropertySet::PartialConfiguration) |
|---|
| 110 | |
|---|
| 111 | { |
|---|
| 112 | std::cout << "decimator Configure called" << std::endl; |
|---|
| 113 | |
|---|
| 114 | std::cout << "Props length : " << props.length() << std::endl; |
|---|
| 115 | |
|---|
| 116 | for (unsigned int i = 0; i < props.length(); i++) { |
|---|
| 117 | std::cout << "Property id : " << props[i].id << std::endl; |
|---|
| 118 | |
|---|
| 119 | // DecimateBy property, sets the decimator factor |
|---|
| 120 | if (strcmp(props[i].id, "DCE:cea26b54-9d86-4b68-a761-14186efa9415") == 0) { |
|---|
| 121 | CORBA::UShort D; |
|---|
| 122 | props[i].value >>= D; |
|---|
| 123 | M = D; |
|---|
| 124 | std::cout << "Decimation factor set to " << M << std::endl; |
|---|
| 125 | |
|---|
| 126 | } else if (strcmp(props[i].id, "DCE:134e5dd8-c773-47af-a557-2837076358c4") == 0) { |
|---|
| 127 | // filter property, Filter coefficients |
|---|
| 128 | CORBA::FloatSeq *coeff_ptr; |
|---|
| 129 | props[i].value >>= coeff_ptr; |
|---|
| 130 | |
|---|
| 131 | len_h = coeff_ptr->length(); |
|---|
| 132 | |
|---|
| 133 | if (len_h < 2) { |
|---|
| 134 | calculateFilterCoefficients = true; |
|---|
| 135 | } else { |
|---|
| 136 | calculateFilterCoefficients = false; |
|---|
| 137 | |
|---|
| 138 | delete []h; |
|---|
| 139 | delete_filter_variables(); |
|---|
| 140 | |
|---|
| 141 | h = new float[len_h]; |
|---|
| 142 | std::cout << "Decimator filter length = " << len_h << std::endl; |
|---|
| 143 | for (unsigned int k = 0; k < len_h; k++) { |
|---|
| 144 | h[k] = (*coeff_ptr)[k]; |
|---|
| 145 | DEBUG(3, Decimator, "Coeff[" << k << "] = " << h[k]) |
|---|
| 146 | } |
|---|
| 147 | fir_i_filter = new SigProc::fir_filter(h, len_h); |
|---|
| 148 | fir_q_filter = new SigProc::fir_filter(h, len_h); |
|---|
| 149 | } |
|---|
| 150 | } else if (strcmp(props[i].id, "DCE:537a42d9-2dd7-45b8-8dfb-f0999115ba71") == 0) { |
|---|
| 151 | const char * prop_str; |
|---|
| 152 | props[i].value >>= prop_str; |
|---|
| 153 | if ( strcmp(prop_str, "FIR") == 0 ) { |
|---|
| 154 | filter_type=FIR; |
|---|
| 155 | DEBUG(3, Decimator, "Filtertype set to FIR") |
|---|
| 156 | } else if ( strcmp(prop_str, "IIR") == 0 ){ |
|---|
| 157 | filter_type=IIR; |
|---|
| 158 | DEBUG(3, Decimator, "Filtertype set to IIR") |
|---|
| 159 | } else { |
|---|
| 160 | std::cerr << "ERROR: Decimator::configure() unknown filter type" << std::endl; |
|---|
| 161 | throw CF::PropertySet::InvalidConfiguration(); |
|---|
| 162 | }; |
|---|
| 163 | } else { |
|---|
| 164 | std::cerr << "ERROR: Decimator::configure(): Unknown property " |
|---|
| 165 | << props[i].id << std::endl; |
|---|
| 166 | throw CF::PropertySet::InvalidConfiguration(); |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | } |
|---|
| 170 | |
|---|
| 171 | |
|---|
| 172 | if (filter_type==FIR) { |
|---|
| 173 | |
|---|
| 174 | if (calculateFilterCoefficients) { |
|---|
| 175 | // calculate filter coefficients dynamically |
|---|
| 176 | unsigned int m(2); // filter delay (symbols) |
|---|
| 177 | float beta(0.5f); // excess bandwidth factor |
|---|
| 178 | len_h = 2*2*M*m+1; // filter length (samples) |
|---|
| 179 | delete [] h; |
|---|
| 180 | h = new float[len_h]; |
|---|
| 181 | SigProc::DesignRRCFilter(2*M, m, beta, h); |
|---|
| 182 | |
|---|
| 183 | // delete old filters |
|---|
| 184 | delete_filter_variables(); |
|---|
| 185 | |
|---|
| 186 | // print coefficients |
|---|
| 187 | for (unsigned int k=0; k<len_h; k++) |
|---|
| 188 | DEBUG(2, Decimator, " h[" << k << "] = " << h[k]); |
|---|
| 189 | |
|---|
| 190 | fir_i_filter = new SigProc::fir_filter(h, len_h); |
|---|
| 191 | fir_q_filter = new SigProc::fir_filter(h, len_h); |
|---|
| 192 | } |
|---|
| 193 | |
|---|
| 194 | } else { |
|---|
| 195 | |
|---|
| 196 | |
|---|
| 197 | |
|---|
| 198 | float *b_f; ///< feedforward filter coefficients |
|---|
| 199 | float *a_f; ///< feedback filter coefficients |
|---|
| 200 | unsigned int f_order; ///< filter order |
|---|
| 201 | // 10th-order Butterworth IIR filter, wc = (1/M)*pi rad, |
|---|
| 202 | f_order = 10; |
|---|
| 203 | b_f = new float[f_order+1]; |
|---|
| 204 | a_f = new float[f_order+1]; |
|---|
| 205 | // Delete old filters |
|---|
| 206 | delete_filter_variables(); |
|---|
| 207 | SigProc::design_butter_lowpass_filter(f_order, 1.0/M, b_f, a_f); |
|---|
| 208 | iir_i_filter = new SigProc::iir_filter(a_f, f_order+1, b_f, f_order+1); |
|---|
| 209 | iir_q_filter = new SigProc::iir_filter(a_f, f_order+1, b_f, f_order+1); |
|---|
| 210 | DEBUG(3, Decimator, "IIR Filter generated") |
|---|
| 211 | delete b_f; |
|---|
| 212 | delete a_f; |
|---|
| 213 | |
|---|
| 214 | } |
|---|
| 215 | |
|---|
| 216 | } |
|---|
| 217 | void Decimator_i::releaseObject() throw (CF::LifeCycle::ReleaseError, CORBA::SystemException) |
|---|
| 218 | |
|---|
| 219 | { |
|---|
| 220 | |
|---|
| 221 | std::cout << "decimator releaseObject called" << std::endl; |
|---|
| 222 | |
|---|
| 223 | delete outFile; |
|---|
| 224 | |
|---|
| 225 | // Clear the component running semaphore so main shuts down everything |
|---|
| 226 | component_running->signal(); |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | void Decimator_i::run_decimation() |
|---|
| 230 | { |
|---|
| 231 | std::cout << "run_decimation thread started" << std::endl; |
|---|
| 232 | |
|---|
| 233 | /** |
|---|
| 234 | #ifdef LOG_DATA |
|---|
| 235 | dump_data pre_decim("pre.dat", 1000, 1000); |
|---|
| 236 | dump_data post_decim("post.dat", 1000, 1000); |
|---|
| 237 | #endif |
|---|
| 238 | **/ |
|---|
| 239 | |
|---|
| 240 | unsigned int len=1024; |
|---|
| 241 | unsigned int len_out=1024; |
|---|
| 242 | PortTypes::ShortSequence I_out, Q_out; |
|---|
| 243 | short * I_buf = new short[len]; |
|---|
| 244 | short * Q_buf = new short[len]; |
|---|
| 245 | bool output_sample(false); |
|---|
| 246 | |
|---|
| 247 | while (1) { |
|---|
| 248 | PortTypes::ShortSequence *I_in(NULL), *Q_in(NULL); |
|---|
| 249 | |
|---|
| 250 | |
|---|
| 251 | dataIn->getData(I_in, Q_in); |
|---|
| 252 | |
|---|
| 253 | len=I_in->length(); |
|---|
| 254 | |
|---|
| 255 | DEBUG(5, Decimator, "Received "<<len<<" samples") |
|---|
| 256 | |
|---|
| 257 | if (len != previous_length) { |
|---|
| 258 | len_out=(unsigned int)(1.0*len/M); |
|---|
| 259 | I_out.length(len_out); |
|---|
| 260 | Q_out.length(len_out); |
|---|
| 261 | delete [] I_buf; |
|---|
| 262 | delete [] Q_buf; |
|---|
| 263 | I_buf = new short[len]; |
|---|
| 264 | Q_buf = new short[len]; |
|---|
| 265 | previous_length=len; |
|---|
| 266 | } |
|---|
| 267 | |
|---|
| 268 | // I_out.length(len_out); |
|---|
| 269 | // Q_out.length(len_out); |
|---|
| 270 | |
|---|
| 271 | /** |
|---|
| 272 | #ifdef PRINT_ENERGY |
|---|
| 273 | float E_in = 0, E_out = 0; |
|---|
| 274 | #endif |
|---|
| 275 | **/ |
|---|
| 276 | |
|---|
| 277 | if (filter_type==FIR) { |
|---|
| 278 | for (unsigned int i = 0; i < len; ++i) { |
|---|
| 279 | |
|---|
| 280 | |
|---|
| 281 | |
|---|
| 282 | |
|---|
| 283 | |
|---|
| 284 | sample_count = (++sample_count) % M; |
|---|
| 285 | if (sample_count == 0) output_sample = true; |
|---|
| 286 | fir_i_filter->do_work(output_sample, (*I_in)[i], I_buf[i]); |
|---|
| 287 | fir_q_filter->do_work(output_sample, (*Q_in)[i], Q_buf[i] ); |
|---|
| 288 | |
|---|
| 289 | /** |
|---|
| 290 | #ifdef LOG_DATA |
|---|
| 291 | pre_decim.write_data((float)(*I_in)[i], (float)(*Q_in)[i]); |
|---|
| 292 | #endif |
|---|
| 293 | |
|---|
| 294 | #ifdef PRINT_ENERGY |
|---|
| 295 | E_in += (*I_in)[i] * (*I_in)[i] + (*Q_in)[i] * (*Q_in)[i]; |
|---|
| 296 | E_out += i_out * i_out + q_out * q_out; |
|---|
| 297 | #endif |
|---|
| 298 | **/ |
|---|
| 299 | } |
|---|
| 300 | } else { |
|---|
| 301 | for (unsigned int i = 0; i < len; ++i) { |
|---|
| 302 | iir_i_filter->do_work( (*I_in)[i], I_buf[i]); |
|---|
| 303 | iir_q_filter->do_work( (*Q_in)[i], Q_buf[i]); |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | } |
|---|
| 307 | |
|---|
| 308 | for (unsigned int i=0; i<len_out; i++) { |
|---|
| 309 | I_out[i] = I_buf[M*i]; |
|---|
| 310 | Q_out[i] = Q_buf[M*i]; |
|---|
| 311 | /** |
|---|
| 312 | #ifdef LOG_DATA |
|---|
| 313 | post_decim.write_data((float)I_buf[M*i], (float)q_buf[M*i]); |
|---|
| 314 | #endif |
|---|
| 315 | **/ |
|---|
| 316 | } |
|---|
| 317 | |
|---|
| 318 | DEBUG(5, Decimator, "Out "<<len_out<<" samples") |
|---|
| 319 | dataIn->bufferEmptied(); |
|---|
| 320 | dataOut->pushPacket(I_out, Q_out); |
|---|
| 321 | /** |
|---|
| 322 | #ifdef PRINT_ENERGY |
|---|
| 323 | std::cout << "Energy in = " << 10 * log10(E_in/decimator->I_in.length() + 0.01) << " Energy out = " << 10 * log10(E_out/len_out + 0.01) << std::endl; |
|---|
| 324 | #endif |
|---|
| 325 | **/ |
|---|
| 326 | } |
|---|
| 327 | |
|---|
| 328 | } |
|---|
| 329 | |
|---|
| 330 | short Decimator_i::f2s(float r) |
|---|
| 331 | { |
|---|
| 332 | if (r > SHRT_MAX) |
|---|
| 333 | return SHRT_MAX; |
|---|
| 334 | |
|---|
| 335 | if (r < SHRT_MIN) |
|---|
| 336 | return SHRT_MIN; |
|---|
| 337 | |
|---|
| 338 | short ret = (short) r; |
|---|
| 339 | |
|---|
| 340 | return ret; |
|---|
| 341 | } |
|---|
| 342 | |
|---|
| 343 | void Decimator_i::delete_filter_variables() |
|---|
| 344 | { |
|---|
| 345 | DEBUG(5, Decimator, "Enter delete_filter_variables") |
|---|
| 346 | if (fir_i_filter!=NULL){ |
|---|
| 347 | delete fir_i_filter; |
|---|
| 348 | fir_i_filter=NULL; |
|---|
| 349 | }; |
|---|
| 350 | |
|---|
| 351 | if (fir_q_filter!=NULL){ |
|---|
| 352 | delete fir_q_filter; |
|---|
| 353 | fir_q_filter=NULL; |
|---|
| 354 | }; |
|---|
| 355 | |
|---|
| 356 | if (iir_i_filter!=NULL){ |
|---|
| 357 | delete iir_i_filter; |
|---|
| 358 | iir_i_filter=NULL; |
|---|
| 359 | }; |
|---|
| 360 | |
|---|
| 361 | if (iir_q_filter!=NULL){ |
|---|
| 362 | delete iir_q_filter; |
|---|
| 363 | iir_q_filter=NULL; |
|---|
| 364 | }; |
|---|
| 365 | |
|---|
| 366 | DEBUG(5, Decimator, "Exit delete_filter_variables") |
|---|
| 367 | } |
|---|