FreeCalypso > hg > fc-magnetite
view src/cs/layer1/p_cfile/l1p_ctl.c @ 685:3fb7384e820d
tpudrv12.h: FCDEV3B goes back to being itself
A while back we had the idea of a FreeCalypso modem family whereby our
current fcdev3b target would some day morph into fcmodem, with multiple
FC modem family products, potentially either triband or quadband, being
firmware-compatible with each other and with our original FCDEV3B. But
in light of the discovery of Tango modules that earlier idea is now being
withdrawn: instead the already existing Tango hw is being adopted into
our FreeCalypso family.
Tango cannot be firmware-compatible with triband OM/FCDEV3B targets
because the original quadband RFFE on Tango modules is wired in TI's
original Leonardo arrangement. Because this Leonardo/Tango way is now
becoming the official FreeCalypso way of driving quadband RFFEs thanks
to the adoption of Tango into our FC family, our earlier idea of
extending FIC's triband RFFE control signals with TSPACT5 no longer makes
much sense - we will probably never produce any new hardware with that
once-proposed arrangement. Therefore, that triband-or-quadband FCFAM
provision is being removed from the code base, and FCDEV3B goes back to
being treated the same way as CONFIG_TARGET_GTAMODEM for RFFE control
purposes.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 24 Sep 2020 21:03:08 +0000 |
parents | 0740b5ff15f6 |
children |
line wrap: on
line source
/************* Revision Controle System Header ************* * GSM Layer 1 software * L1P_CTL.C * * Filename l1p_ctl.c * Copyright 2003 (C) Texas Instruments * ************* Revision Controle System Header *************/ #include "l1_macro.h" #include "l1_confg.h" #if L1_GPRS #if (CODE_VERSION == SIMULATION) #include <string.h> #include "l1_types.h" #include "sys_types.h" #include "l1_const.h" #include "l1_time.h" #include "l1_signa.h" #if TESTMODE #include "l1tm_defty.h" #endif #if (AUDIO_TASK == 1) #include "l1audio_const.h" #include "l1audio_cust.h" #include "l1audio_signa.h" #include "l1audio_defty.h" #include "l1audio_msgty.h" #endif #if (L1_GTT == 1) #include "l1gtt_const.h" #include "l1gtt_defty.h" #endif #if (L1_MP3 == 1) #include "l1mp3_defty.h" #endif #if (L1_MIDI == 1) #include "l1midi_defty.h" #endif #include "l1_defty.h" #include "cust_os.h" #include "l1_msgty.h" #include "l1_varex.h" #include "l1_proto.h" #include "l1_mftab.h" #include "l1_tabs.h" #include "l1_ver.h" #include "l1_ctl.h" #include "l1p_cons.h" #include "l1p_msgt.h" #include "l1p_deft.h" #include "l1p_vare.h" #include "l1p_sign.h" #if (OP_L1_STANDALONE == 1) #ifdef _INLINE #define INLINE static inline // Inline functions when -v option is set #else // when the compiler is ivoked. #define INLINE #endif #endif //0maps00090550 #else #include <string.h> #include "l1_types.h" #include "sys_types.h" #include "l1_const.h" #include "l1_time.h" #include "l1_signa.h" #if (RF_FAM == 61) #include "tpudrv61.h" #endif #if TESTMODE #include "l1tm_defty.h" #endif #if (AUDIO_TASK == 1) #include "l1audio_const.h" #include "l1audio_cust.h" #include "l1audio_defty.h" #endif #if (L1_GTT == 1) #include "l1gtt_const.h" #include "l1gtt_defty.h" #endif #if (L1_MP3 == 1) #include "l1mp3_defty.h" #endif #if (L1_MIDI == 1) #include "l1midi_defty.h" #endif #include "l1_defty.h" #include "cust_os.h" #include "l1_msgty.h" #include "l1_varex.h" #include "l1_proto.h" #include "l1_ctl.h" #include "l1p_cons.h" #include "l1p_msgt.h" #include "l1p_deft.h" #include "l1p_vare.h" #include "l1p_sign.h" #if (OP_L1_STANDALONE == 1) #ifdef _INLINE #define INLINE static inline // Inline functions when -v option is set #else // when the compiler is ivoked. #define INLINE #endif #endif //omaps00090550 #endif #if(RF_FAM == 61) #include "l1_rf61.h" #endif // Macro definition //----------------- #define min(value1,value2) \ value1 < value2 ? value1 : value2 // External prototypes //-------------------- WORD8 l1ctl_encode_delta1(UWORD16 radio_freq); /*********************************************************/ /* GPRS AGC Algorithms */ /*********************************************************/ /*-------------------------------------------------------*/ /* l1pctl_pagc_ctrl() */ /*-------------------------------------------------------*/ /* Description: */ /* =========== */ /* Based on the same principle as the one used for PAGC */ /* algorithm except that we also feed the beacon FIFO */ /* with IL measured on other carriers (Pb parameter is */ /* applied) */ /* This function is used in the control phase of PCCCH, */ /* serving PBCCH and PTCCH reading tasks to determine */ /* which AGC and lna_off must apply */ /* */ /* WARNING: in the layer 1 code, input levels IL(l1) use */ /* format 7.1: */ /* ********************* */ /* * IL(l1) = - 2 x IL * */ /* ********************* */ /* -> Reversed sign, reversed test conditions */ /* -> max replaced by min */ /* ex: if IL -120 dBm, IL(l1) = 240 */ /*-------------------------------------------------------*/ void l1pctl_pagc_ctrl(WORD8 *agc, UWORD8 *lna_off, UWORD16 radio_freq, UWORD8 serving_cell) { UWORD8 pb; WORD16 input_level, new_calibrated_IL; WORD32 freq_index; UWORD16 beacon_frequency; UWORD8 *lna_off_ptr; UWORD8 curve_id; // We memorize the LNA state used for other serving frequencies that can be used // in Packet idle mode static UWORD8 lna_off_others = 0; if (serving_cell == TRUE) { beacon_frequency = l1a_l1s_com.Scell_info.radio_freq; pb = l1a_l1s_com.Scell_info.pb; lna_off_ptr = &lna_off_others; curve_id = MAX_ID; } else { beacon_frequency = l1pa_l1ps_com.pbcchn.bcch_carrier; pb = l1pa_l1ps_com.pbcchn.pb; lna_off_ptr = lna_off; curve_id = AV_ID; } #if(L1_FF_MULTIBAND == 0) freq_index = beacon_frequency - l1_config.std.radio_freq_index_offset; #else freq_index = l1_multiband_radio_freq_convert_into_operative_radio_freq(beacon_frequency); #endif // If the downlink channel is decoded on the beacon frequency if (radio_freq == beacon_frequency) { // Downlink task on the serving beacon: process AGC according to the "beacon IL" input_level = l1a_l1s_com.last_input_level[freq_index].input_level; // lna_off already processed in the read phase *lna_off = l1a_l1s_com.last_input_level[freq_index].lna_off; } // If the downlink channel is decoded on a frequency other than the beacon else { // Process AGC according to "beacon IL + Pb" input_level = (WORD16) (l1a_l1s_com.last_input_level[freq_index].input_level + pb); // IL_2_AGC_xx array size if (input_level>INDEX_MAX) input_level = INDEX_MAX; // lna_off must be processed in the control phase because input_level // depends on last_input_level and Pb, and last_input_level or pb can have changed // at any time // New calibrated IL to reach on radio freq other than beacon new_calibrated_IL = (WORD16) (input_level - l1ctl_encode_delta1(radio_freq) - l1ctl_encode_delta2(radio_freq)); // IL_2_AGC_xx array size if (new_calibrated_IL>INDEX_MAX) new_calibrated_IL = INDEX_MAX; // lna_off computing... l1ctl_encode_lna((UWORD8)(new_calibrated_IL>>1), lna_off_ptr, radio_freq); *lna_off = *lna_off_ptr; } // End if "radio_freq != beacon_frequency" // Process AGC to apply *agc = Cust_get_agc_from_IL(radio_freq, input_level >> 1, curve_id); // Store lna_off and input_level field used for current CTRL in order to be able // to build IL from pm in READ phase. l1a_l1s_com.Scell_used_IL.input_level = (UWORD8)input_level; l1a_l1s_com.Scell_used_IL.lna_off = *lna_off; } // End of "l1pctl_pagc_ctrl" /*-------------------------------------------------------*/ /* l1pctl_pagc_read() */ /*-------------------------------------------------------*/ /* Description : */ /* =========== */ /* Based on the same principle as the one used for PAGC */ /* algorithm except that we also feed the beacon FIFO */ /* with IL measured on other carriers (Pb parameter is */ /* applied) */ /* This function is used in the read phase of PCCCH and */ /* serving PBCCH reading tasks to determine the IL value */ /* store it in the FIFO and find the next IL to use */ /* */ /* WARNING: in the layer 1 code, input levels IL(l1) use */ /* format 7.1: */ /* ********************* */ /* * IL(l1) = - 2 x IL * */ /* ********************* */ /* -> Reversed sign, reversed test conditions */ /* -> max replaced by min */ /* ex: if IL -120 dBm, IL(l1) = 240 */ /*-------------------------------------------------------*/ UWORD8 l1pctl_pagc_read(UWORD8 pm, UWORD16 radio_freq) { UWORD8 i, new_IL; WORD8 delta1_freq, delta2_freq; WORD16 delta_drp_gain=0; UWORD16 lna_value; WORD16 used_agc, current_IL, new_calibrated_IL, current_calibrated_IL; WORD32 serving_index; #if (RF_FAM == 61) UWORD16 arfcn; #endif UWORD8 lna_off; UWORD16 dco_algo_ctl_pw_temp = 0; UWORD8 if_ctl = 0; #if (RF_FAM == 61) && (CODE_VERSION != SIMULATION) UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; #endif #if (L1_FF_MULTIBAND == 0) serving_index = l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset; #else serving_index = l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.Scell_info.radio_freq); #endif /*if (L1_FF_MULTIBAND == 0)*/ // Calibration factors delta1_freq = l1ctl_encode_delta1(radio_freq); delta2_freq = l1ctl_encode_delta2(radio_freq); // AGC used in the control phase (format F7.1) used_agc = (Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.Scell_used_IL_dd.input_level >> 1, MAX_ID)) << 1; // LNA attenuation lna_value = l1a_l1s_com.Scell_used_IL_dd.lna_off * l1ctl_get_lna_att(radio_freq); #if (RF_FAM == 61) // DRP correction #if (L1_FF_MULTIBAND == 0) arfcn = Convert_l1_radio_freq(radio_freq); #else arfcn=radio_freq; #endif #if (CODE_VERSION != SIMULATION) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID , l1a_l1s_com.Scell_used_IL_dd.input_level, radio_freq,if_threshold); lna_off = l1a_l1s_com.Scell_used_IL_dd.lna_off; delta_drp_gain = drp_gain_correction(arfcn, lna_off, used_agc); // F7.1 format if(if_ctl == IF_100KHZ_DSP){ delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; } else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; } #endif #endif // current_IL processing if (0==pm) // Check and filter illegal pm value by using last valid IL { current_IL = l1a_l1s_com.last_input_level[serving_index].input_level - lna_value; } else { current_IL = -(pm - (used_agc - delta_drp_gain) + lna_value - l1ctl_get_g_magic(radio_freq)); // IL normalization to beacon (ILnorm = IL - Pb) if (radio_freq != l1a_l1s_com.Scell_info.radio_freq) current_IL -= l1a_l1s_com.Scell_info.pb; } // Calibrated IL processing // NOTE: calibrated_IL is normalized to beacon. This is needed for the // pccch_lev processing current_calibrated_IL = (WORD16) (current_IL - delta1_freq - delta2_freq); // Protect IL stores against overflow if (current_calibrated_IL>INDEX_MAX) current_calibrated_IL=INDEX_MAX; if (current_IL>INDEX_MAX) current_IL=INDEX_MAX; // FIFO management for (i=3;i>0;i--) l1a_l1s_com.Scell_info.buff_beacon[i] = l1a_l1s_com.Scell_info.buff_beacon[i-1]; l1a_l1s_com.Scell_info.buff_beacon[0] = (UWORD8)current_IL; // Find min IL in FIFO new_IL = l1ctl_find_max(l1a_l1s_com.Scell_info.buff_beacon, 4); // Input levels are always stored with lna_on new_calibrated_IL = (WORD16) (new_IL - delta1_freq - delta2_freq); if (new_calibrated_IL>INDEX_MAX) new_calibrated_IL = INDEX_MAX; l1ctl_encode_lna( (UWORD8)(new_calibrated_IL>>1), &(l1a_l1s_com.last_input_level[serving_index].lna_off), radio_freq ); l1a_l1s_com.last_input_level[serving_index].input_level = new_IL + l1a_l1s_com.last_input_level[serving_index].lna_off * l1ctl_get_lna_att(radio_freq); return((UWORD8)current_calibrated_IL); } // End of "l1pctl_pagc_read" /*-------------------------------------------------------*/ /* l1pctl_transfer_agc_init() */ /*-------------------------------------------------------*/ /* Description : */ /* =========== */ /* Packet transfer AGC algorithm initialization */ /*-------------------------------------------------------*/ void l1pctl_transfer_agc_init() { WORD16 calibrated_IL; UWORD16 radio_freq; WORD32 serving_index; WORD16 input_level; #if (L1_FF_MULTIBAND ==0) serving_index = l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset; #else serving_index = l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.Scell_info.radio_freq); #endif /*if L1_FF_MULTIBAND*/ // Daughter frequencies input level initialization //------------------------------------------------ if (l1pa_l1ps_com.transfer.aset->dl_pwr_ctl.p0 == 255) { // No power control mode AGC algorithm input_level = (WORD16) (l1a_l1s_com.last_input_level[serving_index].input_level + l1a_l1s_com.Scell_info.pb); // Set fn_select to current_fn l1ps.fn_select = l1s.actual_time.fn; // Initialize algorithm in "SEARCH" phase l1ps.phase = SEARCH; } else { // Downlink power control AGC algorithms if (l1pa_l1ps_com.transfer.aset->dl_pwr_ctl.bts_pwr_ctl_mode == 0) { // BTS Power control mode A input_level = (WORD16) (l1a_l1s_com.last_input_level[serving_index].input_level + l1pa_l1ps_com.transfer.aset->dl_pwr_ctl.p0 + 10); } else { // BTS power control mode B input_level = (WORD16) (l1a_l1s_com.last_input_level[serving_index].input_level + l1pa_l1ps_com.transfer.aset->dl_pwr_ctl.p0); // Initialization: PR = P0 l1ps.last_PR_good = l1pa_l1ps_com.transfer.aset->dl_pwr_ctl.p0; } } if (input_level>INDEX_MAX) input_level = INDEX_MAX; l1a_l1s_com.Scell_info.transfer_meas.input_level = (UWORD8)input_level; // Daughter frequencies lna_off processing //---------------------------------------- // We need to know on which frequency band we work if (!l1pa_l1ps_com.transfer.aset->freq_param.chan_sel.h) { // Single frequency radio_freq = l1pa_l1ps_com.transfer.aset->freq_param.chan_sel.rf_channel.single_rf.radio_freq; } else { // Frequency hopping: all frequencies of the frequency list are on the same band // We take the first frequency of the list radio_freq = l1pa_l1ps_com.transfer.aset->freq_param.freq_list.rf_chan_no.A[0]; } calibrated_IL = (WORD16) (l1a_l1s_com.Scell_info.transfer_meas.input_level - l1ctl_encode_delta1(radio_freq) - l1ctl_encode_delta2(radio_freq) - l1a_l1s_com.last_input_level[serving_index].lna_off * l1ctl_get_lna_att(radio_freq)); if (calibrated_IL>INDEX_MAX) calibrated_IL = INDEX_MAX; l1ctl_encode_lna((UWORD8)(calibrated_IL>>1), &(l1a_l1s_com.Scell_info.transfer_meas.lna_off), radio_freq); } // End of "l1pctl_transfer_agc_init" /*-------------------------------------------------------*/ /* l1pctl_transfer_agc_ctrl() */ /*-------------------------------------------------------*/ /* Description : */ /* =========== */ /* This function is used in the control phase of PDTCH/D */ /* to determine which AGC and lna_off must apply */ /*-------------------------------------------------------*/ void l1pctl_transfer_agc_ctrl(WORD8 *agc, UWORD8 *lna_off, UWORD16 radio_freq) { T_INPUT_LEVEL *selected_IL; #if(L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif // input_level selection if (radio_freq == l1a_l1s_com.Scell_info.radio_freq) { // Beacon frequency input_level used for AGC processing #if(L1_FF_MULTIBAND == 0) selected_IL = &l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset]; #else // L1_FF_MULTIBAND = 1 below operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.Scell_info.radio_freq); selected_IL = &(l1a_l1s_com.last_input_level[operative_radio_freq]); #endif // #if(L1_FF_MULTIBAND == 0) else } else { // Daughter frequency input_level used for AGC processing selected_IL = &l1a_l1s_com.Scell_info.transfer_meas; } *agc = Cust_get_agc_from_IL(radio_freq,selected_IL->input_level >> 1, MAX_ID); *lna_off = selected_IL->lna_off; // Store lna_off and input_level field used for current CTRL in order to be able // to build IL from pm in READ phase. l1a_l1s_com.Scell_used_IL.input_level = selected_IL->input_level; l1a_l1s_com.Scell_used_IL.lna_off = *lna_off; } /*-------------------------------------------------------*/ /* l1pctl_npc_agc_read() */ /*-------------------------------------------------------*/ /* Description : */ /* =========== */ /* AGC algorithm in packet transfer used when */ /* NO POWER CONTROL is done by the BTS. */ /* This function is used during the read phase of PDTCH: */ /* 1- to determine the IL value for each timeslot in each*/ /* TDMA */ /* 2- to find the IL value to use for the next PDCH */ /* block */ /* */ /* Algorithm */ /* --------- */ /* For each timeslot i used for PDCH */ /* IL(i) = fct(used AGC, pm) */ /* if (beacon) */ /* ILmax_beacon = max(ILmax_beacon, IL(i)) */ /* else */ /* ILmax_others(i) = max(IL(i), ILmax_others(i)) */ /* */ /* If (burst_nb == 3) */ /* If (ILmax_beacon was found during the block) */ /* FIFO[beacon] updated with ILmax_beacon */ /* transfer_meas = max(FIFO[beacon]) */ /* Reset ILmax_beacon */ /* */ /* For each timeslot i used for PDCH */ /* if (CRC good) */ /* ILmax_correct = max(ILmax_correct, */ /* ILmax_others(i)) */ /* else */ /* ILmax_not_correct = max(ILmax_not_correct, */ /* ILmax_others(i)) */ /* */ /* If (no ILmax_correct was found) */ /* ILselected = ILmax_correct */ /* FNselected = current FN */ /* else */ /* DeltaFN = (current FN - FNselected) % MAX_FN */ /* */ /* if (DeltaFN < 78) */ /* ILweighted = ILselected * (1 - DeltaFN/78) */ /* - 120 * DeltaFN /78 */ /* */ /* if (ILweighted < -120) ILweighted = -120 */ /* if (ILmax_not_correct > ILweighted) */ /* ILselected = ILmax_not_correct */ /* FNselected = current FN */ /* else */ /* ILselected = -120 */ /* FNselected = current FN */ /* */ /* Reset ILmax_others[8] */ /* */ /* WARNING: in the layer 1 code, input levels IL(l1) use */ /* format 7.1: */ /* ********************* */ /* * IL(l1) = - 2 x IL * */ /* ********************* */ /* -> Reversed sign, reversed test conditions */ /* -> max replaced by min */ /* ex: if IL -120 dBm, IL(l1) = 240 */ /* */ /* Parameters */ /* ---------- */ /* "calibrated_IL[8]" */ /* contains the IL found on timeslots */ /* used for PDCH/D. These ILs can be used to process */ /* RXLEV values. */ /* */ /* "*pdsp_db_r_ptr" */ /* Pointer on the DSP DB Read page, used to extract */ /* pm values, burst number and timeslot allocated */ /* for downlink PDCH */ /* */ /* "*pdsp_ndb_ptr" */ /* Pointer on the DSP NDB page, used to extract the */ /* CRC value for each decoded burst */ /* */ /* Global parameters */ /* ----------------- */ /* "l1a_l1s_com.Scell_info.transfer_meas.input_level" */ /* "l1a_l1s_com.Scell_info.transfer_meas.lna_off" */ /* Used to store the ILselected and the associated */ /* lna_off value. */ /* */ /* "l1a_l1s_com.Scell_info.fn_select" */ /* Used to store the FNselected value. */ /* */ /* "l1a_l1s_com.last_input_level[freq index] */ /* .input_level */ /* .lna_off" */ /* Used to store the beacon input level and */ /* the associated lna_off value. */ /* */ /* "l1ps.transfer_beacon_buf[4]" */ /* FIFO[beacon] */ /* */ /* "l1ps.ILmin_beacon" */ /* "l1ps.ILmin_others[8]" */ /*-------------------------------------------------------*/ void l1pctl_npc_agc_read(UWORD8 calibrated_IL[8], T_DB_DSP_TO_MCU_GPRS *pdsp_db_r_ptr, T_NDB_MCU_DSP_GPRS *pdsp_ndb_ptr) { UWORD8 ts; UWORD8 rx_no = 0; UWORD8 bit_mask = 0x80; UWORD8 ILmin_correct = 255; UWORD8 ILmin_not_correct = 255; WORD8 delta1_freq, delta2_freq; WORD16 delta_drp_gain=0; UWORD16 radio_freq, lna_value; WORD16 used_agc; WORD32 serving_index; #if (RF_FAM == 61) UWORD16 arfcn; #endif UWORD8 lna_off; UWORD16 dco_algo_ctl_pw_temp = 0; UWORD8 if_ctl = 0; #if (RF_FAM == 61) && (CODE_VERSION != SIMULATION) UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; #endif #if(L1_FF_MULTIBAND == 0) serving_index = l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset; #else serving_index = l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.Scell_info.radio_freq); #endif // Control phase parameters: same AGC, radio_freq, lna_off used for all PDTCH // *************************************************************************** // Get radio_freq on which the downlink block was received radio_freq = l1a_l1s_com.dedic_set.radio_freq_dd; // Compute calibration factors delta1_freq = l1ctl_encode_delta1(radio_freq); delta2_freq = l1ctl_encode_delta2(radio_freq); // AGC used in the control phase (format F7.1) used_agc = (Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.Scell_used_IL_dd.input_level >> 1, MAX_ID)) << 1; // LNA attenuation lna_value = l1a_l1s_com.Scell_used_IL_dd.lna_off * l1ctl_get_lna_att(radio_freq); // Burst 0: Reset ILmin_beacon and ILmin_others if(pdsp_db_r_ptr->d_burst_nb_gprs == 0) { l1ps.ILmin_beacon = 255; // Not valid for (ts = 0; ts < 8; ts++) { l1ps.ILmin_others[ts] = (UWORD8) l1_config.params.il_min; } } // End if "burst 0" // IL processing for each received burst // ************************************** // For each timeslot on which a burst was received for(ts = 0; ts < 8; ts ++) { if(pdsp_db_r_ptr->d_task_d_gprs & bit_mask) { WORD16 current_IL, current_calibrated_IL; UWORD8 pm; // IL = fct(pm, last_known_agc, lna_value, g_magic) //------------------------------------------------- pm = (UWORD8) ((pdsp_db_r_ptr->a_burst_pm_gprs[ts] & 0xffff) >> 5); // current_IL processing if (0==pm) // Check and filter illegal pm value by using last valid IL { if (radio_freq == l1a_l1s_com.Scell_info.radio_freq) current_IL = l1a_l1s_com.last_input_level[serving_index].input_level - lna_value; else current_IL = l1a_l1s_com.Scell_info.transfer_meas.input_level - lna_value; } else { #if (RF_FAM == 61) // DRP correction #if (L1_FF_MULTIBAND == 0) arfcn = Convert_l1_radio_freq(radio_freq); #else arfcn=radio_freq; #endif #if (CODE_VERSION != SIMULATION) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID , l1a_l1s_com.Scell_used_IL_dd.input_level, radio_freq,if_threshold); lna_off = l1a_l1s_com.Scell_used_IL_dd.lna_off; delta_drp_gain = drp_gain_correction(arfcn, lna_off, used_agc); // F7.1 format if(if_ctl == IF_100KHZ_DSP){ delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; } else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; } #endif #endif current_IL = -(pm - (used_agc - delta_drp_gain) + lna_value - l1ctl_get_g_magic(radio_freq)); } // Calibrated IL processing current_calibrated_IL = current_IL - delta1_freq - delta2_freq; // Protect IL stores against overflow if(current_calibrated_IL>INDEX_MAX) current_calibrated_IL=INDEX_MAX; if (current_IL>INDEX_MAX) current_IL=INDEX_MAX; calibrated_IL[ts] = (UWORD8)(current_calibrated_IL); // Keep ILmax if (radio_freq == l1a_l1s_com.Scell_info.radio_freq) { // Beacon frequency l1ps.ILmin_beacon = min((UWORD8) current_IL, l1ps.ILmin_beacon); } else { // Daughter frequency l1ps.ILmin_others[ts] = min((UWORD8) current_IL,l1ps.ILmin_others[ts]); } // Input Level selection among ILmax found on each timeslot during the block (when burst = 3) // ******************************************************************************************* if(pdsp_db_r_ptr->d_burst_nb_gprs == 3) { // If CRC good if (!(pdsp_ndb_ptr->a_dd_gprs[rx_no][0] & 0x0100)) { // Find the min found IL for blocks that were correctly received ILmin_correct = min(l1ps.ILmin_others[ts],ILmin_correct); } // If CRC bad else { // Find the min found IL for blocks that were not correctly received ILmin_not_correct = min(l1ps.ILmin_others[ts],ILmin_not_correct); } } // End if "burst = 3" // Next downlink block rx_no ++; } // End if "timeslot used for downlink PDCH" // Next timeslot bit_mask >>= 1; } // End for "each timeslot...." // IL selection for the next block if burst = 3 // ********************************************** if(pdsp_db_r_ptr->d_burst_nb_gprs == 3) { WORD16 new_calibrated_IL; // Beacon frequency input level updating //-------------------------------------- // If a PDCH has been received on the beacon if (l1ps.ILmin_beacon != 255) { UWORD8 i, new_IL; // FIFO management for (i=3;i>0;i--) l1a_l1s_com.Scell_info.buff_beacon[i] = l1a_l1s_com.Scell_info.buff_beacon[i-1]; l1a_l1s_com.Scell_info.buff_beacon[0] = l1ps.ILmin_beacon; // Find min IL in FIFO new_IL = l1ctl_find_max(l1a_l1s_com.Scell_info.buff_beacon, 4); // Input levels are always stored with lna_on // lna_off processing new_calibrated_IL = (WORD16) (new_IL - l1ctl_encode_delta1(l1a_l1s_com.Scell_info.radio_freq) - l1ctl_encode_delta2(l1a_l1s_com.Scell_info.radio_freq)); if (new_calibrated_IL>INDEX_MAX) new_calibrated_IL = INDEX_MAX; l1ctl_encode_lna((UWORD8)(new_calibrated_IL>>1), &(l1a_l1s_com.last_input_level[serving_index].lna_off), l1a_l1s_com.Scell_info.radio_freq); l1a_l1s_com.last_input_level[serving_index].input_level = new_IL + l1a_l1s_com.last_input_level[serving_index].lna_off * l1ctl_get_lna_att(l1a_l1s_com.Scell_info.radio_freq); } // End of "beacon frequency input level updating" // Daughter frequencies input level updating //------------------------------------------ // If at least one block was correctly received // (Note: ILs truncated to 240 so 255 isn't valid) if (ILmin_correct != 255) { // Select the min input level found on correctly received blocks l1a_l1s_com.Scell_info.transfer_meas.input_level = ILmin_correct; l1ps.fn_select = l1s.actual_time.fn; // Algorithm switch to "TRACK" phase if it was in "SEARCH" phase l1ps.phase = TRACK; } // No block was correctly received else { UWORD8 input_level_ref = l1a_l1s_com.Scell_info.transfer_meas.input_level - l1a_l1s_com.Scell_info.transfer_meas.lna_off * l1ctl_get_lna_att(radio_freq); // SEARCH phase if (l1ps.phase == SEARCH) { // If measured level superior to currently tracket level, switch to TRACK mode if (input_level_ref > ILmin_not_correct) l1ps.phase = TRACK; // Select the min input level found on badly received blocks l1a_l1s_com.Scell_info.transfer_meas.input_level = ILmin_not_correct; l1ps.fn_select = l1s.actual_time.fn; } // TRACK phase else { // If the IL found on incorrect block is lower than current wanted IL if (ILmin_not_correct < input_level_ref) { // Select the new IL l1a_l1s_com.Scell_info.transfer_meas.input_level = ILmin_not_correct; l1ps.fn_select = l1s.actual_time.fn; } // If the IL found on incorrect block is higher than current wanted IL else { UWORD32 delta_fn; // delta_fn processing for IL selection forgetting factor delta_fn = l1s.actual_time.fn - l1ps.fn_select; // MAX_FN modulo management if (l1s.actual_time.fn < l1ps.fn_select) delta_fn += MAX_FN; // If the last selected IL is more recent than 72 frames // // |....|R...............................C|....| // ^ ^ // fn_selected IL reset to -120 // <--------------------------------------> // 312 // 306 = 312 - 4 (block_size) - 1 (Read phase fn delay) - 1 (Control phase fn advance) if (delta_fn > 306) { WORD16 input_level; // IL initialized to "beacon level - Pb" input_level = (WORD16) ((l1a_l1s_com.last_input_level[serving_index].input_level + l1a_l1s_com.Scell_info.pb) - (l1a_l1s_com.last_input_level[serving_index].lna_off * l1ctl_get_lna_att(l1a_l1s_com.Scell_info.radio_freq))); if (input_level>INDEX_MAX) input_level = INDEX_MAX; l1a_l1s_com.Scell_info.transfer_meas.input_level = (UWORD8)input_level; l1ps.fn_select = l1s.actual_time.fn; // Returns to "SEARCH" phase l1ps.phase = SEARCH; } else { WORD16 input_level; input_level = l1a_l1s_com.Scell_info.transfer_meas.input_level - l1a_l1s_com.Scell_info.transfer_meas.lna_off * l1ctl_get_lna_att(l1ps.read_param.radio_freq_for_lna); if (input_level>INDEX_MAX) input_level = INDEX_MAX; l1a_l1s_com.Scell_info.transfer_meas.input_level = (UWORD8)input_level; } } // End if the IL found on incorrect block is higher than current wanted IL } // End of "track phase" } // End if no block correctly received // lna_off processing new_calibrated_IL = (WORD16) (l1a_l1s_com.Scell_info.transfer_meas.input_level - l1ctl_encode_delta1(l1ps.read_param.radio_freq_for_lna)); if (new_calibrated_IL>INDEX_MAX) new_calibrated_IL = INDEX_MAX; l1ctl_encode_lna((UWORD8)(new_calibrated_IL>>1), &(l1a_l1s_com.Scell_info.transfer_meas.lna_off), l1ps.read_param.radio_freq_for_lna); l1a_l1s_com.Scell_info.transfer_meas.input_level += l1a_l1s_com.Scell_info.transfer_meas.lna_off * l1ctl_get_lna_att(l1ps.read_param.radio_freq_for_lna); } // End if "burst = 3" } // End of "l1pctl_npc_agc_read" /*-------------------------------------------------------*/ /* l1pctl_dpcma_agc_read() */ /*-------------------------------------------------------*/ /* Description : */ /* =========== */ /* AGC algorithm in packet transfer used when the BTS */ /* use DOWNLINK POWER CONTROL mode A. */ /* This function is used during the read phase of PDTCH: */ /* 1- to determine the IL value for each timeslot in each*/ /* TDMA */ /* 2- to find the IL value to use for the next PDCH */ /* block */ /* */ /* Algorithm */ /* --------- */ /* For each timeslot i used for PDCH */ /* IL(i) = fct(used AGC, pm) */ /* if (beacon) */ /* ILmax_beacon = max(ILmax_beacon, IL(i)) */ /* else */ /* ILmax_others(i) = max(IL(i), ILmax_others(i)) */ /* */ /* If (burst_nb == 3) */ /* */ /* For each timeslot i used for PDCH */ /* if (CRC good) and */ /* ((PR_MODE A) or (PR_MODE B and TFI good)) */ /* ILmax = max(ILmax, ILmax_others(i) + P0 + PR(i))*/ /* */ /* ILmax=max(ILmax, ILmax_beacon) */ /* FIFO[beacon] updated with ILmax */ /* last_input_level[serving beacon] = max(FIFO[beacon])*/ /* transfer_meas = max(FIFO[beacon]) - P0 - 5 */ /* */ /* Reset ILmax_others[8] and ILmax_beacon */ /* */ /* WARNING: in the layer 1 code, input levels IL(l1) use */ /* format 7.1: */ /* ********************* */ /* * IL(l1) = - 2 x IL * */ /* ********************* */ /* -> Reversed sign, reversed test conditions */ /* -> max replaced by min */ /* ex: if IL -120 dBm, IL(l1) = 240 */ /* */ /* Parameters */ /* ---------- */ /* "calibrated_IL[8]" */ /* contains the IL found on timeslots */ /* used for PDCH/D. These ILs can be used to process */ /* RXLEV values. */ /* */ /* "*pdsp_db_r_ptr" */ /* Pointer on the DSP DB Read page, used to extract */ /* pm values, burst number and timeslot allocated */ /* for downlink PDCH */ /* */ /* "*pdsp_ndb_ptr" */ /* Pointer on the DSP NDB page, used to extract the */ /* CRC value for each decoded burst */ /* */ /* Global parameters */ /* ----------------- */ /* "l1a_l1s_com.Scell_info.transfer_meas.input_level" */ /* "l1a_l1s_com.Scell_info.transfer_meas.lna_off" */ /* Used to store the ILselected and the associated */ /* lna_off value. */ /* */ /* "l1a_l1s_com.last_input_level[freq. index] */ /* .input_level */ /* .lna_off" */ /* Used to store the beacon input level and */ /* the associated lna_off value. */ /* */ /* "l1ps.transfer_beacon_buf[4]" */ /* FIFO[beacon] */ /* */ /* "l1ps.ILmin_beacon" */ /* "l1ps.ILmin_others[8]" */ /*-------------------------------------------------------*/ void l1pctl_dpcma_agc_read(UWORD8 calibrated_IL[8], T_DB_DSP_TO_MCU_GPRS *pdsp_db_r_ptr, T_NDB_MCU_DSP_GPRS *pdsp_ndb_ptr, UWORD8 pr_table[8]) { UWORD8 ts = 0; UWORD8 rx_no = 0; UWORD8 bit_mask = 0x80; UWORD8 IL_norm_min = 255; WORD8 delta1_freq, delta2_freq; WORD16 delta_drp_gain=0; UWORD16 radio_freq, lna_value; WORD16 used_agc; WORD32 serving_index; #if (RF_FAM == 61) UWORD16 arfcn; #endif UWORD8 lna_off; UWORD16 dco_algo_ctl_pw_temp = 0; UWORD8 if_ctl = 0; #if (RF_FAM == 61) && (CODE_VERSION != SIMULATION) UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; #endif #if(L1_FF_MULTIBAND == 0) serving_index = l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset; #else serving_index = l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.Scell_info.radio_freq); #endif // Control phase parameters: same AGC, radio_freq, lna_off used for all PDTCH // *************************************************************************** // Get radio_freq on which the downlink block was received radio_freq = l1a_l1s_com.dedic_set.radio_freq_dd; // Compute calibration factors delta1_freq = l1ctl_encode_delta1(radio_freq); delta2_freq = l1ctl_encode_delta2(radio_freq); // Last known AGC (format F7.1) used_agc = (Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.Scell_used_IL_dd.input_level >> 1, MAX_ID)) << 1; // LNA attenuation lna_value = l1a_l1s_com.Scell_used_IL_dd.lna_off * l1ctl_get_lna_att(radio_freq); // Burst 0: Reset ILmin_beacon and ILmin_others if(pdsp_db_r_ptr->d_burst_nb_gprs == 0) { l1ps.ILmin_beacon = 255; // Not valid for (ts = 0; ts < 8; ts++) { l1ps.ILmin_others[ts] = 255; // Not valid } } // IL processing for each received burst // ************************************** #if (RF_FAM == 61) // DRP correction #if (L1_FF_MULTIBAND == 0) arfcn = Convert_l1_radio_freq(radio_freq); #else arfcn=radio_freq; #endif #if (CODE_VERSION != SIMULATION) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID , l1a_l1s_com.Scell_used_IL_dd.input_level, radio_freq, if_threshold); lna_off = l1a_l1s_com.Scell_used_IL_dd.lna_off; delta_drp_gain = drp_gain_correction(arfcn, lna_off, used_agc); // F7.1 format if(if_ctl == IF_100KHZ_DSP){ delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; } else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; } #endif #endif // For each timeslot on which a burst was received for(ts = 0; ts < 8; ts ++) { if(pdsp_db_r_ptr->d_task_d_gprs & bit_mask) { WORD16 current_IL, current_calibrated_IL; UWORD8 pm; // IL = fct(pm, last_known_agc, lna_value, g_magic) //------------------------------------------------- pm = (UWORD8) ((pdsp_db_r_ptr->a_burst_pm_gprs[ts] & 0xffff) >> 5); // current_IL processing if (0==pm) // Check and filter illegal pm value by using last valid IL { current_IL = l1a_l1s_com.last_input_level[serving_index].input_level - lna_value; if (radio_freq != l1a_l1s_com.Scell_info.radio_freq) current_IL += (l1ps.read_param.dl_pwr_ctl.p0 + 10); } else { current_IL = -(pm - (used_agc - delta_drp_gain) + lna_value - l1ctl_get_g_magic(radio_freq)); } // Calibrated IL processing current_calibrated_IL = current_IL - delta1_freq - delta2_freq; // Protect IL stores against overflow if(current_calibrated_IL>INDEX_MAX) current_calibrated_IL=INDEX_MAX; if (current_IL>INDEX_MAX) current_IL=INDEX_MAX; calibrated_IL[ts] = (UWORD8)(current_calibrated_IL); // Keep the minimum IL if (radio_freq == l1a_l1s_com.Scell_info.radio_freq) { // Beacon frequency l1ps.ILmin_beacon = min((UWORD8) current_IL,l1ps.ILmin_beacon); } else { // Daughter frequency l1ps.ILmin_others[ts] = min((UWORD8) current_IL, l1ps.ILmin_others[ts]); } // Input Level selection among ILmax found on each timeslot during the block (when burst = 3) //------------------------------------------------------------------------------------------- if(pdsp_db_r_ptr->d_burst_nb_gprs == 3) { // If CRC good if (!(pdsp_ndb_ptr->a_dd_gprs[rx_no][0] & 0x0100)) { // If ((PR_MODE A and TFI good) or (PR_MODE B)) AND PR != 0 [Not usable]) if (((l1ps.read_param.dl_pwr_ctl.pr_mode != 0) || (!(pr_table[ts] & 0x80))) && ((pr_table[ts] & 0x1f) != 0)) { if (l1ps.ILmin_others[ts] != 255) { UWORD8 IL_norm; // IL normalization to beacon (ILnorm = ILmax_others(ts) - P0 - PR) IL_norm = l1ps.ILmin_others[ts] - l1ps.read_param.dl_pwr_ctl.p0 - ((pr_table[ts] & 0x1f) << 1); // Update IL_min with the minimum found IL IL_norm_min = min(IL_norm, IL_norm_min); } } } // End if "CRC good" } // End if "burst = 3" // Next downlink block rx_no ++; } // End if "timeslot used for downlink PDCH" // Next timeslot bit_mask >>= 1; } // End for "each timeslot...." // IL selection for the next block if burst = 3 // ********************************************** if(pdsp_db_r_ptr->d_burst_nb_gprs == 3) { UWORD8 i, new_IL; UWORD16 input_level; WORD16 new_calibrated_IL; // Select the minimum IL between minimum IL found on daughter frequencies (normalized to beacon) // and minimum IL found on the beacon IL_norm_min = min(IL_norm_min, l1ps.ILmin_beacon); // If a valid IL has been found if (IL_norm_min != 255) { // FIFO management for (i=3;i>0;i--) l1a_l1s_com.Scell_info.buff_beacon[i] = l1a_l1s_com.Scell_info.buff_beacon[i-1]; l1a_l1s_com.Scell_info.buff_beacon[0] = IL_norm_min; // last_input_level[serving beacon] updating //------------------------------------------ // Find min IL in FIFO new_IL = l1ctl_find_max(l1a_l1s_com.Scell_info.buff_beacon,4); // Input levels are always stored with lna_on // lna_off processing new_calibrated_IL = (WORD16) (new_IL - l1ctl_encode_delta1(l1a_l1s_com.Scell_info.radio_freq) - l1ctl_encode_delta2(l1a_l1s_com.Scell_info.radio_freq)); if (new_calibrated_IL>INDEX_MAX) new_calibrated_IL = INDEX_MAX; l1ctl_encode_lna((UWORD8)(new_calibrated_IL >> 1), &(l1a_l1s_com.last_input_level[serving_index].lna_off), l1a_l1s_com.Scell_info.radio_freq); l1a_l1s_com.last_input_level[serving_index].input_level = new_IL + l1a_l1s_com.last_input_level[serving_index].lna_off * l1ctl_get_lna_att(l1a_l1s_com.Scell_info.radio_freq); } // transfer_meas updating //----------------------- // IL = (min IL in FIFO) + P0 + 10 (PR = 5 format 7.1) // Input levels are always stored with lna_on input_level = l1a_l1s_com.last_input_level[serving_index].input_level - l1a_l1s_com.last_input_level[serving_index].lna_off * l1ctl_get_lna_att(l1a_l1s_com.Scell_info.radio_freq) + l1ps.read_param.dl_pwr_ctl.p0 + 10; // IL_2_AGC_xx array size if (input_level>INDEX_MAX) input_level = INDEX_MAX; // lna_off processing new_calibrated_IL = (WORD16) (input_level - l1ctl_encode_delta1(l1ps.read_param.radio_freq_for_lna)); if (new_calibrated_IL>INDEX_MAX) new_calibrated_IL = INDEX_MAX; l1ctl_encode_lna((UWORD8)(new_calibrated_IL>>1), &(l1a_l1s_com.Scell_info.transfer_meas.lna_off), l1ps.read_param.radio_freq_for_lna); l1a_l1s_com.Scell_info.transfer_meas.input_level = input_level + l1a_l1s_com.Scell_info.transfer_meas.lna_off * l1ctl_get_lna_att(l1ps.read_param.radio_freq_for_lna); } // End if "burst = 3" } // End of "l1pctl_dpcma_agc_read" /*-------------------------------------------------------*/ /* l1pctl_dpcmb_agc_read() */ /*-------------------------------------------------------*/ /* Description : */ /* =========== */ /* AGC algorithm in packet transfer used when the BTS */ /* use DOWNLINK POWER CONTROL mode B. */ /* This function is used during the read phase of PDTCH: */ /* 1- to determine the IL value for each timeslot in each*/ /* TDMA */ /* 2- to find the IL value to use for the next PDCH */ /* block */ /* */ /* Algorithm */ /* --------- */ /* For each timeslot i used for PDCH */ /* IL(i) = fct(used AGC, pm) */ /* if (beacon) */ /* ILmax_beacon = max(ILmax_beacon, IL(i)) */ /* else */ /* ILmax_others(i) = max(IL(i), ILmax_others(i)) */ /* */ /* If (burst_nb == 3) */ /* */ /* For each timeslot i used for PDCH */ /* if (CRC good) */ /* if (TFI good) last_PR_good = PR(i) */ /* if ((PR_MODE A) or (PR_MODE B and TFI good)) */ /* ILmax = max(ILmax, ILmax_others(i) */ /* + P0 + PR(i)) */ /* */ /* ILmax=max(ILmax, ILmax_beacon) */ /* FIFO[beacon] updated with ILmax */ /* last_input_level[serving beacon] = max(FIFO[beacon])*/ /* transfer_meas = max(FIFO[beacon]) - last_PR_good */ /* */ /* Reset ILmax_others[8] and ILmax_beacon */ /* */ /* WARNING: in the layer 1 code, input levels IL(l1) use */ /* format 7.1: */ /* ********************* */ /* * IL(l1) = - 2 x IL * */ /* ********************* */ /* -> Reversed sign, reversed test conditions */ /* -> max replaced by min */ /* ex: if IL -120 dBm, IL(l1) = 240 */ /* */ /* Parameters */ /* ---------- */ /* "calibrated_IL[8]" */ /* contains the IL found on timeslots */ /* used for PDCH/D. These ILs can be used to process */ /* RXLEV values. */ /* */ /* "*pdsp_db_r_ptr" */ /* Pointer on the DSP DB Read page, used to extract */ /* pm values, burst number and timeslot allocated */ /* for downlink PDCH */ /* */ /* "*pdsp_ndb_ptr" */ /* Pointer on the DSP NDB page, used to extract the */ /* CRC value for each decoded burst */ /* */ /* Global parameters */ /* ----------------- */ /* "l1a_l1s_com.Scell_info.transfer_meas.input_level" */ /* "l1a_l1s_com.Scell_info.transfer_meas.lna_off" */ /* Used to store the ILselected and the associated */ /* lna_off value. */ /* */ /* "l1a_l1s_com.last_input_level[freq. index] */ /* .input_level */ /* .lna_off" */ /* Used to store the beacon input level and */ /* the associated lna_off value. */ /* */ /* "l1ps.transfer_beacon_buf[4]" */ /* FIFO[beacon] */ /* */ /* "l1ps.ILmin_beacon" */ /* "l1ps.ILmin_others[8]" */ /*-------------------------------------------------------*/ void l1pctl_dpcmb_agc_read(UWORD8 calibrated_IL[8], T_DB_DSP_TO_MCU_GPRS *pdsp_db_r_ptr, T_NDB_MCU_DSP_GPRS *pdsp_ndb_ptr, UWORD8 pr_table[8]) { UWORD8 ts = 0; UWORD8 rx_no = 0; UWORD8 bit_mask = 0x80; UWORD8 IL_norm_min = 255; WORD8 delta1_freq, delta2_freq; WORD16 delta_drp_gain=0; UWORD16 radio_freq, lna_value; WORD16 used_agc; WORD32 serving_index; #if (RF_FAM == 61) UWORD16 arfcn; #endif UWORD8 lna_off; UWORD16 dco_algo_ctl_pw_temp = 0; UWORD8 if_ctl = 0; #if (RF_FAM == 61) && (CODE_VERSION != SIMULATION) UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; #endif #if(L1_FF_MULTIBAND == 0) serving_index = l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset; #else serving_index = l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.Scell_info.radio_freq); #endif // Control phase parameters: same AGC, radio_freq, lna_off used for all PDTCH // *************************************************************************** // Get radio_freq on which the downlink block was received radio_freq = l1a_l1s_com.dedic_set.radio_freq_dd; // Compute calibration factors delta1_freq = l1ctl_encode_delta1(radio_freq); delta2_freq = l1ctl_encode_delta2(radio_freq); // Last known AGC (format F7.1) used_agc = (Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.Scell_used_IL_dd.input_level >> 1, MAX_ID)) << 1; // LNA attenuation lna_value = l1a_l1s_com.Scell_used_IL_dd.lna_off * l1ctl_get_lna_att(radio_freq); // Burst 0: Reset ILmin_beacon and ILmin_others if(pdsp_db_r_ptr->d_burst_nb_gprs == 0) { l1ps.ILmin_beacon = 255; // Not valid for (ts = 0; ts < 8; ts++) { l1ps.ILmin_others[ts] = 255; // Not valid } } // IL processing for each received burst // ************************************** // For each timeslot on which a burst was received for(ts = 0; ts < 8; ts ++) { if(pdsp_db_r_ptr->d_task_d_gprs & bit_mask) { WORD16 current_IL, current_calibrated_IL; UWORD8 pm; // IL = fct(pm, last_known_agc, lna_value, g_magic) //------------------------------------------------- pm = (UWORD8) ((pdsp_db_r_ptr->a_burst_pm_gprs[ts] & 0xffff) >> 5); // current_IL processing if (0==pm) // Check and filter illegal pm value by using last valid IL { current_IL = l1a_l1s_com.last_input_level[serving_index].input_level - lna_value; if (radio_freq != l1a_l1s_com.Scell_info.radio_freq) current_IL += (l1ps.last_PR_good); } else { #if (RF_FAM == 61) // DRP correction #if (L1_FF_MULTIBAND == 0) arfcn = Convert_l1_radio_freq(radio_freq); #else arfcn=radio_freq; #endif #if (CODE_VERSION != SIMULATION) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID , l1a_l1s_com.Scell_used_IL_dd.input_level, radio_freq, if_threshold); lna_off = l1a_l1s_com.Scell_used_IL_dd.lna_off; delta_drp_gain = drp_gain_correction(arfcn, lna_off, used_agc); // F7.1 format if(if_ctl == IF_100KHZ_DSP){ delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; } else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; } #endif #endif current_IL = -(pm - ( used_agc - delta_drp_gain) + lna_value - l1ctl_get_g_magic(radio_freq)); } // Calibrated IL processing current_calibrated_IL = current_IL - delta1_freq - delta2_freq; // Protect IL stores against overflow if(current_calibrated_IL>INDEX_MAX) current_calibrated_IL=INDEX_MAX; if (current_IL>INDEX_MAX) current_IL=INDEX_MAX; calibrated_IL[ts] = (UWORD8)(current_calibrated_IL); // Keep the minimum IL if (radio_freq == l1a_l1s_com.Scell_info.radio_freq) { // Beacon frequency l1ps.ILmin_beacon = min((UWORD8) current_IL,l1ps.ILmin_beacon); } else { // Daughter frequency l1ps.ILmin_others[ts] = min((UWORD8) current_IL, l1ps.ILmin_others[ts]); } // Input Level selection among ILmax found on each timeslot during the block (when burst = 3) //------------------------------------------------------------------------------------------- if(pdsp_db_r_ptr->d_burst_nb_gprs == 3) { // If CRC good if (!(pdsp_ndb_ptr->a_dd_gprs[rx_no][0] & 0x0100)) { // If ((PR_MODE A and TFI good) or (PR_MODE B)) if ((l1ps.read_param.dl_pwr_ctl.pr_mode != 0) || (!(pr_table[ts] & 0x80))) { // If TFI good if (!(pr_table[ts] & 0x80)) { // Memorize decoded PR l1ps.last_PR_good = ((pr_table[ts] & 0x1f) << 1); } if (l1ps.ILmin_others[ts] != 255) { UWORD8 IL_norm; // IL normalization to beacon (ILnorm = ILmax_others(ts) - PR) IL_norm = l1ps.ILmin_others[ts] - ((pr_table[ts] & 0x1f) << 1); // Update IL_min with the minimum found IL IL_norm_min = min(IL_norm, IL_norm_min); } } } // End if "CRC good" } // End if "burst = 3" // Next downlink block rx_no ++; } // End if "timeslot used for downlink PDCH" // Next timeslot bit_mask >>= 1; } // End for "each timeslot...." // IL selection for the next block if burst = 3 // ********************************************** if(pdsp_db_r_ptr->d_burst_nb_gprs == 3) { UWORD8 i, new_IL; UWORD16 input_level; WORD16 new_calibrated_IL; // Select the minimum IL between minimum IL found on daughter frequencies (normalized to beacon) // and minimum IL found on the beacon IL_norm_min = min(IL_norm_min, l1ps.ILmin_beacon); // If a valid IL has been found if (IL_norm_min != 255) { // FIFO management for (i=3;i>0;i--) l1a_l1s_com.Scell_info.buff_beacon[i] = l1a_l1s_com.Scell_info.buff_beacon[i-1]; l1a_l1s_com.Scell_info.buff_beacon[0] = IL_norm_min; // last_input_level[serving beacon] updating //------------------------------------------ // Find min IL in FIFO new_IL = l1ctl_find_max(l1a_l1s_com.Scell_info.buff_beacon,4); // Input levels are always stored with lna_on // lna_off processing new_calibrated_IL = (WORD16) (new_IL - l1ctl_encode_delta1(l1a_l1s_com.Scell_info.radio_freq) - l1ctl_encode_delta2(l1a_l1s_com.Scell_info.radio_freq)); if (new_calibrated_IL>INDEX_MAX) new_calibrated_IL = INDEX_MAX; l1ctl_encode_lna((UWORD8)(new_calibrated_IL >> 1), &(l1a_l1s_com.last_input_level[serving_index].lna_off), l1a_l1s_com.Scell_info.radio_freq); l1a_l1s_com.last_input_level[serving_index].input_level = new_IL + l1a_l1s_com.last_input_level[serving_index].lna_off * l1ctl_get_lna_att(l1a_l1s_com.Scell_info.radio_freq); } // transfer_meas updating //----------------------- // IL = (min IL in FIFO) + PR (Middle of the range specified by the last decoded PR with CRC and TFI good) // Input levels are always stored with lna_on input_level = l1a_l1s_com.last_input_level[serving_index].input_level - l1a_l1s_com.last_input_level[serving_index].lna_off * l1ctl_get_lna_att(l1a_l1s_com.Scell_info.radio_freq) + l1ps.last_PR_good; // IL_2_AGC_xx array size if (input_level>INDEX_MAX) input_level = INDEX_MAX; // lna_off processing new_calibrated_IL = (WORD16) (input_level - l1ctl_encode_delta1(l1ps.read_param.radio_freq_for_lna)); if (new_calibrated_IL>INDEX_MAX) new_calibrated_IL = INDEX_MAX; l1ctl_encode_lna((UWORD8)(new_calibrated_IL>>1), &(l1a_l1s_com.Scell_info.transfer_meas.lna_off), l1ps.read_param.radio_freq_for_lna); l1a_l1s_com.Scell_info.transfer_meas.input_level = input_level + l1a_l1s_com.Scell_info.transfer_meas.lna_off * l1ctl_get_lna_att(l1ps.read_param.radio_freq_for_lna); } // End if "burst = 3" } // End of "l1pctl_dpcmb_agc_read" /*-------------------------------------------------------*/ /* l1pctl_pgc() */ /*-------------------------------------------------------*/ /* Description : */ /* ============= */ /* This function is used in packet transfer mode for the*/ /* Read phase of power measurements. It permits to: */ /* - Process the IL value in function of the Pm and AGC */ /* used */ /* - Update the FIFO[beacon] used in packet transfer AGC*/ /* algorithms */ /* - Update last_input_level */ /* */ /* WARNING: in the layer 1 code, input levels IL(l1) use */ /* format 7.1: */ /* ********************* */ /* * IL(l1) = - 2 x IL * */ /* ********************* */ /* -> Reversed sign, reversed test conditions */ /* -> max replaced by min */ /* ex: if IL -120 dBm, IL(l1) = 240 */ /*-------------------------------------------------------*/ UWORD8 l1pctl_pgc(UWORD8 pm, UWORD8 last_known_il, UWORD8 lna_off, UWORD16 radio_freq) { UWORD8 i, new_IL; WORD8 delta1_freq, delta2_freq; WORD16 delta_drp_gain=0; UWORD16 lna_value; WORD16 used_agc, current_IL, current_calibrated_IL, new_calibrated_IL; WORD32 index; #if (RF_FAM == 61) UWORD16 arfcn; #endif UWORD16 dco_algo_ctl_pw_temp = 0; UWORD8 if_ctl = 0; #if (RF_FAM == 61) && (CODE_VERSION != SIMULATION) UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; #endif // Calibration factors delta1_freq = l1ctl_encode_delta1(radio_freq); delta2_freq = l1ctl_encode_delta2(radio_freq); // initialize index #if(L1_FF_MULTIBAND == 0) index = radio_freq - l1_config.std.radio_freq_index_offset; #else index = l1_multiband_radio_freq_convert_into_operative_radio_freq(radio_freq); #endif // LNA attenuation lna_value = lna_off * l1ctl_get_lna_att(radio_freq); // Used AGC in the control phase (format F7.1) used_agc = (Cust_get_agc_from_IL(radio_freq, last_known_il >> 1, PWR_ID)) << 1; #if (RF_FAM == 61) // DRP correction #if (L1_FF_MULTIBAND == 0) arfcn = Convert_l1_radio_freq(radio_freq); #else arfcn=radio_freq; #endif #if (CODE_VERSION != SIMULATION) #if (PWMEAS_IF_MODE_FORCE == 0) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID , last_known_il, radio_freq, if_threshold); #else if_ctl = IF_120KHZ_DSP; dco_algo_ctl_pw_temp = DCO_IF_0KHZ; #endif lna_off = l1a_l1s_com.Scell_used_IL_dd.lna_off; delta_drp_gain = drp_gain_correction(arfcn, lna_off, used_agc); // F7.1 format if(if_ctl == IF_100KHZ_DSP){ delta_drp_gain += SCF_ATTENUATION_LIF_100KHZ; } else{ /* i.e. if_ctl = IF_120KHZ_DSP*/ delta_drp_gain += SCF_ATTENUATION_LIF_120KHZ; } #endif #endif if (0==pm) // Check and filter illegal pm value by using last valid IL current_IL = l1a_l1s_com.last_input_level[index].input_level - lna_value; else current_IL = -(pm - (used_agc - delta_drp_gain) + lna_value - l1ctl_get_g_magic(radio_freq)); // Calibrated IL processing current_calibrated_IL = current_IL - delta1_freq - delta2_freq; // Protect IL stores against overflow if (current_calibrated_IL>INDEX_MAX) current_calibrated_IL=INDEX_MAX; if (current_IL>INDEX_MAX) current_IL=INDEX_MAX; // if radio freq is the serving beacon //------------------------------------ if (radio_freq == l1a_l1s_com.Scell_info.radio_freq) { // FIFO management for (i=3;i>0;i--) l1a_l1s_com.Scell_info.buff_beacon[i] = l1a_l1s_com.Scell_info.buff_beacon[i-1]; l1a_l1s_com.Scell_info.buff_beacon[0] = (UWORD8) current_IL; // Find min IL in FIFO new_IL = l1ctl_find_max(l1a_l1s_com.Scell_info.buff_beacon,4); // lna_off processing new_calibrated_IL = (WORD16) (new_IL - delta1_freq - delta2_freq); if (new_calibrated_IL>INDEX_MAX) new_calibrated_IL = INDEX_MAX; l1ctl_encode_lna((UWORD8)(new_calibrated_IL>>1), &(l1a_l1s_com.last_input_level[index].lna_off), radio_freq); l1a_l1s_com.last_input_level[index].input_level = new_IL + l1a_l1s_com.last_input_level[index].lna_off * l1ctl_get_lna_att(radio_freq); } // if radio freq is a neighbor beacon //----------------------------------- else { // Update last_input_level (IL with LNA ON) l1ctl_encode_lna((UWORD8)(current_calibrated_IL>>1), &(l1a_l1s_com.last_input_level[index].lna_off), radio_freq); l1a_l1s_com.last_input_level[index].input_level = current_IL + l1a_l1s_com.last_input_level[index].lna_off * l1ctl_get_lna_att(radio_freq); } return((UWORD8)current_calibrated_IL); } // End of "l1pctl_pgc" #endif