FreeCalypso > hg > fc-magnetite
view src/cs/layer1/p_cfile/l1p_cmpl.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_CMPL.C * * Filename l1p_cmpl.c * Copyright 2003 (C) Texas Instruments * ************* Revision Controle System Header *************/ #define L1P_CMPL_C //#pragma DUPLICATE_FOR_INTERNAL_RAM_START #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_tabs.h" #include "l1_trace.h" #if L2_L3_SIMUL #include "l2_l3.h" #include "hw_debug.h" #endif #include "l1p_cons.h" #include "l1p_msgt.h" #include "l1p_deft.h" #include "l1p_vare.h" #include "l1p_sign.h" #if TESTMODE #include "l1tm_msgty.h" #include "l1tm_signa.h" #endif #include "macs_def.h" #include "macs_cst.h" #include "sim_cons.h" #include "sim_def.h" extern T_hw FAR hw; #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 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_tabs.h" #include "l1_trace.h" #if L2_L3_SIMUL #include "l2_l3.h" #include "hw_debug.h" #endif #include "l1p_cons.h" #include "l1p_msgt.h" #include "l1p_deft.h" #include "l1p_vare.h" #include "l1p_sign.h" #if TESTMODE #include "l1tm_msgty.h" #include "l1tm_signa.h" #endif #include "macs_def.h" #include "macs_cst.h" #endif #if(RF_FAM == 61) #include "l1_rf61.h" #include "tpudrv61.h" #endif #include "l1_ctl.h" /*-------------------------------------------------------*/ /* Prototypes of external functions used in this file. */ /*-------------------------------------------------------*/ void l1dmacro_synchro (UWORD32 when, UWORD32 value); void l1dmacro_offset (UWORD32 offset_value, WORD32 relative_time); void l1dmacro_rx_synth (UWORD16 arfcn); void l1dmacro_agc (UWORD16 arfcn,WORD8 gain, UWORD8 lna #if (RF_FAM == 61) ,UWORD8 if_ctl #endif ); #if (L1_MADC_ON == 1) #if (RF_FAM == 61) void l1dmacro_rx_nb (UWORD16 arfcn, UWORD8 adc_active, UWORD8 csf_filter_choice #if (NEW_SNR_THRESHOLD == 1) ,UWORD8 saic_flag #endif /* NEW_SNR_THRESHOLD */ ); #endif /* RF_FAM == 61*/ #else /* L1_MADC_ON == 1*/ void l1dmacro_rx_nb (UWORD16 arfcn); #endif /* L1_MADC_ON == 1*/ void l1dmacro_afc (UWORD16 afc_value, UWORD8 win_id); #if (RF_FAM == 61) void l1dtpu_serv_rx_nb (UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off, UWORD32 synchro_serv,UWORD32 new_offset,BOOL change_offset, UWORD8 adc_active, UWORD8 csf_filter_choice, UWORD8 if_ctl #if (NEW_SNR_THRESHOLD == 1) ,UWORD8 saic_flag #endif /* NEW_SNR_THRESHOLD */ ); void l1pdtpu_serv_rx_nb (UWORD16 radio_freq, WORD8 agc, BOOL lna_off, UWORD8 rx_id, UWORD32 offset_serv, UWORD8 num_rx, UWORD8 rx_group_id, BOOL rx_done_flag, UWORD8 adc_active, UWORD8 csf_filter_choice, UWORD8 if_ctl #if (NEW_SNR_THRESHOLD == 1) ,UWORD8 saic_flag #endif /* NEW_SNR_THRESHOLD */ ); #endif /* RF_FAM == 61*/ #if(RF_FAM != 61) void l1dtpu_serv_rx_nb (UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off, UWORD32 synchro_serv,UWORD32 new_offset,BOOL change_offset, UWORD8 adc_active); void l1pdtpu_serv_rx_nb (UWORD16 radio_freq, WORD8 agc, BOOL lna_off, UWORD8 rx_id, UWORD32 offset_serv, UWORD8 num_rx, UWORD8 rx_group_id, BOOL rx_done_flag,UWORD8 adc_active); #endif void l1pdtpu_serv_tx (UWORD16 radio_freq, UWORD8 timing_advance, UWORD32 offset_serv, UWORD8 tx_id, UWORD8 num_tx, UWORD8 tx_group_id, UWORD8 switch_flag, BOOL burst_type, BOOL rx_flag,UWORD8 adc_active); UWORD8 l1pdtpu_interf_meas (UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off, UWORD8 meas_bitmap, UWORD32 offset_serv, UWORD16 win_id, UWORD8 synchro_ts #if(RF_FAM == 61) ,UWORD8 if_ctl #endif ); void l1s_read_l3frm (UWORD8 pwr_level, API *info_address, UWORD32 task_rx); void l1ps_macs_read (UWORD8 pr_table[8]); void l1ps_macs_ctrl (void); #if TESTMODE void l1ps_tmode_macs_ctrl (void); #endif void l1pddsp_transfer_mslot_power (UWORD8 *txpwr, UWORD16 radio_freq, UWORD8 ul_bitmap); void l1pddsp_single_tx_block (UWORD8 burst_nb, UWORD8 *data, UWORD8 tsc, UWORD16 radio_freq); void l1pddsp_idle_prach_data (BOOL polling, UWORD8 cs_type, UWORD16 channel_request_data, UWORD8 bsic, UWORD16 radio_freq); void l1pddsp_idle_prach_power (UWORD8 txpwr, UWORD16 radio_freq, UWORD8 ts); #if FF_L1_IT_DSP_USF void l1pddsp_idle_rx_nb (UWORD8 burst_nb, UWORD8 tsq, UWORD16 radio_freq, UWORD8 timeslot_no, BOOL ptcch_dl, BOOL usf_interrupt); #else void l1pddsp_idle_rx_nb (UWORD8 burst_nb, UWORD8 tsq, UWORD16 radio_freq, UWORD8 timeslot_no, BOOL ptcch_dl); #endif void l1pddsp_ul_ptcch_data (UWORD8 cs_type, UWORD16 channel_request_data, UWORD8 bsic, UWORD16 radio_freq, UWORD8 timeslot_no); void l1ps_tcr_ctrl (UWORD8 pm_position); void l1pd_afc (void); void l1pddsp_interf_meas_ctrl (UWORD8 nb_meas_req); void l1pddsp_meas_ctrl (UWORD8 nbmeas, UWORD8 pm_pos); void maca_power_control (UWORD8 assignment_id, BOOL crc_error, WORD8 bcch_level, UWORD16 *radio_freq, WORD8 *burst_level, UWORD8 *pch); WORD16 l1s_encode_rxlev (UWORD8 inlevel); void l1pctl_pagc_ctrl (WORD8 *agc, UWORD8 *lna_off, UWORD16 radio_freq,UWORD8 serving_cell); UWORD8 l1pctl_pagc_read (UWORD8 pm, UWORD16 radio_freq); void l1pctl_transfer_agc_ctrl (WORD8 *agc, UWORD8 *lna_off, UWORD16 radio_freq); 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); 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]); 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]); void l1ps_macs_header_decoding (UWORD8 rx_no, UWORD8 *tfi_result, UWORD8 *pr); void l1ps_update_read_set_parameters(void); void l1ps_bcch_meas_ctrl (UWORD8 ts); //#pragma DUPLICATE_FOR_INTERNAL_RAM_END /*-------------------------------------------------------*/ /* l1ps_ctrl_single() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* */ /* Input parameters: */ /* ----------------- */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* */ /*-------------------------------------------------------*/ void l1ps_ctrl_single(UWORD8 task, UWORD8 burst_id) { UWORD16 radio_freq; T_INPUT_LEVEL *IL_info_ptr; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; // By default we choose the hardware filter UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER; #endif #if (NEW_SNR_THRESHOLD == 1) UWORD8 saic_flag=0; #endif /* NEW_SNR_THRESHOLD */ // needs to be defined for maca_power_control() function call #define DL_pwr_ctrl l1pa_l1ps_com.transfer.dl_pwr_ctrl if((l1a_l1s_com.l1s_en_task[task] == TASK_ENABLED) && !(l1a_l1s_com.task_param[task] == SEMAPHORE_SET)) // Check the task semaphore. The control body is executed only // when the task semaphore is 0. This semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. { // Catch ARFCN. // ************* // Get ARFCN to be used for current control. radio_freq = l1a_l1s_com.dedic_set.radio_freq; // Traces and debug. // ****************** #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[task].name); if(burst_id == BURST_1) trace_flowchart_dsptx(dltsk_trace[task].name); #endif #if (TRACE_TYPE!=0) if (l1pa_l1ps_com.transfer.single_block.activity & (SINGLE_DL | SINGLE_UL)) // trace only if a window is programmed trace_fct(CST_L1PS_CTRL_SINGLE, radio_freq); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; /**************************************************************************/ /* Program DSP for mulstislot operation... */ /**************************************************************************/ /*===============*/ /* Downlink */ /*===============*/ if(l1pa_l1ps_com.transfer.single_block.activity & SINGLE_DL) { // Programs DSP. #if FF_L1_IT_DSP_USF l1pddsp_idle_rx_nb(burst_id, l1pa_l1ps_com.transfer.aset->tsc, radio_freq, 0, FALSE, FALSE); #else l1pddsp_idle_rx_nb(burst_id, l1pa_l1ps_com.transfer.aset->tsc, radio_freq, 0, FALSE); #endif // Flag DSP programmation. // Set "CTRL_RX" flag in the controle flag registers. l1s.dsp_ctrl_reg |= CTRL_RX; } /*===============*/ /* Uplink */ /*===============*/ if(l1pa_l1ps_com.transfer.single_block.activity & SINGLE_UL) { // Pgme DSP for Single block TX on TS=3. l1pddsp_single_tx_block (burst_id, l1pa_l1ps_com.transfer.single_block.data_array, l1pa_l1ps_com.transfer.aset->tsc, radio_freq); // TXPWR control needs to take into account ALPHA, GAMMA and C values, not only TXPWR MAX // => maca_power_control() needs to be called // Initialization of txpwr control values for all time slots { UWORD8 txpwr[8]; UWORD8 i; // Call Uplink Transmit Power level algorithm #if 0 /* LoCosto version */ maca_power_control(l1pa_l1ps_com.transfer.aset->assignment_id, #else /* TCS211 reconstruction */ maca_power_control(DL_pwr_ctrl.assignment_id, #endif DL_pwr_ctrl.crc_error, DL_pwr_ctrl.bcch_level, DL_pwr_ctrl.radio_freq_tbl, DL_pwr_ctrl.burst_level, txpwr); for(i = 0; i < 8; i++) { l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr[i] = txpwr[i]; } } // Pgme DSP for Transmit power on TS=3. l1pddsp_transfer_mslot_power(l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr, radio_freq, 0x80 >> 3); // Flag DSP programmation. // Set "CTRL_TX" flag in the controle flag registers. l1s.dsp_ctrl_reg |= CTRL_TX; } /**************************************************************************/ /* Program TPU for single slot operation... */ /**************************************************************************/ /*===============*/ /* Downlink */ /*===============*/ if(l1pa_l1ps_com.transfer.single_block.activity & SINGLE_DL) { WORD8 agc; UWORD8 lna_off; // Update AGC l1pctl_transfer_agc_ctrl(&agc, &lna_off, radio_freq); #if (RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID, l1a_l1s_com.Scell_used_IL.input_level , radio_freq, if_threshold); l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function // NOTE: l1a_l1s_com.Scell_used_IL.input_level is updated within // the l1pctl_transfer_agc_ctrl above csf_filter_choice = l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode #if (NEW_SNR_THRESHOLD == 1) ,task ,&saic_flag #endif ); #endif // tpu pgm... l1pdtpu_serv_rx_nb(radio_freq, agc, lna_off, 0, l1s.tpu_offset, 1, 1, TRUE, INACTIVE, csf_filter_choice, if_ctl #if (NEW_SNR_THRESHOLD == 1) ,saic_flag #endif /* NEW_SNR_THRESHOLD */ ); #endif /* RF_FAM == 61*/ #if (RF_FAM != 61) // tpu pgm... #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function // NOTE: l1a_l1s_com.Scell_used_IL.input_level is updated within // the l1pctl_transfer_agc_ctrl above l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode #if (NEW_SNR_THRESHOLD == 1) ,task #endif ); #endif l1pdtpu_serv_rx_nb(radio_freq, agc, lna_off, 0, l1s.tpu_offset, 1, 1, TRUE, INACTIVE); #endif // Set tpu window identifier for Synthesizer and // according to last RX group position. l1s.tpu_win = l1_config.params.rx_synth_load_split + RX_SPLIT_TABLE[0]; // Flag TPU programmation. // Set "CTRL_RX" flag in the controle flag registers. l1s.tpu_ctrl_reg |= CTRL_RX; } /*===============*/ /* Uplink */ /*===============*/ if(l1pa_l1ps_com.transfer.single_block.activity & SINGLE_UL) { // Program single block UL slot. // ****************************** l1pdtpu_serv_tx(radio_freq, l1pa_l1ps_com.transfer.aset->packet_ta.ta, l1s.tpu_offset, 3, 1, 1, 0, TX_NB_BURST, l1pa_l1ps_com.transfer.single_block.activity & SINGLE_DL, INACTIVE); // Set tpu window identifier for Synthesizer and // according to last TX group position. l1s.tpu_win =(UWORD16)( (l1_config.params.rx_synth_load_split) + ((UWORD16)3 * BP_SPLIT) + l1_config.params.tx_nb_load_split); // Flag TPU programmation. // Set "CTRL_TX" flag in the controle flag registers. l1s.tpu_ctrl_reg |= CTRL_TX; #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_NB(task, l1pa_l1ps_com.transfer.aset->packet_ta.ta, l1s.applied_txpwr) #endif } /*===============*/ /* General */ /*===============*/ if(burst_id == BURST_4) { // Single block UL is now complete, reset its activity flag. l1pa_l1ps_com.transfer.single_block.activity &= SINGLE_UL_MASK; if(l1pa_l1ps_com.transfer.aset->allocated_tbf == SINGLE_BLOCK_DL) { // Single block UL is now complete. l1pa_l1ps_com.transfer.single_block.activity &= SINGLE_DL_MASK; } } } // End if(task enabled and semaphore false) else // When the task is aborted, we must continue to make dummy // DSP programming to avoid communication mismatch due // to C/W/R pipelining. { // Flag dummy DSP programmation. // Set "CTRL_TX" flag in the controle flag registers. l1s.dsp_ctrl_reg |= CTRL_TX; } } /*-------------------------------------------------------*/ /* l1ps_ctrl_prach() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* */ /* Input parameters: */ /* ----------------- */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* */ /*-------------------------------------------------------*/ void l1ps_ctrl_prach(UWORD8 task, UWORD8 burst_id) { UWORD16 radio_freq; UWORD8 txpwr; UWORD8 adc_active = INACTIVE; // Get ARFCN to be used for current control. // ****************************************** radio_freq = l1pa_l1ps_com.p_idle_param.radio_freq; // Get TXPWR value txpwr = l1s.applied_txpwr; // Traces and debug. // ****************** #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_RACH, radio_freq); #endif #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[task].name); #endif #if FF_L1_IT_DSP_USF // Whenever the USF status is unknown then the PRACH control execution // has to be postponed until DSP USF interrupt fires. if (l1ps_macs_com.usf_status != USF_AWAITED) { #endif // FF_L1_IT_DSP_USF l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; #if FF_L1_IT_DSP_USF // TPU and DSP have to be programmed for transmission only if the USF is // good otherwise this is not a valid opportunity. If there was no USF // uncertainty then the test is void. if ( (l1ps_macs_com.usf_status != USF_IT_DSP) || (((l1ps_dsp_com.pdsp_ndb_ptr->d_usf_updated_gprs >> ((7-0)*2)) & 0x0003) == USF_GOOD)) { // Flags PRACH burst was controlled to TPU/DSP (not cancelled due to USF) l1pa_l1ps_com.pra_info.prach_controlled = TRUE; #endif // FF_L1_IT_DSP_USF #if (CODE_VERSION!=SIMULATION) #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) L1_trace_string("PRA"); #endif #endif // Programs DSP for required task. // ******************************** { UWORD8 cs_type; if (l1pa_l1ps_com.access_burst_type == ACC_BURST_8) cs_type = CS_PAB8_TYPE; else cs_type = CS_PAB11_TYPE; // ACCESS PRACH dsp control. l1pddsp_idle_prach_data(FALSE, cs_type, l1pa_l1ps_com.pra_info.channel_request_data, l1a_l1s_com.Scell_info.bsic, radio_freq); } l1pddsp_idle_prach_power(txpwr, radio_freq, 3); // ADC measurement // *************** // check if during the RACH an ADC measurement must be performed if (l1a_l1s_com.adc_mode & ADC_EACH_RACH) // perform ADC on each burst adc_active = ACTIVE; // Programs TPU for required task. // ******************************** // tpu pgm... l1dtpu_serv_tx_ra(radio_freq, l1s.tpu_offset, txpwr, adc_active); // Set tpu window identifier for Power meas if any. l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_ra_load_split + l1_config.params.rx_synth_load_split; // Store frame number to report to L3 l1pa_l1ps_com.pra_info.fn_to_report = l1s.next_time.fn; #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_AB(task,txpwr) #endif // Flag DSP and TPU programmation. // ******************************** // Set "CTRL_TX" flag in the controle flag register. l1s.tpu_ctrl_reg |= CTRL_PRACH; l1s.dsp_ctrl_reg |= CTRL_TX; #if FF_L1_IT_DSP_USF }// if ((l1ps_macs_com.usf_status != USF_IT_DSP) || USF_GOOD) else { // PRACH has been cancelled because USF not FREE. Hence Read is skipped. l1pa_l1ps_com.pra_info.prach_controlled = FALSE; } #endif #if FF_L1_IT_DSP_USF } // if (l1ps_macs_com.usf_status != USF_AWAITED) #endif } /*-------------------------------------------------------*/ /* l1ps_ctrl_poll() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* */ /* Input parameters: */ /* ----------------- */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* */ /*-------------------------------------------------------*/ void l1ps_ctrl_poll(UWORD8 task, UWORD8 burst_id) { UWORD16 radio_freq; // Get ARFCN to be used for current control. // ****************************************** if(l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED) radio_freq = l1a_l1s_com.dedic_set.radio_freq; else radio_freq = l1pa_l1ps_com.p_idle_param.radio_freq; // Traces and debug. // ****************** #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_CTRL_POLL, radio_freq); #endif #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[task].name); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; #if (CODE_VERSION!=SIMULATION) #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) L1_trace_string("PRA"); #endif #endif // Programs DSP for required task. // ******************************** { UWORD8 cs_type; cs_type = l1pa_l1ps_com.poll_info.pol_resp_type; if ((cs_type == CS_PAB8_TYPE) || (cs_type == CS_PAB11_TYPE)) { // IDLE POLLING PRACH dsp control. l1pddsp_idle_prach_data(TRUE, cs_type, l1pa_l1ps_com.poll_info.chan_req.prach_data[0], l1a_l1s_com.Scell_info.bsic, radio_freq); l1pddsp_idle_prach_power(l1s.applied_txpwr, radio_freq, 3); // Programs TPU for required task. // ******************************** // tpu pgm... l1dtpu_serv_tx_ra(radio_freq, l1s.tpu_offset, l1s.applied_txpwr,INACTIVE); #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_AB(task,l1s.applied_txpwr) #endif } else { UWORD8 tsc; if(l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED) tsc = l1pa_l1ps_com.transfer.aset->tsc; else tsc = l1pa_l1ps_com.pccch.packet_chn_desc.tsc; // Pgm DSP for Poll Response TX NB on TS=3. l1pddsp_single_tx_block (burst_id, l1pa_l1ps_com.poll_info.chan_req.cs1_data, tsc, radio_freq); // Pgm DSP for Transmit power. l1pddsp_transfer_mslot_power(l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr, radio_freq, 0x80>>3); // Programs TPU for required task. // ******************************** // tpu pgm... l1dtpu_serv_tx_nb(radio_freq, l1pa_l1ps_com.poll_info.timing_advance, l1s.tpu_offset, l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr[3],INACTIVE); #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_NB(task, l1pa_l1ps_com.poll_info.timing_advance, l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr[3]) #endif } } // Set tpu window identifier for Power meas if any. l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_nb_load_split + l1_config.params.rx_synth_load_split; // Store frame number to report to L3 if (burst_id == BURST_4) l1pa_l1ps_com.poll_info.fn_to_report = l1s.next_time.fn; // Flag DSP and TPU programmation. // ******************************** // Set "CTRL_TX" flag in the controle flag register. l1s.tpu_ctrl_reg |= CTRL_TX; l1s.dsp_ctrl_reg |= CTRL_TX; } #if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM //#pragma DUPLICATE_FOR_INTERNAL_RAM_START /*-------------------------------------------------------*/ /* l1s_ctrl_pdtch() */ /*-------------------------------------------------------*/ /* */ /* Description: This is the control function for Multislot Rx/Tx */ /* ------------ */ /* */ /* Input parameters: */ /* ----------------- */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* */ /* Modified parameters from globals: */ /*-------------------------------------------------------*/ void l1ps_ctrl_pdtch(UWORD8 task, UWORD8 burst_id) { if((l1a_l1s_com.l1s_en_task[task] == TASK_ENABLED) && !(l1a_l1s_com.task_param[task] == SEMAPHORE_SET)) // Check the task semaphore. The control body is executed only // when the task semaphore is 0. This semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. { UWORD16 radio_freq; #if (RF_FAM == 61) // By default we choose the hardware filter UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER; #endif #if (NEW_SNR_THRESHOLD == 1) UWORD8 saic_flag=0; #endif /* NEW_SNR_THRESHOLD */ // Traces and debug. // ****************** #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[PDTCH].name); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Catch channel description and ARFCN. // ************************************* // Get ARFCN to be used for current control. This ARFCN comes from // the HOPPING algorithm called just before calling this function. radio_freq = l1a_l1s_com.dedic_set.radio_freq; #if (TRACE_TYPE==5) // in simulation trace only one time by frame trace_fct(CST_L1PS_CTRL_PDTCH, radio_freq); #endif /**************************************************************************/ /* Program DSP for mulstislot operation... */ /**************************************************************************/ { UWORD8 tx_allocation; #if TESTMODE if (l1_config.TestMode && (l1_config.tmode.tx_params.burst_data == 11)) // Call dummy MACS for CMU200 loopback mode l1ps_tmode_macs_ctrl(); else #endif { // Call MACS for Medium control, DATA control and RLC-MACS management l1ps_macs_ctrl(); } #if FF_L1_IT_DSP_USF if (l1ps_macs_com.usf_status != USF_AWAITED) { #endif // Compute tx_allocation mixing NB and RA allocations. tx_allocation = l1ps_macs_com.tx_nb_allocation | l1ps_macs_com.tx_prach_allocation; // Pgme TXPWR only if any UL. if(tx_allocation) { // Pgme DSP for Transmit power. // !!! Warning: This function must be called before l1pdtpu_serv_tx() // !!! a_ctrl_abb_gprs is partly overwritten by l1pdtpu_serv_tx() l1pddsp_transfer_mslot_power(l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr, radio_freq, tx_allocation); } #if FF_L1_IT_DSP_USF } #endif } /**************************************************************************/ /* Program TPU for mulstislot operation... */ /**************************************************************************/ { WORD8 ts = 0; UWORD8 rx_group_id = 0; UWORD8 tx_group_id = 0; BOOL pwr_programmed = FALSE; UWORD8 bit_mask = 0x80; WORD8 agc; UWORD8 lna_off; BOOL rx_done_flag; BOOL adc_done = FALSE; UWORD8 adc_active = INACTIVE; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb = 0; UWORD16 dco_algo_ctl_pw = 0; UWORD8 if_ctl =0; //omaps00090550; UWORD8 tot_num_rx = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; #endif // AGC and LNA_OFF processing //--------------------------- #if FF_L1_IT_DSP_USF #if L1_EDA if (l1ps_macs_com.usf_status != USF_AWAITED) #else if (l1ps_macs_com.usf_status != USF_IT_DSP) #endif #endif // Same AGC is used for all timeslots l1pctl_transfer_agc_ctrl(&agc, &lna_off, radio_freq); #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function // NOTE: l1a_l1s_com.Scell_used_IL.input_level is updated within // the l1pctl_transfer_agc_ctrl above csf_filter_choice = l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode #if (NEW_SNR_THRESHOLD == 1) ,task ,&saic_flag #endif ); #endif while(ts < 8) { #if FF_L1_IT_DSP_USF #if L1_EDA //Depending on USF status got from DSP, RX allocation may change after //receiving the USF interrupt due to USF status updates if ((l1ps_macs_com.rx_allocation & bit_mask) && (l1ps_macs_com.usf_status != USF_AWAITED)) #else if ((l1ps_macs_com.rx_allocation & bit_mask) && (l1ps_macs_com.usf_status != USF_IT_DSP)) #endif #else if(l1ps_macs_com.rx_allocation & bit_mask) #endif { // We have detected the 1st RX slot number for a new RX group. UWORD8 rx_id = ts; // Save 1st RX timeslot number. UWORD8 num_rx = 1; // 1 RX in the RX group for the moment. // Increment the RX group ID. rx_group_id++; #if (RF_FAM == 61) //Increment the total number of RX slots tot_num_rx++; #endif // Increment TS. ts++; // Jump on next timeslot to keep looking for contiguous RX slots. bit_mask >>= 1; // Look for more contiguous RX slots. while((l1ps_macs_com.rx_allocation & bit_mask) && (ts < 8)) { ts++; num_rx++; #if (RF_FAM == 61) tot_num_rx++; #endif bit_mask >>= 1; } // Check if more RX bursts follow if((l1ps_macs_com.rx_allocation << (ts+1)) & 0xFF) rx_done_flag = FALSE; else rx_done_flag = TRUE; #if (RF_FAM == 61) // Locosto DCO if(rx_group_id == 1) { cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID, l1a_l1s_com.Scell_used_IL.input_level, radio_freq,if_threshold); } if(rx_done_flag == TRUE) { //dco_algo_ctl has 0000 00ZL dco_algo_ctl_nb *= 0x55; // replicate 0000 00zL as ZLZL ZLZL // ZLZLZLZL >> 2*(4-tot_num_rx) where i is the tot_num_rx would produce the // desired dco_algo_ctl_nb For Eg if tot_num_rx is 2 the desired pattern is // 0000 ZLZL dco_algo_ctl_nb = dco_algo_ctl_nb >> (2*( 4 - tot_num_rx)); l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); } #endif // ADC measurement // *************** if (adc_done == FALSE) { // check if during the PDTCH burst an ADC measurement must be performed if (l1a_l1s_com.adc_mode & ADC_NEXT_TRAFFIC_DL) // perform ADC only one time { adc_active = ACTIVE; adc_done = TRUE; l1a_l1s_com.adc_mode &= ADC_MASK_RESET_TRAFFIC; // reset in order to have only one ADC measurement in Traffic } else if (l1a_l1s_com.adc_mode & ADC_EACH_TRAFFIC_DL) // perform ADC on each period bloc if (l1s.actual_time.fn_mod104 == 10) //periodic with each PDTCH burst in frame 11 (frame with the lowest CPU load) if ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_traffic_period) // wait for the period { adc_active = ACTIVE; adc_done = TRUE; l1a_l1s_com.adc_cpt = 0; } } // update the TPU with the new TOA if necessary if (rx_group_id == 1) // only if synchro performed l1ctl_update_TPU_with_toa(); #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1PS_CTRL_PDTCH_DL_BURST0 + burst_id, radio_freq); #endif // Program RX scenario. l1pdtpu_serv_rx_nb(radio_freq, agc, lna_off, rx_id, l1s.tpu_offset, num_rx, rx_group_id, rx_done_flag,adc_active #if (RF_FAM == 61) ,csf_filter_choice ,if_ctl #endif #if (NEW_SNR_THRESHOLD == 1) ,saic_flag #endif ); adc_active = INACTIVE; // ADC performed only on the first RX burst // Set tpu window identifier for Synthesizer and // according to last RX group position. l1s.tpu_win = (l1_config.params.rx_synth_load_split) + ((UWORD16)rx_id * BP_SPLIT) + RX_SPLIT_TABLE[num_rx-1]; // Set "CTRL_RX" flag in the controle flag registers. l1s.tpu_ctrl_reg |= CTRL_RX; l1s.dsp_ctrl_reg |= CTRL_RX; } else #if FF_L1_IT_DSP_USF if ((l1ps_macs_com.tx_nb_allocation & bit_mask) && (l1ps_macs_com.usf_status != USF_AWAITED)) #else if(l1ps_macs_com.tx_nb_allocation & bit_mask) #endif { // We have detected the 1st TX NB slot number for a new TX group. UWORD8 tx_id = ts; // Save 1st TX timeslot number. UWORD8 num_tx = 1; // 1 RX in the TX group for the moment. UWORD8 switch_flag; // Increment the TX group ID. tx_group_id++; // Increment TS. ts++; // Jump on next timeslot to keep looking for contiguous TX slots. bit_mask >>= 1; // Look for more contiguous TX slots. while((l1ps_macs_com.tx_nb_allocation & bit_mask) && (ts < 8)) { ts++; num_tx++; bit_mask >>= 1; } // Detect special case: TX NB followed by PRACH. if(l1ps_macs_com.tx_prach_allocation & bit_mask) { switch_flag = 1; } else { switch_flag = 0; } #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1PS_CTRL_PDTCH_UL, radio_freq); #endif // Program TN NB scenario. l1pdtpu_serv_tx(radio_freq, l1pa_l1ps_com.transfer.aset->packet_ta.ta, l1s.tpu_offset, tx_id, num_tx, tx_group_id, switch_flag, 0, // Driver called for Normal Burst. TRUE,INACTIVE);// Flag RX in same frame as TX // Set tpu window identifier for Synthesizer and // according to last TX group position. // TX offset = tx_id * BP_SPLIT // TX load = (num_tx-1) * BP_SPLIT + l1_config.params.tx_load_split l1s.tpu_win = (l1_config.params.rx_synth_load_split) + ((UWORD16)tx_id * BP_SPLIT) + ((UWORD16)(num_tx -1) * BP_SPLIT) + l1_config.params.tx_nb_load_split; // Set "CTRL_TX" flag in the controle flag registers. l1s.tpu_ctrl_reg |= CTRL_TX; l1s.dsp_ctrl_reg |= CTRL_TX; } else #if FF_L1_IT_DSP_USF if ((l1ps_macs_com.tx_prach_allocation & bit_mask) && (l1ps_macs_com.usf_status != USF_AWAITED)) #else if(l1ps_macs_com.tx_prach_allocation & bit_mask) #endif { // We have detected a TX RA. UWORD8 switch_flag; // Increment the TX group ID. tx_group_id++; // Jump on next timeslot. bit_mask >>= 1; // Detect special case: PRACH followed by TX NB. if(l1ps_macs_com.tx_nb_allocation & bit_mask) { switch_flag = 1; } // Detect special case: PRACH followed by PRACH else if (l1ps_macs_com.tx_prach_allocation & bit_mask) { // Solution with DSP patch supporting PRACH|PRACH switch_flag = 2; } else { switch_flag = 0; } #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1PS_CTRL_PDTCH_RA, radio_freq); #endif // Program TX RA scenario. l1pdtpu_serv_tx(radio_freq, l1pa_l1ps_com.transfer.aset->packet_ta.ta, l1s.tpu_offset, ts, 1, // Driver is called for each PRACH. tx_group_id, switch_flag, TX_RA_BURST, // Driver called for PRACH Burst. TRUE,INACTIVE); // Flag RX in same frame as TX // Set tpu window identifier for Synthesizer and // according to last TX group position. // TX offset = ts * BP_SPLIT // TX load = l1_config.params.tx_nb_load_split // original value of TX load (RACH) replaced by TX NB to take into account TX_NB|PRACH with max. TA l1s.tpu_win = (l1_config.params.rx_synth_load_split) + ((UWORD16)ts * BP_SPLIT) + l1_config.params.tx_nb_load_split; // Increment TS. ts++; // Set "CTRL_TX" flag in the controle flag registers. l1s.tpu_ctrl_reg |= CTRL_TX; l1s.dsp_ctrl_reg |= CTRL_TX; } else #if FF_L1_IT_DSP_USF if ((l1ps_macs_com.pwr_allocation & bit_mask) && (pwr_programmed == 0) && (l1ps_macs_com.usf_status != USF_AWAITED)) #else if((l1ps_macs_com.pwr_allocation & bit_mask) && (pwr_programmed == 0)) #endif { // We have detected a PWR allocation and no PWR programmed in current frame. if((l1pa_l1ps_com.transfer.aset->pc_meas_chan == FALSE) && ((l1s.actual_time.t2 == 1) || (l1s.actual_time.t2 == 9) || (l1s.actual_time.t2 == 18))) { #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_CTRL_PC_MEAS_CHAN, (UWORD32)(-1)); #endif // Measurement on the beacon (PC_MEAS_CHAN = 0) l1ps_bcch_meas_ctrl(ts); } else if(l1pa_l1ps_com.l1ps_en_meas & P_TCRMS_MEAS) { // Neighbour Measurement CTRL Phase // Note: Test on l1s.forbid_meas can't be done from the fact that at this // level, l1s.forbid_meas is not set. // l1ps_ctrl_pdtch is called before CTRL of FB26/SB26/SBCNF26. if(!((l1s.actual_time.t2 == 23) && ((l1s.task_status[FB26].current_status != INACTIVE) || (l1s.task_status[SB26].current_status != INACTIVE) || (l1s.task_status[SBCNF26].current_status != INACTIVE)))&& !(l1pa_l1ps_com.tcr_freq_list.new_list_present && ((l1pa_l1ps_com.tcr_freq_list.cres_meas_report == 0) || (l1pa_l1ps_com.tcr_freq_list.cres_meas_report == 103)))) { if(!(l1pa_l1ps_com.meas_param & P_TCRMS_MEAS)) { #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_CTRL_TCR_MEAS_1, (UWORD32)(-1)); #endif l1ps_tcr_ctrl((UWORD8)ts); } } } // End of CTRL PDTCH phase // Increment TS. ts++; // Flag that a PWR as been programmed for current frame. pwr_programmed = TRUE; // Jump on next timeslot. bit_mask >>= 1; // Call PWR control function } else { // Increment TS. ts++; // Jump on next timeslot. bit_mask >>= 1; } } // End of "while(ts < 8)" #if FF_L1_IT_DSP_USF if (l1ps_macs_com.usf_status != USF_AWAITED) #endif // Update of AFC l1pd_afc(); } } // End if(task enabled and semaphore false) else // When the task is aborted, we must continue to make dummy // DSP programming to avoid communication mismatch due // to C/W/R pipelining. { #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1PS_CTRL_PDTCH_DUMMY, (UWORD32)(-1)); #endif // Flag dummy DSP programmation. // Set "CTRL_TX" flag in the controle flag registers. l1s.dsp_ctrl_reg |= CTRL_TX; } } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM /*-------------------------------------------------------*/ /* l1s_read_single() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* */ /* Input parameters: */ /* ----------------- */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* */ /*-------------------------------------------------------*/ void l1ps_read_single(UWORD8 task, UWORD8 burst_id) { if((l1a_l1s_com.l1s_en_task[task] == TASK_ENABLED) && !(l1a_l1s_com.task_param[task] == SEMAPHORE_SET)) // Check the task semaphore. The control body is executed only // when the task semaphore is 0. This semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. { // Read param updating... if (l1ps.read_param.new_set == TRUE) { // If it's the first Read phase of the block (first of the new TBF) if (burst_id == BURST_1) { // Update the "read_param" structure l1ps_update_read_set_parameters(); } } /*--------------------------------------------------------*/ /* READ TRANSMIT TASK RESULTS... */ /*--------------------------------------------------------*/ l1_check_com_mismatch(task); // check PM error only in case of downlink single block if(l1ps.read_param.allocated_tbf == SINGLE_BLOCK_DL) { UWORD32 pm; pm = (l1ps_dsp_com.pdsp_db_r_ptr->a_burst_pm_gprs[0] & 0xffff) >> 5; l1_check_pm_error(pm,task); } // Two phase access: downlink PDCH reading if((l1ps.read_param.allocated_tbf == TWO_PHASE_ACCESS)&& (l1ps_dsp_com.pdsp_db_r_ptr->d_task_d_gprs & (0x80 >> 0))) { UWORD8 IL_for_rxlev[8]; UWORD8 pr_table[8]; if (burst_id == BURST_4) l1ps_macs_header_decoding(0, &(IL_for_rxlev[0]), &(pr_table[0])); // Update AGC and extract IL for RXLEV //------------------------------------ if (l1ps.read_param.dl_pwr_ctl.p0 == 255) { // No power control mode AGC algorithm l1pctl_npc_agc_read(IL_for_rxlev, l1ps_dsp_com.pdsp_db_r_ptr, l1ps_dsp_com.pdsp_ndb_ptr); } 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 l1pctl_dpcma_agc_read(IL_for_rxlev, l1ps_dsp_com.pdsp_db_r_ptr, l1ps_dsp_com.pdsp_ndb_ptr, pr_table); } else { // BTS power control mode B l1pctl_dpcmb_agc_read(IL_for_rxlev, l1ps_dsp_com.pdsp_db_r_ptr, l1ps_dsp_com.pdsp_ndb_ptr, pr_table); } } // End of "AGC algorithm" } #if (TRACE_TYPE!=0) && (TRACE_TYPE !=5) trace_fct(CST_L1PS_READ_SINGLE, l1a_l1s_com.Scell_info.radio_freq); #endif // Read downlink DATA block from MCU/DSP interface. // ************************************************* if(burst_id == BURST_4) { xSignalHeaderRec *msg; #if (TRACE_TYPE==5) // in simulation trace only the 4th burst trace_fct(CST_L1PS_READ_SINGLE, l1a_l1s_com.Scell_info.radio_freq); #endif if(l1ps.read_param.allocated_tbf == TWO_PHASE_ACCESS) // 2 phase ACCESS. { if((l1ps_dsp_com.pdsp_db_r_ptr->d_task_u_gprs & (0x80 >> 3)) && (l1s.task_status[POLL].current_status == INACTIVE)) // UL block sent... { // Send confirmation msg to L3/MACA. msg = os_alloc_sig(sizeof(T_MPHP_SINGLE_BLOCK_CON)); DEBUGMSG(status,NU_ALLOC_ERR) // Return "Single block" purpose. ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->purpose = l1pa_l1ps_com.transfer.aset->assignment_command; ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->assignment_id = l1pa_l1ps_com.transfer.aset->assignment_id; // Return status and CRC error (CRC error not applicable). ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->status = SINGLE_UL_DONE; ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->dl_error_flag = 0; // MSG is sent to L1A to stop PCCCH or CCCH/BCCH reading. msg->SignalCode = L1P_SINGLE_BLOCK_CON; os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } if(l1ps_dsp_com.pdsp_db_r_ptr->d_task_d_gprs & (0x80 >> 0)) // DL block received... { UWORD16 pwr_level; #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif /*(L1_FF_MULTIBAND == 1)*/ // this bloc doesn't compute the burst input level, so the last_input_level is used. #if (L1_FF_MULTIBAND == 0) pwr_level = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq].input_level; #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); pwr_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; #endif // #if (L1_FF_MULTIBAND == 0) else // Read L3 frame block and send msg to L1A. l1s_read_l3frm(pwr_level, &(l1ps_dsp_com.pdsp_ndb_ptr->a_dd_gprs[0][0]), task); } } else { // SYNCHRO task is not schedule if we are in the specific case: // L1A is touching SYNCHRO parameters (tn_difference, dl_tn and dsp_scheduler_mode) // and leave L1A to go in HISR (L1S) in middle of the update (cf. BUG1339) if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET) { //---------------- // Synchro back //---------------- // Save the "timeslot difference" between new and old configuration // in "tn_difference". // tn_difference -> loaded with the number of timeslot to shift. // dl_tn -> loaded with the new timeslot. l1a_l1s_com.tn_difference += l1pa_l1ps_com.transfer.single_block.dl_tn_to_restore - l1a_l1s_com.dl_tn; l1a_l1s_com.dl_tn = l1pa_l1ps_com.transfer.single_block.dl_tn_to_restore; // Select DSP Scheduler used in packet Idle (can be CCCH or PCCCH). if((l1a_l1s_com.l1s_en_task[ALLC] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[NP] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[EP] == TASK_ENABLED)) { // We are in CS Idle on CCCH. l1a_l1s_com.dsp_scheduler_mode = GSM_SCHEDULER; } // Enable SYNCHRO task. l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED; } //------------------ // Confirmation msg //------------------ // Common part... { // Send confirmation msg to L3/MACA. msg = os_alloc_sig(sizeof(T_MPHP_SINGLE_BLOCK_CON)); DEBUGMSG(status,NU_ALLOC_ERR) ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->purpose = l1pa_l1ps_com.transfer.aset->assignment_command; ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->assignment_id = l1pa_l1ps_com.transfer.aset->assignment_id; msg->SignalCode = L1P_SINGLE_BLOCK_CON; // Disable SINGLE task. l1s.task_status[task].current_status = INACTIVE; l1a_l1s_com.l1s_en_task[task] = TASK_DISABLED; } // Differentiated part... if(l1pa_l1ps_com.transfer.aset->allocated_tbf == SINGLE_BLOCK_UL) // SINGLE UL task is complete. { // Return status and CRC error (CRC error not applicable). ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->status = SINGLE_UL_DONE; ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->dl_error_flag = 0; } else if(l1ps.read_param.allocated_tbf == SINGLE_BLOCK_DL) // SINGLE DL task is complete. { API *info_address; UWORD32 i,j; UWORD32 word32; info_address = &(l1ps_dsp_com.pdsp_ndb_ptr->a_dd_gprs[0][0]); // Return status and CRC error ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->status = SINGLE_DL_DONE; ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->dl_error_flag = ((*info_address & 0x0100) >> 8); // Download data from API to message. // Get 24 bytes info. from DSP: CS1 meaningful block is of size 12 UWORD16 data. // !!! WARNING: word32 type is for compatibility with chipset == 0. // Can be word16 if only chipset == 2 is used. for (j=0, i=0; i<12; i++) { word32 = info_address[4 + i]; // Get info word, rem: skip info. header. ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->data_array[j++] = (word32 & 0x000000ff); ((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->data_array[j++] = (word32 & 0x0000ff00) >> 8; } } // send message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } // End else (!TWO_PHASE_ACCESS) } // Set flag used to change the read page at the end of "l1_synch". l1s_dsp_com.dsp_r_page_used = TRUE; } // End if(task enabled and semaphore false) else // When the task is aborted, we must continue to make dummy // DSP/TPU programming to avoid communication mismatch due // to C/W/R pipelining. Dummy MCU/DSP reading is also done. { // Set flag used to change the read page at the end of "l1_synch". l1s_dsp_com.dsp_r_page_used = TRUE; } } #if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM //#pragma DUPLICATE_FOR_INTERNAL_RAM_START /*-------------------------------------------------------*/ /* l1ps_read_pdtch() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* */ /* Input parameters: */ /* ----------------- */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* */ /*-------------------------------------------------------*/ void l1ps_read_pdtch(UWORD8 task, UWORD8 burst_id) { if((l1a_l1s_com.l1s_en_task[task] == TASK_ENABLED) && !(l1a_l1s_com.task_param[task] == SEMAPHORE_SET)) // Check the task semaphore. The control body is executed only // when the task semaphore is 0. This semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. { BOOL beacon; T_INPUT_LEVEL *IL_info_ptr; UWORD16 radio_freq; WORD8 ts = 0; UWORD8 bit_mask = 0x80; WORD8 bcch_level; UWORD8 rx_no = 0; BOOL first_valid_block = TRUE; BOOL crc_error = TRUE; UWORD8 i; UWORD32 best_snr = 0; UWORD32 best_angle = 0; UWORD32 best_pm = 0; UWORD8 IL_for_rxlev[8], pr_table[8]; WORD16 best_rxlev_accu = 0; static BOOL crc_error_tbl[8] = {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE}; static WORD16 rxlev_accu[8] = {0, 0, 0, 0, 0, 0, 0, 0}; static WORD8 burst_level[4] = {(WORD8)0x80, (WORD8)0x80, (WORD8)0x80, (WORD8)0x80}; static UWORD16 radio_freq_tbl[4]; static UWORD32 toa_val[4] = {0, 0, 0, 0}; static UWORD32 snr_val[4] = {0, 0, 0, 0}; #if TESTMODE xSignalHeaderRec *msg; static UWORD32 tm_pm_fullres = 0; static UWORD32 tm_snr = 0; static UWORD32 tm_toa = 0; static WORD16 tm_angle = 0; #endif #define burst_number l1ps_dsp_com.pdsp_db_r_ptr->d_burst_nb_gprs #define DL_pwr_ctrl l1pa_l1ps_com.transfer.dl_pwr_ctrl // Read parameters updating // ************************* // *********** // * WARNING * // *********** // Because of the STI implementation, the parameters under the "l1pa_l1ps_com.transfer.aset" // structure mustn't be used in the Read PDTCH functions // This is due to the following case that may happen: // // C|W R | // |C W R | // | C W R| TBF 1 // | C W|R <--------------------------- (2) This "read phase" must use the TBF 1 parameters while "aset" has already been updated //---------------------- so the read_param structure is used // | C|W R <------------------------- (3) The read_param is updated with TBF 2 parameters // | |C W R at the beguining of the first Read of TBF 2 // | | C W R TBF 2 so when (l1ps.read_param.new_set = TRUE and burst_id = BURST_1) // | | C W R // ^ // (1) TBF 2 starting time detected on this frame (no SYNCHRO change needed between TBF1 and TBF 2) // --> aset parameters updated to TBF 2 // --> l1ps.read_param.new_set set to TRUE // If a new TBF has been enabled... if (l1ps.read_param.new_set == TRUE) { // If it's the first Read phase of the block (first of the new TBF) if (burst_id == BURST_1) { // Update the "read_param" structure l1ps_update_read_set_parameters(); } } // Traces and debug. // ****************** l1_check_com_mismatch(task); radio_freq = l1a_l1s_com.dedic_set.radio_freq_dd; if(l1ps.read_param.pc_meas_chan) { radio_freq_tbl[burst_number] = radio_freq; } else { radio_freq_tbl[burst_number] = l1a_l1s_com.Scell_info.radio_freq; } if (radio_freq == l1a_l1s_com.Scell_info.radio_freq) { beacon=1; IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas_beacon; } else { beacon=0; IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas; } // Call maca_power_control() in order to get TXPWR value if(l1ps_dsp_com.pdsp_db_r_ptr->d_burst_nb_gprs == 2) { UWORD8 txpwr[8]; UWORD8 i; // Due to the CWR pipeleine, maca_power_control() has to be called before the // CTRL of the first PDTCH i.e. in l1ps_ctrl_pdtch(). It means that crc_error, // radio_freq_tbl[], burst_level[] and bcch_level information are stored on // burst4 of READ phase ("l1ps_ctrl_pdtch()") to be used on burst4 of CTRL phase. // Call Uplink Transmit Power level algorithm #if 0 /* LoCosto version */ maca_power_control(l1ps.read_param.assignment_id, #else /* TCS211 reconstruction */ maca_power_control(DL_pwr_ctrl.assignment_id, #endif DL_pwr_ctrl.crc_error, DL_pwr_ctrl.bcch_level, DL_pwr_ctrl.radio_freq_tbl, DL_pwr_ctrl.burst_level, txpwr); #if TESTMODE if(!l1_config.TestMode) #endif { for(i = 0; i < 8; i++) { l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr[i] = txpwr[i]; } } } if(l1ps_dsp_com.pdsp_db_r_ptr->d_burst_nb_gprs == 3) /*---------------------------------------------------*/ /* Complete PDTCH DL block has been processed by DSP */ /*---------------------------------------------------*/ { #if (TRACE_TYPE == 5) // in simulation trace only the latest burst trace_fct(CST_L1PS_READ_PDTCH, radio_freq); #endif // Call MACS... l1ps_macs_read(pr_table); } // Update AGC and extract IL for RXLEV //------------------------------------ if (l1ps.read_param.dl_pwr_ctl.p0 == 255) { // No power control mode AGC algorithm l1pctl_npc_agc_read(IL_for_rxlev, l1ps_dsp_com.pdsp_db_r_ptr, l1ps_dsp_com.pdsp_ndb_ptr); } else { // Downlink power control AGC algorithms if (l1ps.read_param.dl_pwr_ctl.bts_pwr_ctl_mode == 0) { // BTS Power control mode A l1pctl_dpcma_agc_read(IL_for_rxlev, l1ps_dsp_com.pdsp_db_r_ptr, l1ps_dsp_com.pdsp_ndb_ptr, pr_table); } else { // BTS power control mode B l1pctl_dpcmb_agc_read(IL_for_rxlev, l1ps_dsp_com.pdsp_db_r_ptr, l1ps_dsp_com.pdsp_ndb_ptr, pr_table); } } // End of "AGC algorithm" // TOA algorithm is called with toa/snr pair from last block (N-1) // Feed TOA histogram with values from good bursts (crc_error = FALSE) // otherwise input snr = 0. #if (TOA_ALGO != 0) // Good block, TOA from TS=0 #if (TOA_ALGO == 2) if(l1s.toa_var.toa_snr_mask == 0) #else if(l1s.toa_snr_mask == 0) #endif { #if (TOA_ALGO == 2) { UWORD32 snr_temp; snr_temp = (crc_error_tbl[0] == FALSE) ? snr_val[burst_id] : 0; l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa_val[burst_id]); } #else { /* FreeCalypso TCS211 reconstruction */ if (crc_error_tbl[0] == FALSE) { l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_val[burst_id], toa_val[burst_id], &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING == 1) ,0 #endif ); } else { l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa_val[burst_id], &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING == 1) ,0 #endif ); } } #endif } #endif /*---------------------------------------------------*/ /* Read burst demodulation info for control algos */ /* Use all burst results to feed the algos. */ /*---------------------------------------------------*/ while(ts < 8) { if(l1ps_dsp_com.pdsp_db_r_ptr->d_task_d_gprs & bit_mask) { UWORD32 toa; UWORD32 pm; UWORD32 angle; UWORD32 snr; WORD8 rxlev; // Read control results and feed control algorithms. // ************************************************** // Read control information. toa = l1ps_dsp_com.pdsp_db_r_ptr->a_burst_toa_gprs[ts] & 0xffff; pm = (l1ps_dsp_com.pdsp_db_r_ptr->a_burst_pm_gprs[ts] & 0xffff)>>5; angle = l1ps_dsp_com.pdsp_db_r_ptr->a_burst_angle_gprs[ts] & 0xffff; snr = l1ps_dsp_com.pdsp_db_r_ptr->a_burst_snr_gprs[ts] & 0xffff; #if (TRACE_TYPE != 0) && (TRACE_TYPE != 5) // for debug trace all bursts trace_fct(CST_L1PS_READ_PDTCH_BURST, (UWORD32)(-1)); #endif l1_check_pm_error(pm,task); #if TESTMODE // Test mode stats if (l1_config.TestMode) { if (bit_mask & l1_config.tmode.stats_config.stat_gprs_slots) { tm_pm_fullres += (l1ps_dsp_com.pdsp_db_r_ptr->a_burst_pm_gprs[ts] & 0xffff); tm_snr += snr; tm_toa += toa; tm_angle += (WORD16) angle; // signed } } #endif #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev[ts]) #endif #if 0 //(TRACE_TYPE == 1) || (TRACE_TYPE == 4) // TCS211 reconstruction l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev[ts]); #endif #if (BURST_PARAM_LOG_ENABLE == 1) l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev[ts]); #endif //Look for the pairs angle, snr with the maximum snr if (snr > best_snr) { best_snr = snr; best_angle = angle; best_pm = pm; } // store toa value from first TS if (ts==0) { toa_val[burst_id] = toa; snr_val[burst_id] = snr; } // Store Received Signal Level to be used in Uplink Transmit Power Algorithm. // Compute RXLEV rxlev = l1s_encode_rxlev(IL_for_rxlev[ts]); // Find first correct PDTCH, save RXLEV and CRC if(!crc_error_tbl[ts] && first_valid_block) { if(l1ps.read_param.pc_meas_chan) { burst_level[burst_number] = rxlev; } else { burst_level[burst_number] = (WORD8)0x80; } // Measures on first valid block have been performed. Reset flag. first_valid_block = FALSE; // Save crc_error crc_error = crc_error_tbl[ts]; } // End of measurements storage // If All PDTCH are incorrect (bad CRC) save RXLEV and CRC of the best PDTCH if(first_valid_block) { rxlev_accu[ts] += rxlev; if(rxlev_accu[ts] > best_rxlev_accu) { best_rxlev_accu = rxlev_accu[ts]; crc_error = crc_error_tbl[ts]; if(l1ps.read_param.pc_meas_chan) { burst_level[burst_number] = rxlev; } else { burst_level[burst_number] = (WORD8)0x80; } } } // Determine first valid block to be used in next radio block if(l1ps_dsp_com.pdsp_db_r_ptr->d_burst_nb_gprs == 3) /*---------------------------------------------------*/ /* Complete PDTCH DL block has been processed by DSP */ /*---------------------------------------------------*/ { crc_error_tbl[ts] = ((l1ps_dsp_com.pdsp_ndb_ptr->a_dd_gprs[rx_no][0] & 0x0100) >> 8); // Increment Rx burst number rx_no++; } #if TRACE_TYPE==3 stats_samples_nb(toa,pm,angle,snr,burst_id,task); #endif } // End of if(l1ps_dsp_com.pdsp_db_r_ptr->d_task_d_gprs & bit_mask) // Increment timeslot ts++; // Shift Mask. bit_mask >>= 1; } // End of while(ts < 8) // AFC control algorithm is called with values retrieved from // burst with max. snr // AFC algorithm is called on bursts 0 and 2: this is sufficient to // have a correct behavior and this permits to gain CPU // Update AFC: Call AFC control function (KALMAN filter). #if AFC_ALGO #if TESTMODE if (l1_config.afc_enable) #endif { if((burst_id == 0) || (burst_id == 2)) #if (VCXO_ALGO == 0) l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)best_angle, best_snr, radio_freq); #else l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)best_angle, best_snr, radio_freq,l1a_l1s_com.mode); #endif } #endif #if (TRACE_TYPE == 1)||(TRACE_TYPE == 4) if (trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_CONDENSED_PDTCH) { if ((l1pa_l1ps_com.tcr_freq_list.ms_ctrl_dd != 0) || ((l1ps.pc_meas_chan_ctrl == TRUE) && ((l1s.actual_time.t2 == 3) || (l1s.actual_time.t2 == 11) || (l1s.actual_time.t2 == 20)))) trace_info.pdtch_trace.blk_status |= 0x80 >> burst_id; } #endif if(l1ps_dsp_com.pdsp_db_r_ptr->d_burst_nb_gprs == 3) /*---------------------------------------------------*/ /* Complete PDTCH DL block has been processed by DSP */ /*---------------------------------------------------*/ { l1pa_l1ps_com.transfer.dl_pwr_ctrl.crc_error = crc_error; /* * FreeCalypso TCS211 reconstruction: the following line * has been taken from the TSM30 source. */ l1pa_l1ps_com.transfer.dl_pwr_ctrl.assignment_id = l1ps.read_param.assignment_id; if(l1ps.read_param.pc_meas_chan) { // Due to the CWR pipeleine, maca_power_control() has to be called before the // CTRL of the first PDTCH i.e. in l1ps_ctrl_pdtch(). It means that crc_error, // radio_freq_tbl[], burst_level[] and bcch_level information are stored on // burst4 of READ phase to be used on burst4 of CTRL phase. l1pa_l1ps_com.transfer.dl_pwr_ctrl.bcch_level = (WORD8)0x80; for(i = 0; i < 4; i++) { l1pa_l1ps_com.transfer.dl_pwr_ctrl.radio_freq_tbl[i] = radio_freq_tbl[i]; l1pa_l1ps_com.transfer.dl_pwr_ctrl.burst_level[i] = burst_level[i]; } } else { // Measures have been performed on BCCH Serving Cell. "burst_level" table is // not applicable. // Download measures made on BCCH Serving Cell. l1pa_l1ps_com.transfer.dl_pwr_ctrl.bcch_level = l1pa_l1ps_com.tcr_freq_list.beacon_meas; for(i = 0; i < 4; i++) { l1pa_l1ps_com.transfer.dl_pwr_ctrl.radio_freq_tbl[i] = radio_freq_tbl[i]; l1pa_l1ps_com.transfer.dl_pwr_ctrl.burst_level[i] = (WORD8)0x80; } // Measures on BCCH Serving Cell are only performed every 40ms while // maca_power_control() is called every 20ms. "beacon_meas" must then // be set to invalid (0x80) until next Serving Cell measure. l1pa_l1ps_com.tcr_freq_list.beacon_meas = (WORD8)0x80; } #if TESTMODE // Test mode stats if (l1_config.TestMode) { // Allocate result message. msg = os_alloc_sig(sizeof(T_TMODE_PDTCH_INFO)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = TMODE_PDTCH_INFO; ((T_TMODE_PDTCH_INFO *)(msg->SigP))->pm_fullres = tm_pm_fullres; // F26.6 ((T_TMODE_PDTCH_INFO *)(msg->SigP))->snr = tm_snr; ((T_TMODE_PDTCH_INFO *)(msg->SigP))->toa = tm_toa; ((T_TMODE_PDTCH_INFO *)(msg->SigP))->angle = tm_angle; // signed for (i=0;i<8;i++) ((T_TMODE_PDTCH_INFO *)(msg->SigP))->crc_error_tbl[i] = crc_error_tbl[i]; // send TMODE_TCH_INFO message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) // reset static TM variables for stats collection tm_pm_fullres = 0; tm_snr = 0; tm_toa = 0; tm_angle = 0; } #endif } } //end of test "if((en_task) && !(task_param))" // End of task -> task must become INACTIVE. // PDTCH can be pipelined and therefore must stay active if // it has already reentered the flow. if(burst_id == BURST_4) { if(l1s.task_status[task].current_status == RE_ENTERED) l1s.task_status[task].current_status = ACTIVE; else l1s.task_status[task].current_status = INACTIVE; } #if 0 /* FreeCalypso TCS211 reconstruction */ l1ddsp_read_iq_dump(task); #endif // Flag the use of the MCU/DSP dual page read interface. // ****************************************************** // Set flag used to change the read page at the end of "l1_synch". l1s_dsp_com.dsp_r_page_used = TRUE; } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM /*-------------------------------------------------------*/ /* l1ps_read_pra_result() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : */ /*-------------------------------------------------------*/ void l1ps_read_pra_result(UWORD8 task, UWORD8 burst_id) { /*--------------------------------------------------------*/ /* READ TRANSMIT TASK RESULTS... */ /*--------------------------------------------------------*/ /*---------------------------------------------------*/ /* Packet Access task. */ /*---------------------------------------------------*/ // Rem: confirmation message is sent at "CTRL" to be able to give FN%42432. BOOL confirm_flag = TRUE; // Default is: confirmation message is sent. // Desactivate the PRACH task. l1s.task_status[task].current_status = INACTIVE; l1_check_com_mismatch(task); #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_PRA, l1pa_l1ps_com.p_idle_param.radio_freq); #endif #if FF_L1_IT_DSP_USF // Check PRACH was controlled if (l1pa_l1ps_com.pra_info.prach_controlled) { #endif // Check USF in case of Dynamic Allocation. if(l1pa_l1ps_com.pra_info.prach_alloc != FIX_PRACH_ALLOC) { API cs_type = l1ps_dsp_com.pdsp_ndb_ptr->a_du_gprs[0][0]; if(cs_type != CS_NONE_TYPE) confirm_flag = FALSE; } if (confirm_flag == TRUE) { // Send confirmation msg to L1A. // ****************************** // For ACCESS phase, a confirmation msg is sent to L1A. xSignalHeaderRec *msg; // send L1C_RA_DONE to L1A... msg = os_alloc_sig(sizeof(T_MPHP_RA_CON)); DEBUGMSG(status,NU_ALLOC_ERR) ((T_MPHP_RA_CON *)(msg->SigP))->fn = l1pa_l1ps_com.pra_info.fn_to_report; ((T_MPHP_RA_CON *)(msg->SigP))->channel_request_data = l1pa_l1ps_com.pra_info.channel_request_data; msg->SignalCode = L1P_RA_DONE; os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } // Set flag used to change the read page at the end of "l1_synch". l1s_dsp_com.dsp_r_page_used = TRUE; #if FF_L1_IT_DSP_USF } // if (l1pa_l1ps_com.pra_info.prach_controlled) #endif } /*-------------------------------------------------------*/ /* l1ps_read_poll_result() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : */ /*-------------------------------------------------------*/ void l1ps_read_poll_result(UWORD8 task, UWORD8 burst_id) { /*--------------------------------------------------------*/ /* READ TRANSMIT TASK RESULTS... */ /*--------------------------------------------------------*/ l1_check_com_mismatch(task); #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) // in debug trace all reads trace_fct(CST_L1PS_READ_POLL, l1pa_l1ps_com.p_idle_param.radio_freq); #endif /*--------------------------------------------------------*/ /* POLL task (4xPRACH) upon packet queueing notification. */ /*--------------------------------------------------------*/ // Deactivate the PRACH task. if(burst_id == BURST_4) { // POLL is a 'one shot' task --> disable task l1a_l1s_com.l1s_en_task[task] = TASK_DISABLED; l1s.task_status[task].current_status = INACTIVE; #if (TRACE_TYPE==5) // in simulation trace only the latest burst trace_fct(CST_L1PS_READ_POLL, l1pa_l1ps_com.p_idle_param.radio_freq); #endif // Send confirmation msg to L1A. // ****************************** // For PACKET POLLING, a confirmation msg is sent to L1A. { xSignalHeaderRec *msg; // send L1C_RA_DONE to L1A... msg = os_alloc_sig(sizeof(T_MPHP_POLLING_IND)); DEBUGMSG(status,NU_ALLOC_ERR) ((T_MPHP_POLLING_IND *)(msg->SigP))->fn = l1pa_l1ps_com.poll_info.fn_to_report; msg->SignalCode = L1P_POLL_DONE; os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } } #if 0 /* FreeCalypso TCS211 reconstruction */ l1ddsp_read_iq_dump(task); #endif // Set flag used to change the read page at the end of "l1_synch". l1s_dsp_com.dsp_r_page_used = TRUE; } #if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM !=0)) // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM enabled //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_START // KEEP IN EXTERNAL MEM otherwise /*-------------------------------------------------------*/ /* l1ps_ctrl_snb_dl() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* packet serving cell normal burst reading tasks: PNP, */ /* PEP, PALLC. This function is the control function for */ /* reading a normal burst on the packet serving cell. */ /* It programs the DSP and the TPU for reading a */ /* normal burst. This function flags the reading of the */ /* Packet Normal paging burst which flag is used in */ /* measurement manager procedure. */ /* Here below is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Catch ARFCN and set CIPHERING reduced frame */ /* number. */ /* - Traces and debug. */ /* - Programs DSP for required task. */ /* - Programs TPU for required task. */ /* - Flag the reading of a Packet Normal Paging */ /* burst. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "l1a_l1s_com.task_param" */ /* task semaphore bit register. Used to skip */ /* the body of this function if L1A has changed or */ /* is changing some of the task parameters. */ /* */ /* "task" */ /* PNP, Packet Normal paging reading task. */ /* PEP, Packet Extended paging reading task. */ /* PALLC, All Packet serving cell PCCCH reading task. */ /* */ /* "burst_id" */ /* BURST_1, 1st burst of the task. */ /* BURST_2, 2nd burst of the task. */ /* BURST_3, 3rd burst of the task. */ /* BURST_4, 4th burst of the task. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.Scell_info" */ /* Serving cell information structure. */ /* .radio_freq, serving cell beacon frequency. */ /* */ /* "l1s.afc" */ /* current AFC value to be applied for the given task. */ /* */ /* "l1s.tpu_offset" */ /* value for the TPU SYNCHRO and OFFSET registers */ /* for current serving cell setting. It is used here */ /* to refresh the TPU SYNCHRO and OFFSET registers */ /* with a corrected (time tracking of the serving) */ /* value prior to reading a serving cell normal burst. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "pnp_ctrl" */ /* Flag set when a packet normal paging burst reading */ /* is controled. This flag is used by the packet */ /* measurement manager procedure, at the end of L1S, */ /* in order to scheduling the neighbor cell */ /* measurements. */ /* -> set to 1. */ /* */ /* */ /* "l1s.tpu_ctrl_reg" */ /* bit register used to know at the end of L1S if */ /* something has been programmed on the MCU/TPU com. */ /* This is used mainly to swap then the com. page at */ /* the end of a control frame. */ /* -> set CTRL_RX bit in the register. */ /* */ /* "l1s.dsp_ctrl_reg" */ /* bit register used to know at the end of L1S if */ /* something has been programmed on the MCU/DSP com. */ /* This is used mainly to swap then the com. page at */ /* the end of a control frame. */ /* -> set CTRL_RX bit in the register. */ /* */ /*-------------------------------------------------------*/ void l1ps_ctrl_snb_dl(UWORD8 task, UWORD8 burst_id) { UWORD16 Scell_radio_freq; UWORD8 tsc; WORD8 agc; UWORD8 lna_off; UWORD8 adc_active = INACTIVE; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; // By default we choose the hardware filter UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER; #endif #if (NEW_SNR_THRESHOLD == 1) UWORD8 saic_flag = 0; #endif /* NEW_SNR_THRESHOLD */ #if (FF_L1_FAST_DECODING == 1) BOOL fast_decoding_authorized = FALSE; if ( (burst_id == BURST_1) && (l1a_apihisr_com.fast_decoding.status == C_FAST_DECODING_FORBIDDEN) ) { l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_NONE; } fast_decoding_authorized = l1s_check_fast_decoding_authorized(task); if ( fast_decoding_authorized && l1s_check_deferred_control(task,burst_id) ) { /* Control is deferred until the upcoming fast decoding IT */ return; } /* if (fast_decoding_authorized)*/ /* In all other cases, control must be performed now. */ #endif /* FF_L1_FAST_DECODING == 1 */ if(!(l1a_l1s_com.task_param[task] == SEMAPHORE_SET)) // Check the task semaphore. The control body is executed only // when the task semaphore is 0. This semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. { Scell_radio_freq = l1a_l1s_com.Scell_info.radio_freq; // Catch training sequence code from serving cell BCC (part of BSIC). tsc = l1pa_l1ps_com.pccch.packet_chn_desc.tsc; // Packet PAGC Algorithm // ********************** // for PCCCH serving blocks (PPCH, PEPCH, all PCCCH) we use // PAGC algorithm. Reference is serving cell. l1pctl_pagc_ctrl(&agc, &lna_off, l1pa_l1ps_com.p_idle_param.radio_freq,TRUE); #if(RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID , l1a_l1s_com.Scell_used_IL.input_level, l1pa_l1ps_com.p_idle_param.radio_freq, if_threshold); l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); #endif #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function // NOTE: l1a_l1s_com.Scell_used_IL.input_level is updated within // the function l1pctl_pagc_ctrl csf_filter_choice = l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode #if (NEW_SNR_THRESHOLD == 1) ,task ,&saic_flag #endif ); #endif // Debug. // ****************** l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; #if (FF_L1_FAST_DECODING == 1) l1ddsp_load_fast_dec_task(task,burst_id); #endif // Programs DSP Rx Packet Idle burst, still on Timeslot number = 0 // due to previous synchro. #if FF_L1_IT_DSP_USF { BOOL usf_it = FALSE; // Force IT USF interrupt during PCCCH reorg for Fast USF usage during // Packet Access. Switch to PA could happen any time during PCCCH reorg. // Only relevant for RBN%3 = 0 and 1 if (l1a_l1s_com.l1s_en_task[PALLC] == TASK_ENABLED) { if (/*(l1s.next_time.fn_mod13 >= 0) && omaps00090550*/(l1s.next_time.fn_mod13 <= 7)) usf_it = TRUE; } l1pddsp_idle_rx_nb(burst_id, tsc, l1pa_l1ps_com.p_idle_param.radio_freq, 0, FALSE, usf_it); } #else l1pddsp_idle_rx_nb(burst_id, tsc, l1pa_l1ps_com.p_idle_param.radio_freq, 0, FALSE); #endif // ADC measurement // *************** // check if during the 1st burst of the bloc an ADC measurement must be performed if ((burst_id == BURST_1) && (task == PNP)) { if (l1a_l1s_com.l1s_en_task[PALLC] == TASK_DISABLED) // no reorg mode { if (l1a_l1s_com.adc_mode & ADC_NEXT_NORM_PAGING) // perform ADC only one time { adc_active = ACTIVE; l1a_l1s_com.adc_mode &= ADC_MASK_RESET_IDLE; // reset in order to have only one ADC measurement in Idle } else { if (l1a_l1s_com.adc_mode & ADC_EACH_NORM_PAGING) // perform ADC on each "period" x bloc if ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_idle_period) // wait for the period { adc_active = ACTIVE; l1a_l1s_com.adc_cpt = 0; } } } else // ADC measurement in reorg mode { if (l1a_l1s_com.adc_mode & ADC_NEXT_NORM_PAGING_REORG) // perform ADC only one time { adc_active = ACTIVE; l1a_l1s_com.adc_mode &= ADC_MASK_RESET_IDLE; // reset in order to have only one ADC measurement in Idle } else { if (l1a_l1s_com.adc_mode & ADC_EACH_NORM_PAGING_REORG) // perform ADC on each "period" x bloc if ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_idle_period) // wait for the period { adc_active = ACTIVE; l1a_l1s_com.adc_cpt = 0; } } } } #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1PS_CTRL_SNB_DL, -1); #endif // Programs TPU for required task. // ******************************** // update the TPU with the new TOA if necessary l1ctl_update_TPU_with_toa(); // tpu pgm... l1dtpu_serv_rx_nb(l1pa_l1ps_com.p_idle_param.radio_freq, agc, lna_off, l1s.tpu_offset, l1s.tpu_offset, FALSE,adc_active #if (RF_FAM == 61) ,csf_filter_choice ,if_ctl #endif #if (NEW_SNR_THRESHOLD == 1) ,saic_flag #endif /* NEW_SNR_THRESHOLD */ ); // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + RX_LOAD); } // Flag the reading of a Normal Packet Paging burst. // ************************************************* // Set PNP controlled flag, used in l1s_meas_manager() to generate measurement only // if we are not receiving a PPCH. if((task == PNP) || (task == PEP) || (task == PALLC)) l1pa_l1ps_com.cr_freq_list.pnp_ctrl = burst_id + 1; // Flag DSP and TPU programmation. // ******************************** // Set "CTRL_RX" flag in the controle flag register. l1s.tpu_ctrl_reg |= CTRL_RX; l1s.dsp_ctrl_reg |= CTRL_RX; } // end of procedure /*-------------------------------------------------------*/ /* l1ps_read_nb_dl() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: PNP,PEP,PALLC. */ /* */ /* Here is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low and task still enabled. */ /* - Traces and debug. */ /* - Read control results and feed control algo. */ /* - Read DL DATA block from MCU/DSP interface. */ /* - Disactivate task. */ /* - Flag the use of the MCU/DSP dual page read */ /* interface. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* PNP, Packet Normal paging reading task. */ /* PEP, Packet Extended paging reading task. */ /* PALLC, All packet serving cell PCCCH reading task. */ /* */ /* "burst_id" */ /* BURST_1, 1st burst of the task. */ /* BURST_2, 2nd burst of the task. */ /* BURST_3, 3rd burst of the task. */ /* BURST_4, 4th burst of the task. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1pa_l1ps_com.task_param[NBR_DL_L1S_TASKS]" */ /* packet task semaphore table. Used to skip */ /* the body of this function if L1A has changed or */ /* is changing some of the task parameters. */ /* */ /* "l1a_l1s_com.l1s_en_task[NBR_DL_L1S_TASKS]" */ /* L1S task enable. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.task_status[task].current_status" */ /* current task status. It must be reset (INACTIVE) */ /* when the task is completed. */ /* -> disactivate task. */ /* */ /* "l1s_dsp_com.dsp_r_page_used" */ /* Flag used by the function which closes L1S */ /* execution ("l1s_end_manager()") to know if the */ /* MCU/DSP read page must be switched. */ /* -> Set to 1. */ /* */ /* Use of MCU/DSP interface: */ /* ------------------------- */ /* "l1s_dsp_com.dsp_ndb_ptr" */ /* pointer to the non double buffered part (NDB) of */ /* the MCU/DSP interface. This part is R/W for both */ /* DSP and MCU. */ /* */ /* "l1s_dsp_com.dsp_db_r_ptr" */ /* pointer to the double buffered part (DB) of the */ /* MCU/DSP interface. This pointer points to the READ */ /* page. */ /* */ /*-------------------------------------------------------*/ void l1ps_read_nb_dl(UWORD8 task, UWORD8 burst_id) { UWORD32 toa=0; //omaps00090550 UWORD32 pm=0; //omaps00090550; UWORD32 angle =0; //omaps00090550 UWORD32 snr =0; //omaps00090550 BOOL en_task; BOOL task_param; UWORD16 scell_radio_freq; static UWORD16 pwr_level; #if (FF_L1_FAST_DECODING == 1) UWORD8 skipped_bursts = 0; BOOL fast_decoding_authorized = l1s_check_fast_decoding_authorized(task); BOOL fast_decoded = (l1a_apihisr_com.fast_decoding.status == C_FAST_DECODING_COMPLETE); if (fast_decoded) { skipped_bursts = BURST_4 - burst_id; } #endif /* if (FF_L1_FAST_DECODING == 1) */ /*--------------------------------------------------------*/ /* READ SERVING CELL RECEIVE TASK RESULTS... */ /*--------------------------------------------------------*/ /* Rem: only a partial result is present in the mcu<-dsp */ /* communication buffer. The DATA BLOCK content itself is */ /* in the last comm. (BURST_4) */ /*--------------------------------------------------------*/ // Get "enable" task flag and "synchro semaphore" for current task. en_task = l1a_l1s_com.l1s_en_task[task]; task_param = l1a_l1s_com.task_param[task]; if((en_task) && !(task_param)) // Check the task semaphore and the task enable bit. The reading // task body is executed only when the task semaphore is 0 and the // task is still enabled. // The semaphore can be set to 1 whenever L1A makes some changes // to the task parameters. The task can be disabled by L1A. { // Traces and debug. // ****************** l1_check_com_mismatch(task); // Read control results and feed control algorithms. // ************************************************** if ((task != PBCCHN_TRAN) && (task != PBCCHN_IDLE)) { // From the fact that PBCCHS can be read in CS mode, // Idle mode and Packet Idle mode, a check on the current active DSP scheduler mode // has to be performed. // Read control information. // We keep compatibility with (chipset == 0) imply mask with 0xffff. // If only (chipset == 2) is used, mask can be removed. if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER) { toa = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA] & 0xffff; pm = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM] & 0xffff) >> 5; angle = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_ANGLE] & 0xffff; snr = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_SNR] & 0xffff; } else { toa = l1ps_dsp_com.pdsp_db_r_ptr->a_burst_toa_gprs[0] & 0xffff; pm = (l1ps_dsp_com.pdsp_db_r_ptr->a_burst_pm_gprs[0] & 0xffff)>>5; angle = l1ps_dsp_com.pdsp_db_r_ptr->a_burst_angle_gprs[0] & 0xffff; snr = l1ps_dsp_com.pdsp_db_r_ptr->a_burst_snr_gprs[0] & 0xffff; } #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1PS_READ_NB_DL, -1); #endif l1_check_pm_error(pm,task); // Update AGC: Call PAGC algorithm l1a_l1s_com.Scell_IL_for_rxlev = l1pctl_pagc_read((UWORD8)pm, l1pa_l1ps_com.p_idle_param.radio_freq_dd); #if (FF_L1_FAST_DECODING == 1) if (skipped_bursts>0) { l1ctl_pagc_missing_bursts(skipped_bursts); } #endif /* if (FF_L1_FAST_DECODING == 1) */ // Update AFC: Call AFC control function (KALMAN filter). #if AFC_ALGO { WORD16 old_afc = l1s.afc; WORD16 old_count= l1s.afc_frame_count; scell_radio_freq = l1a_l1s_com.Scell_info.radio_freq; #if (VCXO_ALGO==0) l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, scell_radio_freq); #else l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, scell_radio_freq,l1a_l1s_com.mode); #endif #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_AFC_OPEN) buffer_trace (4,(WORD16)angle,old_count,old_afc,l1s.afc); #endif #endif } #endif // Feed TOA histogram only when the TOA result is used in the task CTRL function if (task != PBCCHS) { //Feed TOA histogram. #if (TOA_ALGO != 0) #if (TOA_ALGO == 2) if(l1s.toa_var.toa_snr_mask == 0) #else if(l1s.toa_snr_mask == 0) #endif { #if (TOA_ALGO == 2) UWORD32 snr_temp; snr_temp = (l1a_l1s_com.Scell_IL_for_rxlev < IL_FOR_RXLEV_SNR) ? snr: 0; l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa); #else /* FreeCalypso TCS211 reconstruction */ if (l1a_l1s_com.Scell_IL_for_rxlev < IL_FOR_RXLEV_SNR) { l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa, &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING == 1) ,0 #endif ); } else { l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING == 1) ,0 #endif ); } #endif } #endif } } #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, l1a_l1s_com.Scell_IL_for_rxlev + l1a_l1s_com.Scell_info.pb) #endif #if 0 //(TRACE_TYPE == 1) || (TRACE_TYPE == 4) // TCS211 reconstruction l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, l1a_l1s_com.Scell_IL_for_rxlev + l1a_l1s_com.Scell_info.pb); #endif #if (BURST_PARAM_LOG_ENABLE == 1) l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, l1a_l1s_com.Scell_IL_for_rxlev + l1a_l1s_com.Scell_info.pb); #endif // compute the Data bloc Power. // ****************************** if(burst_id == BURST_1) pwr_level = 0; // add the burst power pwr_level += l1a_l1s_com.Scell_IL_for_rxlev; // Read downlink DATA block from MCU/DSP interface. // ************************************************* #if (FF_L1_FAST_DECODING == 1) /* Perform the reporting if - Burst is the 4th one (whether CRC is ok or not) - Fast decoding enabled and CRC already ok */ if ( (burst_id == BURST_4) || fast_decoded ) #else /* #if (FF_L1_FAST_DECODING == 1) */ if(burst_id == BURST_4) #endif /* FF_L1_FAST_DECODING */ { #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace(task); #endif #if (FF_L1_FAST_DECODING == 1) /* Data power block = pwr_level / (nb of bursts)*/ pwr_level = pwr_level / (burst_id + 1); #else /* #if (FF_L1_FAST_DECODING == 1) */ // the data power bloc = pwr_level/4. pwr_level = pwr_level >> 2; #endif /* #if (FF_L1_FAST_DECODING == 1) #else*/ // Read L3 frame block and send msg to L1A. #if (FF_L1_FAST_DECODING == 1) if(!fast_decoding_authorized) { /* When fast decoding wasn't used, burst_id is undefined (for the trace) */ l1a_l1s_com.last_fast_decoding = 0; } else { l1a_l1s_com.last_fast_decoding = burst_id + 1; } #endif /* #if (FF_L1_FAST_DECODING == 1) */ // Read L3 frame block and send msg to L1A. if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER) l1s_read_l3frm(pwr_level,&(l1s_dsp_com.dsp_ndb_ptr->a_cd[0]), task); else l1s_read_l3frm(pwr_level,&(l1ps_dsp_com.pdsp_ndb_ptr->a_dd_gprs[0][0]), task); } // End if... } //end of test "if((en_task) && !(task_param))" // Disactivate task. // ****************** // End of task -> task must become INACTIVE. // Rem: some TASKS (PALLC, PNP (with SPLIT > M)) can be pipelined and therefore // must stay active if they have already reentered the flow. #if (FF_L1_FAST_DECODING == 1) /*------------------------------------------------------*/ /* Perform the reporting if */ /* - Burst is the 4th one (whether CRC is ok or not) */ /* - Fast decoding enabled and CRC already ok */ /*------------------------------------------------------*/ if ( (burst_id == BURST_4) || fast_decoded ) #else /* #if (FF_L1_FAST_DECODING == 1) */ if(burst_id == BURST_4) #endif /* #if (FF_L1_FAST_DECODING == 1) #else*/ { #if (FF_L1_FAST_DECODING == 1) if(task == PNP) { if (l1a_apihisr_com.fast_decoding.contiguous_decoding == TRUE) { /* A new block has started, a new fast API IT is expected */ l1a_apihisr_com.fast_decoding.contiguous_decoding = FALSE; l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_AWAITED; } else if(task == l1a_apihisr_com.fast_decoding.task) { /* Reset decoding status */ l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_NONE; } } /*task == PNP */ #endif /* #if (FF_L1_FAST_DECODING == 1) */ if(l1s.task_status[task].current_status == RE_ENTERED) l1s.task_status[task].current_status = ACTIVE; else l1s.task_status[task].current_status = INACTIVE; #if (FF_L1_FAST_DECODING == 1) if (burst_id != BURST_4) { l1s_clean_mftab(task, burst_id + 3); if(l1s.frame_count == (4 -burst_id)) { l1s.frame_count = 1; } } #endif /* #if (FF_L1_FAST_DECODING == 1) */ } #if 0 /* FreeCalypso TCS211 reconstruction */ l1ddsp_read_iq_dump(task); #endif // Flag the use of the MCU/DSP dual page read interface. // ****************************************************** // Set flag used to change the read page at the end of "l1_synch". l1s_dsp_com.dsp_r_page_used = TRUE; } // end of procedure //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END // KEEP IN EXTERNAL MEM otherwise #endif /*-------------------------------------------------------*/ /* l1ps_ctrl_pbcch() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: neighbor cell PBCCH. */ /* This function is the control function */ /* for reading a PBCCH burst on the neighbor cell. */ /* This control function: */ /* a) shifts the OFFSET register to match the normal */ /* burst received task with the PBCCH timeslot number.*/ /* */ /* b) programs a normal burst reading and restores the */ /* OFFSET to the serving cell timeslot. On the last */ /* control (4th burst), the SYNCHRO/OFFSET registers */ /* are shifted back to the normal idle mode PCCH */ /* reading setting. Here is a summary of the */ /* execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Traces and debug. */ /* - Programs DSP for PBCCH task, reading 1 burst. */ /* - Programs TPU for PBCCH task, reading 1 burst. */ /* - Shift TPU SYNCHRO/OFFSET registers back to the */ /* PACKET PAGING TASK timeslot. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* PBCCH_TRA or PBCCH_IDLE or PBCCHS */ /* Serving Cell PBCCH reading task. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1pa_l1ps_com.pbcch " */ /* Neigh/serv Cell PBCCH description structure. */ /* */ /* "l1a_l1s_com.Scell_info.radio_freq" */ /* BSIC of the serving cell. It is used here to pass */ /* the training sequence number (part of BSIC) to the */ /* DSP. */ /* */ /* "l1a_l1s_com.offset_tn0" */ /* value to load in the OFFSET register to shift then */ /* any receive task to the timeslot 0 of the neighbor */ /* cell or PBCCH timeslot number . */ /* */ /* "l1s.tpu_offset" */ /* value for the TPU SYNCHRO and OFFSET registers */ /* for current serving cell setting. It is used here */ /* at the end of the PBCCH task controls to restore */ /* the SYNCHRO/OFFSET registers to the normal setting */ /* in idle mode. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.actual_time, l1s.next_time" */ /* frame number and derived numbers for current frame */ /* and next frame. */ /* -> update to cope with side effect due to synchro. */ /* changes/restores. */ /* */ /* "l1s.tpu_ctrl_reg" */ /* bit register used to know at the end of L1S if */ /* something has been programmed on the MCU/TPU com. */ /* This is used mainly to swap then the com. page at */ /* the end of a control frame. */ /* -> set CTRL_RX bit in the register. */ /* */ /* "l1s.dsp_ctrl_reg" */ /* bit register used to know at the end of L1S if */ /* something has been programmed on the MCU/DSP com. */ /* This is used mainly to swap then the com. page at */ /* the end of a control frame. */ /* -> set CTRL_RX bit in the register. */ /* */ /*-------------------------------------------------------*/ void l1ps_ctrl_pbcch(UWORD8 task, UWORD8 burst_id) { UWORD16 rx_radio_freq; UWORD32 offset_pbcch; WORD8 agc; UWORD8 lna_off; UWORD32 dsp_task; UWORD8 tsc; UWORD8 serving_cell; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb=0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; // By default we choose the hardware filter UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER; #endif #if (NEW_SNR_THRESHOLD == 1) UWORD8 saic_flag=0; #endif /* NEW_SNR_THRESHOLD */ static WORD32 new_tpu_offset; static BOOL change_synchro; #define PbcchS l1pa_l1ps_com.pbcchs #define PbcchN l1pa_l1ps_com.pbcchn #if (CODE_VERSION == SIMULATION) UWORD32 tpu_w_page; if (hw.tpu_r_page==0) tpu_w_page=1; else tpu_w_page=0; hw.rx_id[tpu_w_page][0]=0; hw.num_rx[tpu_w_page][0]=1; hw.rx_group_id[tpu_w_page]=1; #endif if (task == PBCCHS) { tsc = PbcchS.packet_chn_desc.tsc; offset_pbcch = (PbcchS.tn_pbcch * TN_WIDTH); serving_cell = TRUE; } else { tsc = PbcchN.packet_chn_desc.tsc; offset_pbcch = PbcchN.time_alignmt; serving_cell = FALSE; } if((l1a_l1s_com.l1s_en_task[task] == TASK_ENABLED) && !(l1a_l1s_com.task_param[task] == SEMAPHORE_SET)) // Check the task semaphore. The control body is executed only // when the task semaphore is 0. This semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. { // Get ARFCN to be used for current control. Output of the hopping algorithm. rx_radio_freq = l1pa_l1ps_com.p_idle_param.radio_freq; // Traces and debug. // ****************** #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[task].name); #endif #if (TRACE_TYPE!=0) if (task == PBCCHS) trace_fct(CST_L1PS_CTRL_PBCCHS, l1a_l1s_com.Scell_info.radio_freq); else trace_fct(CST_L1PS_CTRL_PBCCHN, PbcchN.bcch_carrier); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Programs DSP for PBCCHN task according to the DSP scheduler used // ***************************************************************** switch(l1a_l1s_com.dsp_scheduler_mode) { // dsp pgm is made using GSM scheduler... case GSM_SCHEDULER: dsp_task = l1s_swap_iq_dl(rx_radio_freq, task); // dsp pgm... l1ddsp_load_rx_task(dsp_task,burst_id,tsc); break; // dsp pgm is made using GPRS scheduler... case GPRS_SCHEDULER: #if FF_L1_IT_DSP_USF l1pddsp_idle_rx_nb(burst_id,tsc,rx_radio_freq,0,FALSE,FALSE); #else l1pddsp_idle_rx_nb(burst_id,tsc,rx_radio_freq,0,FALSE); #endif break; } // Check if "Synchro" change is needed. // ************************************* // If so the synchro is changed by 4 timeslots. if(burst_id == BURST_1) { if (task == PBCCHS) change_synchro = PbcchS.change_synchro; else change_synchro = PbcchN.change_synchro; if(change_synchro) { // compute TPU offset for "current timeslot + 4 timeslot" new_tpu_offset = l1s.tpu_offset + (4 * TN_WIDTH); if(new_tpu_offset >= TPU_CLOCK_RANGE) new_tpu_offset -= TPU_CLOCK_RANGE; // Slide synchro to match current timeslot + 4 timeslot. l1dmacro_synchro(SWITCH_TIME, new_tpu_offset); } else { new_tpu_offset = l1s.tpu_offset; } } // TPU pgm... //----------- offset_pbcch += new_tpu_offset; if (offset_pbcch >= TPU_CLOCK_RANGE) offset_pbcch -= TPU_CLOCK_RANGE; // add for debug TPU simu #if (CODE_VERSION == SIMULATION) if (task == PBCCHS) // PBCCH serving, compute Ts related to the L1 synchro on the serving hw.rx_id[tpu_w_page][0]=((TPU_CLOCK_RANGE-new_tpu_offset+offset_pbcch)%TPU_CLOCK_RANGE)/TN_WIDTH; else // PBCCH Neighbor -> special value for PBCCHN detection in the DSP task hw.rx_id[tpu_w_page][0]=10; #endif // agc is set with the input_level computed from PAGC algo l1pctl_pagc_ctrl(&agc, &lna_off, rx_radio_freq, serving_cell); #if(RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID , l1a_l1s_com.Scell_used_IL.input_level , rx_radio_freq, if_threshold); l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); #endif #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function // NOTE: l1a_l1s_com.Scell_used_IL.input_level is updated within // l1pctl_pagc_ctrl if(task == PBCCHS) { // Call SAIC only for PBCCHS, not for PBCCHN_TRAN or PBCCHN_IDLE csf_filter_choice = l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode #if (NEW_SNR_THRESHOLD == 1) ,task ,&saic_flag #endif ); } #endif l1dmacro_offset (offset_pbcch, l1_config.params.rx_change_offset_time); // Slide offset to cope with PBCCHN in the new sychro. l1dmacro_rx_synth(rx_radio_freq); // load SYNTH. l1dmacro_agc (rx_radio_freq,agc, lna_off #if(RF_FAM == 61) ,if_ctl #endif ); // load AGC. #if (L1_MADC_ON == 1) #if (RF_FAM == 61) l1dmacro_rx_nb (rx_radio_freq,INACTIVE, csf_filter_choice #if (NEW_SNR_THRESHOLD == 1) ,saic_flag #endif /* NEW_SNR_THRESHOLD */ ); // RX window for NB. #endif /* RF_FAM == 61*/ #else /* L1_MADC_ON == 1*/ l1dmacro_rx_nb (rx_radio_freq); // RX window for NB. #endif if (task == PBCCHS) { #if ((ANLG_FAM == 1) || (ANLG_FAM == 2) || (ANLG_FAM == 3)) l1ddsp_load_afc(l1s.afc); // Loading the afc value in DB,Flag the presence of a new afc value to send #endif #if (RF_FAM == 61) l1dtpu_load_afc(l1s.afc); #endif } l1dmacro_offset (new_tpu_offset, IMM); // Restore offset. } // End if(task enabled and semaphore false) // Remark: //-------- // When the task is aborted, we must continue to make dummy // DSP programming to avoid communication mismatch due // to C/W/R pipelining. // We must also ensure the Synchro back since synchro change has surely be done // in the 1st CTRL phase. // Shift TPU SYNCHRO/OFFSET registers back to the default timeslot (normally PCCCH one). // ************************************************************************************** // When the PBCCHN or PBCCHS reading control is completed , // the SYNCHRO/OFFSET registers are shifted back to the normal idle // setting used for PCCH reading on the serving cell. // Check if "Synchro" change was needed. // If so the synchro is changed to recover normal synchro. if(burst_id == BURST_4) { if(change_synchro) { // Slide synchro back to mach current serving timeslot. l1dmacro_synchro(SWITCH_TIME, l1s.tpu_offset); // Increment frame number. l1s.actual_time = l1s.next_time; l1s.next_time = l1s.next_plus_time; l1s_increment_time(&(l1s.next_plus_time), 1); // Increment "next_plus time". l1s.tpu_ctrl_reg |= CTRL_SYCB; l1s.dsp_ctrl_reg |= CTRL_SYNC; #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) trace_fct(CST_L1S_ADJUST_TIME, -1); #endif } } // Flag DSP and TPU programmation. // ******************************** // Set "CTRL_RX" flag in the controle flag register. l1s.tpu_ctrl_reg |= CTRL_RX; l1s.dsp_ctrl_reg |= CTRL_RX; // This task is not compatible with Neigh. Measurement. Store task length // in "forbid_meas" to indicate when the task will last. if((burst_id == BURST_1) && (task != PBCCHN_IDLE)) { // In PBCCHN_IDLE task, l1s.forbid_meas is set by the AGC ctrl l1s.forbid_meas = TASK_ROM_MFTAB[task].size; } } #if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM //#pragma DUPLICATE_FOR_INTERNAL_RAM_START /*-------------------------------------------------------*/ /* l1ps_ctrl_ptcch() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* */ /* Input parameters: */ /* ----------------- */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* */ /*-------------------------------------------------------*/ void l1ps_ctrl_ptcch(UWORD8 param1, UWORD8 param2) { UWORD16 radio_freq; UWORD8 burst_nb; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; #endif #if (NEW_SNR_THRESHOLD == 1) UWORD8 saic_flag=0; #endif /* NEW_SNR_THRESHOLD*/ if(!(l1a_l1s_com.task_param[PTCCH] == SEMAPHORE_SET)) // Check the task semaphore. The control body is executed only // when the task semaphore is 0. This semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. { WORD8 ts; radio_freq = l1pa_l1ps_com.transfer.ptcch.radio_freq; // Traces and debug. // ****************** #if (TRACE_TYPE!=0) if(l1pa_l1ps_com.transfer.ptcch.activity && (PTCCH_DL || PTCCH_UL ) == 0) // trace only if a window is programmed. trace_fct(CST_L1PS_CTRL_PTCCH_EMPTY, radio_freq); #endif #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[PTCCH].name); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; switch (l1s.next_time.fn_mod104) { case 12: burst_nb=0; break; case 38: burst_nb=1; break; case 64: burst_nb=2; break; case 90: burst_nb=3; break; default: burst_nb=0; break; } // Compute timeslot number referenced to current camp timeslot. ts = l1pa_l1ps_com.transfer.aset->packet_ta.ta_tn - l1a_l1s_com.dl_tn; if(ts < 0) ts += 8; else if(ts >= 8) ts -= 8; if(l1pa_l1ps_com.transfer.ptcch.activity & PTCCH_DL) // PTCCH DL activity bit is set: PTCCH DL programmation is required. { #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_CTRL_PTCCH_DL_BURST0 + burst_nb, radio_freq); #endif // Programs DSP for PTCCH/DL. // *************************** { #if FF_L1_IT_DSP_USF l1pddsp_idle_rx_nb(burst_nb, l1pa_l1ps_com.transfer.aset->tsc, radio_freq, ts, TRUE, FALSE); #else l1pddsp_idle_rx_nb(burst_nb, l1pa_l1ps_com.transfer.aset->tsc, radio_freq, ts, TRUE); #endif } // Programs TPU for PTCCH/DL task. // ******************************** { WORD8 agc; UWORD8 lna_off; // AGC updating //------------- l1pctl_pagc_ctrl(&agc, &lna_off, radio_freq,TRUE); #if(RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID, l1a_l1s_com.Scell_used_IL.input_level , radio_freq, if_threshold); l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); #endif #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function // NOTE: l1a_l1s_com.Scell_used_IL.input_level is updated within // the function l1pctl_pagc_ctrl l1ctl_saic(l1a_l1s_com.Scell_used_IL.input_level,l1a_l1s_com.mode #if (NEW_SNR_THRESHOLD == 1) ,PTCCH ,&saic_flag #endif ); #endif // Compute timeslot number referenced to current camp timeslot. // Rem: COULD BE DONE ASYNCHRONOUSLY changing ta_tn definition!!! ts = l1pa_l1ps_com.transfer.aset->packet_ta.ta_tn - l1a_l1s_com.dl_tn; if(ts < 0) ts += 8; else if(ts >= 8) ts -= 8; // Program RX Normal Burst scenario. l1pdtpu_serv_rx_nb(radio_freq, agc, lna_off, ts, l1s.tpu_offset, 1, 1, TRUE,INACTIVE #if(RF_FAM == 61) ,L1_SAIC_HARDWARE_FILTER ,if_ctl #endif #if (NEW_SNR_THRESHOLD == 1) ,saic_flag #endif /* NEW_SNR_THRESHOLD */ ); // Set "CTRL_RX" flag in the controle flag registers. l1s.tpu_ctrl_reg |= CTRL_RX; l1s.dsp_ctrl_reg |= CTRL_RX; } } if(l1pa_l1ps_com.transfer.ptcch.activity & PTCCH_UL) // PTCCH UL activity bit is set: PTCCH UL programmation required. { UWORD8 adc_active = INACTIVE; #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_CTRL_PTCCH_UL, radio_freq); #endif // Programs DSP for PTCCH/UL. // *************************** { UWORD8 cs_type; UWORD16 ptcch_ul_data; // Access burst type ? if (l1pa_l1ps_com.access_burst_type == ACC_BURST_8) { // PRACH 8 bits: data = (0111 1111)b cs_type = CS_PAB8_TYPE; ptcch_ul_data = 0x7F; } else { // PRACH 11 bits: data = (111 1111 1111)b cs_type = CS_PAB11_TYPE; ptcch_ul_data = 0x7FF; } // "As" IDLE POLLING PRACH dsp control. l1pddsp_ul_ptcch_data(cs_type, ptcch_ul_data, l1a_l1s_com.Scell_info.bsic, radio_freq, ts+3); l1pddsp_idle_prach_power(l1s.applied_txpwr, radio_freq, ts+3); } // ADC measurement // *************** { // check if during the SACCH burst an ADC measurement must be performed if (l1a_l1s_com.adc_mode & ADC_NEXT_TRAFFIC_UL) // perform ADC only one time { adc_active = ACTIVE; l1a_l1s_com.adc_mode &= ADC_MASK_RESET_TRAFFIC; // reset in order to have only one ADC measurement in Traffic } else if (l1a_l1s_com.adc_mode & ADC_EACH_TRAFFIC_UL) // perform ADC on each period bloc if ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_traffic_period) // wait for the period { adc_active = ACTIVE; l1a_l1s_com.adc_cpt = 0; } } // Programs TPU for PTCCH/UL task. // ******************************** { // Program TX RA scenario. l1pdtpu_serv_tx(radio_freq, 0, // TA=0. l1s.tpu_offset, ts+3, // tx_id. 1, // 1 PRACH. 1, // tx_group_id. 0, // No switch NB->RA 1, // Driver called for PRACH Burst. l1pa_l1ps_com.transfer.ptcch.activity & PTCCH_DL,adc_active); // Flag RX in same frame as TX } // PTCCH/UL has been executed, // -> PTCCH/DL is then requested for schedule. // -> PTCCH/UL activity flag must be reset. l1pa_l1ps_com.transfer.ptcch.request_dl = TRUE; l1pa_l1ps_com.transfer.ptcch.activity ^= PTCCH_UL; // Set "CTRL_TX" flag in the controle flag register. l1s.tpu_ctrl_reg |= CTRL_TX; l1s.dsp_ctrl_reg |= CTRL_TX; #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_AB(PTCCH,l1s.applied_txpwr) #endif } // End of PTCCH UL programmation } // End of if(...semaphore...) // This task is not compatible with Neigh. Measurement. Store task length // in "forbid_meas" to indicate when the task will last. l1s.forbid_meas = TASK_ROM_MFTAB[PTCCH].size; } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM #if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM //#pragma DUPLICATE_FOR_INTERNAL_RAM_START /*-------------------------------------------------------*/ /* l1s_read_ptcch() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* */ /* Input parameters: */ /* ----------------- */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* */ /*-------------------------------------------------------*/ void l1ps_read_ptcch(UWORD8 param1, UWORD8 param2) { // Traces and debug. // ****************** l1_check_com_mismatch(PTCCH); if(l1pa_l1ps_com.transfer.ptcch.activity & PTCCH_DL) // PTCCH/DL has been executed, { UWORD32 pm; WORD8 ts; // Compute timeslot number referenced to current camp timeslot. ts = l1pa_l1ps_com.transfer.aset->packet_ta.ta_tn - l1a_l1s_com.dl_tn; if(ts < 0) ts += 8; else if(ts >= 8) ts -= 8; #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_PTCCH_DL, l1pa_l1ps_com.transfer.ptcch.radio_freq); #endif // Read control results and feed control algorithms. // ************************************************** // Read control information. pm = (l1ps_dsp_com.pdsp_db_r_ptr->a_burst_pm_gprs[ts] & 0xffff) >> 5; l1_check_pm_error(pm,PTCCH); if(l1s.actual_time.fn_mod104 == 91) // Read PTCCH/DL data block from DSP/MCU interface, a_dd_md_gprs[]. { BOOL crc; UWORD8 ordered_ta; crc = (l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[0] & 0x0100) >> 8; if(!crc) // Block correct, we extract new TA... { UWORD8 word_position = 4+ (l1pa_l1ps_com.transfer.aset->packet_ta.ta_index >> 1); UWORD8 byte_position = l1pa_l1ps_com.transfer.aset->packet_ta.ta_index & 0x01; // Download ordered TA... // IF byte_position // Upper byte contains TA... // ELSE // Lower byte contains TA... // (see GSM04.04) ordered_ta = (l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[word_position] >> (8*byte_position)) & 0x7f; if (ordered_ta < 64) { // PTCCH/DL contains a valid TA for MS: update TA l1pa_l1ps_com.transfer.aset->packet_ta.ta = ordered_ta; // PTCCH/DL activity bit must reset when new TA has been successfully received. l1pa_l1ps_com.transfer.ptcch.activity ^= PTCCH_DL; } } #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) if (trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_DL_PTCCH) // whatever the value is, trace it { Trace_dl_ptcch(ordered_ta, crc, l1pa_l1ps_com.transfer.aset->packet_ta.ta_index, l1pa_l1ps_com.transfer.aset->packet_ta.ta_tn, l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[4], l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[5], l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[6], l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[7], l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[8], l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[9], l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[10], l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[11]); } #endif #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_DL_PTCCH(crc, ordered_ta) // Replace with ordered TA #endif // Reset CS type. l1ps_dsp_com.pdsp_ndb_ptr->a_dd_md_gprs[0] = CS_NONE_TYPE; } } else { #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_PTCCH_UL, l1pa_l1ps_com.transfer.ptcch.radio_freq); #endif } // Set flag used to change the read page at the end of "l1_synch". l1s_dsp_com.dsp_r_page_used = TRUE; // End of task -> task must become INACTIVE. l1s.task_status[PTCCH].current_status = INACTIVE; } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM #if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM //#pragma DUPLICATE_FOR_INTERNAL_RAM_START /*-------------------------------------------------------*/ /* l1ps_ctrl_itmeas() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* task ITMEAS. */ /* This function is the control function for measuring */ /* the signal strength on several specified timeslots (on*/ /* which it's possible according to the multi-slot class)*/ /* of an indicated carrier. */ /* It programs the DSP and the TPU for doing these */ /* measurements */ /* Here below is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Traces and debug. */ /* - Determines on which timeslots measurements can */ /* be done */ /* - Programs DSP for required task. */ /* - Programs TPU for required task. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1pa_l1ps_com.itmeas" */ /* Interference measurement parameters structure */ /* */ /* "l1a_l1s_com.dl_tn" */ /* Timeslot on which L1 is synchronized */ /* */ /* "l1pa_l1ps_com.transfer.aset->multislot_class" */ /* Multi-slot class in Packet transfer */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* */ /* "l1s.tpu_ctrl_reg" */ /* bit register used to know at the end of L1S if */ /* something has been programmed on the MCU/TPU com. */ /* This is used mainly to swap then the com. page at */ /* the end of a control frame. */ /* -> set CTRL_RX bit in the register. */ /* */ /* "l1s.dsp_ctrl_reg" */ /* bit register used to know at the end of L1S if */ /* something has been programmed on the MCU/DSP com. */ /* This is used mainly to swap then the com. page at */ /* the end of a control frame. */ /* -> set CTRL_RX bit in the register. */ /*-------------------------------------------------------*/ void l1ps_ctrl_itmeas(UWORD8 param1, UWORD8 param2) { #if (RF_FAM == 61) UWORD16 dco_algo_ctl_pw = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GPRS; UWORD8 ts = 0; #endif // Traces and debug. // ****************** #if (TRACE_TYPE==5) trace_fct(CST_L1PS_CTRL_ITMEAS, l1pa_l1ps_com.itmeas.radio_freq); #endif // Timeslots selection // ******************** // Packet transfer mode <-> PDTCH task enabled: condition to check !!!! //--------------------- // Timeslots already selected in l1p_asyn.c // Packet idle mode //----------------- if (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_DISABLED) { // If a RX has been programmed on this frame if (l1s.dsp_ctrl_reg & CTRL_RX) { // The pre-processed bitmap with Rx taken into account is taken l1pa_l1ps_com.itmeas.meas_bitmap = l1pa_l1ps_com.itmeas.idle_tn_rx; } else { // The pre-processed bitmap without Rx taken into account is taken l1pa_l1ps_com.itmeas.meas_bitmap = l1pa_l1ps_com.itmeas.idle_tn_no_rx; } } // End if 'packet idle mode' l1pa_l1ps_com.itmeas.dsp_r_page_switch_req = FALSE; // If some measurements can be done if (l1pa_l1ps_com.itmeas.meas_bitmap != 0) { UWORD8 nbmeas; // DSP read page switched or not during the ITMEAS read phase ? if (l1s.dsp_ctrl_reg == NO_CTRL) { // A control task hasn't already been done in this frame --> Read page switch l1pa_l1ps_com.itmeas.dsp_r_page_switch_req = TRUE; } // Traces and debug. // ****************** #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1PS_CTRL_ITMEAS, l1pa_l1ps_com.itmeas.radio_freq); #endif #if(RF_FAM == 61) // Locosto DCO #if (PWMEAS_IF_MODE_FORCE == 0) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw, &if_ctl, (UWORD8) L1_IL_INVALID , 0, l1pa_l1ps_com.itmeas.radio_freq, if_threshold); #else if_ctl = IF_120KHZ_DSP; dco_algo_ctl_pw = DCO_IF_0KHZ; #endif #endif // Program TPU // ************ #if (RF_FAM != 61) nbmeas = l1pdtpu_interf_meas(l1pa_l1ps_com.itmeas.radio_freq, l1_config.params.high_agc, 0, l1pa_l1ps_com.itmeas.meas_bitmap, l1s.tpu_offset, l1s.tpu_win, l1a_l1s_com.dl_tn); #endif #if (RF_FAM == 61) nbmeas = l1pdtpu_interf_meas(l1pa_l1ps_com.itmeas.radio_freq, l1_config.params.high_agc, 0, l1pa_l1ps_com.itmeas.meas_bitmap, l1s.tpu_offset, l1s.tpu_win, l1a_l1s_com.dl_tn, if_ctl); #endif // Program DSP // ************ l1pddsp_interf_meas_ctrl(nbmeas); #if(RF_FAM == 61) // TBD // Reproduce the DCO control for all the power measurement dco_algo_ctl_pw = dco_algo_ctl_pw * 0x55; // Replicate ZLZLZLZL dco_algo_ctl_pw = dco_algo_ctl_pw >> (2*(4 - nbmeas)); // reduce to ZLs of Nbr if(l1s.tcr_prog_done==1) { dco_algo_ctl_pw=((dco_algo_ctl_pw<<2)|(l1s_dsp_com.dsp_db_common_w_ptr->d_dco_algo_ctrl_pw&0x3)); } l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw); // of Meas Programmed #endif // Flag DSP and TPU programmation. // ******************************** // Set "CTRL_RX" flag in the controle flag register. l1s.tpu_ctrl_reg |= CTRL_MS; l1s.dsp_ctrl_reg |= CTRL_MS; } // End if 'nbmeas != 0' // This task is not compatible with Neigh. Measurement. Store task length // in "forbid_meas" to indicate when the task will last. // Rem: Only FB51 task starts from this ctrl function. l1s.forbid_meas = TASK_ROM_MFTAB[ITMEAS].size; } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM #if (MOVE_IN_INTERNAL_RAM == 0) // Must be followed by the pragma used to duplicate the funtion in internal RAM //#pragma DUPLICATE_FOR_INTERNAL_RAM_START /*-------------------------------------------------------*/ /* l1ps_read_itmeas() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* */ /* This function is a "COMPLEX" function used for the */ /* L1S ITMEAS task. */ /* */ /* Here is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low and task still enabled. */ /* - Traces and debug. */ /* - Read interference measurement results in NDB */ /* - Fill and send reporting message */ /* - Disactivate task. */ /* - Flag the use of the MCU/DSP dual page read */ /* interface if needed. */ /* */ /* Input parameters: */ /* ----------------- */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1pa_l1ps_com.itmeas" */ /* Interference measurement parameters structure */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.task_status[task].current_status" */ /* current task status. It must be reset (INACTIVE) */ /* when the task is completed. */ /* -> disactivate task. */ /* */ /* "l1s_dsp_com.dsp_r_page_used" */ /* Flag used by the function which closes L1S */ /* execution ("l1s_end_manager()") to know if the */ /* MCU/DSP read page must be switched. */ /* -> Set to 1 only if no other task was controlled */ /* in the same frame as ITMEAS */ /* */ /* Use of MCU/DSP interface: */ /* ------------------------- */ /* "l1s_dsp_com.dsp_ndb_ptr" */ /* pointer to the non double buffered part (NDB) of */ /* the MCU/DSP interface. This part is R/W for both */ /* DSP and MCU. */ /*-------------------------------------------------------*/ void l1ps_read_itmeas(UWORD8 param1, UWORD8 param2) { xSignalHeaderRec *msg; UWORD8 i; WORD8 delta1_freq, delta2_freq; UWORD16 g_magic; if(!(l1a_l1s_com.task_param[ITMEAS]) && (l1a_l1s_com.l1s_en_task[ITMEAS])) { // Traces and debug. // ****************** #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_ITMEAS, l1pa_l1ps_com.itmeas.radio_freq); #endif // Allocate result message. // ************************ msg = os_alloc_sig(sizeof(T_L1P_ITMEAS_IND)); DEBUGMSG(status,NU_ALLOC_ERR) // Fill msg signal code msg->SignalCode = L1P_ITMEAS_IND; // Fill msg contents // ****************** ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn = l1s.actual_time.fn; // Report measurement bitmap ((T_L1P_ITMEAS_IND *)(msg->SigP))->meas_bitmap = l1pa_l1ps_com.itmeas.meas_bitmap; // Read result from DSP g_magic = l1ctl_get_g_magic(l1pa_l1ps_com.itmeas.radio_freq); delta1_freq = l1ctl_encode_delta1(l1pa_l1ps_com.itmeas.radio_freq); delta2_freq = l1ctl_encode_delta2(l1pa_l1ps_com.itmeas.radio_freq); for (i = 0; i < 8; i++) { UWORD8 pm; WORD16 IL_for_rxlev; pm = (l1ps_dsp_com.pdsp_ndb_ptr->a_interf_meas_gprs[i] & 0xffff) >> 5; // IL processing if (pm == 0) { ((T_L1P_ITMEAS_IND *)(msg->SigP))->rxlev[i] = (WORD8)0x80; } else { IL_for_rxlev = -(pm - (l1_config.params.high_agc << 1) - g_magic) - delta1_freq - delta2_freq; ((T_L1P_ITMEAS_IND *)(msg->SigP))->rxlev[i] = l1s_encode_rxlev(IL_for_rxlev); } } // If the Read phase is done during fn_mod26 = 13 --> measurements have been done // during a PTCCH frame if (l1s.actual_time.t2 == 13) { ((T_L1P_ITMEAS_IND *)(msg->SigP))->position = PTCCH_FRAME; } else // Measurements done during a search frame { ((T_L1P_ITMEAS_IND *)(msg->SigP))->position = SEARCH_FRAME; } // send message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) // ITMEAS is a 'one shot' task --> disable task l1a_l1s_com.l1s_en_task[ITMEAS] = TASK_DISABLED; } // End if "task enabled and semaphore false" // End of task -> task must become INACTIVE. l1s.task_status[ITMEAS].current_status = INACTIVE; // Switch DSP read page if needed if(l1pa_l1ps_com.itmeas.dsp_r_page_switch_req) { // Set flag used to change the read page at the end of "l1_synch". l1s_dsp_com.dsp_r_page_used = TRUE; } } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM //#pragma DUPLICATE_FOR_INTERNAL_RAM_START #endif //#pragma DUPLICATE_FOR_INTERNAL_RAM_END