FreeCalypso > hg > fc-magnetite
comparison src/cs/layer1/cfile/l1_ctl.c @ 69:50a15a54801e
src/cs/layer1: import from tcs211-l1-reconst project
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Sat, 01 Oct 2016 23:45:38 +0000 |
| parents | |
| children | af1bacf61dc6 |
comparison
equal
deleted
inserted
replaced
| 68:838717193e09 | 69:50a15a54801e |
|---|---|
| 1 /************* Revision Controle System Header ************* | |
| 2 * GSM Layer 1 software | |
| 3 * L1_CTL.C | |
| 4 * | |
| 5 * Filename l1_ctl.c | |
| 6 * Copyright 2003 (C) Texas Instruments | |
| 7 * | |
| 8 ************* Revision Controle System Header *************/ | |
| 9 | |
| 10 #define L1_CTL_C | |
| 11 | |
| 12 #include "l1_macro.h" | |
| 13 #include "l1_confg.h" | |
| 14 | |
| 15 #if (CODE_VERSION == SIMULATION) | |
| 16 #include <string.h> | |
| 17 #include "l1_types.h" | |
| 18 #include "sys_types.h" | |
| 19 #include "l1_const.h" | |
| 20 #include "l1_time.h" | |
| 21 #include "l1_signa.h" | |
| 22 | |
| 23 #if TESTMODE | |
| 24 #include "l1tm_defty.h" | |
| 25 #endif | |
| 26 #if (AUDIO_TASK == 1) | |
| 27 #include "l1audio_const.h" | |
| 28 #include "l1audio_cust.h" | |
| 29 #include "l1audio_signa.h" | |
| 30 #include "l1audio_defty.h" | |
| 31 #include "l1audio_msgty.h" | |
| 32 #endif | |
| 33 #if (L1_GTT == 1) | |
| 34 #include "l1gtt_const.h" | |
| 35 #include "l1gtt_defty.h" | |
| 36 #endif | |
| 37 #if (L1_MP3 == 1) | |
| 38 #include "l1mp3_defty.h" | |
| 39 #endif | |
| 40 #if (L1_MIDI == 1) | |
| 41 #include "l1midi_defty.h" | |
| 42 #endif | |
| 43 //ADDED FOR AAC | |
| 44 #if (L1_AAC == 1) | |
| 45 #include "l1aac_defty.h" | |
| 46 #endif | |
| 47 #include "l1_defty.h" | |
| 48 #include "cust_os.h" | |
| 49 #include "l1_msgty.h" | |
| 50 #include "l1_varex.h" | |
| 51 #include "l1_proto.h" | |
| 52 #include "l1_mftab.h" | |
| 53 #include "l1_tabs.h" | |
| 54 #include "l1_ver.h" | |
| 55 #if L2_L3_SIMUL | |
| 56 #include "hw_debug.h" | |
| 57 #endif | |
| 58 | |
| 59 #if TESTMODE | |
| 60 #include "l1tm_msgty.h" | |
| 61 #include "l1tm_varex.h" | |
| 62 #endif | |
| 63 | |
| 64 #include "l1_ctl.h" | |
| 65 | |
| 66 #ifdef _INLINE | |
| 67 #define INLINE static inline // Inline functions when -v option is set | |
| 68 #else // when the compiler is ivoked. | |
| 69 #define INLINE | |
| 70 #endif | |
| 71 #else | |
| 72 #include <string.h> | |
| 73 #include "l1_types.h" | |
| 74 #include "sys_types.h" | |
| 75 #include "l1_const.h" | |
| 76 #include "l1_time.h" | |
| 77 #include "l1_signa.h" | |
| 78 | |
| 79 #if (RF_FAM == 61) | |
| 80 #include "tpudrv61.h" | |
| 81 #endif | |
| 82 | |
| 83 #if TESTMODE | |
| 84 #include "l1tm_defty.h" | |
| 85 #endif | |
| 86 #if (AUDIO_TASK == 1) | |
| 87 #include "l1audio_const.h" | |
| 88 #include "l1audio_cust.h" | |
| 89 #include "l1audio_defty.h" | |
| 90 #endif | |
| 91 #if (L1_GTT == 1) | |
| 92 #include "l1gtt_const.h" | |
| 93 #include "l1gtt_defty.h" | |
| 94 #endif | |
| 95 #if (L1_MP3 == 1) | |
| 96 #include "l1mp3_defty.h" | |
| 97 #endif | |
| 98 #if (L1_MIDI == 1) | |
| 99 #include "l1midi_defty.h" | |
| 100 #endif | |
| 101 //ADDED FOR AAC | |
| 102 #if (L1_AAC == 1) | |
| 103 #include "l1aac_defty.h" | |
| 104 #endif | |
| 105 #include "l1_defty.h" | |
| 106 #include "cust_os.h" | |
| 107 #include "l1_msgty.h" | |
| 108 #include "l1_varex.h" | |
| 109 #include "l1_proto.h" | |
| 110 #include "l1_tabs.h" | |
| 111 #include "l1_ctl.h" | |
| 112 #if L2_L3_SIMUL | |
| 113 #include "hw_debug.h" | |
| 114 #endif | |
| 115 | |
| 116 #if TESTMODE | |
| 117 #include "l1tm_msgty.h" | |
| 118 #include "l1tm_varex.h" | |
| 119 #endif | |
| 120 #ifdef _INLINE | |
| 121 #define INLINE static inline // Inline functions when -v option is set | |
| 122 #else // when the compiler is ivoked. | |
| 123 #define INLINE | |
| 124 #endif | |
| 125 #endif | |
| 126 | |
| 127 #if(RF_FAM == 61) | |
| 128 #include "l1_rf61.h" | |
| 129 #endif | |
| 130 | |
| 131 #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) | |
| 132 #include "l1_trace.h" | |
| 133 #endif | |
| 134 | |
| 135 extern SYS_UWORD16 Convert_l1_radio_freq(SYS_UWORD16 radio_freq); | |
| 136 #if(RF_FAM == 61) | |
| 137 extern WORD16 drp_gain_correction(UWORD16 arfcn, UWORD8 lna_off, UWORD16 agc); | |
| 138 #endif | |
| 139 | |
| 140 #define LNA_OFF 1 | |
| 141 #define LNA_ON 0 | |
| 142 | |
| 143 | |
| 144 | |
| 145 | |
| 146 /************************************/ | |
| 147 /* Automatic frequency compensation */ | |
| 148 /************************************/ | |
| 149 | |
| 150 /* | |
| 151 * FreeCalypso TCS211 reconstruction: the following 3 functions | |
| 152 * have been added in the LoCosto version of this module. | |
| 153 * We have conditioned them out in order to match the original | |
| 154 * TCS211 object; their uses have been conditioned out as well. | |
| 155 * | |
| 156 * These functions will need to re-enabled when their uses are | |
| 157 * re-enabled. | |
| 158 */ | |
| 159 | |
| 160 #if 0 | |
| 161 | |
| 162 #define L1_WORD16_POS_MAX (32767) | |
| 163 #define L1_WORD16_NEG_MAX (-32768) | |
| 164 #define L1_WORD32_POS_MAX ((unsigned long)(1<<31)-1) | |
| 165 #define L1_WORD32_NEG_MAX (-(unsigned long)(1<<31)) | |
| 166 | |
| 167 INLINE WORD16 Add_Sat_sign_16b(WORD16 val1, WORD16 val2) | |
| 168 { | |
| 169 WORD32 temp; | |
| 170 WORD16 result; | |
| 171 | |
| 172 temp = (WORD32)((WORD32)val1 + (WORD32)val2); | |
| 173 if(temp > L1_WORD16_POS_MAX) | |
| 174 { | |
| 175 temp = L1_WORD16_POS_MAX; | |
| 176 } | |
| 177 if(temp < L1_WORD16_NEG_MAX) | |
| 178 { | |
| 179 temp = L1_WORD16_NEG_MAX; | |
| 180 } | |
| 181 result = (WORD16)((temp)&(0x0000FFFF)); | |
| 182 return(result); | |
| 183 } | |
| 184 | |
| 185 INLINE WORD32 Add_Sat_sign_32b(WORD32 val1, WORD32 val2) | |
| 186 { | |
| 187 WORD32 temp_high_high; | |
| 188 UWORD32 temp_low_low; | |
| 189 UWORD16 carry; | |
| 190 WORD32 result; | |
| 191 WORD16 high_val1, high_val2; | |
| 192 UWORD16 low_val1, low_val2; | |
| 193 | |
| 194 high_val1 = (WORD16)(val1>>16); | |
| 195 high_val2 = (WORD16)(val2>>16); | |
| 196 low_val1 = (UWORD16)(val1&0x0000FFFF); | |
| 197 low_val2 = (UWORD16)(val2&0x0000FFFF); | |
| 198 | |
| 199 temp_high_high = (WORD32)high_val1 + (WORD32)high_val2; | |
| 200 temp_low_low = (UWORD32)low_val1 + (UWORD32)low_val2; | |
| 201 carry = (UWORD16)(temp_low_low >> 16); | |
| 202 temp_high_high = temp_high_high + (UWORD32)(carry); | |
| 203 | |
| 204 | |
| 205 result = val1 + val2; | |
| 206 if(temp_high_high > L1_WORD16_POS_MAX) | |
| 207 { | |
| 208 result = L1_WORD32_POS_MAX; | |
| 209 } | |
| 210 if(temp_high_high < L1_WORD16_NEG_MAX) | |
| 211 { | |
| 212 result = L1_WORD32_NEG_MAX; | |
| 213 } | |
| 214 | |
| 215 return(result); | |
| 216 } | |
| 217 | |
| 218 INLINE WORD32 Sat_Mult_20sign_16unsign(WORD32 val1, UWORD32 val2) | |
| 219 { | |
| 220 WORD32 result; | |
| 221 | |
| 222 result = val1 * val2; | |
| 223 if(val1>0) /* val2 is > 0*/ | |
| 224 { | |
| 225 if(result < 0) /* overflow */ | |
| 226 { | |
| 227 result = L1_WORD32_POS_MAX; | |
| 228 } | |
| 229 } | |
| 230 if(val1<0) /* val2 is > 0*/ | |
| 231 { | |
| 232 if(result > 0) /* overflow */ | |
| 233 { | |
| 234 result = L1_WORD32_NEG_MAX; | |
| 235 } | |
| 236 } | |
| 237 return(result); | |
| 238 } | |
| 239 #endif | |
| 240 | |
| 241 INLINE WORD32 Add_40b( WORD32 guard1guard2, WORD32 lvar1, WORD32 lvar2, WORD16 *guardout ) | |
| 242 { | |
| 243 WORD32 result, temp, carry, Lvar1, Lvar2; | |
| 244 WORD16 guard1,guard2; | |
| 245 | |
| 246 guard1=(WORD16) ((WORD32) guard1guard2>>16); | |
| 247 guard2=(WORD16) guard1guard2; | |
| 248 | |
| 249 /* lvar1 and lvar2 are both 48 bits variables */ | |
| 250 /* We 1st add the low parts of lvar1 and lvar2 and we give */ | |
| 251 /* a 32 bits result and a carry if needed */ | |
| 252 Lvar1 = (UWORD16)lvar1; | |
| 253 Lvar2 = (UWORD16)lvar2; | |
| 254 | |
| 255 temp = Lvar1 + Lvar2; | |
| 256 | |
| 257 carry = temp >> 16; | |
| 258 | |
| 259 result = temp & 0x0000ffffL; | |
| 260 | |
| 261 /* We now add the two high parts of var1 and var2 (scaled */ | |
| 262 /* to a 16 bits format) and carry (if any) and we give a */ | |
| 263 /* 48 bits results. */ | |
| 264 Lvar1 = (UWORD32)lvar1 >> 16; | |
| 265 Lvar2 = (UWORD32)lvar2 >> 16; | |
| 266 | |
| 267 temp = Lvar1 + Lvar2 + carry; | |
| 268 | |
| 269 carry = (UWORD32)temp >> 16; | |
| 270 | |
| 271 temp = (UWORD32)temp << 16; | |
| 272 | |
| 273 result = result | temp; | |
| 274 | |
| 275 temp = guard1 + guard2 + carry; | |
| 276 | |
| 277 *guardout = (WORD16)temp; | |
| 278 | |
| 279 return( result ); | |
| 280 } | |
| 281 | |
| 282 | |
| 283 INLINE WORD32 Mult_40b(WORD32 var1, WORD16 var2, WORD16 *guardout) | |
| 284 { | |
| 285 WORD32 mult,guard1guard2; | |
| 286 WORD32 aux1; | |
| 287 UWORD32 aux2; | |
| 288 WORD16 neg_flag=0; | |
| 289 WORD32 var1_low_nosign,var2_nosign; | |
| 290 | |
| 291 if (var2<0) | |
| 292 { | |
| 293 var2=-var2; | |
| 294 neg_flag=1; | |
| 295 } | |
| 296 | |
| 297 /*aux1 = AccHigh(var1)*var2 */ | |
| 298 aux1 = (WORD32)(var1>>16) * (WORD32)var2; | |
| 299 /* 16 bits * 16 bits -> 32 bits result */ | |
| 300 | |
| 301 /*aux2 = AccLow(var1)*var2 (unsigned multiplication) */ | |
| 302 /* Performs the sign suppression of the words */ | |
| 303 var1_low_nosign = (UWORD16)var1; | |
| 304 var2_nosign = (UWORD16) var2; | |
| 305 | |
| 306 aux2 = (UWORD32)var1_low_nosign * (UWORD32)var2_nosign; | |
| 307 | |
| 308 /*Shift aux1=F48 of 16 bit left */ | |
| 309 guard1guard2=aux1&0xFFFF0000L;/*guard1=(WORD16)(aux1>>16)*/ | |
| 310 /*guard2=0x0000 */ | |
| 311 aux1=aux1<<16; | |
| 312 | |
| 313 | |
| 314 /* ((var1_high*var2)<<16) +(var1_low*var2) = aux1 + aux2 */ | |
| 315 /* aux1 and aux2 are both 48 bits variables */ | |
| 316 /* We first add the low pats of aux1 and aux2 and we give*/ | |
| 317 /* a 32 bits result and a carry if needed */ | |
| 318 mult=Add_40b(guard1guard2,aux1,aux2,guardout ); | |
| 319 | |
| 320 if (neg_flag) | |
| 321 { | |
| 322 mult=-mult; | |
| 323 if (*guardout!=0) | |
| 324 *guardout=-(*guardout)-1; | |
| 325 else | |
| 326 *guardout=-1; | |
| 327 } | |
| 328 | |
| 329 return(mult); | |
| 330 } | |
| 331 | |
| 332 | |
| 333 /***********************************************************************/ | |
| 334 /* This function allows to multiply a WORD32 and a WORD16, both POSITIVE, */ | |
| 335 /* variables. Result is WORD32. */ | |
| 336 /***********************************************************************/ | |
| 337 INLINE WORD32 UMult_40b(WORD32 var1, WORD16 var2, WORD16 *guardout) | |
| 338 { | |
| 339 WORD32 mult,guard1guard2; | |
| 340 UWORD32 aux1,aux2; | |
| 341 WORD32 var1_high_nosign,var1_low_nosign,var2_nosign; | |
| 342 | |
| 343 | |
| 344 /*aux1 = AccHigh(var1)*var2 (unsigned multiplication) */ | |
| 345 /* Performs the sign suppression of the words */ | |
| 346 var1_high_nosign = (UWORD32)var1>>16; | |
| 347 var2_nosign = (UWORD16) var2; | |
| 348 | |
| 349 aux1 = (UWORD32)var1_high_nosign * (UWORD32)var2_nosign; | |
| 350 | |
| 351 /*aux2 = AccLow(var1)*var2 (unsigned multiplication) */ | |
| 352 /* Performs the sign suppression of the words */ | |
| 353 var1_low_nosign = (WORD32)((UWORD16)var1); | |
| 354 | |
| 355 aux2 = (UWORD32)var1_low_nosign * (UWORD32)var2_nosign; | |
| 356 | |
| 357 /*Shift aux1=F48 of 16 bit left */ | |
| 358 guard1guard2=aux1&0xFFFF0000L;/*guard1=(WORD16)(aux1>>16)*/ | |
| 359 /*guard2=0x0000 */ | |
| 360 aux1=aux1<<16; | |
| 361 | |
| 362 | |
| 363 /* ((var1_high*var2)<<16) +(var1_low*var2) = aux1 + aux2 */ | |
| 364 mult=Add_40b(guard1guard2,aux1,aux2,guardout); | |
| 365 | |
| 366 return(mult); | |
| 367 } | |
| 368 | |
| 369 | |
| 370 /*-------------------------------------------------------*/ | |
| 371 /* l1ctl_afc() */ | |
| 372 /*-------------------------------------------------------*/ | |
| 373 /* Parameters : */ | |
| 374 /* Return : */ | |
| 375 /* Functionality : */ | |
| 376 /*-------------------------------------------------------*/ | |
| 377 #if (VCXO_ALGO == 0) | |
| 378 WORD16 l1ctl_afc (UWORD8 phase, UWORD32 *frame_count, WORD16 angle, WORD32 snr, UWORD16 radio_freq) | |
| 379 #else | |
| 380 WORD16 l1ctl_afc (UWORD8 phase, UWORD32 *frame_count, WORD16 angle, WORD32 snr, UWORD16 radio_freq, UWORD32 l1_mode) | |
| 381 #endif | |
| 382 { | |
| 383 /*************************/ | |
| 384 /* Variables declaration */ | |
| 385 /*************************/ | |
| 386 WORD16 i=0; | |
| 387 UWORD32 denom; /* F12.20 */ | |
| 388 WORD32 var_32,num,Phi_32=0,var1,var2,guard1guard2; | |
| 389 static UWORD32 P=C_cov_start; /* F12.20 */ | |
| 390 static WORD32 Psi=0; /* F13.19 */ | |
| 391 static WORD16 Psi_quant[C_N_del+1]; /* F13.3 */ | |
| 392 WORD16 var_16; | |
| 393 WORD16 Phi=0; /* F1.15 */ | |
| 394 WORD16 quotient,guard1,guard2,guardout; | |
| 395 UWORD32 LGuard; | |
| 396 WORD16 denomH,denomH_3msb; | |
| 397 UWORD32 K=0; /* algo 1 */ | |
| 398 | |
| 399 static WORD16 old_Psi_quant[C_N_del+1]; | |
| 400 static WORD32 old_Psi=0; | |
| 401 | |
| 402 #if (VCXO_ALGO == 1) | |
| 403 static WORD32 psi_past[C_N_del+1]; /* F13.19 */ | |
| 404 static WORD16 psi_quant; /* F13.3 */ | |
| 405 static WORD16 quant_avg; | |
| 406 static UWORD32 M_Count; | |
| 407 static WORD32 psi_avg[C_PSI_AVG_SIZE_D+1]; // Data history array | |
| 408 static WORD16 B_Count; // Counter for consecutive SNR below C_thr_snr | |
| 409 #if 0 /* LoCosto added var */ | |
| 410 UWORD16 L = 10433; // Gain algo2 | |
| 411 #endif | |
| 412 static UWORD16 first_avg; | |
| 413 static UWORD16 good_snr; | |
| 414 | |
| 415 /* to be able to keep in memory the old AFC variables in case of spurious | |
| 416 FB detection */ | |
| 417 static WORD32 old_psi_past[C_N_del+1]; /* F13.19 */ | |
| 418 static WORD16 old_psi_quant; /* F13.3 */ | |
| 419 | |
| 420 #endif | |
| 421 #if (L1_FF_MULTIBAND == 1) | |
| 422 UWORD8 physical_band_id; | |
| 423 #endif | |
| 424 | |
| 425 #if 0 /* LoCosto added var init */ | |
| 426 //Set AFC close loop gain for ALGO_AFC_LQG_PREDICTOR. | |
| 427 if(l1_mode==I_MODE)//MS is in Idle mode | |
| 428 L = 41732; //F0.20 L=41732/2^20 = 0.04 | |
| 429 else //All other modes than Idle | |
| 430 L = 10433; //F0.20 L=10433/2^20 = 0.01 | |
| 431 #endif | |
| 432 | |
| 433 #if (L1_FF_MULTIBAND == 0) | |
| 434 | |
| 435 if (((l1_config.std.id == DUAL) || (l1_config.std.id == DUALEXT) || (l1_config.std.id == DUAL_US)) && | |
| 436 #if (VCXO_ALGO == 1) | |
| 437 ((phase != AFC_INIT_CENTER) || (phase != AFC_INIT_MIN) || (phase != AFC_INIT_MAX))) | |
| 438 #else | |
| 439 (phase != AFC_INIT)) | |
| 440 #endif | |
| 441 { | |
| 442 if (radio_freq >= l1_config.std.first_radio_freq_band2) | |
| 443 { | |
| 444 angle = (angle + 1) >> 1; | |
| 445 } | |
| 446 } | |
| 447 | |
| 448 else if (((l1_config.std.id == DCS1800) || (l1_config.std.id == PCS1900)) && | |
| 449 #if (VCXO_ALGO == 1) | |
| 450 ((phase != AFC_INIT_CENTER) || (phase != AFC_INIT_MIN) || (phase != AFC_INIT_MAX))) | |
| 451 #else | |
| 452 (phase != AFC_INIT)) | |
| 453 #endif | |
| 454 { | |
| 455 angle = (angle + 1) >> 1; | |
| 456 } | |
| 457 | |
| 458 #else // L1_FF_MULTIBAND = 1 below | |
| 459 | |
| 460 #if (VCXO_ALGO == 1) | |
| 461 if((phase != AFC_INIT_CENTER) || (phase != AFC_INIT_MIN) || (phase != AFC_INIT_MAX)) | |
| 462 #else | |
| 463 if(phase != AFC_INIT) | |
| 464 #endif | |
| 465 { | |
| 466 physical_band_id = l1_multiband_radio_freq_convert_into_physical_band_id(radio_freq); | |
| 467 | |
| 468 if( (multiband_rf[physical_band_id].gsm_band_identifier == DCS1800) || (multiband_rf[physical_band_id].gsm_band_identifier == PCS1900)) | |
| 469 { | |
| 470 angle = (angle + 1) >> 1; | |
| 471 } | |
| 472 } | |
| 473 | |
| 474 #endif // #if (L1_FF_MULTIBAND == 1) else | |
| 475 | |
| 476 | |
| 477 | |
| 478 /*********************************/ | |
| 479 /* frequency offset compensation */ | |
| 480 /*********************************/ | |
| 481 /* Initialization */ | |
| 482 | |
| 483 #if (VCXO_ALGO == 1) | |
| 484 switch (l1_config.params.afc_algo) | |
| 485 { | |
| 486 | |
| 487 /* algo1 only: */ | |
| 488 case ALGO_AFC_KALMAN: | |
| 489 { | |
| 490 #endif | |
| 491 #if (VCXO_ALGO == 0) | |
| 492 if (phase==AFC_INIT) | |
| 493 { | |
| 494 // WARNING | |
| 495 // In this case, "angle" variable contains EEPROM_AFC initialization value | |
| 496 // directly loaded from EEPROM, and "snr" variable is not meaningful. | |
| 497 /* Static variables initialisation */ | |
| 498 P=C_cov_start; | |
| 499 Psi=0; | |
| 500 if (angle>C_max_step) | |
| 501 Psi_quant[C_N_del]=C_max_step; | |
| 502 else | |
| 503 if(angle<C_min_step) | |
| 504 Psi_quant[C_N_del]=C_min_step; | |
| 505 else Psi_quant[C_N_del]=angle; | |
| 506 | |
| 507 Psi=l1_config.params.psi_st*Psi_quant[C_N_del]; /* F0.16 * F13.3 = F13.19 */ | |
| 508 } /* end AFC_INIT*/ | |
| 509 else | |
| 510 { | |
| 511 if (phase==AFC_OPEN_LOOP) | |
| 512 { | |
| 513 /* delay line for Psi_quant values */ | |
| 514 for (i=1;i<=C_N_del;i++) | |
| 515 Psi_quant[i-1]=Psi_quant[i]; | |
| 516 | |
| 517 var_32=(WORD32)((WORD32)angle*l1_config.params.psi_sta_inv)<<4; | |
| 518 /*(F16.0 * F1.15 = F17.15) << 4 = F13.19 */ | |
| 519 | |
| 520 #if(RF_FAM == 61) | |
| 521 /* In order to implement the NINT function for a F16.0, we check */ | |
| 522 /* if var_32 + 0.5*2**18 is a multiple of 2**18 */ | |
| 523 quotient=(WORD16)((WORD32)(((WORD32)(var_32+(1<<17)))/(1<<18))); | |
| 524 var_16=quotient*4; | |
| 525 #else | |
| 526 /* In order to implement the NINT function for a F16.0, we check */ | |
| 527 /* if var_32 + 0.5*2**19 is a multiple of 2**19 */ | |
| 528 quotient=(WORD16)((WORD32)(((WORD32)(var_32+(1<<18)))/(1<<19))); | |
| 529 var_16=quotient*8; | |
| 530 #endif | |
| 531 if (var_16>C_max_step) | |
| 532 Psi_quant[C_N_del]=Add_Sat_sign_16b(Psi_quant[C_N_del],C_max_step); | |
| 533 else | |
| 534 if(var_16<C_min_step) | |
| 535 Psi_quant[C_N_del]=Add_Sat_sign_16b(Psi_quant[C_N_del],C_min_step); | |
| 536 else Psi_quant[C_N_del]=Add_Sat_sign_16b(Psi_quant[C_N_del],var_16); /* F13.3 */ | |
| 537 | |
| 538 Psi=l1_config.params.psi_st*Psi_quant[C_N_del]; /* F0.16 * F13.3 = F13.19 */ | |
| 539 }/*end if AFC_OPEN_LOOP*/ | |
| 540 | |
| 541 else | |
| 542 { | |
| 543 /* delay line for Psi_quant values */ | |
| 544 for (i=1;i<=C_N_del;i++) | |
| 545 Psi_quant[i-1]=Psi_quant[i]; | |
| 546 | |
| 547 /********************/ | |
| 548 /* Filter algorithm */ | |
| 549 /********************/ | |
| 550 | |
| 551 /* Covariance error is increased of C_Q */ | |
| 552 P=P+(*frame_count)*C_Q; | |
| 553 | |
| 554 /* Clipping of P */ | |
| 555 if (P>C_thr_P) P=C_thr_P; | |
| 556 | |
| 557 if (snr>=C_thr_snr) | |
| 558 { | |
| 559 /* Clipping of error angle */ | |
| 560 if (angle>C_thr_phi) | |
| 561 angle=C_thr_phi; | |
| 562 if (angle<-C_thr_phi) | |
| 563 angle=-C_thr_phi; | |
| 564 | |
| 565 /* Kalman gain */ | |
| 566 /*K=P*(1/(P+C_a0_kalman+(C_g_kalman*RNS))) */ | |
| 567 /*C_a0_kalman=0.01 */ | |
| 568 /*C_g_kalman =0.05 */ | |
| 569 num=(C_g_kalman/snr)+P+C_a0_kalman; | |
| 570 /* (F2.30 / F6.10) = F 12.20 */ | |
| 571 | |
| 572 /* denom = P << 19 = F 1.39 */ | |
| 573 /* extension of denom=P to a 40 bits variable */ | |
| 574 /* denom (F12.20) << 16 = F 4.36 */ | |
| 575 guard1=(WORD16)((WORD32)P>>16); | |
| 576 /* denom = P<<16 = (F4.36) << 3 = F 1.39 */ | |
| 577 denomH=(UWORD16)P; | |
| 578 /* Low part of denom is equal to 0, because P has been 16 */ | |
| 579 /* bits left shifted previously. */ | |
| 580 denomH_3msb=(denomH>>13)&0x0007; | |
| 581 guard1=(guard1<<3)|denomH_3msb; | |
| 582 denomH<<=3; | |
| 583 denom=(UWORD32)denomH<<16; | |
| 584 /* num + guard1 are a 40 bits representation of P */ | |
| 585 /* In order to compute P(F1.39)/num, we sample P in guard1 */ | |
| 586 /* (scaled to a 32 bits number) and num (32 bits number) */ | |
| 587 /* K = ((guard1<<24)/num)<<8 + (denom/num) */ | |
| 588 var1=(WORD32)guard1<<24; | |
| 589 var1=var1/num; | |
| 590 var1=(WORD32)var1<<8; | |
| 591 /* var2 is an unsigned variable, var1 contains signed guard*/ | |
| 592 /* bits. */ | |
| 593 var2=denom/num; | |
| 594 K = (var1+var2)<<1; /* F1.39 / F12.20 = F13.19 */ | |
| 595 /* F13.19 << 1 = F12.20 */ | |
| 596 | |
| 597 /* Clipping of the Kalman gain */ | |
| 598 if (K>=C_thr_K) | |
| 599 K=C_thr_K; | |
| 600 | |
| 601 /*******************************************************/ | |
| 602 /* P=(1-K)*P = 0.8 * 0.5 at maximum */ | |
| 603 /*******************************************************/ | |
| 604 /* Perform a positive variable F12.20 multiplication by*/ | |
| 605 /* positive variable F12.20 */ | |
| 606 var_16=(WORD16)(1048576L-K); /* acclow(1-K) = F12.20 */ | |
| 607 guard1=0; /* positive variable */ | |
| 608 var1=UMult_40b(P,var_16,&guard1); | |
| 609 var_16=(WORD16)((1048576L-K)>>16); | |
| 610 /* acchigh(1-K) = F12.20 */ | |
| 611 var2=P*var_16; /* var2 = 0x80000 * 0xc */ | |
| 612 /* at maximum, so result */ | |
| 613 /* is 32 bits WORD32 and */ | |
| 614 /* equal 0x600000 */ | |
| 615 /* extension of var2 to a 40 bits variable : var2<<16 */ | |
| 616 guard2=(WORD16)((WORD32)var2>>16); | |
| 617 guard1guard2=((WORD32)guard1<<16) |((WORD32) guard2&0x0000FFFFL); | |
| 618 var2=var2<<16; | |
| 619 var_32=Add_40b(guard1guard2,var1,var2,&guardout); | |
| 620 /* var_32 (F8.40) >> 16 = F8.24 */ | |
| 621 LGuard=(WORD32)guardout<<16; | |
| 622 var1=(UWORD32)var_32>>16; | |
| 623 /* var_32 >> 4 = F12.20 */ | |
| 624 P=(var1+LGuard)>>4; | |
| 625 | |
| 626 Phi_32=Mult_40b(l1_config.params.psi_st_32,Psi_quant[0],&guardout); | |
| 627 /* F0.32 * F13.3 = F5.35 */ | |
| 628 LGuard=(WORD32)guardout<<16; /* var_32 (F5.35) >> 16 */ | |
| 629 /* F13.19 */ | |
| 630 var1=(UWORD32)Phi_32>>16; | |
| 631 Phi_32=Psi-(LGuard+var1); /* F13.19 */ | |
| 632 | |
| 633 /*Phi=angle-Phi_32*/ | |
| 634 Phi_32=((WORD32)angle<<4)-Phi_32; | |
| 635 /* F1.15 * 4 = F13.19 */ | |
| 636 Phi=(WORD16)(Phi_32>>4); /* F17.15 */ | |
| 637 /*var1=K*Phi F12.20 * F1.15 = 13.35 */ | |
| 638 guard1=0; | |
| 639 var1=Mult_40b(K,Phi,&guard1); | |
| 640 /* var1 (F13.35) >> 16 */ | |
| 641 /* F13.19 */ | |
| 642 LGuard=(WORD32)guard1<<16; | |
| 643 var1=(UWORD32)var1>>16; | |
| 644 Psi+=var1+LGuard; | |
| 645 }/*if snr */ | |
| 646 | |
| 647 var_32=Mult_40b(Psi,l1_config.params.psi_st_inv,&guardout); | |
| 648 /* F13.19 * C = F13.19 */ | |
| 649 | |
| 650 #if(RF_FAM == 61) | |
| 651 /* In order to implement the NINT function for a F13.3, we check */ | |
| 652 /* if var_32 + 0.5*2**18 is a multiple of 2**18 */ | |
| 653 quotient=(WORD16)((WORD32)(((WORD32)(var_32+(1<<17)))/(1<<18))); | |
| 654 var_16=quotient*4; | |
| 655 #else | |
| 656 /* In order to implement the NINT function for a F13.3, we check */ | |
| 657 /* if var_32 + 0.5*2**19 is a multiple of 2**19 */ | |
| 658 quotient=(WORD16)((WORD32)(((WORD32)(var_32+(1<<18)))/(1<<19))); | |
| 659 var_16=quotient*8; | |
| 660 #endif | |
| 661 if (var_16>C_max_step) | |
| 662 Psi_quant[C_N_del]=C_max_step; | |
| 663 else | |
| 664 if(var_16<C_min_step) | |
| 665 Psi_quant[C_N_del]=C_min_step; | |
| 666 else Psi_quant[C_N_del]=var_16; /* F13.3 */ | |
| 667 | |
| 668 }/*end AFC_CLOSE_LOOP*/ | |
| 669 } /* end else AFC_INIT*/ | |
| 670 | |
| 671 *frame_count=0; | |
| 672 return(Psi_quant[C_N_del]>>3); /* F16.0 */ | |
| 673 | |
| 674 #else | |
| 675 | |
| 676 } /* end case algo 1 */ | |
| 677 | |
| 678 | |
| 679 /* algo2 + init + estimator/predictor */ | |
| 680 case ALGO_AFC_LQG_PREDICTOR: | |
| 681 { | |
| 682 /******************************************************************/ | |
| 683 /* (New) VCXO Algorithm */ | |
| 684 /******************************************************************/ | |
| 685 | |
| 686 switch (phase) { | |
| 687 case AFC_INIT_CENTER : | |
| 688 case AFC_INIT_MAX : | |
| 689 case AFC_INIT_MIN : | |
| 690 quant_avg = 0; | |
| 691 M_Count = 0; | |
| 692 #if 0 /* present in LoCosto but not in TCS211 */ | |
| 693 for (i = 0; i <= C_PSI_AVG_SIZE_D ; i++) //omaps00090550 | |
| 694 psi_avg[i] = 0; | |
| 695 #endif | |
| 696 first_avg = 1; | |
| 697 good_snr = 0; | |
| 698 | |
| 699 // DAC search algorithm is as follows - up to 12 attempts are made | |
| 700 // DAC search algorithm uses three values : DAC_center -> DAC_max -> DAC_min -> | |
| 701 // The first four attempts are made on DAC_center | |
| 702 // The next four attempts are made on DAC_max | |
| 703 // The last four attempts are made on DAC_min | |
| 704 // There are statistical reasons for trying four times | |
| 705 | |
| 706 switch (phase) | |
| 707 { | |
| 708 case AFC_INIT_CENTER: | |
| 709 psi_quant = l1_config.params.afc_dac_center; | |
| 710 break; | |
| 711 case AFC_INIT_MAX: | |
| 712 psi_quant = l1_config.params.afc_dac_max; | |
| 713 break; | |
| 714 case AFC_INIT_MIN: | |
| 715 psi_quant = l1_config.params.afc_dac_min; | |
| 716 break; | |
| 717 default : | |
| 718 break; | |
| 719 } | |
| 720 | |
| 721 /* F0.32 * F13.3 = F5.35 */ | |
| 722 psi_past[C_N_del]=Mult_40b(l1_config.params.psi_st_32,psi_quant, &guardout); | |
| 723 /* (F13.3<<16 )+(F5.35>>16) = F13.19 */ | |
| 724 psi_past[C_N_del]=((WORD32)guardout<<16)+((UWORD32)psi_past[C_N_del]>>16); | |
| 725 | |
| 726 break; | |
| 727 | |
| 728 case AFC_OPEN_LOOP : | |
| 729 { | |
| 730 /* VCXO changes for spurious FB detection */ | |
| 731 if (l1s.spurious_fb_detected == TRUE) | |
| 732 { | |
| 733 psi_quant = old_psi_quant; | |
| 734 | |
| 735 for(i=0;i<C_N_del+1;i++) | |
| 736 psi_past[i] = old_psi_past[i]; | |
| 737 | |
| 738 /* reset the spurious_fb_detected_flag */ | |
| 739 l1s.spurious_fb_detected = FALSE; | |
| 740 } /* end of spuriousFB detected */ | |
| 741 | |
| 742 /* save in memory the old AFC related values */ | |
| 743 old_psi_quant = psi_quant; | |
| 744 | |
| 745 for(i=0;i<C_N_del+1;i++) | |
| 746 old_psi_past[i] = psi_past[i]; | |
| 747 | |
| 748 /* delay line for psi_quant values */ | |
| 749 for (i = 1; i <= C_N_del; i++) | |
| 750 psi_past[i-1] = psi_past[i]; | |
| 751 | |
| 752 /* (F16.0 * F1.15 = F17.15) << 4 = F13.19 */ | |
| 753 var_32 = (WORD32) ((WORD32)angle * l1_config.params.psi_sta_inv) << 4; | |
| 754 | |
| 755 #if(RF_FAM == 61) | |
| 756 /* In order to implement the NINT function for a F16.0,*/ | |
| 757 /*we check if var_32 + 0.5*2**18 is a multiple of 2**18 */ | |
| 758 var_16 = (WORD16) | |
| 759 ((WORD32) (((WORD32)(var_32 + (1<<17))) / (1<<18))); | |
| 760 var_16 = var_16 * 4; | |
| 761 #else | |
| 762 /* In order to implement the NINT function for a F16.0,*/ | |
| 763 /*we check if var_32 + 0.5*2**19 is a multiple of 2**19 */ | |
| 764 var_16 = (WORD16) | |
| 765 ((WORD32) (((WORD32)(var_32 + (1<<18))) / (1<<19))); | |
| 766 var_16 = var_16 * 8; | |
| 767 #endif | |
| 768 | |
| 769 #if 0 /* LoCosto code with saturation */ | |
| 770 if (var_16 > C_max_step) | |
| 771 psi_quant = Add_Sat_sign_16b(psi_quant,C_max_step); | |
| 772 else if (var_16 < C_min_step) | |
| 773 psi_quant = Add_Sat_sign_16b(psi_quant,C_min_step); | |
| 774 else psi_quant = Add_Sat_sign_16b(psi_quant,var_16); /* F13.3 */ | |
| 775 #else /* matching TCS211 */ | |
| 776 if (var_16 > C_max_step) | |
| 777 psi_quant += C_max_step; | |
| 778 else if (var_16 < C_min_step) | |
| 779 psi_quant += C_min_step; | |
| 780 else psi_quant += var_16; /* F13.3 */ | |
| 781 #endif | |
| 782 | |
| 783 /* F0.32 * F13.3 = F5.35 */ | |
| 784 psi_past[C_N_del]=Mult_40b(l1_config.params.psi_st_32,psi_quant, &guardout); | |
| 785 /* (F13.3<<16 )+(F5.35>>16) = F13.19 */ | |
| 786 psi_past[C_N_del]=((WORD32)guardout<<16)+((UWORD32)psi_past[C_N_del]>>16); | |
| 787 | |
| 788 } | |
| 789 break; | |
| 790 | |
| 791 case AFC_CLOSED_LOOP : | |
| 792 | |
| 793 /* delay line for psi_quant values */ | |
| 794 for (i = 1; i <= C_N_del; i++) | |
| 795 psi_past[i-1] = psi_past[i]; | |
| 796 | |
| 797 /************************************/ | |
| 798 /* Estimation */ | |
| 799 /************************************/ | |
| 800 if ( (l1_config.params.rgap_algo != 0) && | |
| 801 ((l1_mode==CON_EST_MODE2)||(l1_mode==DEDIC_MODE) | |
| 802 #if L1_GPRS | |
| 803 || l1_mode==PACKET_TRANSFER_MODE | |
| 804 #endif | |
| 805 )) | |
| 806 { | |
| 807 | |
| 808 M_Count += *frame_count; | |
| 809 if (snr >= l1_config.params.afc_snr_thr) { | |
| 810 // Accumulate average over N TDMA frames | |
| 811 psi_avg[0] += psi_past[C_N_del]; | |
| 812 // Count number of good snr's within window_avg_size chunks | |
| 813 good_snr++; | |
| 814 } | |
| 815 // M_Count >= M ? | |
| 816 if (M_Count >= l1_config.params.afc_win_avg_size_M) { | |
| 817 // M_Count counts how far we have reached in the window_avg_size blocks | |
| 818 | |
| 819 // Scale estimate relative to good snr - Don't divide by zero in case of bad measurements | |
| 820 if (good_snr > 0) | |
| 821 psi_avg[0] /= good_snr; | |
| 822 | |
| 823 // We now have an estimation over window_avg_size TDMA frames in psi_avg[0] | |
| 824 if (first_avg == 1) { | |
| 825 first_avg = 0; | |
| 826 // Use first estimation as best guess for the other avg values | |
| 827 // This is used both at initialisation and when returning from reception gap | |
| 828 for (i = 1; i <= C_PSI_AVG_SIZE_D ; i++) | |
| 829 psi_avg[i] = psi_avg[0]; | |
| 830 } | |
| 831 | |
| 832 // Estimation 1st order | |
| 833 // Use biggest window to reduce noise effects signal in psi values | |
| 834 // NOTE: Due to performance issues division by MSIZE is in predictor | |
| 835 if (l1_config.params.rgap_algo >= 1) { | |
| 836 quant_avg = (WORD16) (psi_avg[0] - psi_avg[C_PSI_AVG_SIZE_D]); | |
| 837 } | |
| 838 | |
| 839 for (i = C_PSI_AVG_SIZE_D - 1; i >= 0 ; i--) | |
| 840 psi_avg[i+1] = psi_avg[i]; | |
| 841 psi_avg[0] = 0; | |
| 842 M_Count = 0; | |
| 843 good_snr = 0; | |
| 844 } | |
| 845 | |
| 846 } else { | |
| 847 // No estmation when in Idle mode (DEEP or BIG SLEEP) => Reset! | |
| 848 first_avg = 1; | |
| 849 M_Count = 0; | |
| 850 good_snr = 0; | |
| 851 psi_avg[0] = 0; | |
| 852 } | |
| 853 | |
| 854 if (snr >= l1_config.params.afc_snr_thr) { | |
| 855 /********************/ | |
| 856 /* Filter algorithm */ | |
| 857 /********************/ | |
| 858 | |
| 859 /* No prediction during normal operation */ | |
| 860 B_Count= 0; | |
| 861 | |
| 862 /* Clip error angle */ | |
| 863 if (angle > C_thr_phi) | |
| 864 angle = C_thr_phi; | |
| 865 if (angle < -C_thr_phi) | |
| 866 angle = -C_thr_phi; | |
| 867 | |
| 868 Phi_32 = psi_past[C_N_del] - psi_past[0]; /* F13.19 */ | |
| 869 /* Phi = angle - Phi_32*/ | |
| 870 Phi_32 = ((WORD32) angle << 4) - Phi_32; | |
| 871 /* F1.15 * 4 = F13.19 */ | |
| 872 #if 0 /* LoCosto code */ | |
| 873 Phi = (WORD16)((WORD32)((WORD32)(Phi_32 + (1<<3)))/ (1<<4)); /* F17.15 */ | |
| 874 #else /* TCS211 reconstruction */ | |
| 875 Phi = Phi_32 >> 4; | |
| 876 #endif | |
| 877 /* (F0.20 * F1.15) >> 16 = F13.19 */ | |
| 878 #if 0 /* LoCosto code with saturation and L */ | |
| 879 var_32 = (L * Phi + (1<<15)) >> 16; | |
| 880 psi_past[C_N_del] = Add_Sat_sign_32b(psi_past[C_N_del],var_32); | |
| 881 #else /* matching TCS211 */ | |
| 882 psi_past[C_N_del] += (10433 * Phi) >> 16; | |
| 883 #endif | |
| 884 | |
| 885 } | |
| 886 else | |
| 887 { | |
| 888 /************************************/ | |
| 889 /* Prediction */ | |
| 890 /************************************/ | |
| 891 | |
| 892 // Only predict in dedicated mode | |
| 893 // NO prediction in idle mode | |
| 894 // l1a_l1s_com.dedic_set.SignalCode = NULL | |
| 895 if ( (l1_config.params.rgap_algo != 0) && | |
| 896 ((l1_mode==CON_EST_MODE2)||(l1_mode==DEDIC_MODE) | |
| 897 #if L1_GPRS | |
| 898 || l1_mode==PACKET_TRANSFER_MODE | |
| 899 #endif | |
| 900 )) | |
| 901 { | |
| 902 /* Prediction of psi during reception gaps */ | |
| 903 B_Count | |
| 904 += *frame_count; | |
| 905 | |
| 906 /* Predict psi ONLY when we have sufficient measurements available */ | |
| 907 /* If we don't have enough measurements we don't do anything (= 0th order estimation)*/ | |
| 908 | |
| 909 // Was the consecutive bad SNRs threshold value exceeded? | |
| 910 if (B_Count>= l1_config.params.rgap_bad_snr_count_B) { | |
| 911 | |
| 912 // Predict with 0th order estimation is the default | |
| 913 | |
| 914 // Predict with 1st order estimation | |
| 915 if (l1_config.params.rgap_algo >= 1) | |
| 916 { | |
| 917 #if 0 /* LoCosto code with saturation */ | |
| 918 psi_past[C_N_del] = Add_Sat_sign_32b(psi_past[C_N_del], | |
| 919 ((quant_avg * (l1_config.params.rgap_bad_snr_count_B))/(C_MSIZE)) | |
| 920 ); | |
| 921 #else /* matching TCS211 */ | |
| 922 psi_past[C_N_del] += | |
| 923 ((quant_avg * (l1_config.params.rgap_bad_snr_count_B))/(C_MSIZE)); | |
| 924 #endif | |
| 925 } | |
| 926 | |
| 927 B_Count= B_Count - l1_config.params.rgap_bad_snr_count_B; | |
| 928 | |
| 929 // Indicate by raising first_avg flag that a reception gap has occurred | |
| 930 // I.e. the psi_avg table must be reinitialised after leaving reception gap | |
| 931 first_avg = 1; | |
| 932 | |
| 933 // Counters in estimation part must also be reset | |
| 934 M_Count = 0; | |
| 935 good_snr = 0; | |
| 936 psi_avg[0] = 0; | |
| 937 } | |
| 938 } | |
| 939 } | |
| 940 | |
| 941 /* Quantize psi value */ | |
| 942 | |
| 943 /* F0.19 * 16.0 = F16.19 */ | |
| 944 #if 0 /* LoCosto code */ | |
| 945 var_32 = Sat_Mult_20sign_16unsign(psi_past[C_N_del],l1_config.params.psi_st_inv); | |
| 946 #else /* TCS211 reconstruction */ | |
| 947 var_32 = psi_past[C_N_del] * l1_config.params.psi_st_inv; | |
| 948 #endif | |
| 949 | |
| 950 #if(RF_FAM == 61) | |
| 951 /* In order to implement the NINT function for a F13.3,*/ | |
| 952 /*we check if var_32 + 0.5*2**18 is a multiple of 2**18 */ | |
| 953 var_16 = (WORD16) | |
| 954 ((WORD32)((WORD32)(var_32 + (1<<17))) / (1<<18)); | |
| 955 var_16 = var_16 * 4; | |
| 956 #else | |
| 957 /* In order to implement the NINT function for a F13.3,*/ | |
| 958 /*we check if var_32 + 0.5*2**19 is a multiple of 2**19 */ | |
| 959 var_16 = (WORD16) | |
| 960 ((WORD32)((WORD32)(var_32 + (1<<18))) / (1<<19)); | |
| 961 var_16 = var_16 * 8; | |
| 962 #endif | |
| 963 if (var_16 > C_max_step) | |
| 964 psi_quant = C_max_step; | |
| 965 else if (var_16 < C_min_step) | |
| 966 psi_quant = C_min_step; | |
| 967 else | |
| 968 psi_quant = var_16; /* F13.3 */ | |
| 969 break; | |
| 970 } // switch phase | |
| 971 | |
| 972 *frame_count = 0; | |
| 973 | |
| 974 return (psi_quant >> 3); /* F16.0 */ | |
| 975 } /* end case algo 2 */ | |
| 976 | |
| 977 /* algo1 + init + estimator/predictor */ | |
| 978 case ALGO_AFC_KALMAN_PREDICTOR: | |
| 979 { | |
| 980 if ((phase==AFC_INIT_CENTER) || (phase==AFC_INIT_MAX) || (phase==AFC_INIT_MIN)) | |
| 981 { | |
| 982 // WARNING | |
| 983 // In this case, "angle" variable contains EEPROM_AFC initialization value | |
| 984 // directly loaded from EEPROM, and "snr" variable is not meaningful. | |
| 985 /* Static variables initialisation */ | |
| 986 | |
| 987 quant_avg = 0; | |
| 988 M_Count = 0; | |
| 989 #if 0 /* present in LoCosto but not in TCS211 */ | |
| 990 for (i = 0; i <=C_PSI_AVG_SIZE_D ; i++) //omaps00090550 | |
| 991 psi_avg[i] = 0; | |
| 992 #endif | |
| 993 first_avg = 1; | |
| 994 good_snr = 0; | |
| 995 | |
| 996 // DAC search algorithm is as follows - up to 12 attempts are made | |
| 997 // DAC search algorithm uses three values : DAC_center -> DAC_max -> DAC_min -> | |
| 998 // The first four attempts are made on DAC_center | |
| 999 // The next four attempts are made on DAC_max | |
| 1000 // The last four attempts are made on DAC_min | |
| 1001 // There are statistical reasons for trying four times | |
| 1002 | |
| 1003 switch (phase) { | |
| 1004 case AFC_INIT_CENTER: | |
| 1005 Psi_quant[C_N_del] = l1_config.params.afc_dac_center; | |
| 1006 break; | |
| 1007 case AFC_INIT_MAX: | |
| 1008 Psi_quant[C_N_del] = l1_config.params.afc_dac_max; | |
| 1009 break; | |
| 1010 case AFC_INIT_MIN: | |
| 1011 Psi_quant[C_N_del] = l1_config.params.afc_dac_min; | |
| 1012 break; | |
| 1013 default : | |
| 1014 break; | |
| 1015 } | |
| 1016 | |
| 1017 P=C_cov_start; | |
| 1018 Psi=0; | |
| 1019 if (angle>C_max_step) | |
| 1020 Psi_quant[C_N_del]=C_max_step; | |
| 1021 else | |
| 1022 if(angle<C_min_step) | |
| 1023 Psi_quant[C_N_del]=C_min_step; | |
| 1024 else Psi_quant[C_N_del]=angle; | |
| 1025 | |
| 1026 /* F0.32 * F13.3 = F5.35 */ | |
| 1027 Psi=Mult_40b(l1_config.params.psi_st_32,Psi_quant[C_N_del], &guardout); | |
| 1028 /* (F13.3<<16 )+(F5.35>>16) = F13.19 */ | |
| 1029 Psi=((WORD32)guardout<<16)+((UWORD32)Psi>>16); | |
| 1030 | |
| 1031 } /* end AFC_INIT*/ | |
| 1032 else | |
| 1033 { | |
| 1034 if (phase==AFC_OPEN_LOOP) | |
| 1035 { | |
| 1036 /* relaod last good values in the ALGO */ | |
| 1037 if (l1s.spurious_fb_detected == TRUE) | |
| 1038 { | |
| 1039 for(i=0;i<C_N_del+1;i++) | |
| 1040 Psi_quant[i] = old_Psi_quant[i]; | |
| 1041 | |
| 1042 Psi = old_Psi; | |
| 1043 l1s.spurious_fb_detected = FALSE; | |
| 1044 } | |
| 1045 | |
| 1046 /* Save the old values in memory */ | |
| 1047 for(i=0;i<C_N_del+1;i++) | |
| 1048 old_Psi_quant[i] = Psi_quant[i]; | |
| 1049 old_Psi = Psi; | |
| 1050 | |
| 1051 /* delay line for Psi_quant values */ | |
| 1052 for (i=1;i<=C_N_del;i++) | |
| 1053 Psi_quant[i-1]=Psi_quant[i]; | |
| 1054 | |
| 1055 var_32=(WORD32)((WORD32)angle*l1_config.params.psi_sta_inv)<<4; | |
| 1056 /*(F16.0 * F1.15 = F17.15) << 4 = F13.19 */ | |
| 1057 | |
| 1058 #if(RF_FAM == 61) | |
| 1059 /* In order to implement the NINT function for a F16.0, we check */ | |
| 1060 /* if var_32 + 0.5*2**18 is a multiple of 2**18 */ | |
| 1061 quotient=(WORD16)((WORD32)(((WORD32)(var_32+(1<<17)))/(1<<18))); | |
| 1062 var_16=quotient*4; | |
| 1063 #else | |
| 1064 /* In order to implement the NINT function for a F16.0, we check */ | |
| 1065 /* if var_32 + 0.5*2**19 is a multiple of 2**19 */ | |
| 1066 quotient=(WORD16)((WORD32)(((WORD32)(var_32+(1<<18)))/(1<<19))); | |
| 1067 var_16=quotient*8; | |
| 1068 #endif | |
| 1069 | |
| 1070 #if 0 /* LoCosto code with saturation */ | |
| 1071 if (var_16>C_max_step) | |
| 1072 Psi_quant[C_N_del]=Add_Sat_sign_16b(Psi_quant[C_N_del],C_max_step); | |
| 1073 else if (var_16<C_min_step) | |
| 1074 Psi_quant[C_N_del]=Add_Sat_sign_16b(Psi_quant[C_N_del],C_min_step); | |
| 1075 else Psi_quant[C_N_del]=Add_Sat_sign_16b(Psi_quant[C_N_del],var_16); /* F13.3 */ | |
| 1076 #else /* matching TCS211 */ | |
| 1077 if (var_16>C_max_step) | |
| 1078 Psi_quant[C_N_del] += C_max_step; | |
| 1079 else if (var_16<C_min_step) | |
| 1080 Psi_quant[C_N_del] += C_min_step; | |
| 1081 else Psi_quant[C_N_del] += var_16; /* F13.3 */ | |
| 1082 #endif | |
| 1083 | |
| 1084 /* F0.32 * F13.3 = F5.35 */ | |
| 1085 Psi=Mult_40b(l1_config.params.psi_st_32,Psi_quant[C_N_del], &guardout); | |
| 1086 /* (F13.3<<16 )+(F5.35>>16) = F13.19 */ | |
| 1087 Psi=((WORD32)guardout<<16)+((UWORD32)Psi>>16); | |
| 1088 | |
| 1089 }/*end if AFC_OPEN_LOOP*/ | |
| 1090 else | |
| 1091 { | |
| 1092 | |
| 1093 /* delay line for Psi_quant values */ | |
| 1094 for (i=1;i<=C_N_del;i++) | |
| 1095 Psi_quant[i-1]=Psi_quant[i]; | |
| 1096 | |
| 1097 /************************************/ | |
| 1098 /* Estimation */ | |
| 1099 /************************************/ | |
| 1100 if ( (l1_config.params.rgap_algo != 0) && | |
| 1101 ((l1_mode==CON_EST_MODE2)||(l1_mode==DEDIC_MODE) | |
| 1102 #if L1_GPRS | |
| 1103 || l1_mode==PACKET_TRANSFER_MODE | |
| 1104 #endif | |
| 1105 )) | |
| 1106 { | |
| 1107 | |
| 1108 M_Count += *frame_count; | |
| 1109 if (snr >= l1_config.params.afc_snr_thr) { | |
| 1110 // Accumulate average over N TDMA frames | |
| 1111 psi_avg[0] += psi_past[C_N_del]; | |
| 1112 // Count number of good snr's within window_avg_size chunks | |
| 1113 good_snr++; | |
| 1114 } | |
| 1115 | |
| 1116 // M_Count >= M ? | |
| 1117 if (M_Count >= l1_config.params.afc_win_avg_size_M) { | |
| 1118 // M_Count counts how far we have reached in the window_avg_size blocks | |
| 1119 | |
| 1120 // Scale estimate relative to good snr - Don't divide by zero in case of bad measurements | |
| 1121 if (good_snr > 0) | |
| 1122 psi_avg[0] /= good_snr; | |
| 1123 | |
| 1124 // We now have an estimation over window_avg_size TDMA frames in psi_avg[0] | |
| 1125 if (first_avg == 1) { | |
| 1126 first_avg = 0; | |
| 1127 // Use first estimation as best guess for the other avg values | |
| 1128 // This is used both at initialisation and when returning from reception gap | |
| 1129 for (i = 1; i <= C_PSI_AVG_SIZE_D ; i++) | |
| 1130 psi_avg[i] = psi_avg[0]; | |
| 1131 } | |
| 1132 | |
| 1133 // Estimation 1st order | |
| 1134 // Use biggest window to reduce noise effects signal in psi values | |
| 1135 // NOTE: Due to performance issues division by MSIZE is in predictor | |
| 1136 if (l1_config.params.rgap_algo >= 1) { | |
| 1137 quant_avg = (WORD16) (psi_avg[0] - psi_avg[C_PSI_AVG_SIZE_D]); | |
| 1138 } | |
| 1139 | |
| 1140 for (i = C_PSI_AVG_SIZE_D - 1; i >= 0 ; i--) | |
| 1141 psi_avg[i+1] = psi_avg[i]; | |
| 1142 psi_avg[0] = 0; | |
| 1143 M_Count = 0; | |
| 1144 good_snr = 0; | |
| 1145 } | |
| 1146 | |
| 1147 } else { | |
| 1148 // No estmation when in Idle mode (DEEP or BIG SLEEP) => Reset! | |
| 1149 first_avg = 1; | |
| 1150 M_Count = 0; | |
| 1151 good_snr = 0; | |
| 1152 psi_avg[0] = 0; | |
| 1153 } | |
| 1154 | |
| 1155 /********************/ | |
| 1156 /* Filter algorithm */ | |
| 1157 /********************/ | |
| 1158 | |
| 1159 /* Covariance error is increased of C_Q */ | |
| 1160 P=P+(*frame_count)*C_Q; | |
| 1161 | |
| 1162 /* Clipping of P */ | |
| 1163 if (P>C_thr_P) P=C_thr_P; | |
| 1164 | |
| 1165 if (snr>=C_thr_snr) | |
| 1166 { | |
| 1167 /* Clipping of error angle */ | |
| 1168 if (angle>C_thr_phi) | |
| 1169 angle=C_thr_phi; | |
| 1170 if (angle<-C_thr_phi) | |
| 1171 angle=-C_thr_phi; | |
| 1172 | |
| 1173 /* Kalman gain */ | |
| 1174 /*K=P*(1/(P+C_a0_kalman+(C_g_kalman*RNS))) */ | |
| 1175 /*C_a0_kalman=0.01 */ | |
| 1176 /*C_g_kalman =0.05 */ | |
| 1177 num=(C_g_kalman/snr)+P+C_a0_kalman; | |
| 1178 /* (F2.30 / F6.10) = F 12.20 */ | |
| 1179 | |
| 1180 /* denom = P << 19 = F 1.39 */ | |
| 1181 /* extension of denom=P to a 40 bits variable */ | |
| 1182 /* denom (F12.20) << 16 = F 4.36 */ | |
| 1183 guard1=(WORD16)((WORD32)P>>16); | |
| 1184 /* denom = P<<16 = (F4.36) << 3 = F 1.39 */ | |
| 1185 denomH=(UWORD16)P; | |
| 1186 /* Low part of denom is equal to 0, because P has been 16 */ | |
| 1187 /* bits left shifted previously. */ | |
| 1188 denomH_3msb=(denomH>>13)&0x0007; | |
| 1189 guard1=(guard1<<3)|denomH_3msb; | |
| 1190 denomH<<=3; | |
| 1191 denom=denomH<<16; //(UWORD32) removed typecast omaps00090550 | |
| 1192 /* num + guard1 are a 40 bits representation of P */ | |
| 1193 /* In order to compute P(F1.39)/num, we sample P in guard1 */ | |
| 1194 /* (scaled to a 32 bits number) and num (32 bits number) */ | |
| 1195 /* K = ((guard1<<24)/num)<<8 + (denom/num) */ | |
| 1196 var1=(WORD32)guard1<<24; | |
| 1197 var1=var1/num; | |
| 1198 var1=(WORD32)var1<<8; | |
| 1199 /* var2 is an unsigned variable, var1 contains signed guard*/ | |
| 1200 /* bits. */ | |
| 1201 #if 0 /* fixed LoCosto code */ | |
| 1202 var2= ((WORD32)(denom)/(num)); //omaps00090550 | |
| 1203 #else /* matching TCS211 */ | |
| 1204 var2= denom / num; | |
| 1205 #endif | |
| 1206 K = (var1+var2)<<1; /* F1.39 / F12.20 = F13.19 */ | |
| 1207 /* F13.19 << 1 = F12.20 */ | |
| 1208 | |
| 1209 /* Clipping of the Kalman gain */ | |
| 1210 if (K>=C_thr_K) | |
| 1211 K=C_thr_K; | |
| 1212 | |
| 1213 /*******************************************************/ | |
| 1214 /* P=(1-K)*P = 0.8 * 0.5 at maximum */ | |
| 1215 /*******************************************************/ | |
| 1216 /* Perform a positive variable F12.20 multiplication by*/ | |
| 1217 /* positive variable F12.20 */ | |
| 1218 var_16=(WORD16)(1048576L-K); /* acclow(1-K) = F12.20 */ | |
| 1219 guard1=0; /* positive variable */ | |
| 1220 var1=UMult_40b(P,var_16,&guard1); | |
| 1221 var_16=(WORD16)((1048576L-K)>>16); | |
| 1222 /* acchigh(1-K) = F12.20 */ | |
| 1223 var2=P*var_16; /* var2 = 0x80000 * 0xc */ | |
| 1224 /* at maximum, so result */ | |
| 1225 /* is 32 bits WORD32 and */ | |
| 1226 /* equal 0x600000 */ | |
| 1227 /* extension of var2 to a 40 bits variable : var2<<16 */ | |
| 1228 guard2=(WORD16)((WORD32)var2>>16); | |
| 1229 guard1guard2=((WORD32)guard1<<16) |((WORD32) guard2&0x0000FFFFL); | |
| 1230 var2=var2<<16; | |
| 1231 var_32=Add_40b(guard1guard2,var1,var2,&guardout); | |
| 1232 /* var_32 (F8.40) >> 16 = F8.24 */ | |
| 1233 LGuard=(WORD32)guardout<<16; | |
| 1234 var1=(UWORD32)var_32>>16; | |
| 1235 /* var_32 >> 4 = F12.20 */ | |
| 1236 P=(var1+LGuard)>>4; | |
| 1237 | |
| 1238 Phi_32=Mult_40b(l1_config.params.psi_st_32,Psi_quant[0],&guardout); | |
| 1239 /* F0.32 * F13.3 = F5.35 */ | |
| 1240 LGuard=(WORD32)guardout<<16; /* var_32 (F5.35) >> 16 */ | |
| 1241 /* F13.19 */ | |
| 1242 var1=(UWORD32)Phi_32>>16; | |
| 1243 Phi_32=Psi-(LGuard+var1); /* F13.19 */ | |
| 1244 | |
| 1245 /*Phi=angle-Phi_32*/ | |
| 1246 Phi_32=((WORD32)angle<<4)-Phi_32; | |
| 1247 /* F1.15 * 4 = F13.19 */ | |
| 1248 Phi=(WORD16)(Phi_32>>4); /* F17.15 */ | |
| 1249 /*var1=K*Phi F12.20 * F1.15 = 13.35 */ | |
| 1250 guard1=0; | |
| 1251 var1=Mult_40b(K,Phi,&guard1); | |
| 1252 /* var1 (F13.35) >> 16 */ | |
| 1253 /* F13.19 */ | |
| 1254 LGuard=(WORD32)guard1<<16; | |
| 1255 var1=(UWORD32)var1>>16; | |
| 1256 Psi+=var1+LGuard; | |
| 1257 } else { | |
| 1258 /************************************/ | |
| 1259 /* Prediction */ | |
| 1260 /************************************/ | |
| 1261 | |
| 1262 // Only predict in dedicated mode | |
| 1263 // NO prediction in idle mode | |
| 1264 // l1a_l1s_com.dedic_set.SignalCode = NULL | |
| 1265 if ( (l1_config.params.rgap_algo != 0) && | |
| 1266 ((l1_mode==CON_EST_MODE2)||(l1_mode==DEDIC_MODE) | |
| 1267 #if L1_GPRS | |
| 1268 || l1_mode==PACKET_TRANSFER_MODE | |
| 1269 #endif | |
| 1270 )) | |
| 1271 { | |
| 1272 | |
| 1273 /* Prediction of psi during reception gaps */ | |
| 1274 B_Count+= *frame_count; | |
| 1275 | |
| 1276 /* Predict psi ONLY when we have sufficient measurements available */ | |
| 1277 /* If we don't have enough measurements we don't do anything (= 0th order estimation)*/ | |
| 1278 | |
| 1279 // Was the consecutive bad SNRs threshold value exceeded? | |
| 1280 if (B_Count>= l1_config.params.rgap_bad_snr_count_B) { | |
| 1281 | |
| 1282 // Predict with 0th order estimation is the default | |
| 1283 | |
| 1284 // Predict with 1st order estimation | |
| 1285 if (l1_config.params.rgap_algo >= 1) | |
| 1286 Psi += ((quant_avg * (l1_config.params.rgap_bad_snr_count_B))/(C_MSIZE)); | |
| 1287 | |
| 1288 B_Count= B_Count - l1_config.params.rgap_bad_snr_count_B; | |
| 1289 | |
| 1290 // Indicate by raising first_avg flag that a reception gap has occurred | |
| 1291 // I.e. the psi_avg table must be reinitialised after leaving reception gap | |
| 1292 first_avg = 1; | |
| 1293 | |
| 1294 // Counters in estimation part must also be reset | |
| 1295 M_Count = 0; | |
| 1296 good_snr = 0; | |
| 1297 psi_avg[0] = 0; | |
| 1298 } | |
| 1299 } | |
| 1300 } | |
| 1301 | |
| 1302 /* Quantize psi value */ | |
| 1303 | |
| 1304 var_32=Mult_40b(Psi,l1_config.params.psi_st_inv,&guardout); | |
| 1305 /* F13.19 * C = F13.19 */ | |
| 1306 | |
| 1307 #if(RF_FAM == 61) | |
| 1308 /* In order to implement the NINT function for a F13.3, we check */ | |
| 1309 /* if var_32 + 0.5*2**18 is a multiple of 2**18 */ | |
| 1310 quotient=(WORD16)((WORD32)(((WORD32)(var_32+(1<<17)))/(1<<18))); | |
| 1311 var_16=quotient*4; | |
| 1312 #else | |
| 1313 /* In order to implement the NINT function for a F13.3, we check */ | |
| 1314 /* if var_32 + 0.5*2**19 is a multiple of 2**19 */ | |
| 1315 quotient=(WORD16)((WORD32)(((WORD32)(var_32+(1<<18)))/(1<<19))); | |
| 1316 var_16=quotient*8; | |
| 1317 #endif | |
| 1318 if (var_16>C_max_step) | |
| 1319 Psi_quant[C_N_del]=C_max_step; | |
| 1320 else | |
| 1321 if(var_16<C_min_step) | |
| 1322 Psi_quant[C_N_del]=C_min_step; | |
| 1323 else Psi_quant[C_N_del]=var_16; /* F13.3 */ | |
| 1324 | |
| 1325 | |
| 1326 }/*end AFC_CLOSE_LOOP*/ | |
| 1327 } /* end else AFC_INIT*/ | |
| 1328 | |
| 1329 *frame_count = 0; | |
| 1330 return(Psi_quant[C_N_del]>>3); /* F16.0 */ | |
| 1331 } /* end case algo 3 */ | |
| 1332 #endif | |
| 1333 | |
| 1334 #if (VCXO_ALGO == 1) | |
| 1335 default: | |
| 1336 return 0; | |
| 1337 //omaps00090550 break; | |
| 1338 } // end of Switch | |
| 1339 #endif | |
| 1340 | |
| 1341 } /* end l1ctl_afc */ | |
| 1342 | |
| 1343 | |
| 1344 /************************************/ | |
| 1345 /* Automatic timing control (TOA) */ | |
| 1346 /************************************/ | |
| 1347 | |
| 1348 #if (TOA_ALGO == 2) | |
| 1349 | |
| 1350 #define TOA_DEBUG_ENABLE 0 | |
| 1351 | |
| 1352 | |
| 1353 #if (TOA_DEBUG_ENABLE == 1) | |
| 1354 | |
| 1355 #define TOA_MAKE_ZERO 0 | |
| 1356 | |
| 1357 #define TOA_LOG_BUFFER_LENGTH 4096 | |
| 1358 | |
| 1359 typedef struct | |
| 1360 { | |
| 1361 UWORD16 SNR_val; | |
| 1362 UWORD16 TOA_val; | |
| 1363 UWORD16 l1_mode; | |
| 1364 UWORD16 toa_frames_counter; | |
| 1365 UWORD16 fn_mod42432; | |
| 1366 }T_TOA_log_debug; | |
| 1367 | |
| 1368 | |
| 1369 T_TOA_log_debug toa_log_debug[TOA_LOG_BUFFER_LENGTH]; | |
| 1370 UWORD32 toa_log_index; | |
| 1371 | |
| 1372 UWORD32 toa_make_zero_f; | |
| 1373 | |
| 1374 #endif | |
| 1375 | |
| 1376 /*-------------------------------------------------------*/ | |
| 1377 /* l1ctl_toa() */ | |
| 1378 /*-------------------------------------------------------*/ | |
| 1379 /* Parameters : */ | |
| 1380 /* Return : */ | |
| 1381 /* Functionality : */ | |
| 1382 /*-------------------------------------------------------*/ | |
| 1383 | |
| 1384 WORD16 l1ctl_toa (UWORD8 phase, UWORD32 l1_mode, UWORD16 SNR_val, UWORD16 TOA_val) | |
| 1385 { | |
| 1386 WORD16 TOA_period_len = TOA_PERIOD_LEN [l1_mode]; | |
| 1387 WORD16 TOA_SHIFT=ISH_INVALID; | |
| 1388 UWORD16 cumul_abs; | |
| 1389 WORD16 cumul_sign; | |
| 1390 WORD32 prod_tmp, div_tmp,prod_sign; | |
| 1391 WORD32 toa_update_flag=0; | |
| 1392 WORD16 cumul; | |
| 1393 UWORD16 cumul_counter; | |
| 1394 #if (NEW_TOA_ALGO == 1) | |
| 1395 UWORD16 Trans_active; | |
| 1396 static WORD16 cumul_noTrans =0; | |
| 1397 static UWORD16 period_counter_noTrans =0; | |
| 1398 | |
| 1399 if ((l1_mode==CON_EST_MODE2)||(l1_mode==DEDIC_MODE) | |
| 1400 #if L1_GPRS | |
| 1401 || l1_mode==PACKET_TRANSFER_MODE | |
| 1402 #endif | |
| 1403 ) | |
| 1404 Trans_active=TRUE; | |
| 1405 else Trans_active=FALSE; | |
| 1406 #endif | |
| 1407 if (phase==TOA_INIT) | |
| 1408 { | |
| 1409 #if (NEW_TOA_ALGO == 1) | |
| 1410 cumul_noTrans =0; | |
| 1411 period_counter_noTrans =0; | |
| 1412 #endif | |
| 1413 | |
| 1414 l1s.toa_var.toa_frames_counter=0; | |
| 1415 l1s.toa_var.toa_accumul_counter=0; | |
| 1416 l1s.toa_var.toa_accumul_value=0; | |
| 1417 #if (TOA_DEBUG_ENABLE == 1) | |
| 1418 toa_log_index = 0; | |
| 1419 #if (TOA_MAKE_ZERO == 1) | |
| 1420 toa_make_zero_f = 1; | |
| 1421 #else | |
| 1422 toa_make_zero_f = 0; | |
| 1423 #endif | |
| 1424 #endif | |
| 1425 | |
| 1426 return (TOA_SHIFT); | |
| 1427 } | |
| 1428 | |
| 1429 cumul = l1s.toa_var.toa_accumul_value; | |
| 1430 cumul_counter = l1s.toa_var.toa_accumul_counter; | |
| 1431 | |
| 1432 #if (TOA_DEBUG_ENABLE == 1) | |
| 1433 toa_log_debug[toa_log_index].SNR_val = SNR_val; | |
| 1434 toa_log_debug[toa_log_index].TOA_val = TOA_val; | |
| 1435 toa_log_debug[toa_log_index].l1_mode = l1_mode; | |
| 1436 toa_log_debug[toa_log_index].toa_frames_counter = l1s.toa_var.toa_frames_counter; | |
| 1437 toa_log_debug[toa_log_index].fn_mod42432 = l1s.actual_time.fn_mod42432; | |
| 1438 | |
| 1439 toa_log_index++; | |
| 1440 if(toa_log_index == TOA_LOG_BUFFER_LENGTH) | |
| 1441 { | |
| 1442 toa_log_index = 0; | |
| 1443 } | |
| 1444 #endif /* #if (TOA_DEBUG_ENABLE == 1) */ | |
| 1445 | |
| 1446 #if (TRACE_TYPE == 5) | |
| 1447 trace_toa_sim_ctrl(SNR_val, TOA_val, l1_mode, l1s.toa_var.toa_frames_counter, | |
| 1448 l1s.toa_var.toa_accumul_counter, l1s.toa_var.toa_accumul_value); | |
| 1449 #endif | |
| 1450 | |
| 1451 l1s.toa_var.toa_frames_counter++; | |
| 1452 | |
| 1453 { | |
| 1454 /* Fix for TOA */ | |
| 1455 #define DSP_CALC_NO_TABS_HO 0x3CA4 | |
| 1456 | |
| 1457 UWORD16 *toa_ho_fix; | |
| 1458 toa_ho_fix=(UWORD16 *)API_address_dsp2mcu(DSP_CALC_NO_TABS_HO); | |
| 1459 | |
| 1460 if ((TOA_val >= 22) || (TOA_val <= 6)) { | |
| 1461 *toa_ho_fix = 1; | |
| 1462 } | |
| 1463 | |
| 1464 if (*toa_ho_fix == 1) { | |
| 1465 if((TOA_val <= 18) && (TOA_val >= 10)) { | |
| 1466 *toa_ho_fix = 0; | |
| 1467 } | |
| 1468 } else { | |
| 1469 *toa_ho_fix = 0; | |
| 1470 } | |
| 1471 } | |
| 1472 | |
| 1473 | |
| 1474 #if (NEW_TOA_ALGO == 1) | |
| 1475 if (Trans_active) | |
| 1476 { | |
| 1477 #endif | |
| 1478 if (SNR_val>= L1_TOA_SNR_THRESHOLD) | |
| 1479 { | |
| 1480 cumul_counter++; | |
| 1481 | |
| 1482 prod_tmp = L1_TOA_LAMBDA * cumul; | |
| 1483 prod_tmp = prod_tmp + ((0x00004000)); // basically for rounding | |
| 1484 div_tmp = ((prod_tmp >> 15) & (0x0000FFFF)); | |
| 1485 cumul = div_tmp; | |
| 1486 | |
| 1487 // implemented below is | |
| 1488 // cumul = cumul + (L1_TOA_ONE_MINUS_LAMBDA * signum(TOA_Val - L1_TOA_EXPECTED_TOA)) | |
| 1489 if(TOA_val > L1_TOA_EXPECTED_TOA) { | |
| 1490 cumul = cumul + L1_TOA_ONE_MINUS_LAMBDA; | |
| 1491 } | |
| 1492 else if (TOA_val < L1_TOA_EXPECTED_TOA) { | |
| 1493 cumul = cumul - L1_TOA_ONE_MINUS_LAMBDA; | |
| 1494 } | |
| 1495 } // End if SNR_val | |
| 1496 | |
| 1497 if(l1s.toa_var.toa_update_flag == TRUE) | |
| 1498 { | |
| 1499 toa_update_flag = 1; | |
| 1500 } | |
| 1501 | |
| 1502 if (toa_update_flag) | |
| 1503 { | |
| 1504 cumul_sign = (cumul>0)? 1: -1; | |
| 1505 cumul_abs = cumul_sign*cumul; | |
| 1506 if(cumul_counter <= 5) | |
| 1507 { | |
| 1508 TOA_SHIFT = (cumul_abs<=L1_TOA_THRESHOLD_15)? 0: cumul_sign; | |
| 1509 } | |
| 1510 else if(cumul_counter == 6) | |
| 1511 { | |
| 1512 TOA_SHIFT = (cumul_abs<=L1_TOA_THRESHOLD_20)? 0: cumul_sign; | |
| 1513 } | |
| 1514 else if(cumul_counter == 7) | |
| 1515 { | |
| 1516 TOA_SHIFT = (cumul_abs<=L1_TOA_THRESHOLD_25)? 0: cumul_sign; | |
| 1517 } | |
| 1518 else if(cumul_counter >= 8) | |
| 1519 { | |
| 1520 TOA_SHIFT = (cumul_abs<=L1_TOA_THRESHOLD_30)? 0: cumul_sign; | |
| 1521 } | |
| 1522 #if (TRACE_TYPE==1) || (TRACE_TYPE==4) | |
| 1523 trace_info.toa_trace_var.toa_accumul_value = cumul; | |
| 1524 trace_info.toa_trace_var.toa_accumul_counter = cumul_counter; | |
| 1525 trace_info.toa_trace_var.toa_frames_counter = l1s.toa_var.toa_frames_counter; | |
| 1526 #endif | |
| 1527 | |
| 1528 cumul = 0; | |
| 1529 cumul_counter = 0; | |
| 1530 l1s.toa_var.toa_frames_counter = 0; | |
| 1531 l1s.toa_var.toa_update_flag = FALSE; | |
| 1532 | |
| 1533 #if (TOA_DEBUG_ENABLE == 1) | |
| 1534 #if (TOA_MAKE_ZERO == 1) | |
| 1535 if (toa_make_zero_f == 1) | |
| 1536 { | |
| 1537 TOA_SHIFT=0; | |
| 1538 } | |
| 1539 #endif /*#if (TOA_DEBUG_ENABLE == 1)*/ | |
| 1540 #endif /*#if (TOA_MAKE_ZERO == 1)*/ | |
| 1541 | |
| 1542 } // end of if toa_update_flag | |
| 1543 #if (NEW_TOA_ALGO == 1) | |
| 1544 | |
| 1545 } | |
| 1546 | |
| 1547 else | |
| 1548 { | |
| 1549 period_counter_noTrans++; | |
| 1550 | |
| 1551 if (SNR_val>= L1_TOA_SNR_THRESHOLD) | |
| 1552 { | |
| 1553 cumul_noTrans = cumul_noTrans + TOA_val - L1_TOA_EXPECTED_TOA; | |
| 1554 | |
| 1555 } // End if SNR_val | |
| 1556 | |
| 1557 if (l1s.toa_var.toa_update_flag == TRUE) | |
| 1558 { | |
| 1559 switch (period_counter_noTrans) | |
| 1560 { | |
| 1561 case 2: | |
| 1562 if (cumul_noTrans>=0) | |
| 1563 TOA_SHIFT = (cumul_noTrans+1) >>1 ; | |
| 1564 else | |
| 1565 TOA_SHIFT = (cumul_noTrans) >>1 ; | |
| 1566 break; | |
| 1567 case 3: /* Not fully accurate rounding*/ | |
| 1568 if (cumul_noTrans>=0) | |
| 1569 TOA_SHIFT = (cumul_noTrans+2)/3 ; | |
| 1570 else | |
| 1571 TOA_SHIFT = (cumul_noTrans-2)/3 ; | |
| 1572 break; | |
| 1573 case 4: | |
| 1574 if (cumul_noTrans>=0) | |
| 1575 TOA_SHIFT = (cumul_noTrans+2) >>2 ; | |
| 1576 else | |
| 1577 TOA_SHIFT = (cumul_noTrans+1) >>2 ; | |
| 1578 break; | |
| 1579 default: | |
| 1580 TOA_SHIFT = cumul_noTrans; | |
| 1581 break; | |
| 1582 } /* end switch*/ | |
| 1583 | |
| 1584 if (TOA_SHIFT>8) | |
| 1585 TOA_SHIFT =8; | |
| 1586 if (TOA_SHIFT<-8) | |
| 1587 TOA_SHIFT =-8; | |
| 1588 | |
| 1589 #if (TRACE_TYPE==1) || (TRACE_TYPE==4) | |
| 1590 trace_info.toa_trace_var.toa_accumul_value = cumul_noTrans; | |
| 1591 trace_info.toa_trace_var.toa_accumul_counter = period_counter_noTrans; | |
| 1592 trace_info.toa_trace_var.toa_frames_counter = period_counter_noTrans; | |
| 1593 #endif | |
| 1594 | |
| 1595 cumul_noTrans = 0; | |
| 1596 period_counter_noTrans = 0; | |
| 1597 l1s.toa_var.toa_update_flag = FALSE; | |
| 1598 #if (TOA_DEBUG_ENABLE == 1) | |
| 1599 #if (TOA_MAKE_ZERO == 1) | |
| 1600 if (toa_make_zero_f == 1) | |
| 1601 { | |
| 1602 TOA_SHIFT=0; | |
| 1603 } | |
| 1604 #endif /*#if (TOA_DEBUG_ENABLE == 1)*/ | |
| 1605 #endif /*#if (TOA_MAKE_ZERO == 1)*/ | |
| 1606 | |
| 1607 } // end if update_flag | |
| 1608 } | |
| 1609 #endif | |
| 1610 // error a TOA is waiting to be updated in the TPU and will be erased | |
| 1611 #if (TRACE_TYPE==1) || (TRACE_TYPE==4) | |
| 1612 if (l1s.toa_var.toa_shift != ISH_INVALID) | |
| 1613 { | |
| 1614 l1_trace_toa_not_updated (); // should not occur!! | |
| 1615 } | |
| 1616 #endif | |
| 1617 | |
| 1618 if (TOA_SHIFT != ISH_INVALID) // new TOA => set the mask frames | |
| 1619 { | |
| 1620 // Set mask counter to 2 (2 frames masked). | |
| 1621 l1s.toa_var.toa_snr_mask = 2; | |
| 1622 } | |
| 1623 | |
| 1624 l1s.toa_var.toa_accumul_value = cumul; | |
| 1625 l1s.toa_var.toa_accumul_counter = cumul_counter; | |
| 1626 | |
| 1627 return(TOA_SHIFT); | |
| 1628 | |
| 1629 } // l1ctl_toa | |
| 1630 | |
| 1631 | |
| 1632 #else | |
| 1633 /*-------------------------------------------------------*/ | |
| 1634 /* l1ctl_toa_update() */ | |
| 1635 /*-------------------------------------------------------*/ | |
| 1636 /* Parameters : */ | |
| 1637 /* Return : */ | |
| 1638 /* Functionality : */ | |
| 1639 /*-------------------------------------------------------*/ | |
| 1640 WORD16 l1ctl_toa_update(UWORD32 *TOASP, UWORD32 l1_mode) | |
| 1641 { | |
| 1642 static UWORD16 Old_TOA_estimated=12; //unit is Qbit | |
| 1643 UWORD32 TOAMAX; | |
| 1644 WORD16 IZW,ISH,i; | |
| 1645 UWORD32 TOA_estimated=0; //unit is Qbit | |
| 1646 UWORD16 Trans_active; | |
| 1647 | |
| 1648 if ((l1_mode==CON_EST_MODE2)||(l1_mode==DEDIC_MODE) | |
| 1649 #if L1_GPRS | |
| 1650 || l1_mode==PACKET_TRANSFER_MODE | |
| 1651 #endif | |
| 1652 ) | |
| 1653 Trans_active=TRUE; | |
| 1654 else Trans_active=FALSE; | |
| 1655 | |
| 1656 /* TOA offset computation and clock adjustement */ | |
| 1657 TOAMAX=0; | |
| 1658 for (i=1;i<TOA_HISTO_LEN;i++) | |
| 1659 { | |
| 1660 if (TOASP[i]>TOAMAX) | |
| 1661 TOAMAX=TOASP[i]; | |
| 1662 } | |
| 1663 TOAMAX >>= C_RED; | |
| 1664 i=1;IZW=0; | |
| 1665 while (i<TOA_HISTO_LEN && IZW==0) | |
| 1666 { | |
| 1667 if (TOASP[i]>=TOAMAX) | |
| 1668 IZW=i; | |
| 1669 i++; | |
| 1670 } | |
| 1671 | |
| 1672 /* Estimated TOA calculation */ | |
| 1673 if (TOASP[IZW-1]<(2*TOAMAX/3)) | |
| 1674 { | |
| 1675 TOA_estimated=IZW; | |
| 1676 TOA_estimated *= 4; // unit in QBit | |
| 1677 } | |
| 1678 else | |
| 1679 { | |
| 1680 #if 0 /* fix added in LoCosto, not present in TCS211 */ | |
| 1681 UWORD32 TOA_divisor; | |
| 1682 #endif | |
| 1683 TOA_estimated=(TOASP[IZW]*IZW)+(TOASP[IZW-1]*(IZW-1)>>C_GEW); | |
| 1684 TOA_estimated *= 8; //F13.3 in order to have qBit precision | |
| 1685 #if 0 | |
| 1686 TOA_divisor = TOASP[IZW]+(TOASP[IZW-1] >> C_GEW); | |
| 1687 if (TOA_divisor!=0) | |
| 1688 #endif | |
| 1689 { | |
| 1690 TOA_estimated /= TOASP[IZW]+(TOASP[IZW-1] >> C_GEW); | |
| 1691 TOA_estimated /= 2; // unit in QBit ("/8" then "*4" = "/2") | |
| 1692 } | |
| 1693 #if 0 | |
| 1694 else | |
| 1695 { | |
| 1696 TOA_estimated = 0; | |
| 1697 } | |
| 1698 #endif | |
| 1699 } | |
| 1700 | |
| 1701 if (Trans_active) | |
| 1702 TOA_estimated=(TOA_estimated+(Old_TOA_estimated+4)) / 2; | |
| 1703 | |
| 1704 /* Offset calculation*/ | |
| 1705 if (TOA_estimated>=17 || TOA_estimated<=15) | |
| 1706 ISH=TOA_estimated - 16; | |
| 1707 else | |
| 1708 ISH=0; | |
| 1709 | |
| 1710 if (Trans_active) | |
| 1711 { | |
| 1712 if (ISH>1) ISH=1; | |
| 1713 if (ISH<-1) ISH=-1; | |
| 1714 } | |
| 1715 else | |
| 1716 { | |
| 1717 if (ISH>8) ISH=8; | |
| 1718 if (ISH<-8) ISH=-8; | |
| 1719 } | |
| 1720 | |
| 1721 Old_TOA_estimated = TOA_estimated - ISH - 4; | |
| 1722 | |
| 1723 | |
| 1724 return (ISH); | |
| 1725 } | |
| 1726 | |
| 1727 /*-------------------------------------------------------*/ | |
| 1728 /* l1ctl_toa() */ | |
| 1729 /*-------------------------------------------------------*/ | |
| 1730 /* Parameters : */ | |
| 1731 /* Return : */ | |
| 1732 /* Functionality : generate an histogram of TOA weighted */ | |
| 1733 /* with SNR */ | |
| 1734 /*-------------------------------------------------------*/ | |
| 1735 WORD16 l1ctl_toa(UWORD8 phase, UWORD32 l1_mode, UWORD16 SNR_val, UWORD16 TOA_val, BOOL *toa_update, UWORD16 *toa_period_count | |
| 1736 #if (FF_L1_FAST_DECODING == 1) | |
| 1737 , UWORD8 skipped_values | |
| 1738 #endif | |
| 1739 ) | |
| 1740 { | |
| 1741 // xSignalHeaderRec *msg; | |
| 1742 UWORD16 i; | |
| 1743 WORD16 TOA_period_len = TOA_PERIOD_LEN[l1_mode]; | |
| 1744 static UWORD32 histo[TOA_HISTO_LEN]; | |
| 1745 static WORD16 period_counter=0; | |
| 1746 UWORD32 SNR_ZW; | |
| 1747 WORD16 ISH=ISH_INVALID; | |
| 1748 | |
| 1749 UWORD8 histo_center; | |
| 1750 | |
| 1751 #if 0 | |
| 1752 if ((l1_mode==CON_EST_MODE2)||(l1_mode==DEDIC_MODE)) | |
| 1753 histo_center=4; | |
| 1754 else | |
| 1755 histo_center=5; | |
| 1756 #else | |
| 1757 histo_center=4; | |
| 1758 #endif | |
| 1759 | |
| 1760 | |
| 1761 if (phase==TOA_INIT) | |
| 1762 { | |
| 1763 period_counter=0; | |
| 1764 | |
| 1765 for (i=0;i<TOA_HISTO_LEN;i++) | |
| 1766 histo[i]=0; | |
| 1767 histo[histo_center]=128; //F6.10 | |
| 1768 | |
| 1769 return(ISH); | |
| 1770 } | |
| 1771 #if (FF_L1_FAST_DECODING == 1) | |
| 1772 /* Manage any missing bursts due to fast decoding */ | |
| 1773 period_counter += skipped_values; | |
| 1774 #endif | |
| 1775 | |
| 1776 period_counter++; | |
| 1777 /* Filter update */ | |
| 1778 if (SNR_val>=C_SNRGR) | |
| 1779 { | |
| 1780 if (SNR_val>C_SNR_THR) | |
| 1781 SNR_ZW=C_SNR_THR; | |
| 1782 else | |
| 1783 SNR_ZW=SNR_val; | |
| 1784 histo[TOA_val+1]+=SNR_ZW; /* if TOA=0 histo[1]++ */ | |
| 1785 /* if TOA=1 histo[2]++ */ | |
| 1786 /* ... */ | |
| 1787 /* if TOA=9 histo[10]++ */ | |
| 1788 /* histo[0] is reserved for computation */ | |
| 1789 } | |
| 1790 | |
| 1791 #if L1_GPRS | |
| 1792 if (l1_mode==PACKET_TRANSFER_MODE) | |
| 1793 { | |
| 1794 if (*toa_update) | |
| 1795 { | |
| 1796 // Get ISH. | |
| 1797 ISH = l1ctl_toa_update(histo, l1_mode); | |
| 1798 | |
| 1799 //reset TOA period length counter | |
| 1800 period_counter=0; | |
| 1801 | |
| 1802 //reset histogram | |
| 1803 for (i=0;i<TOA_HISTO_LEN;i++) | |
| 1804 histo[i]=0; | |
| 1805 histo[histo_center]=128; //F6.10 | |
| 1806 | |
| 1807 *toa_update = FALSE; // reset TOA update flag | |
| 1808 *toa_period_count = 0; // reset TOA period counter | |
| 1809 } | |
| 1810 } | |
| 1811 else | |
| 1812 #endif | |
| 1813 if (period_counter>=TOA_period_len) | |
| 1814 // It is time to compute a new ISH and to reset the histogram. | |
| 1815 // Rem: ">=" is very important since a "l1 mode" change can give | |
| 1816 // a "TOA_period_len" smaller than the previous one an | |
| 1817 // therefore a "period_counter" may be already higher than | |
| 1818 // the new "TOA_period_len". | |
| 1819 { | |
| 1820 // Get ISH. | |
| 1821 ISH = l1ctl_toa_update(histo, l1_mode); | |
| 1822 | |
| 1823 //reset TOA period length counter | |
| 1824 period_counter=0; | |
| 1825 | |
| 1826 //reset histogram | |
| 1827 for (i=0;i<TOA_HISTO_LEN;i++) | |
| 1828 histo[i]=0; | |
| 1829 histo[histo_center]=128; //F6.10 | |
| 1830 } | |
| 1831 | |
| 1832 // error a TOA is waiting to be updated in the TPU and will be erased | |
| 1833 #if (TRACE_TYPE==1) || (TRACE_TYPE==4) | |
| 1834 if (l1s.toa_shift != ISH_INVALID) | |
| 1835 { | |
| 1836 l1_trace_toa_not_updated(); // should not occur !! | |
| 1837 } | |
| 1838 #endif | |
| 1839 | |
| 1840 if (ISH != ISH_INVALID) // new TOA => set the mask frames | |
| 1841 { | |
| 1842 // Set mask counter to 2 (2 frames masked). | |
| 1843 l1s.toa_snr_mask = 2; | |
| 1844 } | |
| 1845 | |
| 1846 return(ISH); | |
| 1847 } | |
| 1848 #endif | |
| 1849 | |
| 1850 /*-------------------------------------------------------*/ | |
| 1851 /* l1ctl_txpwr() */ | |
| 1852 /*-------------------------------------------------------*/ | |
| 1853 /* Parameters : */ | |
| 1854 /* Return : */ | |
| 1855 /* Functionality : */ | |
| 1856 /*-------------------------------------------------------*/ | |
| 1857 UWORD8 l1ctl_txpwr(UWORD8 target_txpwr, UWORD8 current_txpwr) | |
| 1858 { | |
| 1859 if(target_txpwr > current_txpwr) | |
| 1860 { | |
| 1861 current_txpwr ++; // Increase TX power by 2 dB. | |
| 1862 } | |
| 1863 else | |
| 1864 if(target_txpwr < current_txpwr) | |
| 1865 { | |
| 1866 current_txpwr --; // Decrease TX power by 2 dB. | |
| 1867 } | |
| 1868 | |
| 1869 return(current_txpwr); | |
| 1870 } | |
| 1871 | |
| 1872 | |
| 1873 /************************************/ | |
| 1874 /* Automatic Gain Control */ | |
| 1875 /************************************/ | |
| 1876 /*-------------------------------------------------------*/ | |
| 1877 /* l1ctl_encode_delta1() */ | |
| 1878 /*-------------------------------------------------------*/ | |
| 1879 /* Parameters : */ | |
| 1880 /* Return : */ | |
| 1881 /* Functionality : */ | |
| 1882 /*-------------------------------------------------------*/ | |
| 1883 #if(L1_FF_MULTIBAND == 0) | |
| 1884 WORD8 l1ctl_encode_delta1(UWORD16 radio_freq) | |
| 1885 { | |
| 1886 WORD8 freq_band; | |
| 1887 | |
| 1888 switch(l1_config.std.id) | |
| 1889 { | |
| 1890 case GSM: | |
| 1891 case GSM_E: | |
| 1892 case DCS1800: | |
| 1893 case PCS1900: | |
| 1894 case GSM850: | |
| 1895 freq_band = l1_config.std.cal_freq1_band1; | |
| 1896 break; | |
| 1897 case DUAL: | |
| 1898 case DUALEXT: | |
| 1899 case DUAL_US: | |
| 1900 if(radio_freq >= l1_config.std.first_radio_freq_band2) | |
| 1901 freq_band = l1_config.std.cal_freq1_band2; | |
| 1902 else | |
| 1903 freq_band = l1_config.std.cal_freq1_band1; | |
| 1904 break; | |
| 1905 } | |
| 1906 return(freq_band); | |
| 1907 } | |
| 1908 #endif | |
| 1909 /*-------------------------------------------------------*/ | |
| 1910 /* l1ctl_encode_lna() */ | |
| 1911 /*-------------------------------------------------------*/ | |
| 1912 /* Parameters : */ | |
| 1913 /* Return : */ | |
| 1914 /* Functionality : */ | |
| 1915 /*-------------------------------------------------------*/ | |
| 1916 #if (L1_FF_MULTIBAND == 0) | |
| 1917 void l1ctl_encode_lna( UWORD8 input_level, | |
| 1918 UWORD8 *lna_state, | |
| 1919 UWORD16 radio_freq) | |
| 1920 { | |
| 1921 | |
| 1922 /*** LNA Hysteresis is implemented as following : | |
| 1923 | |
| 1924 | | |
| 1925 On|---<>----+-------+ | |
| 1926 | | | | |
| 1927 LNA | | | | |
| 1928 | ^ v | |
| 1929 | | | | |
| 1930 | | | | |
| 1931 Off| +-------+----<>----- | |
| 1932 +-------------------------------- | |
| 1933 50 40 30 20 input_level /-dBm | |
| 1934 THR_HIGH THR_LOW ***/ | |
| 1935 | |
| 1936 | |
| 1937 | |
| 1938 | |
| 1939 | |
| 1940 if(((l1_config.std.id == DUAL) || (l1_config.std.id == DUALEXT) ||(l1_config.std.id == DUAL_US)) && | |
| 1941 (radio_freq >= l1_config.std.first_radio_freq_band2)) | |
| 1942 { | |
| 1943 if ( input_level > l1_config.std.lna_switch_thr_high_band2 ) // < -40dBm ? | |
| 1944 { | |
| 1945 *lna_state = LNA_ON; // lna_off = FALSE | |
| 1946 } | |
| 1947 else if ( input_level < l1_config.std.lna_switch_thr_low_band2 ) // > -30dBm ? | |
| 1948 { | |
| 1949 *lna_state = LNA_OFF; // lna off = TRUE | |
| 1950 } | |
| 1951 } | |
| 1952 else | |
| 1953 { | |
| 1954 if ( input_level > l1_config.std.lna_switch_thr_high_band1 ) // < -40dBm ? | |
| 1955 { | |
| 1956 *lna_state = LNA_ON; // lna_off = FALSE | |
| 1957 } | |
| 1958 else if ( input_level < l1_config.std.lna_switch_thr_low_band1 ) // > -30dBm ? | |
| 1959 { | |
| 1960 *lna_state = LNA_OFF; // lna off = TRUE | |
| 1961 } | |
| 1962 } | |
| 1963 | |
| 1964 } | |
| 1965 | |
| 1966 #endif | |
| 1967 | |
| 1968 /*-------------------------------------------------------*/ | |
| 1969 /* l1ctl_csgc() */ | |
| 1970 /*-------------------------------------------------------*/ | |
| 1971 /* Description: */ | |
| 1972 /* ============ */ | |
| 1973 /* If we are running the first pass of a measurement */ | |
| 1974 /* session, we use the HIGH_AGC default agc setting to */ | |
| 1975 /* compute the input level from the measured power from */ | |
| 1976 /* the DSP. If this input level is saturated we set a */ | |
| 1977 /* saturation flag, otherwise we validate the measure and*/ | |
| 1978 /* store, for the considered carrier, the input level. */ | |
| 1979 /* When all the carriers have been scanned and some have */ | |
| 1980 /* been flagged "saturated", we measure them with the */ | |
| 1981 /* LOW_AGC agc setting, then store, for the considered */ | |
| 1982 /* carrier, the input level. */ | |
| 1983 /*-------------------------------------------------------*/ | |
| 1984 UWORD8 l1ctl_csgc(UWORD8 pm, UWORD16 radio_freq) | |
| 1985 { | |
| 1986 WORD16 current_IL, current_calibrated_IL; | |
| 1987 WORD8 delta1_freq, delta2_freq; | |
| 1988 WORD16 delta_drp_gain=0; | |
| 1989 UWORD32 index; | |
| 1990 UWORD16 g_magic; | |
| 1991 #if (RF_FAM == 61) && (L1_FF_MULTIBAND == 0) | |
| 1992 UWORD16 arfcn; | |
| 1993 #endif | |
| 1994 UWORD16 dco_algo_ctl_pw_temp = 0; | |
| 1995 UWORD8 if_ctl = 0; | |
| 1996 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 1997 UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; | |
| 1998 #endif | |
| 1999 | |
| 2000 #if (L1_FF_MULTIBAND == 0) | |
| 2001 | |
| 2002 // initialize index | |
| 2003 index = radio_freq - l1_config.std.radio_freq_index_offset; | |
| 2004 | |
| 2005 #else | |
| 2006 | |
| 2007 index = | |
| 2008 l1_multiband_radio_freq_convert_into_operative_radio_freq(radio_freq); | |
| 2009 | |
| 2010 #endif /*if(L1_FF_MULTIBAND == 0)*/ | |
| 2011 | |
| 2012 delta1_freq = l1ctl_encode_delta1(radio_freq); | |
| 2013 delta2_freq = l1ctl_encode_delta2(radio_freq); | |
| 2014 | |
| 2015 g_magic = l1ctl_get_g_magic(radio_freq); | |
| 2016 | |
| 2017 #if (RF_FAM == 61) && (L1_FF_MULTIBAND == 0) | |
| 2018 arfcn = Convert_l1_radio_freq(radio_freq); | |
| 2019 #endif | |
| 2020 | |
| 2021 if (l1a_l1s_com.full_list.meas_1st_pass_read) | |
| 2022 { | |
| 2023 // We validate or not power measure (pm) for the considered carrier | |
| 2024 // with measurement achieved with HIGH_AGC setting. We are working | |
| 2025 // with non calibrated IL to avoid saturation | |
| 2026 #if(RF_FAM == 61) | |
| 2027 #if (CODE_VERSION != SIMULATION) | |
| 2028 | |
| 2029 #if (PWMEAS_IF_MODE_FORCE == 0) | |
| 2030 cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_INVALID , | |
| 2031 0, | |
| 2032 radio_freq,if_threshold); | |
| 2033 #else | |
| 2034 if_ctl = IF_120KHZ_DSP; | |
| 2035 dco_algo_ctl_pw_temp = DCO_IF_0KHZ; | |
| 2036 #endif | |
| 2037 | |
| 2038 #if (L1_FF_MULTIBAND == 0) | |
| 2039 delta_drp_gain = drp_gain_correction(arfcn, LNA_ON, (l1_config.params.high_agc << 1)); // F7.1 format | |
| 2040 #else | |
| 2041 delta_drp_gain = drp_gain_correction(radio_freq, LNA_ON, (l1_config.params.high_agc << 1)); // F7.1 format | |
| 2042 #endif // MULTIBAND == 0 else | |
| 2043 | |
| 2044 if(if_ctl == IF_100KHZ_DSP){ | |
| 2045 delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; | |
| 2046 } | |
| 2047 else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ | |
| 2048 delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; | |
| 2049 } | |
| 2050 | |
| 2051 #endif | |
| 2052 #endif | |
| 2053 if (0==pm) // Check and filter illegal pm value by using last valid IL | |
| 2054 current_IL = (WORD16)(l1a_l1s_com.last_input_level[index].input_level); | |
| 2055 else | |
| 2056 { | |
| 2057 #if TESTMODE | |
| 2058 if (!l1_config.agc_enable) | |
| 2059 current_IL = (WORD16)(-(pm - ( (l1_config.tmode.rx_params.agc << 1) - delta_drp_gain ) - g_magic)); | |
| 2060 else | |
| 2061 #endif | |
| 2062 current_IL = (WORD16)(-(pm - ( (l1_config.params.high_agc <<1) - delta_drp_gain) - g_magic)); | |
| 2063 // for array index purpose, we work with positive IL | |
| 2064 | |
| 2065 } | |
| 2066 | |
| 2067 // NOTE: lna_value do not appear in this formula because lna is ALWAYS ON for | |
| 2068 // ---- this algorithm, so lna_value=lna_off*l1_config.params.lna_att_gsm=0 | |
| 2069 | |
| 2070 if ((current_IL<l1_config.params.high_agc_sat_thr) // Warning : we are working with positive IL | |
| 2071 // for IL_2_AGC_xx index purpose. | |
| 2072 #if TESTMODE | |
| 2073 && (l1_config.agc_enable) | |
| 2074 #endif | |
| 2075 ) | |
| 2076 { | |
| 2077 // pm is saturated so measure is not valid | |
| 2078 l1a_l1s_com.full_list.nbr_sat_carrier_ctrl++; | |
| 2079 l1a_l1s_com.full_list.nbr_sat_carrier_read++; | |
| 2080 l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_read] = 1; | |
| 2081 } | |
| 2082 else | |
| 2083 { | |
| 2084 current_calibrated_IL = current_IL - delta1_freq - delta2_freq; | |
| 2085 | |
| 2086 #if TESTMODE | |
| 2087 // When running with fixed AGC setting saturated carriers may occur: | |
| 2088 // protect against negative IL; | |
| 2089 if ((!l1_config.agc_enable) && (current_calibrated_IL < 0)) | |
| 2090 { | |
| 2091 current_calibrated_IL=0; | |
| 2092 current_IL=0; | |
| 2093 } | |
| 2094 #endif | |
| 2095 | |
| 2096 // Protect IL stores against overflow | |
| 2097 if (current_calibrated_IL>INDEX_MAX) | |
| 2098 current_calibrated_IL=INDEX_MAX; | |
| 2099 if (current_IL>INDEX_MAX) | |
| 2100 current_IL=INDEX_MAX; | |
| 2101 | |
| 2102 // we validate the measure and save input_level and lna_off fields. | |
| 2103 l1ctl_encode_lna((UWORD8)(current_calibrated_IL>>1), | |
| 2104 &(l1a_l1s_com.last_input_level[index].lna_off), | |
| 2105 radio_freq); | |
| 2106 | |
| 2107 l1a_l1s_com.last_input_level[index].input_level = (UWORD8)current_IL + | |
| 2108 l1ctl_get_lna_att(radio_freq) * | |
| 2109 l1a_l1s_com.last_input_level[index].lna_off; | |
| 2110 | |
| 2111 l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_read] = 0; | |
| 2112 } | |
| 2113 } | |
| 2114 else // 2nd pass if any. | |
| 2115 { | |
| 2116 // we validate the measure and save input_level and lna_off(always 0) | |
| 2117 // fields. | |
| 2118 #if(RF_FAM == 61) | |
| 2119 #if (CODE_VERSION != SIMULATION) | |
| 2120 cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_INVALID, | |
| 2121 0,radio_freq,if_threshold); | |
| 2122 #if (L1_FF_MULTIBAND == 0) | |
| 2123 delta_drp_gain = drp_gain_correction(arfcn, LNA_ON, (l1_config.params.low_agc << 1)); // F7.1 format | |
| 2124 #else | |
| 2125 delta_drp_gain = drp_gain_correction(radio_freq, LNA_ON, (l1_config.params.low_agc << 1)); // F7.1 format | |
| 2126 #endif | |
| 2127 if(if_ctl == IF_100KHZ_DSP){ | |
| 2128 delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; | |
| 2129 } | |
| 2130 else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ | |
| 2131 delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; | |
| 2132 } | |
| 2133 #endif | |
| 2134 #endif | |
| 2135 | |
| 2136 | |
| 2137 if (0==pm) // Check and filter illegal pm value by using last valid IL | |
| 2138 current_IL = (WORD16)(l1a_l1s_com.last_input_level[index].input_level); | |
| 2139 else | |
| 2140 current_IL = (WORD16)(-(pm - ( (l1_config.params.low_agc << 1) - delta_drp_gain ) - g_magic)); | |
| 2141 | |
| 2142 current_calibrated_IL = current_IL - delta1_freq - delta2_freq; | |
| 2143 | |
| 2144 // Protect IL stores against overflow | |
| 2145 if (current_calibrated_IL>INDEX_MAX) | |
| 2146 current_calibrated_IL=INDEX_MAX; | |
| 2147 if (current_IL>INDEX_MAX) | |
| 2148 current_IL=INDEX_MAX; | |
| 2149 | |
| 2150 l1ctl_encode_lna((UWORD8)(current_calibrated_IL>>1), | |
| 2151 &(l1a_l1s_com.last_input_level[index].lna_off), | |
| 2152 radio_freq); | |
| 2153 | |
| 2154 l1a_l1s_com.last_input_level[index].input_level = (UWORD8)current_IL + | |
| 2155 l1ctl_get_lna_att(radio_freq) * | |
| 2156 l1a_l1s_com.last_input_level[index].lna_off; | |
| 2157 | |
| 2158 l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_read] = 0; | |
| 2159 } | |
| 2160 | |
| 2161 return((UWORD8)current_calibrated_IL); | |
| 2162 } | |
| 2163 | |
| 2164 /*-------------------------------------------------------*/ | |
| 2165 /* l1ctl_pgc() */ | |
| 2166 /*-------------------------------------------------------*/ | |
| 2167 /* Description : For a given radio_freq, last_known_agc is */ | |
| 2168 /* ============ based on a prior knowledge (the last */ | |
| 2169 /* stored input_level for the considered */ | |
| 2170 /* carrier). From the power measurement on */ | |
| 2171 /* this carrier (pm), we update the */ | |
| 2172 /* input_level for this carrier, for the */ | |
| 2173 /* next task to control. */ | |
| 2174 /*-------------------------------------------------------*/ | |
| 2175 UWORD8 l1ctl_pgc(UWORD8 pm, UWORD8 last_known_il, | |
| 2176 UWORD8 lna_off, UWORD16 radio_freq) | |
| 2177 { | |
| 2178 WORD32 last_known_agc; | |
| 2179 WORD32 current_IL, current_calibrated_IL; | |
| 2180 WORD8 delta1_freq, delta2_freq; | |
| 2181 WORD16 delta_drp_gain=0; | |
| 2182 WORD32 index, lna_value; | |
| 2183 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2184 UWORD16 arfcn; | |
| 2185 #endif | |
| 2186 UWORD16 dco_algo_ctl_pw_temp = 0; | |
| 2187 UWORD8 if_ctl = 0; | |
| 2188 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2189 UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; | |
| 2190 #endif | |
| 2191 | |
| 2192 #if (L1_FF_MULTIBAND == 0) | |
| 2193 | |
| 2194 // initialize index | |
| 2195 index = radio_freq - l1_config.std.radio_freq_index_offset; | |
| 2196 | |
| 2197 #else | |
| 2198 | |
| 2199 index = l1_multiband_radio_freq_convert_into_operative_radio_freq(radio_freq); | |
| 2200 | |
| 2201 #endif // #if (L1_FF_MULTIBAND == 0) else | |
| 2202 | |
| 2203 delta1_freq = l1ctl_encode_delta1(radio_freq); | |
| 2204 delta2_freq = l1ctl_encode_delta2(radio_freq); | |
| 2205 | |
| 2206 lna_value = lna_off * l1ctl_get_lna_att(radio_freq); | |
| 2207 | |
| 2208 last_known_agc = (Cust_get_agc_from_IL(radio_freq, last_known_il >> 1, PWR_ID)) << 1; | |
| 2209 // F7.1 in order to be compatible with | |
| 2210 // pm and IL formats [-20,+140 in F7.1] | |
| 2211 // contain the input_level value we use | |
| 2212 // in the associated CTL task to build | |
| 2213 // the agc used in this CTL. | |
| 2214 | |
| 2215 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2216 #if (L1_FF_MULTIBAND == 0) | |
| 2217 arfcn = Convert_l1_radio_freq(radio_freq); | |
| 2218 #else | |
| 2219 arfcn = radio_freq; | |
| 2220 #endif | |
| 2221 #endif | |
| 2222 | |
| 2223 #if(RF_FAM == 61) | |
| 2224 #if (CODE_VERSION != SIMULATION) | |
| 2225 | |
| 2226 #if (PWMEAS_IF_MODE_FORCE == 0) | |
| 2227 cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID , | |
| 2228 last_known_il, | |
| 2229 radio_freq,if_threshold); | |
| 2230 #else | |
| 2231 if_ctl = IF_120KHZ_DSP; | |
| 2232 dco_algo_ctl_pw_temp = DCO_IF_0KHZ; | |
| 2233 #endif | |
| 2234 | |
| 2235 delta_drp_gain = drp_gain_correction(arfcn, lna_off, last_known_agc); // F7.1 format | |
| 2236 if(if_ctl == IF_100KHZ_DSP){ | |
| 2237 delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; | |
| 2238 } | |
| 2239 else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ | |
| 2240 delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; | |
| 2241 } | |
| 2242 | |
| 2243 #endif | |
| 2244 #endif | |
| 2245 | |
| 2246 if (0==pm) // Check and filter illegal pm value by using last valid IL | |
| 2247 current_IL = l1a_l1s_com.last_input_level[index].input_level - lna_value; | |
| 2248 else | |
| 2249 current_IL = -(pm - (last_known_agc - delta_drp_gain) + lna_value - l1ctl_get_g_magic(radio_freq)); | |
| 2250 | |
| 2251 current_calibrated_IL = current_IL - delta1_freq - delta2_freq; | |
| 2252 | |
| 2253 // Protect IL stores against overflow | |
| 2254 if (current_calibrated_IL>INDEX_MAX) | |
| 2255 current_calibrated_IL=INDEX_MAX; | |
| 2256 if (current_IL>INDEX_MAX) | |
| 2257 current_IL=INDEX_MAX; | |
| 2258 | |
| 2259 // we validate the measure and save input_level and lna_off fields | |
| 2260 l1ctl_encode_lna((UWORD8)(current_calibrated_IL>>1), | |
| 2261 &(l1a_l1s_com.last_input_level[index].lna_off), | |
| 2262 radio_freq); | |
| 2263 | |
| 2264 l1a_l1s_com.last_input_level[index].input_level = (UWORD8)current_IL + | |
| 2265 l1ctl_get_lna_att(radio_freq) * | |
| 2266 l1a_l1s_com.last_input_level[index].lna_off; | |
| 2267 | |
| 2268 return((UWORD8)current_calibrated_IL); | |
| 2269 } | |
| 2270 | |
| 2271 | |
| 2272 /*-------------------------------------------------------*/ | |
| 2273 /* l1ctl_pgc2() */ | |
| 2274 /*-------------------------------------------------------*/ | |
| 2275 /* Description : */ | |
| 2276 /* ============= */ | |
| 2277 /* from power measurement pm_high_agc, */ | |
| 2278 /* achieve with an HIGH_AGC setting, and pm_low_agc */ | |
| 2279 /* achieve with a LOW_AGC seeting, we deduce the new */ | |
| 2280 /* AGC to apply in the next CTL task. */ | |
| 2281 /*-------------------------------------------------------*/ | |
| 2282 void l1ctl_pgc2(UWORD8 pm_high_agc, UWORD8 pm_low_agc, UWORD16 radio_freq) | |
| 2283 { | |
| 2284 UWORD8 pm; | |
| 2285 WORD32 IL_high_agc, IL_low_agc, new_IL, current_calibrated_IL; | |
| 2286 WORD8 delta1_freq, delta2_freq; | |
| 2287 WORD16 delta_high_drp_gain=0; | |
| 2288 WORD16 delta_low_drp_gain=0; | |
| 2289 WORD32 index; | |
| 2290 UWORD16 g_magic; | |
| 2291 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2292 UWORD16 arfcn; | |
| 2293 #endif | |
| 2294 UWORD16 dco_algo_ctl_pw_temp = 0; | |
| 2295 UWORD8 if_ctl = 0; | |
| 2296 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2297 UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; | |
| 2298 #endif | |
| 2299 | |
| 2300 #if (L1_FF_MULTIBAND == 0) | |
| 2301 | |
| 2302 // initialize index | |
| 2303 index = radio_freq - l1_config.std.radio_freq_index_offset; | |
| 2304 | |
| 2305 #else | |
| 2306 | |
| 2307 index = | |
| 2308 l1_multiband_radio_freq_convert_into_operative_radio_freq(radio_freq); | |
| 2309 | |
| 2310 #endif // #if (L1_FF_MULTIBAND == 0) else | |
| 2311 | |
| 2312 delta1_freq = l1ctl_encode_delta1(radio_freq); | |
| 2313 delta2_freq = l1ctl_encode_delta2(radio_freq); | |
| 2314 | |
| 2315 g_magic = l1ctl_get_g_magic(radio_freq); | |
| 2316 | |
| 2317 // lna_off was set to 0 during CTRL, so lna_value = 0 do not appear in the following | |
| 2318 // formula. | |
| 2319 | |
| 2320 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2321 #if (L1_FF_MULTIBAND == 0) | |
| 2322 arfcn = Convert_l1_radio_freq(radio_freq); | |
| 2323 #else | |
| 2324 arfcn = radio_freq; | |
| 2325 #endif | |
| 2326 #endif | |
| 2327 | |
| 2328 if ((0==pm_high_agc) || (0==pm_low_agc)) // Check and filter illegal pm value(s) by using last valid IL | |
| 2329 new_IL = l1a_l1s_com.last_input_level[index].input_level; | |
| 2330 else | |
| 2331 { | |
| 2332 | |
| 2333 #if(RF_FAM == 61) | |
| 2334 #if (CODE_VERSION != SIMULATION) | |
| 2335 | |
| 2336 #if (PWMEAS_IF_MODE_FORCE == 0) | |
| 2337 cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_INVALID , | |
| 2338 0, | |
| 2339 radio_freq,if_threshold); | |
| 2340 #else | |
| 2341 if_ctl = IF_120KHZ_DSP; | |
| 2342 dco_algo_ctl_pw_temp = DCO_IF_0KHZ; | |
| 2343 #endif | |
| 2344 | |
| 2345 | |
| 2346 delta_high_drp_gain = drp_gain_correction(arfcn, LNA_ON, (l1_config.params.high_agc << 1)); // F7.1 format | |
| 2347 delta_low_drp_gain = drp_gain_correction(arfcn, LNA_ON, (l1_config.params.low_agc << 1)); // F7.1 format | |
| 2348 if(if_ctl == IF_100KHZ_DSP){ | |
| 2349 delta_high_drp_gain += SCF_ATTENUATION_LIF_100KHZ; | |
| 2350 delta_low_drp_gain += SCF_ATTENUATION_LIF_100KHZ; | |
| 2351 } | |
| 2352 else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ | |
| 2353 delta_high_drp_gain += SCF_ATTENUATION_LIF_120KHZ; | |
| 2354 delta_low_drp_gain += SCF_ATTENUATION_LIF_120KHZ; | |
| 2355 } | |
| 2356 #endif | |
| 2357 #endif | |
| 2358 | |
| 2359 IL_high_agc = -(pm_high_agc - ((l1_config.params.high_agc << 1) - delta_high_drp_gain) - g_magic); | |
| 2360 IL_low_agc = -(pm_low_agc - ((l1_config.params.low_agc << 1) - delta_low_drp_gain) - g_magic); | |
| 2361 | |
| 2362 // HIGH_AGC and LOW_AGC are formatted to F7.1 in order to be compatible with | |
| 2363 // pm and IL formats | |
| 2364 | |
| 2365 if (IL_low_agc>=l1_config.params.low_agc_noise_thr) | |
| 2366 // pm_low_agc was on the noise floor, so not valid | |
| 2367 { | |
| 2368 // whatever the value of pm_high_agc, we consider it | |
| 2369 // as the right setting | |
| 2370 new_IL = IL_high_agc; | |
| 2371 pm = pm_high_agc; | |
| 2372 } | |
| 2373 else | |
| 2374 { | |
| 2375 // pm_low_agc is valid. | |
| 2376 if (IL_high_agc<=l1_config.params.high_agc_sat_thr) | |
| 2377 { | |
| 2378 // pm_high_agc is not valid, it's saturated. | |
| 2379 new_IL = IL_low_agc; | |
| 2380 pm = pm_low_agc; | |
| 2381 } | |
| 2382 else | |
| 2383 { | |
| 2384 // both pm_low_agc and pm_high_agc are valid, so we test the one that | |
| 2385 // gives the maximum input level and consider it as the right setting. | |
| 2386 if (IL_high_agc<=IL_low_agc) | |
| 2387 { | |
| 2388 new_IL = IL_high_agc; | |
| 2389 pm = pm_high_agc; | |
| 2390 } | |
| 2391 else | |
| 2392 { | |
| 2393 new_IL = IL_low_agc; | |
| 2394 pm = pm_low_agc; | |
| 2395 } | |
| 2396 } | |
| 2397 } | |
| 2398 } | |
| 2399 | |
| 2400 #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) | |
| 2401 RTTL1_FILL_MON_MEAS(pm_high_agc, IL_high_agc - delta1_freq - delta2_freq, MS_AGC_ID, radio_freq) | |
| 2402 RTTL1_FILL_MON_MEAS(pm_low_agc, IL_low_agc - delta1_freq - delta2_freq, MS_AGC_ID, radio_freq) | |
| 2403 #endif | |
| 2404 | |
| 2405 current_calibrated_IL = new_IL - delta1_freq - delta2_freq; | |
| 2406 | |
| 2407 // Protect IL stores against overflow | |
| 2408 if (current_calibrated_IL>INDEX_MAX) | |
| 2409 current_calibrated_IL=INDEX_MAX; | |
| 2410 if (new_IL>INDEX_MAX) | |
| 2411 new_IL=INDEX_MAX; | |
| 2412 | |
| 2413 // Updating of input_level and lna_off fields in order to correctly | |
| 2414 // setting the AGC for the next task. | |
| 2415 l1ctl_encode_lna((UWORD8)(current_calibrated_IL>>1), | |
| 2416 &(l1a_l1s_com.last_input_level[index].lna_off), | |
| 2417 radio_freq); | |
| 2418 | |
| 2419 l1a_l1s_com.last_input_level[index].input_level = (UWORD8)new_IL + | |
| 2420 l1ctl_get_lna_att(radio_freq) * | |
| 2421 l1a_l1s_com.last_input_level[index].lna_off; | |
| 2422 } | |
| 2423 | |
| 2424 | |
| 2425 /*-------------------------------------------------------*/ | |
| 2426 /* l1ctl_find_max() */ | |
| 2427 /*-------------------------------------------------------*/ | |
| 2428 /* Parameters : */ | |
| 2429 /* Return : */ | |
| 2430 /* Functionality : */ | |
| 2431 /*-------------------------------------------------------*/ | |
| 2432 UWORD8 l1ctl_find_max(UWORD8 *buff, UWORD8 buffer_len) | |
| 2433 { | |
| 2434 | |
| 2435 // WARNING: for array index purpose we work with POSITIVE input level | |
| 2436 // so maximum search for negative numbers is equivalent to | |
| 2437 // minimum search for positive numbers!!!!!! | |
| 2438 // (-30 > -120 but 30 < 120) | |
| 2439 | |
| 2440 UWORD8 maximum = 240; | |
| 2441 UWORD8 i; | |
| 2442 | |
| 2443 for (i=0; i<buffer_len; i++) | |
| 2444 { | |
| 2445 if (buff[i]<maximum) | |
| 2446 maximum=buff[i]; | |
| 2447 } | |
| 2448 | |
| 2449 return(maximum); | |
| 2450 } | |
| 2451 | |
| 2452 /*-------------------------------------------------------*/ | |
| 2453 /* l1ctl_pagc() */ | |
| 2454 /*-------------------------------------------------------*/ | |
| 2455 /* Description : */ | |
| 2456 /* =========== */ | |
| 2457 /* We deduce the last_known_agc from the last stored */ | |
| 2458 /* input_level for the considered carrier. We use this */ | |
| 2459 /* agc value to "build" the input level linked to the pm */ | |
| 2460 /* we have just read. */ | |
| 2461 /* This input level is used to feed a fifo of 4 elements */ | |
| 2462 /* and then compute an input_level maximum. This value is*/ | |
| 2463 /* used to update the input_level for this carrier. This */ | |
| 2464 /* input_level will be used for the next task to control.*/ | |
| 2465 /*-------------------------------------------------------*/ | |
| 2466 UWORD8 l1ctl_pagc(UWORD8 pm, UWORD16 radio_freq, T_INPUT_LEVEL *IL_info_ptr) | |
| 2467 { | |
| 2468 WORD8 delta1_freq, delta2_freq; | |
| 2469 WORD16 delta_drp_gain=0; | |
| 2470 WORD32 last_known_agc; | |
| 2471 UWORD8 IL_max; | |
| 2472 WORD32 current_IL, current_calibrated_IL; | |
| 2473 UWORD8 i; | |
| 2474 WORD32 lna_value; | |
| 2475 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2476 UWORD16 arfcn; | |
| 2477 #endif | |
| 2478 UWORD8 lna_off; | |
| 2479 UWORD16 dco_algo_ctl_pw_temp = 0; | |
| 2480 UWORD8 if_ctl = 0; | |
| 2481 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2482 UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; | |
| 2483 #endif | |
| 2484 | |
| 2485 delta1_freq = l1ctl_encode_delta1(radio_freq); | |
| 2486 delta2_freq = l1ctl_encode_delta2(radio_freq); | |
| 2487 | |
| 2488 // Update fifo | |
| 2489 for (i=3;i>0;i--) | |
| 2490 l1a_l1s_com.Scell_info.buff_beacon[i]=l1a_l1s_com.Scell_info.buff_beacon[i-1]; | |
| 2491 | |
| 2492 // from the lna state (ON/OFF) we compute the attenuation | |
| 2493 // that was applied to signal when performing the power | |
| 2494 // measure. | |
| 2495 lna_value = l1a_l1s_com.Scell_used_IL_dd.lna_off * l1ctl_get_lna_att(radio_freq); | |
| 2496 | |
| 2497 // Compute applied agc for this pm | |
| 2498 last_known_agc = (Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.Scell_used_IL_dd.input_level >> 1, MAX_ID)) << 1; | |
| 2499 // F7.1 in order to be compatible | |
| 2500 // with pm and IL formats | |
| 2501 // contain the input_level value we use | |
| 2502 // in the associated CTL task to build | |
| 2503 // the agc used in this CTL. | |
| 2504 | |
| 2505 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2506 #if (L1_FF_MULTIBAND == 0) | |
| 2507 arfcn = Convert_l1_radio_freq(radio_freq); | |
| 2508 #else | |
| 2509 arfcn = radio_freq; | |
| 2510 #endif | |
| 2511 #endif | |
| 2512 | |
| 2513 #if(RF_FAM == 61) | |
| 2514 #if (CODE_VERSION != SIMULATION) | |
| 2515 | |
| 2516 cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID , | |
| 2517 l1a_l1s_com.Scell_used_IL_dd.input_level, | |
| 2518 radio_freq,if_threshold); | |
| 2519 lna_off = l1a_l1s_com.Scell_used_IL_dd.lna_off; | |
| 2520 delta_drp_gain = drp_gain_correction(arfcn, lna_off, last_known_agc); // F7.1 format | |
| 2521 if(if_ctl == IF_100KHZ_DSP){ | |
| 2522 delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; | |
| 2523 } | |
| 2524 else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ | |
| 2525 delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; | |
| 2526 } | |
| 2527 | |
| 2528 #endif | |
| 2529 #endif | |
| 2530 | |
| 2531 if (0==pm) // Check and filter illegal pm value by using last valid IL | |
| 2532 current_IL = IL_info_ptr->input_level - lna_value; | |
| 2533 else | |
| 2534 current_IL = -(pm - (last_known_agc - delta_drp_gain) + lna_value - l1ctl_get_g_magic(radio_freq)); | |
| 2535 | |
| 2536 current_calibrated_IL = current_IL - delta1_freq - delta2_freq; | |
| 2537 | |
| 2538 // Protect IL stores against overflow | |
| 2539 if (current_calibrated_IL>INDEX_MAX) | |
| 2540 current_calibrated_IL=INDEX_MAX; | |
| 2541 if (current_IL>INDEX_MAX) | |
| 2542 current_IL=INDEX_MAX; | |
| 2543 | |
| 2544 l1a_l1s_com.Scell_info.buff_beacon[0] = (UWORD8)current_IL; | |
| 2545 | |
| 2546 IL_max = l1ctl_find_max(&(l1a_l1s_com.Scell_info.buff_beacon[0]),4); | |
| 2547 | |
| 2548 //input levels are always stored with lna_on | |
| 2549 l1ctl_encode_lna( (UWORD8)(current_calibrated_IL>>1), | |
| 2550 &(IL_info_ptr->lna_off), | |
| 2551 radio_freq ); | |
| 2552 | |
| 2553 IL_info_ptr->input_level = IL_max + l1ctl_get_lna_att(radio_freq) * | |
| 2554 IL_info_ptr->lna_off; | |
| 2555 | |
| 2556 #if L2_L3_SIMUL | |
| 2557 #if (DEBUG_TRACE==BUFFER_TRACE_PAGC) | |
| 2558 buffer_trace(4,IL_info_ptr->input_level,last_known_agc, | |
| 2559 l1a_l1s_com.Scell_used_IL_dd.input_level,Cust_get_agc_from_IL(radio_freq, IL_max >> 1, MAX_ID)); | |
| 2560 #endif | |
| 2561 #endif | |
| 2562 | |
| 2563 return((UWORD8)current_calibrated_IL); | |
| 2564 } | |
| 2565 | |
| 2566 /*-------------------------------------------------------*/ | |
| 2567 /* l1ctl_dpagc() */ | |
| 2568 /*-------------------------------------------------------*/ | |
| 2569 /* Description : */ | |
| 2570 /* =========== */ | |
| 2571 /* Based on the same principle as the one used for PAGC */ | |
| 2572 /* algorithm except that we feed 3 different fifo: */ | |
| 2573 /* 1) one is dedicated to BCCH carrier */ | |
| 2574 /* 2) another one is dedicated to all the other type of */ | |
| 2575 /* bursts */ | |
| 2576 /* 3) the last one is dedicated to non DTX influenced */ | |
| 2577 /* bursts */ | |
| 2578 /*-------------------------------------------------------*/ | |
| 2579 UWORD8 l1ctl_dpagc(BOOL dtx_on, BOOL beacon, UWORD8 pm, UWORD16 radio_freq, T_INPUT_LEVEL *IL_info_ptr) | |
| 2580 { | |
| 2581 UWORD8 av_G_all, av_G_DTX; | |
| 2582 UWORD8 max_G_all, max_G_DTX; | |
| 2583 WORD32 last_known_agc, new_IL, current_calibrated_IL; | |
| 2584 WORD8 delta1_freq, delta2_freq; | |
| 2585 WORD16 delta_drp_gain=0; | |
| 2586 UWORD8 i; | |
| 2587 UWORD8 *tab_ptr; | |
| 2588 T_DEDIC_SET *aset; | |
| 2589 WORD32 lna_value; | |
| 2590 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2591 UWORD16 arfcn; | |
| 2592 #endif | |
| 2593 UWORD8 lna_off; | |
| 2594 UWORD16 dco_algo_ctl_pw_temp = 0; | |
| 2595 UWORD8 if_ctl = 0; | |
| 2596 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2597 UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; | |
| 2598 #endif | |
| 2599 | |
| 2600 delta1_freq = l1ctl_encode_delta1(radio_freq); | |
| 2601 delta2_freq = l1ctl_encode_delta2(radio_freq); | |
| 2602 | |
| 2603 aset = l1a_l1s_com.dedic_set.aset; | |
| 2604 | |
| 2605 if (beacon) | |
| 2606 tab_ptr = l1a_l1s_com.Scell_info.buff_beacon; | |
| 2607 else | |
| 2608 tab_ptr = aset->G_all; | |
| 2609 | |
| 2610 // Update fifo | |
| 2611 for (i=DPAGC_FIFO_LEN-1;i>0;i--) | |
| 2612 tab_ptr[i]=tab_ptr[i-1]; | |
| 2613 | |
| 2614 #if TESTMODE | |
| 2615 if (!l1_config.agc_enable) | |
| 2616 { | |
| 2617 // AGC gain can only be controlled in 2dB steps as the bottom bit (bit zero) | |
| 2618 // corresponds to the lna_off bit | |
| 2619 last_known_agc = (l1_config.tmode.rx_params.agc) << 1; | |
| 2620 lna_value = (l1_config.tmode.rx_params.lna_off) * l1ctl_get_lna_att(radio_freq); | |
| 2621 } | |
| 2622 else | |
| 2623 #endif | |
| 2624 { | |
| 2625 #if DPAGC_MAX_FLAG | |
| 2626 last_known_agc = (Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.Scell_used_IL_dd.input_level >> 1, MAX_ID)) << 1; | |
| 2627 // F7.1 in order to be compatible with pm and IL formats | |
| 2628 #else | |
| 2629 last_known_agc = (Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.Scell_used_IL_dd.input_level >> 1, AV_ID)) << 1; | |
| 2630 // F7.1 in order to be compatible with pm and IL formats | |
| 2631 #endif | |
| 2632 // input_level_dd : contain the input_level value we use | |
| 2633 // in the associated CTL task to build the agc used in this CTL. | |
| 2634 | |
| 2635 lna_value = l1a_l1s_com.Scell_used_IL_dd.lna_off * l1ctl_get_lna_att(radio_freq); | |
| 2636 } | |
| 2637 | |
| 2638 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2639 #if (L1_FF_MULTIBAND == 0) | |
| 2640 arfcn = Convert_l1_radio_freq(radio_freq); | |
| 2641 #else | |
| 2642 arfcn = radio_freq; | |
| 2643 #endif | |
| 2644 #endif | |
| 2645 | |
| 2646 #if(RF_FAM == 61) | |
| 2647 #if (CODE_VERSION != SIMULATION) | |
| 2648 | |
| 2649 cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID , | |
| 2650 l1a_l1s_com.Scell_used_IL_dd.input_level, | |
| 2651 radio_freq,if_threshold); | |
| 2652 lna_off = l1a_l1s_com.Scell_used_IL_dd.lna_off; | |
| 2653 delta_drp_gain = drp_gain_correction(arfcn, lna_off, last_known_agc); // F7.1 format | |
| 2654 if(if_ctl == IF_100KHZ_DSP){ | |
| 2655 delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; | |
| 2656 } | |
| 2657 else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ | |
| 2658 delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; | |
| 2659 } | |
| 2660 | |
| 2661 #endif | |
| 2662 #endif | |
| 2663 | |
| 2664 if (0==pm) // Check and filter illegal pm value by using last valid IL | |
| 2665 new_IL = IL_info_ptr->input_level - lna_value; | |
| 2666 else | |
| 2667 new_IL = -(pm - (last_known_agc - delta_drp_gain) + lna_value - l1ctl_get_g_magic(radio_freq)); | |
| 2668 | |
| 2669 current_calibrated_IL = new_IL - delta1_freq - delta2_freq; | |
| 2670 | |
| 2671 // Protect IL stores against overflow | |
| 2672 if (current_calibrated_IL>INDEX_MAX) | |
| 2673 current_calibrated_IL=INDEX_MAX; | |
| 2674 | |
| 2675 #if TESTMODE | |
| 2676 if (l1tm.tmode_state.dedicated_active) // Implies l1_config.TestMode = 1 | |
| 2677 { | |
| 2678 // Update l1tm.tmode_stats.rssi_fifo (delay line from index 3 to 0) | |
| 2679 for (i=(sizeof(l1tm.tmode_stats.rssi_fifo)/sizeof(l1tm.tmode_stats.rssi_fifo[0]))-1; i>0; i--) | |
| 2680 { | |
| 2681 l1tm.tmode_stats.rssi_fifo[i] = l1tm.tmode_stats.rssi_fifo[i-1]; | |
| 2682 } | |
| 2683 l1tm.tmode_stats.rssi_fifo[0] = current_calibrated_IL; // rssi value is F7.1 | |
| 2684 l1tm.tmode_stats.rssi_recent = current_calibrated_IL; // rssi value is F7.1 | |
| 2685 } | |
| 2686 #endif | |
| 2687 | |
| 2688 if (new_IL>INDEX_MAX) | |
| 2689 new_IL=INDEX_MAX; | |
| 2690 | |
| 2691 tab_ptr[0] = (UWORD8)new_IL; | |
| 2692 | |
| 2693 if (dtx_on && !beacon) | |
| 2694 { | |
| 2695 // Update DTX fifo | |
| 2696 for (i=DPAGC_FIFO_LEN-1;i>0;i--) | |
| 2697 aset->G_DTX[i]=aset->G_DTX[i-1]; | |
| 2698 | |
| 2699 aset->G_DTX[0]=tab_ptr[0]; | |
| 2700 } | |
| 2701 | |
| 2702 /* Computation of MAX{G_all[i],G_DTX[j]} i,j=0..3 */ | |
| 2703 #if DPAGC_MAX_FLAG | |
| 2704 max_G_all = l1ctl_find_max(&(tab_ptr[0]),DPAGC_FIFO_LEN); | |
| 2705 | |
| 2706 if (!beacon) | |
| 2707 { | |
| 2708 max_G_DTX = l1ctl_find_max(&(aset->G_DTX[0]),DPAGC_FIFO_LEN); | |
| 2709 | |
| 2710 // WARNING: for array index purpose we work with POSITIVE input level | |
| 2711 // so maximum search for negative numbers is equivalent to | |
| 2712 // minimum search for positive numbers!!!!!! | |
| 2713 // (-30 > -120 but 30 < 120) | |
| 2714 if (max_G_all <= max_G_DTX) | |
| 2715 new_IL = max_G_all; | |
| 2716 else | |
| 2717 new_IL = max_G_DTX; | |
| 2718 } | |
| 2719 else | |
| 2720 new_IL = max_G_all; | |
| 2721 #else | |
| 2722 av_G_all=av_G_DTX=0; | |
| 2723 | |
| 2724 for (i=0;i<DPAGC_FIFO_LEN;i++) | |
| 2725 av_G_all += tab_ptr[i]; | |
| 2726 | |
| 2727 av_G_all /= DPAGC_FIFO_LEN; | |
| 2728 | |
| 2729 if (!beacon) | |
| 2730 { | |
| 2731 for (i=0;i<DPAGC_FIFO_LEN;i++) | |
| 2732 av_G_DTX += aset->G_DTX[i]; | |
| 2733 | |
| 2734 av_G_DTX /= DPAGC_FIFO_LEN; | |
| 2735 | |
| 2736 if (av_G_all >= av_G_DTX) | |
| 2737 new_IL = av_G_all; | |
| 2738 else | |
| 2739 new_IL = av_G_DTX; | |
| 2740 } | |
| 2741 else | |
| 2742 new_IL = av_G_all; | |
| 2743 #endif | |
| 2744 | |
| 2745 // Updating of input_level and lna_off fields in order to correctly | |
| 2746 // setting the AGC for the next task. | |
| 2747 // input_level is always store with lna_on | |
| 2748 l1ctl_encode_lna( (UWORD8)(current_calibrated_IL>>1), | |
| 2749 &(IL_info_ptr->lna_off), | |
| 2750 radio_freq ); | |
| 2751 | |
| 2752 IL_info_ptr->input_level = (UWORD8)new_IL + l1ctl_get_lna_att(radio_freq) * | |
| 2753 IL_info_ptr->lna_off; | |
| 2754 | |
| 2755 #if L2_L3_SIMUL | |
| 2756 #if (DEBUG_TRACE==BUFFER_TRACE_DPAGC) | |
| 2757 buffer_trace(4,IL_info_ptr->input_level,last_known_agc, | |
| 2758 l1a_l1s_com.Scell_used_IL_dd.input_level,Cust_get_agc_from_IL(radio_freq, new_IL >> 1, MAX_ID)); | |
| 2759 #endif | |
| 2760 #endif | |
| 2761 | |
| 2762 return((UWORD8)current_calibrated_IL); | |
| 2763 } | |
| 2764 | |
| 2765 #if (AMR == 1) | |
| 2766 /*-------------------------------------------------------*/ | |
| 2767 /* l1ctl_dpagc_amr() */ | |
| 2768 /*-------------------------------------------------------*/ | |
| 2769 /* Description : */ | |
| 2770 /* =========== */ | |
| 2771 /* Based on the same principle as the one used for DPAGC */ | |
| 2772 /* algorithm except that the way to feed the G_dtx is */ | |
| 2773 /* different */ | |
| 2774 /*-------------------------------------------------------*/ | |
| 2775 UWORD8 l1ctl_dpagc_amr(BOOL dtx_on, BOOL beacon, UWORD8 pm, UWORD16 radio_freq, T_INPUT_LEVEL *IL_info_ptr) | |
| 2776 { | |
| 2777 UWORD8 av_G_all, av_G_DTX; | |
| 2778 UWORD8 max_G_all, max_G_DTX, max_il; | |
| 2779 WORD32 last_known_agc, new_IL, current_calibrated_IL; | |
| 2780 WORD8 delta1_freq, delta2_freq; | |
| 2781 WORD16 delta_drp_gain=0; | |
| 2782 UWORD8 i; | |
| 2783 UWORD8 *tab_ptr, *tab_amr_ptr; | |
| 2784 T_DEDIC_SET *aset; | |
| 2785 WORD32 lna_value; | |
| 2786 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2787 UWORD16 arfcn; | |
| 2788 #endif | |
| 2789 UWORD8 lna_off; | |
| 2790 UWORD16 dco_algo_ctl_pw_temp = 0; | |
| 2791 UWORD8 if_ctl = 0; | |
| 2792 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2793 UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; | |
| 2794 #endif | |
| 2795 | |
| 2796 delta1_freq = l1ctl_encode_delta1(radio_freq); | |
| 2797 delta2_freq = l1ctl_encode_delta2(radio_freq); | |
| 2798 | |
| 2799 aset = l1a_l1s_com.dedic_set.aset; | |
| 2800 | |
| 2801 if (beacon) | |
| 2802 tab_ptr = l1a_l1s_com.Scell_info.buff_beacon; | |
| 2803 else | |
| 2804 tab_ptr = aset->G_all; | |
| 2805 | |
| 2806 // Update fifo | |
| 2807 for (i=DPAGC_FIFO_LEN-1;i>0;i--) | |
| 2808 tab_ptr[i]=tab_ptr[i-1]; | |
| 2809 | |
| 2810 tab_amr_ptr = aset->G_amr; | |
| 2811 for (i=DPAGC_AMR_FIFO_LEN-1;i>0;i--) | |
| 2812 tab_amr_ptr[i]=tab_amr_ptr[i-1]; | |
| 2813 | |
| 2814 #if TESTMODE | |
| 2815 if (!l1_config.agc_enable) | |
| 2816 { | |
| 2817 // AGC gain can only be controlled in 2dB steps as the bottom bit (bit zero) | |
| 2818 // corresponds to the lna_off bit | |
| 2819 last_known_agc = (l1_config.tmode.rx_params.agc) << 1; | |
| 2820 lna_value = (l1_config.tmode.rx_params.lna_off) * l1ctl_get_lna_att(radio_freq); | |
| 2821 } | |
| 2822 else | |
| 2823 #endif | |
| 2824 { | |
| 2825 #if DPAGC_MAX_FLAG | |
| 2826 last_known_agc = (Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.Scell_used_IL_dd.input_level >> 1, MAX_ID)) << 1; | |
| 2827 // F7.1 in order to be compatible with pm and IL formats | |
| 2828 #else | |
| 2829 last_known_agc = (Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.Scell_used_IL_dd.input_level >> 1, AV_ID)) << 1; | |
| 2830 // F7.1 in order to be compatible with pm and IL formats | |
| 2831 #endif | |
| 2832 // input_level_dd : contain the input_level value we use | |
| 2833 // in the associated CTL task to build the agc used in this CTL. | |
| 2834 | |
| 2835 lna_value = l1a_l1s_com.Scell_used_IL_dd.lna_off * l1ctl_get_lna_att(radio_freq); | |
| 2836 } | |
| 2837 | |
| 2838 #if (RF_RAM == 61) && (CODE_VERSION != SIMULATION) | |
| 2839 #if (L1_FF_MULTIBAND == 0) | |
| 2840 arfcn = Convert_l1_radio_freq(radio_freq); | |
| 2841 #else | |
| 2842 arfcn = radio_freq; | |
| 2843 #endif | |
| 2844 #endif | |
| 2845 | |
| 2846 #if(RF_FAM == 61) | |
| 2847 #if (CODE_VERSION != SIMULATION) | |
| 2848 cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID , | |
| 2849 l1a_l1s_com.Scell_used_IL_dd.input_level, | |
| 2850 radio_freq,if_threshold); | |
| 2851 lna_off = l1a_l1s_com.Scell_used_IL_dd.lna_off; | |
| 2852 delta_drp_gain = drp_gain_correction(arfcn, lna_off, last_known_agc); // F7.1 format | |
| 2853 if(if_ctl == IF_100KHZ_DSP){ | |
| 2854 delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; | |
| 2855 } | |
| 2856 else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ | |
| 2857 delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; | |
| 2858 } | |
| 2859 #endif | |
| 2860 #endif | |
| 2861 | |
| 2862 if (0==pm) // Check and filter illegal pm value by using last valid IL | |
| 2863 new_IL = IL_info_ptr->input_level - lna_value; | |
| 2864 else | |
| 2865 new_IL = -(pm - (last_known_agc - delta_drp_gain) + lna_value - l1ctl_get_g_magic(radio_freq)); | |
| 2866 | |
| 2867 current_calibrated_IL = new_IL - delta1_freq - delta2_freq; | |
| 2868 | |
| 2869 // Protect IL stores against overflow | |
| 2870 if (current_calibrated_IL>INDEX_MAX) | |
| 2871 current_calibrated_IL=INDEX_MAX; | |
| 2872 | |
| 2873 #if TESTMODE | |
| 2874 if (l1tm.tmode_state.dedicated_active) // Implies l1_config.TestMode = 1 | |
| 2875 { | |
| 2876 // Update l1tm.tmode_stats.rssi_fifo (delay line from index 3 to 0) | |
| 2877 for (i=(sizeof(l1tm.tmode_stats.rssi_fifo)/sizeof(l1tm.tmode_stats.rssi_fifo[0]))-1; i>0; i--) | |
| 2878 { | |
| 2879 l1tm.tmode_stats.rssi_fifo[i] = l1tm.tmode_stats.rssi_fifo[i-1]; | |
| 2880 } | |
| 2881 l1tm.tmode_stats.rssi_fifo[0] = current_calibrated_IL; // rssi value is F7.1 | |
| 2882 l1tm.tmode_stats.rssi_recent = current_calibrated_IL; // rssi value is F7.1 | |
| 2883 } | |
| 2884 #endif | |
| 2885 | |
| 2886 if (new_IL>INDEX_MAX) | |
| 2887 new_IL=INDEX_MAX; | |
| 2888 | |
| 2889 tab_ptr[0] = (UWORD8)new_IL; | |
| 2890 tab_amr_ptr[0] = (UWORD8)new_IL; | |
| 2891 | |
| 2892 if (dtx_on && !beacon) | |
| 2893 { | |
| 2894 // a new AMR block is received, feed the G_dtx with the max_il of the block | |
| 2895 for (i=DPAGC_FIFO_LEN-1;i>0;i--) | |
| 2896 aset->G_DTX[i]=aset->G_DTX[i-1]; | |
| 2897 | |
| 2898 if (l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AHS_MODE) | |
| 2899 { | |
| 2900 // Keep the max_il between the last 2 bursts | |
| 2901 if (aset->G_amr[0] > aset->G_amr[1]) | |
| 2902 max_il = aset->G_amr[0]; | |
| 2903 else | |
| 2904 max_il = aset->G_amr[1]; | |
| 2905 } | |
| 2906 else | |
| 2907 { | |
| 2908 // Keep the max_il between the last 4 bursts | |
| 2909 max_il = l1ctl_find_max(&aset->G_amr[0], DPAGC_AMR_FIFO_LEN); | |
| 2910 } | |
| 2911 | |
| 2912 aset->G_DTX[0]= max_il; | |
| 2913 } | |
| 2914 | |
| 2915 /* Computation of MAX{G_all[i],G_DTX[j]} i,j=0..3 */ | |
| 2916 #if DPAGC_MAX_FLAG | |
| 2917 max_G_all = l1ctl_find_max(&(tab_ptr[0]),DPAGC_FIFO_LEN); | |
| 2918 | |
| 2919 if (!beacon) | |
| 2920 { | |
| 2921 max_G_DTX = l1ctl_find_max(&(aset->G_DTX[0]),DPAGC_FIFO_LEN); | |
| 2922 | |
| 2923 // WARNING: for array index purpose we work with POSITIVE input level | |
| 2924 // so maximum search for negative numbers is equivalent to | |
| 2925 // minimum search for positive numbers!!!!!! | |
| 2926 // (-30 > -120 but 30 < 120) | |
| 2927 if (max_G_all <= max_G_DTX) | |
| 2928 new_IL = max_G_all; | |
| 2929 else | |
| 2930 new_IL = max_G_DTX; | |
| 2931 } | |
| 2932 else | |
| 2933 new_IL = max_G_all; | |
| 2934 #else | |
| 2935 av_G_all=av_G_DTX=0; | |
| 2936 | |
| 2937 for (i=0;i<DPAGC_FIFO_LEN;i++) | |
| 2938 av_G_all += tab_ptr[i]; | |
| 2939 | |
| 2940 av_G_all /= DPAGC_FIFO_LEN; | |
| 2941 | |
| 2942 if (!beacon) | |
| 2943 { | |
| 2944 for (i=0;i<DPAGC_FIFO_LEN;i++) | |
| 2945 av_G_DTX += aset->G_DTX[i]; | |
| 2946 | |
| 2947 av_G_DTX /= DPAGC_FIFO_LEN; | |
| 2948 | |
| 2949 if (av_G_all >= av_G_DTX) | |
| 2950 new_IL = av_G_all; | |
| 2951 else | |
| 2952 new_IL = av_G_DTX; | |
| 2953 } | |
| 2954 else | |
| 2955 new_IL = av_G_all; | |
| 2956 #endif | |
| 2957 | |
| 2958 // Updating of input_level and lna_off fields in order to correctly | |
| 2959 // setting the AGC for the next task. | |
| 2960 // input_level is always store with lna_on | |
| 2961 | |
| 2962 l1ctl_encode_lna( (UWORD8)(current_calibrated_IL>>1), | |
| 2963 &(IL_info_ptr->lna_off), | |
| 2964 radio_freq ); | |
| 2965 IL_info_ptr->input_level = (UWORD8)new_IL + l1ctl_get_lna_att(radio_freq) * | |
| 2966 IL_info_ptr->lna_off; | |
| 2967 | |
| 2968 #if L2_L3_SIMUL | |
| 2969 #if (DEBUG_TRACE==BUFFER_TRACE_DPAGC) | |
| 2970 buffer_trace(4,IL_info_ptr->input_level,last_known_agc, | |
| 2971 l1a_l1s_com.Scell_used_IL_dd.input_level,Cust_get_agc_from_IL(radio_freq, new_IL >> 1, MAX_ID)); | |
| 2972 #endif | |
| 2973 #endif | |
| 2974 | |
| 2975 return((UWORD8)current_calibrated_IL); | |
| 2976 } | |
| 2977 #endif // AMR == 1 | |
| 2978 | |
| 2979 /*-------------------------------------------------------*/ | |
| 2980 /* l1ctl_get_g_magic() */ | |
| 2981 /*-------------------------------------------------------*/ | |
| 2982 /* Parameters : */ | |
| 2983 /* Return : */ | |
| 2984 /* Functionality : */ | |
| 2985 /*-------------------------------------------------------*/ | |
| 2986 #if (L1_FF_MULTIBAND == 0) | |
| 2987 UWORD16 l1ctl_get_g_magic(UWORD16 radio_freq) | |
| 2988 { | |
| 2989 | |
| 2990 | |
| 2991 if ((l1_config.std.id == DUAL) || (l1_config.std.id == DUALEXT) || (l1_config.std.id == DUAL_US)) | |
| 2992 { | |
| 2993 if (radio_freq >= l1_config.std.first_radio_freq_band2) | |
| 2994 return(l1_config.std.g_magic_band2); | |
| 2995 else | |
| 2996 return(l1_config.std.g_magic_band1); | |
| 2997 } | |
| 2998 else | |
| 2999 return(l1_config.std.g_magic_band1); | |
| 3000 | |
| 3001 | |
| 3002 } | |
| 3003 #endif | |
| 3004 | |
| 3005 /*-------------------------------------------------------*/ | |
| 3006 /* l1ctl_get_lna_att() */ | |
| 3007 /*-------------------------------------------------------*/ | |
| 3008 /* Parameters : */ | |
| 3009 /* Return : */ | |
| 3010 /* Functionality : */ | |
| 3011 /*-------------------------------------------------------*/ | |
| 3012 #if (L1_FF_MULTIBAND == 0) | |
| 3013 UWORD16 l1ctl_get_lna_att(UWORD16 radio_freq) | |
| 3014 { | |
| 3015 | |
| 3016 | |
| 3017 if ((l1_config.std.id == DUAL) || (l1_config.std.id == DUALEXT) || (l1_config.std.id == DUAL_US)) | |
| 3018 { | |
| 3019 if (radio_freq >= l1_config.std.first_radio_freq_band2) | |
| 3020 return(l1_config.std.lna_att_band2); | |
| 3021 else | |
| 3022 return(l1_config.std.lna_att_band1); | |
| 3023 } | |
| 3024 else | |
| 3025 return(l1_config.std.lna_att_band1); | |
| 3026 | |
| 3027 | |
| 3028 } | |
| 3029 #endif | |
| 3030 /*-------------------------------------------------------*/ | |
| 3031 /* l1ctl_update_TPU_with_toa() */ | |
| 3032 /*-------------------------------------------------------*/ | |
| 3033 /* Parameters : */ | |
| 3034 /* Return : */ | |
| 3035 /* Functionality : */ | |
| 3036 /*-------------------------------------------------------*/ | |
| 3037 void l1ctl_update_TPU_with_toa(void) | |
| 3038 { | |
| 3039 #if (TOA_ALGO != 0) | |
| 3040 WORD16 toa_shift; | |
| 3041 | |
| 3042 #if (TOA_ALGO == 2) | |
| 3043 toa_shift = l1s.toa_var.toa_shift; | |
| 3044 #else | |
| 3045 toa_shift = l1s.toa_shift; | |
| 3046 #endif | |
| 3047 | |
| 3048 if (toa_shift != ISH_INVALID) | |
| 3049 // New ISH (TOA shift) has been stored in "l1s.toa_shift". | |
| 3050 { | |
| 3051 // NEW !!! For EOTD measurements in IDLE mode, cut AFC updates... | |
| 3052 #if (L1_EOTD==1) | |
| 3053 #if (L1_GPRS) | |
| 3054 if ( (l1a_l1s_com.nsync.eotd_meas_session == FALSE) || | |
| 3055 (l1a_l1s_com.mode == DEDIC_MODE)|| | |
| 3056 (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)) | |
| 3057 #else | |
| 3058 if ( (l1a_l1s_com.nsync.eotd_meas_session == FALSE) || | |
| 3059 (l1a_l1s_com.mode == DEDIC_MODE)) | |
| 3060 #endif | |
| 3061 { | |
| 3062 // In dedicated or transfer modes we need to track an TOA | |
| 3063 // updates to post correct th results, else E-OTD implementation | |
| 3064 // has qb errors... | |
| 3065 | |
| 3066 if( (l1a_l1s_com.nsync.eotd_meas_session == TRUE) | |
| 3067 && (l1a_l1s_com.nsync.eotd_toa_phase == 1) ) | |
| 3068 { | |
| 3069 l1a_l1s_com.nsync.eotd_toa_tracking += toa_shift; | |
| 3070 } | |
| 3071 #endif | |
| 3072 // Update tpu offset. | |
| 3073 l1s.tpu_offset = (l1s.tpu_offset + TPU_CLOCK_RANGE + toa_shift) % TPU_CLOCK_RANGE; | |
| 3074 | |
| 3075 #if (TRACE_TYPE==1) || (TRACE_TYPE==4) | |
| 3076 #if (GSM_IDLE_RAM == 0) | |
| 3077 l1_trace_new_toa(); | |
| 3078 #else | |
| 3079 l1_trace_new_toa_intram(); | |
| 3080 #endif | |
| 3081 #endif | |
| 3082 | |
| 3083 #if (L1_EOTD==1) | |
| 3084 } | |
| 3085 #endif | |
| 3086 | |
| 3087 #if (TRACE_TYPE == 5) | |
| 3088 #if (TOA_ALGO == 2) | |
| 3089 trace_toa_sim_update (toa_shift,l1s.tpu_offset); | |
| 3090 #endif | |
| 3091 #endif | |
| 3092 | |
| 3093 // Reset ISH. | |
| 3094 #if (TOA_ALGO == 2) | |
| 3095 l1s.toa_var.toa_shift = ISH_INVALID; // Reset the ISH. | |
| 3096 #else | |
| 3097 l1s.toa_shift = ISH_INVALID; // Reset the ISH. | |
| 3098 #endif | |
| 3099 } | |
| 3100 #endif | |
| 3101 } | |
| 3102 | |
| 3103 | |
| 3104 /*-------------------------------------------------------*/ | |
| 3105 /* l1ctl_saic() */ | |
| 3106 /*-------------------------------------------------------*/ | |
| 3107 /* Parameters : */ | |
| 3108 /* Return : */ | |
| 3109 /* Functionality : */ | |
| 3110 /*-------------------------------------------------------*/ | |
| 3111 | |
| 3112 #if (L1_SAIC != 0) | |
| 3113 #define SWH_CHANTAP_INIT 0xFFD068CE | |
| 3114 #if (NEW_SNR_THRESHOLD == 1) | |
| 3115 UWORD8 l1ctl_saic (UWORD8 IL_for_rxlev, UWORD32 l1_mode, UWORD8 task, UWORD8 * saic_flag) | |
| 3116 #else | |
| 3117 UWORD8 l1ctl_saic (UWORD8 IL_for_rxlev, UWORD32 l1_mode) | |
| 3118 #endif /* NEW_SNR_THRESHOLD */ | |
| 3119 { | |
| 3120 UWORD16 SWH_flag = 0; | |
| 3121 UWORD8 CSF_Filter_choice = L1_SAIC_HARDWARE_FILTER; | |
| 3122 #if (NEW_SNR_THRESHOLD == 0) | |
| 3123 volatile UWORD16 *ptr; | |
| 3124 UWORD8 saic_flag; | |
| 3125 #endif /* NEW_SNR_THRESHOLD */ | |
| 3126 #if (NEW_SNR_THRESHOLD == 0) | |
| 3127 ptr = (volatile UWORD16 * ) (SWH_CHANTAP_INIT); | |
| 3128 *ptr = 0; | |
| 3129 saic_flag=1; | |
| 3130 #else | |
| 3131 *saic_flag=0; | |
| 3132 #endif | |
| 3133 | |
| 3134 switch (l1_mode) | |
| 3135 { | |
| 3136 case DEDIC_MODE: // GSM DEDICATED MODE | |
| 3137 { | |
| 3138 #if (NEW_SNR_THRESHOLD == 1) | |
| 3139 *saic_flag=1; | |
| 3140 #endif | |
| 3141 if(IL_for_rxlev < L1_SAIC_GENIE_GSM_DEDIC_THRESHOLD) | |
| 3142 { | |
| 3143 SWH_flag=1; | |
| 3144 } | |
| 3145 | |
| 3146 break; | |
| 3147 } | |
| 3148 #if L1_GPRS | |
| 3149 case PACKET_TRANSFER_MODE: // PACKET TRANSFER MODE | |
| 3150 { | |
| 3151 #if (NEW_SNR_THRESHOLD == 0) | |
| 3152 #if (L1_SAIC == 1) | |
| 3153 if(IL_for_rxlev < L1_SAIC_GENIE_GPRS_PCKT_TRAN_THRESHOLD) | |
| 3154 { | |
| 3155 *ptr = 4; | |
| 3156 } | |
| 3157 #endif /*#if (L1_SAIC == 3)*/ | |
| 3158 #endif | |
| 3159 | |
| 3160 #if (L1_SAIC == 3) | |
| 3161 if(IL_for_rxlev < L1_SAIC_GENIE_GPRS_PCKT_TRAN_THRESHOLD) | |
| 3162 { | |
| 3163 SWH_flag = 1; | |
| 3164 } | |
| 3165 #endif /*#if (L1_SAIC == 3)*/ | |
| 3166 break; | |
| 3167 } | |
| 3168 #endif /*#if L1_GPRS*/ | |
| 3169 default: /* GSM OR GPRS IDLE MODES */ | |
| 3170 { | |
| 3171 #if ((L1_SAIC == 2)||(L1_SAIC == 3)) | |
| 3172 if(IL_for_rxlev < L1_SAIC_GENIE_GSM_GPRS_IDLE_THRESHOLD) | |
| 3173 { | |
| 3174 SWH_flag=1; | |
| 3175 } | |
| 3176 #endif | |
| 3177 break; | |
| 3178 } | |
| 3179 } | |
| 3180 | |
| 3181 l1ddsp_load_swh_flag (SWH_flag , | |
| 3182 #if (NEW_SNR_THRESHOLD == 0) | |
| 3183 saic_flag | |
| 3184 #else | |
| 3185 *saic_flag | |
| 3186 #endif | |
| 3187 ); | |
| 3188 | |
| 3189 if(SWH_flag == 1) | |
| 3190 { | |
| 3191 CSF_Filter_choice = L1_SAIC_PROGRAMMABLE_FILTER; | |
| 3192 } | |
| 3193 | |
| 3194 | |
| 3195 #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) | |
| 3196 l1_trace_saic(SWH_flag, | |
| 3197 #if (NEW_SNR_THRESHOLD == 0) | |
| 3198 saic_flag | |
| 3199 #else | |
| 3200 *saic_flag | |
| 3201 #endif | |
| 3202 ); | |
| 3203 #endif | |
| 3204 #if (TRACE_TYPE == 5) | |
| 3205 trace_saic_sim(IL_for_rxlev, l1_mode, SWH_flag); | |
| 3206 #endif | |
| 3207 | |
| 3208 return(CSF_Filter_choice); | |
| 3209 } | |
| 3210 #endif | |
| 3211 | |
| 3212 #if (FF_L1_FAST_DECODING == 1) | |
| 3213 /*-----------------------------------------------------------------*/ | |
| 3214 /* l1ctl_pagc_missing_bursts */ | |
| 3215 /*-----------------------------------------------------------------*/ | |
| 3216 /* */ | |
| 3217 /* Description: */ | |
| 3218 /* ------------ */ | |
| 3219 /* When fast decoding is active, fewer bursts are decoded. As a */ | |
| 3220 /* result, fewer gain values are available. The PAGC algo must */ | |
| 3221 /* be updated with the missed values. */ | |
| 3222 /* */ | |
| 3223 /* Input parameters: */ | |
| 3224 /* ----------------- */ | |
| 3225 /* UWORD8 skipped_values: the number of skipped bursts due to fast */ | |
| 3226 /* decoding. */ | |
| 3227 /* */ | |
| 3228 /* Input parameters from globals: */ | |
| 3229 /* ------------------------------ */ | |
| 3230 /* l1a_l1s_com.Scell_info.buff_beacon: Input Level (IL) FIFO */ | |
| 3231 /* l1_config.params.il_min: minimum level */ | |
| 3232 /* */ | |
| 3233 /* Output parameters: */ | |
| 3234 /* ------------------ */ | |
| 3235 /* none */ | |
| 3236 /* */ | |
| 3237 /* Modified parameters from globals: */ | |
| 3238 /* --------------------------------- */ | |
| 3239 /* l1a_l1s_com.Scell_info.buff_beacon: Input Level (IL) FIFO */ | |
| 3240 /* */ | |
| 3241 /*-----------------------------------------------------------------*/ | |
| 3242 | |
| 3243 void l1ctl_pagc_missing_bursts (UWORD8 skipped_values) | |
| 3244 { | |
| 3245 UWORD8 i = 0; | |
| 3246 | |
| 3247 /* skipped_values cannot be greater than 3, otherwise this is an error | |
| 3248 * and the PAGC algorithm mustn't be updated. */ | |
| 3249 if (skipped_values > 3) | |
| 3250 { | |
| 3251 return; | |
| 3252 } | |
| 3253 | |
| 3254 /* Update fifo by removing skipped_values of samples */ | |
| 3255 for (i = 3; i > (skipped_values - 1); i--) | |
| 3256 { | |
| 3257 l1a_l1s_com.Scell_info.buff_beacon[i] = l1a_l1s_com.Scell_info.buff_beacon[i-skipped_values]; | |
| 3258 } | |
| 3259 | |
| 3260 /* Insert minimum IL level as many times a burst has been skipped */ | |
| 3261 for (i = 0; i < skipped_values; i++) | |
| 3262 { | |
| 3263 l1a_l1s_com.Scell_info.buff_beacon[i] = l1_config.params.il_min; | |
| 3264 } | |
| 3265 } | |
| 3266 #endif /* #if (FF_L1_FAST_DECODING == 1) */ |
