| 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 | #ifndef SIG_PROC_H |
|---|
| 25 | #define SIG_PROC_H |
|---|
| 26 | |
|---|
| 27 | #include <iostream> |
|---|
| 28 | #include <fstream> |
|---|
| 29 | #include <string> |
|---|
| 30 | |
|---|
| 31 | #ifdef FPM |
|---|
| 32 | #include "fixed.h" |
|---|
| 33 | #endif |
|---|
| 34 | |
|---|
| 35 | namespace SigProc { |
|---|
| 36 | |
|---|
| 37 | //----------------------------------------------------------------------------- |
|---|
| 38 | // |
|---|
| 39 | // Design root raised-cosine filter |
|---|
| 40 | // |
|---|
| 41 | //----------------------------------------------------------------------------- |
|---|
| 42 | void DesignRRCFilter( |
|---|
| 43 | unsigned int k, // samples per symbol |
|---|
| 44 | unsigned int m, // delay |
|---|
| 45 | float beta, // rolloff factor ( 0 < beta <= 1 ) |
|---|
| 46 | float *& h, // pointer to filter coefficients |
|---|
| 47 | unsigned int & h_len // length of filter (len = 2*m*k+1) |
|---|
| 48 | ); |
|---|
| 49 | |
|---|
| 50 | //----------------------------------------------------------------------------- |
|---|
| 51 | // |
|---|
| 52 | // P/N Sequence |
|---|
| 53 | // |
|---|
| 54 | //----------------------------------------------------------------------------- |
|---|
| 55 | |
|---|
| 56 | /// P/N Sequence |
|---|
| 57 | class PNSequence |
|---|
| 58 | { |
|---|
| 59 | public: |
|---|
| 60 | /// default constructor |
|---|
| 61 | PNSequence(); |
|---|
| 62 | |
|---|
| 63 | /// destructor |
|---|
| 64 | ~PNSequence(); |
|---|
| 65 | |
|---|
| 66 | private: |
|---|
| 67 | // g: generator polynomial |
|---|
| 68 | // a: initial polynomial state |
|---|
| 69 | }; |
|---|
| 70 | |
|---|
| 71 | //----------------------------------------------------------------------------- |
|---|
| 72 | // |
|---|
| 73 | // Automatic Gain Control class |
|---|
| 74 | // |
|---|
| 75 | //----------------------------------------------------------------------------- |
|---|
| 76 | /** \brief Automatic gain control signal processor |
|---|
| 77 | * |
|---|
| 78 | */ |
|---|
| 79 | class AutomaticGainControl |
|---|
| 80 | { |
|---|
| 81 | public: |
|---|
| 82 | /// default constructor |
|---|
| 83 | AutomaticGainControl(); |
|---|
| 84 | |
|---|
| 85 | /// Destructor |
|---|
| 86 | ~AutomaticGainControl(); |
|---|
| 87 | |
|---|
| 88 | /// Set signal processing values |
|---|
| 89 | void SetValues( |
|---|
| 90 | float _elo, |
|---|
| 91 | float _ehi, |
|---|
| 92 | float _ka, |
|---|
| 93 | float _kr, |
|---|
| 94 | float _gmin, |
|---|
| 95 | float _gmax); |
|---|
| 96 | |
|---|
| 97 | /// Get signal processing values |
|---|
| 98 | void GetValues( |
|---|
| 99 | float & _elo, |
|---|
| 100 | float & _ehi, |
|---|
| 101 | float & _ka, |
|---|
| 102 | float & _kr, |
|---|
| 103 | float & _gmin, |
|---|
| 104 | float & _gmax); |
|---|
| 105 | |
|---|
| 106 | /// Get status |
|---|
| 107 | void GetStatus(float & _gain, float & _energy); |
|---|
| 108 | |
|---|
| 109 | /// track signal energy and apply gain (real) |
|---|
| 110 | void ApplyGain(short & I); |
|---|
| 111 | |
|---|
| 112 | /// track signal energy and apply gain (complex) |
|---|
| 113 | void ApplyGain(short & I, short & Q); |
|---|
| 114 | |
|---|
| 115 | private: |
|---|
| 116 | /// disallow copy constructor |
|---|
| 117 | AutomaticGainControl(AutomaticGainControl &); |
|---|
| 118 | |
|---|
| 119 | /// compute necessary gain value from measured energy |
|---|
| 120 | void ComputeGain(); |
|---|
| 121 | |
|---|
| 122 | /// low energy threshold |
|---|
| 123 | float energy_lo; |
|---|
| 124 | |
|---|
| 125 | /// high energy threshold |
|---|
| 126 | float energy_hi; |
|---|
| 127 | |
|---|
| 128 | /// attack time constant |
|---|
| 129 | float ka; |
|---|
| 130 | |
|---|
| 131 | /// release time constant |
|---|
| 132 | float kr; |
|---|
| 133 | |
|---|
| 134 | /// minimum gain value |
|---|
| 135 | float gmin; |
|---|
| 136 | |
|---|
| 137 | /// maximum gain value |
|---|
| 138 | float gmax; |
|---|
| 139 | |
|---|
| 140 | /// actual tracking gain value |
|---|
| 141 | float gain; |
|---|
| 142 | |
|---|
| 143 | /// actual tracking average energy value |
|---|
| 144 | float energy; |
|---|
| 145 | |
|---|
| 146 | /// low-pass filter coefficient for estimating average energy |
|---|
| 147 | float zeta; |
|---|
| 148 | |
|---|
| 149 | /// average energy threshold for smoother tracking |
|---|
| 150 | float energy_av; |
|---|
| 151 | |
|---|
| 152 | }; |
|---|
| 153 | |
|---|
| 154 | class phase_detect { |
|---|
| 155 | |
|---|
| 156 | public: |
|---|
| 157 | phase_detect(float scale_factor); |
|---|
| 158 | |
|---|
| 159 | void do_work(short I_in, short Q_in, short I_nco, short Q_nco, short &out); |
|---|
| 160 | |
|---|
| 161 | private: |
|---|
| 162 | phase_detect(const phase_detect &); |
|---|
| 163 | |
|---|
| 164 | float scale_factor; |
|---|
| 165 | }; |
|---|
| 166 | |
|---|
| 167 | |
|---|
| 168 | class nco { |
|---|
| 169 | public: |
|---|
| 170 | nco(); |
|---|
| 171 | nco(unsigned int max_out); |
|---|
| 172 | |
|---|
| 173 | void do_work(short control_voltage, short &sine, short &cosine); |
|---|
| 174 | |
|---|
| 175 | private: |
|---|
| 176 | nco(const nco &); |
|---|
| 177 | |
|---|
| 178 | int freq_index; |
|---|
| 179 | int max_out; |
|---|
| 180 | }; |
|---|
| 181 | |
|---|
| 182 | class gain { |
|---|
| 183 | public: |
|---|
| 184 | gain(); |
|---|
| 185 | |
|---|
| 186 | void do_work(float gain, short data_in, short &out); |
|---|
| 187 | |
|---|
| 188 | private: |
|---|
| 189 | gain(const gain &); |
|---|
| 190 | |
|---|
| 191 | }; |
|---|
| 192 | |
|---|
| 193 | class iir_filter { |
|---|
| 194 | public: |
|---|
| 195 | iir_filter(float a[], unsigned int len_a, float b[], unsigned int len_b); |
|---|
| 196 | |
|---|
| 197 | void do_work(short x, short &y); |
|---|
| 198 | |
|---|
| 199 | private: |
|---|
| 200 | iir_filter(const iir_filter &); |
|---|
| 201 | |
|---|
| 202 | float *A; |
|---|
| 203 | float *B; |
|---|
| 204 | unsigned int len_A, len_B; |
|---|
| 205 | |
|---|
| 206 | float *v; |
|---|
| 207 | unsigned int len_v; |
|---|
| 208 | unsigned int next_v; |
|---|
| 209 | }; |
|---|
| 210 | |
|---|
| 211 | |
|---|
| 212 | //----------------------------------------------------------------------------- |
|---|
| 213 | // |
|---|
| 214 | // FIR polyphase filter bank |
|---|
| 215 | // |
|---|
| 216 | //----------------------------------------------------------------------------- |
|---|
| 217 | /** \brief Finite impulse response (FIR) polyphase filter bank |
|---|
| 218 | * |
|---|
| 219 | * This class implementes a finite impulse response (FIR) polyphase filter |
|---|
| 220 | * bank useful for decimators that need to interpolate samples in digital |
|---|
| 221 | * receivers. |
|---|
| 222 | * |
|---|
| 223 | * Certain filter prototypes are supported, including |
|---|
| 224 | * - raised-cosine |
|---|
| 225 | * - root raised-cosine |
|---|
| 226 | * - gaussian |
|---|
| 227 | * - triangular |
|---|
| 228 | * - hamming |
|---|
| 229 | * |
|---|
| 230 | * The user can also load coefficients... |
|---|
| 231 | * |
|---|
| 232 | */ |
|---|
| 233 | class FIRPolyphaseFilterBank { |
|---|
| 234 | public: |
|---|
| 235 | /// \brief Initializing constructor |
|---|
| 236 | /// |
|---|
| 237 | /// This constructor calculates the filter coefficients for several |
|---|
| 238 | /// different filter types using just a few parameters. The filters |
|---|
| 239 | /// currently supported are: |
|---|
| 240 | /// - 'rrcos' : square-root raised-cosine |
|---|
| 241 | /// |
|---|
| 242 | FIRPolyphaseFilterBank( |
|---|
| 243 | char * _type, // type of filter |
|---|
| 244 | unsigned int _k, // samples per symbol |
|---|
| 245 | unsigned int _m, // delay |
|---|
| 246 | float _beta, // excess bandwidth factor |
|---|
| 247 | unsigned int _Npfb // number of filters |
|---|
| 248 | ); |
|---|
| 249 | |
|---|
| 250 | /// \brief Initializing constructor |
|---|
| 251 | /// |
|---|
| 252 | /// This constructor loads filter bank coefficients which have |
|---|
| 253 | /// been generated externally. The coefficients are copied from |
|---|
| 254 | /// the input array to a new buffer. |
|---|
| 255 | FIRPolyphaseFilterBank( |
|---|
| 256 | float * _H, // filter bank coefficients |
|---|
| 257 | unsigned int _h_len,// length of each filter |
|---|
| 258 | unsigned int _Npfb // number of filters |
|---|
| 259 | ); |
|---|
| 260 | |
|---|
| 261 | /// destructor |
|---|
| 262 | ~FIRPolyphaseFilterBank(); |
|---|
| 263 | |
|---|
| 264 | /// Push input value into buffer |
|---|
| 265 | void PushInput(int _x); |
|---|
| 266 | |
|---|
| 267 | /// Compute filter output from current buffer state using specific |
|---|
| 268 | /// filter from filter bank matrix |
|---|
| 269 | void ComputeOutput( |
|---|
| 270 | short &y, // output sample |
|---|
| 271 | unsigned int _b // filter bank index |
|---|
| 272 | ); |
|---|
| 273 | |
|---|
| 274 | /// Feset filter buffer |
|---|
| 275 | void ResetBuffer(); |
|---|
| 276 | |
|---|
| 277 | /// prints filter bank coefficients to the screen |
|---|
| 278 | void PrintFilterBankCoefficients(); |
|---|
| 279 | |
|---|
| 280 | private: |
|---|
| 281 | /// disallow copy constructor |
|---|
| 282 | FIRPolyphaseFilterBank(const FIRPolyphaseFilterBank&); |
|---|
| 283 | |
|---|
| 284 | /// type of filter; can be one of the following |
|---|
| 285 | /// - 'rrcos' |
|---|
| 286 | /// - 'gaussian' |
|---|
| 287 | char * type; |
|---|
| 288 | |
|---|
| 289 | /// samples per symbol |
|---|
| 290 | unsigned int k; |
|---|
| 291 | |
|---|
| 292 | /// symbol delay |
|---|
| 293 | unsigned int m; |
|---|
| 294 | |
|---|
| 295 | /// excess bandwidth factor |
|---|
| 296 | float beta; |
|---|
| 297 | |
|---|
| 298 | /// number of filters in bank |
|---|
| 299 | unsigned int Npfb; |
|---|
| 300 | |
|---|
| 301 | /// \brief filter bank coefficients matrix |
|---|
| 302 | /// |
|---|
| 303 | /// The coefficients are stored in a one-dimensional array which |
|---|
| 304 | /// is realized as a two-dimensional matrix. The array is of |
|---|
| 305 | /// length Npfb*h_len (the number of filters in the bank times |
|---|
| 306 | /// the length of each filter). |
|---|
| 307 | float *H; |
|---|
| 308 | |
|---|
| 309 | /// length of each filter |
|---|
| 310 | unsigned int h_len; |
|---|
| 311 | |
|---|
| 312 | /// circular input buffer |
|---|
| 313 | short *v; |
|---|
| 314 | |
|---|
| 315 | /// input buffer index head |
|---|
| 316 | signed int i_head; |
|---|
| 317 | |
|---|
| 318 | /// input buffer length |
|---|
| 319 | unsigned int v_len; |
|---|
| 320 | |
|---|
| 321 | /// transpose filter bank coefficient matrix |
|---|
| 322 | void TransposeCoefficientMatrix(); |
|---|
| 323 | |
|---|
| 324 | // ----- calculate filter bank coefficients ----- |
|---|
| 325 | |
|---|
| 326 | /// Calculate root raised-cosine coefficients |
|---|
| 327 | void CalculateRRCFilterCoefficients(); |
|---|
| 328 | |
|---|
| 329 | /// Calculate |
|---|
| 330 | void CalculateGaussianFilterCoefficients(); |
|---|
| 331 | |
|---|
| 332 | /// \brief Calculate derivative filter coefficients |
|---|
| 333 | /// |
|---|
| 334 | /// Approximates... |
|---|
| 335 | /// \f[ \dot{h}_m(nT) = h_{m+1}(nT) - h_{m-1}(nT), \ \ m=1,2,\ldots,...M-2 \f] |
|---|
| 336 | /// \f[ \dot{h}_0(nT) = h_{1}(nT) - h_{M-1}(nT)\f] |
|---|
| 337 | /// \f[ \dot{h}_{M-1}(nT) = h_{M-2}(nT) - h_{0}(nT)\f] |
|---|
| 338 | /// |
|---|
| 339 | void CalculateDerivativeFilterCoefficients(); |
|---|
| 340 | |
|---|
| 341 | }; |
|---|
| 342 | |
|---|
| 343 | |
|---|
| 344 | |
|---|
| 345 | class fir_filter { |
|---|
| 346 | public: |
|---|
| 347 | fir_filter(float a[], unsigned int len_a); |
|---|
| 348 | |
|---|
| 349 | void do_work(bool run_filter, short in_sample, short &out_sample); |
|---|
| 350 | void reset(); |
|---|
| 351 | |
|---|
| 352 | private: |
|---|
| 353 | fir_filter(const fir_filter &); |
|---|
| 354 | |
|---|
| 355 | #ifdef FPM |
|---|
| 356 | mad_fixed_t *A; |
|---|
| 357 | mad_fixed_t *v; |
|---|
| 358 | #else |
|---|
| 359 | float *A; |
|---|
| 360 | short *v; |
|---|
| 361 | #endif |
|---|
| 362 | unsigned int len_A; |
|---|
| 363 | |
|---|
| 364 | unsigned int len_v; |
|---|
| 365 | unsigned int next_v; |
|---|
| 366 | }; |
|---|
| 367 | |
|---|
| 368 | class dump_data { |
|---|
| 369 | public: |
|---|
| 370 | dump_data(const char *filename, long start_sample, long number_of_samples); |
|---|
| 371 | ~dump_data(); |
|---|
| 372 | |
|---|
| 373 | void write_data(float data, const char *msg = ""); |
|---|
| 374 | void write_data(float a, float b, const char *msg = ""); |
|---|
| 375 | |
|---|
| 376 | private: |
|---|
| 377 | dump_data(); |
|---|
| 378 | dump_data(const dump_data &); |
|---|
| 379 | |
|---|
| 380 | std::ofstream *out_file; |
|---|
| 381 | |
|---|
| 382 | long start_sample, stop_sample; |
|---|
| 383 | long current_sample; |
|---|
| 384 | |
|---|
| 385 | }; |
|---|
| 386 | |
|---|
| 387 | class dc_block { |
|---|
| 388 | public: |
|---|
| 389 | dc_block(const float forget_factor); |
|---|
| 390 | ~dc_block(); |
|---|
| 391 | |
|---|
| 392 | void do_work(short in, short &out); |
|---|
| 393 | |
|---|
| 394 | private: |
|---|
| 395 | dc_block(); |
|---|
| 396 | dc_block(const dc_block &); |
|---|
| 397 | |
|---|
| 398 | float forget_factor; |
|---|
| 399 | int prev_input, prev_output; |
|---|
| 400 | |
|---|
| 401 | }; |
|---|
| 402 | } |
|---|
| 403 | |
|---|
| 404 | #endif |
|---|