| 70 | | // Find frame header |
| | 77 | // Find frame header using Costas loop |
| | 78 | bool FrameSynchronizerDSP::FindFrameHeaderCostasLoop( |
| | 79 | short * I_in, |
| | 80 | short * Q_in, |
| | 81 | unsigned int input_length, |
| | 82 | unsigned int &num_read, |
| | 83 | short * I_out, |
| | 84 | short * Q_out, |
| | 85 | unsigned int output_length, |
| | 86 | unsigned int &num_written) |
| | 87 | { |
| | 88 | alpha_s = 0.027f; |
| | 89 | beta_s = 1.02f; |
| | 90 | |
| | 91 | int i(0); |
| | 92 | short I, Q; |
| | 93 | num_read = 0; |
| | 94 | num_written = 0; |
| | 95 | //printf("nco CV = %f\n", cv/(2*PI)); |
| | 96 | |
| | 97 | while ( i < (signed int) input_length ) { |
| | 98 | v++; |
| | 99 | |
| | 100 | // apply nco to input sample |
| | 101 | ApplyNCO(I_in[i], Q_in[i], I, Q); |
| | 102 | //I = I_in[i]; |
| | 103 | //Q = Q_in[i]; |
| | 104 | i++; |
| | 105 | |
| | 106 | // push samples into buffer |
| | 107 | PushInput(I, Q); |
| | 108 | |
| | 109 | // compute filtered outputs (stored in mf_i, mf_q) |
| | 110 | ComputeFilterBankOutputs(); |
| | 111 | |
| | 112 | // compute costas loop phase error on matched-filter outputs |
| | 113 | ///\todo matched filter output won't work because of delay |
| | 114 | pd2_cl = GenerateCostasLoopPhaseError(I, Q); |
| | 115 | //pd2_cl = GenerateCostasLoopPhaseError(mf_i, mf_q); |
| | 116 | pd2_cl /= Ac; |
| | 117 | |
| | 118 | // advance costas loop filter |
| | 119 | AdvanceCostasLoopFilter(); |
| | 120 | |
| | 121 | // update nco |
| | 122 | UpdateNCO(); |
| | 123 | //I_out[num_written] = mf_i; |
| | 124 | //Q_out[num_written] = mf_q; |
| | 125 | //num_written++; |
| | 126 | |
| | 127 | // decimate |
| | 128 | if ( v >= (signed int) k ) { |
| | 129 | // enable output |
| | 130 | v -= k; |
| | 131 | I_out[num_written] = mf_i; |
| | 132 | Q_out[num_written] = mf_q; |
| | 133 | num_written++; |
| | 134 | //printf("I = %d, Q = %d\n", mf_i, mf_q); |
| | 135 | |
| | 136 | // generate timing error |
| | 137 | GenerateTimingError(); |
| | 138 | |
| | 139 | // advance timing loop filter |
| | 140 | AdvanceTimingLoopFilter(); |
| | 141 | |
| | 142 | // compute filter bank index |
| | 143 | ComputeFilterBankIndex(); |
| | 144 | |
| | 145 | // update v |
| | 146 | switch (lc) { |
| | 147 | case SHIFT: |
| | 148 | // normal operation; do nothing |
| | 149 | break; |
| | 150 | case SKIP: |
| | 151 | v--; |
| | 152 | //printf("skip\n"); |
| | 153 | lc = SHIFT; |
| | 154 | break; |
| | 155 | case STUFF: |
| | 156 | v++; |
| | 157 | //printf("stuff\n"); |
| | 158 | lc = SHIFT; |
| | 159 | break; |
| | 160 | default:; |
| | 161 | } |
| | 162 | |
| | 163 | // push sample into buffer |
| | 164 | inputBuffer.Push(mf_i); |
| | 165 | r = CorrelateSequence( pnFrameSyncCode, 255 ); |
| | 166 | |
| | 167 | if ( abs(r) > int( Ac/2 ) ) { |
| | 168 | r_frame_sync = abs(r); |
| | 169 | std::cout << "PN FRAME SYNC CODE FOUND!!!" << std::endl; |
| | 170 | std::cout << " r = " << r_frame_sync << std::endl; |
| | 171 | |
| | 172 | // check for phase inversion; if so inject pi radians into NCO |
| | 173 | // [not sure how well this will work with band-limited pulse shapes] |
| | 174 | if ( r<0 ) { |
| | 175 | std::cout << " [Frame sync found negative PN code]" << std::endl; |
| | 176 | nco_control += PI; |
| | 177 | } |
| | 178 | |
| | 179 | operationalMode = EXTRACT_CONTROL_CODES; |
| | 180 | inputBuffer.Release(); |
| | 181 | numControlCodesReceived = 0; |
| | 182 | |
| | 183 | //num_read = i+1; |
| | 184 | //return true; |
| | 185 | |
| | 186 | // reduce bandwidth of loop filters for steady tracking mode |
| | 187 | //UpdatePhaseLoopFilterCoefficients(0.0025f); |
| | 188 | //UpdateTimingLoopFilterCoefficients(ALPHA_T_LO, BETA_T_LO); |
| | 189 | |
| | 190 | } |
| | 191 | |
| | 192 | } |
| | 193 | } |
| | 194 | |
| | 195 | num_read = input_length; |
| | 196 | return false; |
| | 197 | } |
| | 198 | |
| | 199 | // Extract frame header |
| | 200 | bool FrameSynchronizerDSP::ExtractFrameHeader( |
| | 201 | short * I_in, |
| | 202 | short * Q_in, |
| | 203 | unsigned int input_length, |
| | 204 | unsigned int &num_read, |
| | 205 | short * I_out, |
| | 206 | short * Q_out, |
| | 207 | unsigned int output_length, |
| | 208 | unsigned int &num_written) |
| | 209 | { |
| | 210 | //unsigned int i; |
| | 211 | //short I, Q; |
| | 212 | //num_read = 0; |
| | 213 | //num_written = 0; |
| | 214 | return false; |
| | 215 | } |
| | 216 | |
| | 217 | |
| | 218 | // Find frame header using conventional method |
| 93 | | // apply nco to input sample |
| 94 | | ApplyNCO(I_in[i], Q_in[i], I, Q); |
| 95 | | //I = I_in[i]; |
| 96 | | //Q = Q_in[i]; |
| 97 | | i++; |
| 98 | | |
| 99 | | // push samples into buffer |
| 100 | | PushInput(I, Q); |
| 101 | | |
| 102 | | // compute filtered outputs (stored in mf_i, mf_q) |
| 103 | | ComputeFilterBankOutputs(); |
| 104 | | |
| 105 | | // compute costas loop phase error on matched-filter outputs |
| 106 | | ///\todo matched filter output won't work because of delay |
| 107 | | //pd2_cl = GenerateCostasLoopPhaseError(I, Q); |
| 108 | | pd2_cl = GenerateCostasLoopPhaseError(mf_i, mf_q); |
| 109 | | pd2_cl /= Ac; |
| 110 | | |
| 111 | | // advance costas loop filter |
| 112 | | AdvanceCostasLoopFilter(); |
| 113 | | |
| 114 | | // update nco |
| 115 | | UpdateNCO(); |
| 116 | | //I_out[num_written] = mf_i; |
| 117 | | //Q_out[num_written] = mf_q; |
| 118 | | //num_written++; |
| 119 | | |
| 120 | | // decimate |
| | 239 | PushInputs( I_in, Q_in, i, input_length ); |
| | 240 | |
| | 281 | // generate timing error |
| | 282 | GenerateTimingError(); |
| | 283 | |
| | 284 | // advance timing loop filter |
| | 285 | AdvanceTimingLoopFilter(); |
| | 286 | |
| | 287 | // compute filter bank index |
| | 288 | ComputeFilterBankIndex(); |
| | 289 | |
| | 290 | |
| | 291 | // Update lock detection |
| | 292 | e_i = lock_zeta*(float)(abs(mf_i)) + (1-lock_zeta)*e_i; |
| | 293 | e_q = lock_zeta*(float)(abs(mf_q)) + (1-lock_zeta)*e_q; |
| | 294 | header_phase_lock_delay_counter++; |
| | 295 | lock_detect = e_i/e_q; |
| | 296 | if ( header_phase_lock_delay_counter == header_phase_lock_delay && |
| | 297 | lock_detect < 1.25f ) { |
| | 298 | header_phase_lock_delay_counter = 0; |
| | 299 | lock_detect = e_i/e_q; |
| | 300 | printf(" lock_detect = %f\n", lock_detect); |
| | 301 | //if ( lock_detect < 1.25 ) { |
| | 302 | unsigned int N_est = (input_length < 256) ? input_length : 256; |
| | 303 | wcTs = 2*PI*EstimateCarrierOffset(I_in, Q_in, N_est, false); |
| | 304 | printf(" estimate: %f\n", wcTs/(2*PI)); |
| | 305 | cv = 0; |
| | 306 | nco_control = 0; |
| | 307 | q_c = 0; |
| | 308 | q_hat_c = 0; |
| | 309 | buff2_c = 0; |
| | 310 | q_prime_c = 0; |
| | 311 | //} |
| | 312 | } else { |
| | 313 | // Calculate phase error |
| | 314 | |
| | 315 | q_c = GeneratePhaseError( mf_i, mf_q ); |
| | 316 | q_c /= Ac; |
| | 317 | } |
| | 318 | |
| | 319 | AdvancePhaseLoopFilter(); |
| | 320 | |