| 1 | /**************************************************************************** |
|---|
| 2 | |
|---|
| 3 | Copyright 2007 Virginia Polytechnic Institute and State University |
|---|
| 4 | |
|---|
| 5 | This file is part of the OSSIE SymbolSyncPoly. |
|---|
| 6 | |
|---|
| 7 | OSSIE SymbolSyncPoly 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 SymbolSyncPoly 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 SymbolSyncPoly; 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 SYMBOLSYNCPOLYDSP_IMPL_H |
|---|
| 25 | #define SYMBOLSYNCPOLYDSP_IMPL_H |
|---|
| 26 | |
|---|
| 27 | #include <stdlib.h> |
|---|
| 28 | #include "sigproc/SigProc.h" |
|---|
| 29 | |
|---|
| 30 | /// Signal flow control for polyphase filter bank synchronizer |
|---|
| 31 | enum flow_control { |
|---|
| 32 | SHIFT = 0, ///< normal operation |
|---|
| 33 | SKIP = 1, ///< filter bank underflow |
|---|
| 34 | STUFF = 2 ///< filter bank overflow |
|---|
| 35 | }; |
|---|
| 36 | |
|---|
| 37 | /** \brief Digital signal processing for the symbol synchronizer component |
|---|
| 38 | * implemented with the polyphase filter bank |
|---|
| 39 | * |
|---|
| 40 | * |
|---|
| 41 | */ |
|---|
| 42 | class SymbolSyncPolyDSP |
|---|
| 43 | { |
|---|
| 44 | public: |
|---|
| 45 | /// Initializing constructor |
|---|
| 46 | SymbolSyncPolyDSP(); |
|---|
| 47 | |
|---|
| 48 | /// Destructor |
|---|
| 49 | ~SymbolSyncPolyDSP(); |
|---|
| 50 | |
|---|
| 51 | /// Configure filter bank |
|---|
| 52 | /// |
|---|
| 53 | /// \param[in] type Type of filter prototype |
|---|
| 54 | /// \param[in] _k Samples per symbol |
|---|
| 55 | /// \param[in] _m Symbol delay |
|---|
| 56 | /// \param[in] _beta Excess bandwidth factor |
|---|
| 57 | /// \param[in] _Npfb Number of filters in the polyphase filter bank |
|---|
| 58 | void ConfigureFilterBank(char * type, |
|---|
| 59 | unsigned int _k, |
|---|
| 60 | unsigned int _m, |
|---|
| 61 | float _beta, |
|---|
| 62 | unsigned int _Npfb); |
|---|
| 63 | |
|---|
| 64 | /// |
|---|
| 65 | ///\todo change to : void UpdateTimingLoopFilterCoefficients(float _BT); |
|---|
| 66 | void UpdateTimingLoopFilterCoefficients(float _alpha, float _beta) { |
|---|
| 67 | alpha = _alpha; |
|---|
| 68 | beta = _beta; |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | /// Estimate timing information |
|---|
| 72 | /// \todo implement this method!!! |
|---|
| 73 | void EstimateTiming(short * I_in, |
|---|
| 74 | short * Q_in, |
|---|
| 75 | unsigned int N_in); |
|---|
| 76 | |
|---|
| 77 | /// \brief Main signal processing loop |
|---|
| 78 | /// |
|---|
| 79 | /// This method performs simultaneous synchronization and decimation. It |
|---|
| 80 | /// assumes that the calling platform takes care of memory management. |
|---|
| 81 | /// N_out initially stores the number of memory elements allocated to |
|---|
| 82 | /// I_out and Q_out, and assumes that this number is sufficiently large |
|---|
| 83 | /// to run the algorithm. The method returns N_out as the actual number |
|---|
| 84 | /// of elements stored in I_out and Q_out. This is approximately |
|---|
| 85 | /// \f$ N_{out} \approx N_{in}/k \f$ |
|---|
| 86 | /// |
|---|
| 87 | /// \param[in] I_in In-phase input signal |
|---|
| 88 | /// \param[in] Q_in Quadrature input signal |
|---|
| 89 | /// \param[in] N_in Number of input samples |
|---|
| 90 | /// \param[out] I_out In-phase output signal |
|---|
| 91 | /// \param[out] Q_out Quadrature output signal |
|---|
| 92 | /// \param[out] N_out Number of output samples |
|---|
| 93 | void SynchronizeAndDecimate(short * I_in, |
|---|
| 94 | short * Q_in, |
|---|
| 95 | unsigned int N_in, |
|---|
| 96 | short *& I_out, |
|---|
| 97 | short *& Q_out, |
|---|
| 98 | unsigned int & N_out); |
|---|
| 99 | |
|---|
| 100 | protected: |
|---|
| 101 | |
|---|
| 102 | /// \brief Calculate error from MF and dMF |
|---|
| 103 | /// |
|---|
| 104 | /// The error signal is the maximum likelihood estimate of the phase offset, viz. |
|---|
| 105 | /// \f[ \hat{e}(nT) = \dot{h}(nT) h(nT) \f] |
|---|
| 106 | void GenerateTimingErrorSignal() { |
|---|
| 107 | q = -( float(mf_i)*float(dmf_i) + float(mf_q)*float(dmf_q) )/2.0f; |
|---|
| 108 | q /= Ac*Ac; |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | /// Advance IIR loop filter |
|---|
| 112 | /// \todo use better loop filter |
|---|
| 113 | void AdvanceTimingLoopFilter() { |
|---|
| 114 | q_hat = beta*q_hat - alpha*(q_hat-q); |
|---|
| 115 | b_soft = b_soft - q_hat*float(Npfb); |
|---|
| 116 | } |
|---|
| 117 | |
|---|
| 118 | /// Compute (quantize) filter bank index from soft loop filter output |
|---|
| 119 | void ComputeFilterBankIndex(); |
|---|
| 120 | |
|---|
| 121 | /// Pushes inputs determined by flow control as necessary |
|---|
| 122 | void PushInputs( short * I_in, short * Q_in, unsigned int &i, unsigned int N_in ); |
|---|
| 123 | |
|---|
| 124 | /// Pushes inputs determined by flow control as necessary |
|---|
| 125 | void PushInput( short I_in, short Q_in ) { |
|---|
| 126 | MF_i->PushInput( I_in ); |
|---|
| 127 | dMF_i->PushInput( I_in ); |
|---|
| 128 | MF_q->PushInput( Q_in ); |
|---|
| 129 | dMF_q->PushInput( Q_in ); |
|---|
| 130 | } |
|---|
| 131 | |
|---|
| 132 | /// |
|---|
| 133 | void ComputeFilterBankOutputs() { |
|---|
| 134 | // Filter in-phase signal with MF and dMF with filter bank b |
|---|
| 135 | MF_i->ComputeOutput(mf_i, b); |
|---|
| 136 | dMF_i->ComputeOutput(dmf_i, b); |
|---|
| 137 | |
|---|
| 138 | // Filter quadrature signal with MF and dMF with filter bank b |
|---|
| 139 | MF_q->ComputeOutput(mf_q, b); |
|---|
| 140 | dMF_q->ComputeOutput(dmf_q, b); |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | SigProc::FIRPolyphaseFilterBank * MF_i; ///< In-phase matched filter bank |
|---|
| 144 | SigProc::FIRPolyphaseFilterBank * dMF_i; ///< In-phase derivative matched filter bank |
|---|
| 145 | |
|---|
| 146 | SigProc::FIRPolyphaseFilterBank * MF_q; ///< Quadrature matched filter bank |
|---|
| 147 | SigProc::FIRPolyphaseFilterBank * dMF_q; ///< Quadrature derivative matched filter bank |
|---|
| 148 | |
|---|
| 149 | short mf_i; ///< In-phase matched filter output |
|---|
| 150 | short dmf_i; ///< In-phase derivative matched filter output |
|---|
| 151 | short mf_q; ///< Quadrature matched filter output |
|---|
| 152 | short dmf_q; ///< Quadrature derivative matched filter output |
|---|
| 153 | |
|---|
| 154 | float Ac; ///< Approximate signal amplitude |
|---|
| 155 | float alpha; ///< loop filter coefficient, \f$\alpha\f$ |
|---|
| 156 | float beta; ///< loop filter coefficient, \f$\beta\f$ |
|---|
| 157 | float q; ///< Error signal |
|---|
| 158 | float q_hat; ///< Filtered error signal |
|---|
| 159 | |
|---|
| 160 | float b_soft; ///< soft filter bank index |
|---|
| 161 | int b; ///< hard filter bank index |
|---|
| 162 | int Npfb; ///< number of filters in bank |
|---|
| 163 | |
|---|
| 164 | unsigned int k; ///< samples per symbol |
|---|
| 165 | unsigned int v; ///< sample counter for output sample enable |
|---|
| 166 | |
|---|
| 167 | flow_control lc; ///< loop flow control state |
|---|
| 168 | |
|---|
| 169 | bool isConfigured; ///< flag set when ConfigureFilterBank() is invoked properly |
|---|
| 170 | |
|---|
| 171 | private: |
|---|
| 172 | /// Disallow copy constructor |
|---|
| 173 | SymbolSyncPolyDSP(SymbolSyncPolyDSP&); |
|---|
| 174 | |
|---|
| 175 | }; |
|---|
| 176 | |
|---|
| 177 | #endif |
|---|
| 178 | |
|---|