FreeCalypso > hg > fc-tourmaline
view src/cs/layer1/cfile/l1_cmplx.c @ 291:a72feaed133a
PWT buzzer driver: conditionalize on TARGET_HAS_BUZZER
Here we add a new target config preprocessor symbol TARGET_HAS_BUZZER,
currently defined for c11x and c139; later we also expect to have it
on for FC Venus, and in FC Magnetite we are going to turn it on for
target dsample, just for the sake of completeness and philosophical
correctness.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 26 Mar 2022 19:31:18 +0000 |
parents | 4e78acac3d88 |
children | edcb8364d45b |
line wrap: on
line source
/************* Revision Controle System Header ************* * GSM Layer 1 software * L1_CMPLX.C * * Filename l1_cmplx.c * Copyright 2003 (C) Texas Instruments * ************* Revision Controle System Header *************/ #define L1_CMPLX_C //#pragma DUPLICATE_FOR_INTERNAL_RAM_START #include "l1_macro.h" #include "l1_confg.h" #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" #include <l1_trace.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 //ADDED FOR AAC #if (L1_AAC == 1) #include "l1aac_defty.h" #endif #include "l1_defty.h" #include "cust_os.h" #include "l1_msgty.h" #include "l1_varex.h" #include "l1_proto.h" #include "l1_mftab.h" #include "l1_tabs.h" #include "l1_ver.h" #if L2_L3_SIMUL #include "l2_l3.h" #include "hw_debug.h" #endif #if L1_GPRS #include "l1p_cons.h" #include "l1p_msgt.h" #include "l1p_deft.h" #include "l1p_vare.h" #include "l1p_sign.h" #endif #include "sim_cons.h" #include "sim_def.h" extern T_hw FAR hw; #else #include "abb.h" #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" #if (RF_FAM == 60) #include "pld.h" #endif #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 //ADDED FOR AAC #if (L1_AAC == 1) #include "l1aac_defty.h" #endif #include "l1_defty.h" #include "cust_os.h" #include "l1_msgty.h" #include "l1_varex.h" #include "l1_proto.h" #include "l1_mftab.h" #include "l1_tabs.h" #include "l1_ver.h" #include "l1_trace.h" #include "l1_ctl.h" #if L2_L3_SIMUL #include "l2_l3.h" #include "hw_debug.h" #include "l2_simul.h" #endif #if L1_GPRS #include "l1p_cons.h" #include "l1p_msgt.h" #include "l1p_deft.h" #include "l1p_vare.h" #include "l1p_sign.h" #endif #endif #if(RF_FAM == 61) #include "l1_rf61.h" #include "tpudrv61.h" #endif #include "l1_ctl.h" #if W_A_DSP1 extern UWORD8 old_sacch_DSP_bug; #endif #if TESTMODE #include "l1tm_msgty.h" #include "l1tm_signa.h" #include "l1tm_varex.h" void l1tm_fill_burst (UWORD16 pattern, UWORD16 *TM_ul_data); #if (ANLG_FAM != 11) void ABB_Write_Uplink_Data(SYS_UWORD16 *TM_ul_data); #else // TODO #endif #endif #if ((TRACE_TYPE==2) || (TRACE_TYPE==3)) extern void L1_trace_string(char *s); extern void L1_trace_char (char s); #endif #if (GSM_IDLE_RAM != 0) #if (OP_L1_STANDALONE == 1) #include "csmi_simul.h" #else #include "csmi/sleep.h" #endif #endif #if (RF_FAM == 61) #include "l1_rf61.h" #if (DRP_FW_EXT==1) #include "l1_drp_inc.h" #else #include "drp_drive.h" #endif #endif /*-------------------------------------------------------*/ /* 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 ); void l1dmacro_rx_nb (UWORD16 arfcn); void l1dmacro_afc (UWORD16 afc_value, UWORD8 win_id); void l1dmacro_adc_read_rx (void); #if (CODE_VERSION != SIMULATION) #if (L1_MADC_ON ==1) void l1dmacro_adc_read_rx_cs_mode0(void); #endif #endif #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); #endif #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*/ ); #endif /* RF_FAM == 61*/ void l1ddsp_meas_read (UWORD8 nbmeas, UWORD8 *pm); #if L1_GPRS void l1pddsp_synchro (UWORD8 switch_mode, UWORD8 camp_timeslot); void l1pddsp_load_bcchn_task (UWORD8 tsq,UWORD16 radio_freq); void l1pddsp_meas_ctrl (UWORD8 nbmeas, UWORD8 pm_pos); void l1pddsp_meas_read (UWORD8 nbmeas, UWORD8 *a_pm); #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 #endif #if (RF_FAM == 61) void cust_get_if_dco_ctl_algo (UWORD16* dco_algo_ctl, UWORD8* if_ctl, UWORD8 input_level_flag, UWORD8 input_level, UWORD16 radio_freq, UWORD8 if_threshold); #endif //#pragma DUPLICATE_FOR_INTERNAL_RAM_END extern UWORD16 toa_tab[4]; #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 UWORD16 toa_tab[4]; //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #endif #if TESTMODE UWORD16 TM_ul_data[16]; //Uplink data to be stored into Omega Uplink buffer #endif #if ((REL99 == 1) && (FF_BHO == 1)) void l1dtpu_neig_fbsb(UWORD16 radio_freq, WORD8 agc, UWORD8 lna_off); // Blind handover #endif /*-------------------------------------------------------*/ /* l1s_ctrl_hwtest() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* task HWTEST. This function check the checksum of the */ /* DSP. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.dsp_ctrl_reg" */ /* bit register used to know at the end of L1S if */ /* something has been programmed on the MCU/DSP */ /* interface. This is used mainly to swap then the */ /* com. page at the end of a control frame. */ /* -> set CTRL_TEST bit in the register. */ /*-------------------------------------------------------*/ void l1s_ctrl_hwtest(UWORD8 task, UWORD8 param2) { // Flag DSP programmation. // ************************ l1ddsp_load_monit_task(DSP_TASK_CODE[task],0); // Set "CTRL_TEST" flag in the controle flag register. l1s.dsp_ctrl_reg |= CTRL_TEST; } /*-------------------------------------------------------*/ /* l1s_read_hwtest() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* task HWTEST. This function read the checksum of the */ /* DSP. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1a_l1s_com.l1s_en_task" */ /* L1S task enable bit register. */ /* -> disable HWTEST task. */ /* */ /* "l1s.task_status[HWTEST].current_status" */ /* current task status for HWTEST task. */ /* -> disactivate HWTEST task. */ /* */ /*-------------------------------------------------------*/ void l1s_read_hwtest(UWORD8 task, UWORD8 param2) { #if (TRACE_TYPE==2) || (TRACE_TYPE==3)//OMAPS00090550 UWORD32 flash_type = 0; #endif xSignalHeaderRec *msg; #if (CODE_VERSION != SIMULATION) #if (DSP == 33) || (DSP == 34) || (DSP == 35) || (DSP == 36) || (DSP == 37) || (DSP == 38) || (DSP == 39) l1s.version.dsp_code_version = l1s_dsp_com.dsp_ndb_ptr->d_version_number1; l1s.version.dsp_checksum = (UWORD16) (l1s_dsp_com.dsp_db_r_ptr->a_pm[1] & 0xffff); l1s.version.dsp_patch_version = l1s_dsp_com.dsp_ndb_ptr->d_version_number2; #else l1s.version.dsp_code_version = (UWORD16) (l1s_dsp_com.dsp_db_r_ptr->a_pm[0] & 0xffff); l1s.version.dsp_checksum = (UWORD16) (l1s_dsp_com.dsp_db_r_ptr->a_pm[1] & 0xffff); //l1s.version.dsp_patch_version = (UWORD16) (l1s_dsp_com.dsp_db_r_ptr->a_pm[2] & 0xffff); l1s.version.dsp_patch_version = (UWORD32) *((API *) SC_CHKSUM_VER); //NOTE: dsp_patch_version is duplicated in d_version_number #endif #endif // NOT_SIMULATION // send L1_INIT_HW_CON to L1A... msg = os_alloc_sig(sizeof(T_TST_TEST_HW_CON)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = L1_TEST_HW_INFO; // added for the new naming convention ((T_TST_TEST_HW_CON*)(msg->SigP))->dsp_code_version = l1s.version.dsp_code_version; ((T_TST_TEST_HW_CON*)(msg->SigP))->dsp_checksum = l1s.version.dsp_checksum; ((T_TST_TEST_HW_CON*)(msg->SigP))->dsp_patch_version = l1s.version.dsp_patch_version; ((T_TST_TEST_HW_CON*)(msg->SigP))->mcu_tcs_program_release = l1s.version.mcu_tcs_program_release; ((T_TST_TEST_HW_CON*)(msg->SigP))->mcu_tcs_official = l1s.version.mcu_tcs_official; ((T_TST_TEST_HW_CON*)(msg->SigP))->mcu_tcs_internal = l1s.version.mcu_tcs_internal; os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) #if (TRACE_TYPE==2) || (TRACE_TYPE==3) uart_trace_checksum(flash_type); #endif // HWTEST task is completed, make it INACTIVE. // It is a 1 shot task, it must be also disabled in L1S. l1s.task_status[task].current_status = INACTIVE; l1a_l1s_com.l1s_en_task[HWTEST] = TASK_DISABLED; // 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" only. l1s_dsp_com.dsp_r_page_used = TRUE; } /*-------------------------------------------------------*/ /* l1s_new_synchro() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* task SYNCHRO. This function mainly adapts the L1/TPU */ /* timebase to a new setting. This new setting can come */ /* from a timeslot change or a full change of serving */ /* cell. This change is a big discontinuity, it requires */ /* some global variable reset. Here is a summary of the */ /* execution: */ /* */ /* - Traces for debug. */ /* - Disables the L1S task SYNCHRO (SYNCHRO is 1 shot) */ /* and make it inactive (current status set to */ /* INACTIVE). */ /* - Compute timeshift. */ /* - Program serving cell fine timeshift for TPU. */ /* - Execute serving cell frame number timeshift. */ /* - Flag TPU programmation. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1a_l1s_com.tn_difference" */ /* timeslot difference between new and old setting. */ /* This is used when timeshift is due to a change of */ /* timeslot but on the same serving cell. */ /* -> reset to 0. */ /* */ /* "l1a_l1s_com.Scell_inf.time_alignmt" */ /* fine time difference between current setting and */ /* new setting to achieve. */ /* -> reset to 0. */ /* */ /* "l1a_l1s_com.Scell_inf.fn_offset" */ /* frame number offset between current setting and new */ /* setting to achieve. */ /* -> reset to 0. */ /* */ /* "l1s.tpu_offset" */ /* value for SYNCHRO and OFFSET register in the TPU */ /* for current serving cell setting. */ /* -> set to the new setting. */ /* */ /* "l1a_l1s_com.l1s_en_task" */ /* L1S task enable bit register. */ /* -> disable SYNCHRO task. */ /* */ /* "l1s.task_status[SYNCHRO].current_status" */ /* current task status for SYNCHRO task. */ /* -> disactivate SYNCHRO task. */ /* */ /* "l1s.actual_time, l1s.next_time" */ /* frame number and derived numbers for current frame */ /* and next frame. */ /* -> update to new setting. */ /* */ /* "l1s.tpu_ctrl_reg" */ /* bit register used to know at the end of L1S if */ /* something has been programmed on the MCU/TPU */ /* interface. This is used mainly to swap then the */ /* com. page at the end of a control frame. */ /* -> set CTRL_SYNC bit in the register. */ /* */ /*-------------------------------------------------------*/ void l1s_new_synchro(UWORD8 param1, UWORD8 param2) { WORD32 offset; UWORD32 tpu_offset_shift; T_CELL_INFO *sptr = &(l1a_l1s_com.Scell_info); // Traces for debug mainly used during L1 simulation. // *************************************************** #if (TRACE_TYPE!=0) trace_fct(CST_L1S_NEW_SYNCHRO, l1a_l1s_com.Scell_info.radio_freq); #endif #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_tpu(dltsk_trace[SYNCHRO].name); #endif // Disable SYNCHRO task. // ********************** // SYNCHRO task is a one shot task enabled by L1A and // disables after its execution in L1S. Here is the disabling. l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_DISABLED; l1s.task_status[SYNCHRO].current_status = INACTIVE; #if 0 /* FreeCalypso TCS211 reconstruction */ #if L1_GPRS //Change of mode when synchro is executed when switching from idle to transfer //In this case, PDTCH task has been enabled in transfer mode manager, but the mode is still not PACKET_TRANSFER_MODE if((l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) && (l1a_l1s_com.mode != PACKET_TRANSFER_MODE)) l1a_l1s_com.mode = PACKET_TRANSFER_MODE; #endif #endif // Compute timeshift. // ******************* if(l1a_l1s_com.tn_difference < 0) // "tn_difference" field is not 0 only when the new serving cell is the same // as the old one. Therefore, we are just changing the timeslot. // If the new timeslot if lower than the old one then the serving FN must // be incremented by 1. To do so, we use the "fn_offset" field which is // loaded with "1". { sptr->fn_offset += 1; l1a_l1s_com.tn_difference += 8; } // update the TPU with the new TOA if necessary l1ctl_update_TPU_with_toa(); // Manage shifting value for TPU offset register... // if staying on the same serving cell but changing the RX timeslot (CCCH_GROUP or timeslot), // then the "timeslot difference" between old and new configuration is given in "tn_difference", // else "tn_difference" must contain 0. tpu_offset_shift = (sptr->time_alignmt) + (l1a_l1s_com.tn_difference * BP_DURATION); // Clear "timeslot difference" parameter. l1a_l1s_com.tn_difference = 0; // Get FN difference between actual synchro and the one we are going to switch to. // The switch (slide of OFFSET and REG_COM_INT) is performed at the time "OFFSET - epsilon". // If "tpu_offset_shift" is greater than "OFFSET - epsilon (called SWITCH_TIME)" then // the next interrupt is going to occur very soon after the switch, and new FN comes directly // from current FN + the "fn_offset" (minus 1 since FN has just been incremented). Else 1 frame // is missed and new FN comes from "fn_offset + 1" (minus 1 since FN has just been incremented). offset = sptr->fn_offset - 1; if(tpu_offset_shift <= SWITCH_TIME) offset++; #if L1_FF_WA_OMAPS00099442 if(l1a_l1s_com.change_tpu_offset_flag == TRUE){ l1s.tpu_offset = (l1s.tpu_offset + (TPU_CLOCK_RANGE >> 1) ) % TPU_CLOCK_RANGE; l1a_l1s_com.change_tpu_offset_flag = FALSE; } #endif // Shift "tpu_offset" accordingly to the computed "tpu_offset_shift" value. // Rem: "%" is required since the result value can be greater than 2*TPU_CLOCK_RANGE. l1s.tpu_offset = (l1s.tpu_offset + tpu_offset_shift) % TPU_CLOCK_RANGE; // Program serving cell fine timeshift for TPU. // ********************************************* // Store the fine time shifting program in the MCU/TPU com. l1dmacro_synchro(SWITCH_TIME, l1s.tpu_offset); // Execute serving cell frame number timeshift. // ********************************************* // Slide frame numbers and derived numbers to jump on new setting. l1s_increment_time(&(l1s.actual_time), offset); // Update actual_time. l1s.next_time = l1s.actual_time; l1s_increment_time(&(l1s.next_time), 1); // Next time is actual_time + 1 #if L1_GPRS l1s.next_plus_time = l1s.next_time; l1s_increment_time(&(l1s.next_plus_time), 1); // Next_plus time is next_time + 1 #endif #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) trace_fct(CST_L1S_ADJUST_TIME, (UWORD32)(-1));//OMAPS00090550 #endif #if (TOA_ALGO == 2) // Fix in case of handovers and Test Mode l1s.toa_var.toa_update_fn = l1s.toa_var.toa_update_fn + offset; if(l1s.toa_var.toa_update_fn >= MAX_FN) { l1s.toa_var.toa_update_fn-= MAX_FN; } #endif // the FN was changed: it could have an impact on the gauging algorithm //Nina modify to save power, not forbid deep sleep, only force gauging in next paging /* FreeCalypso Frankenstein: see l1_async.c regarding Nina's change */ #define NINA_ADDED 0 #if NINA_ADDED if(l1s.force_gauging_next_paging_due_to_CCHR != 1) #endif { l1s.pw_mgr.enough_gaug = FALSE; // forbid Deep sleep until next gauging } // Clear Serving offset and bob. sptr->fn_offset = 0; sptr->time_alignmt = 0; // Flag TPU programmation. // ************************ // Set "CTRL_SYNC" flag in the controle flag register. l1s.tpu_ctrl_reg |= CTRL_SYNC; #if (CODE_VERSION == SIMULATION) si_scheduling(MPHC_SCELL_NBCCH_REQ, NULL, TRUE); si_scheduling(MPHC_SCELL_EBCCH_REQ, NULL, TRUE); #endif #if TESTMODE // Continuous mode: if we are in continuous mode: return to the no continuous mode. if ((l1_config.TestMode) && (l1_config.tmode.rf_params.tmode_continuous == TM_CONTINUOUS)) l1_config.tmode.rf_params.tmode_continuous = TM_NO_CONTINUOUS; #endif #if L1_GPRS // Signals the GSM->GPRS or GPRS->GSM switch to the DSP. // ****************************************************** l1pddsp_synchro(l1a_l1s_com.dsp_scheduler_mode, l1a_l1s_com.dl_tn); // Flag DSP programmation. // Set "CTRL_SYNC" flag in the controle flag register. l1s.dsp_ctrl_reg |= CTRL_SYNC; #endif #if (CODE_VERSION == SIMULATION) si_scheduling(MPHC_SCELL_NBCCH_REQ, NULL, TRUE); si_scheduling(MPHC_SCELL_EBCCH_REQ, NULL, TRUE); #endif } /*-------------------------------------------------------*/ /* l1s_ctrl_ADC() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* task ADC. This function program the L1/TPU in order */ /* to perform an ADC measurement in CS_MODE0 */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* */ /*-------------------------------------------------------*/ void l1s_ctrl_ADC(UWORD8 param1, UWORD8 param2) { // Traces and debug. // ****************** #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_ADC, (UWORD32)(-1));//OMAPS00090550 #endif #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[task].name); #endif // In CS_MODE0, MPHC_RXLEV_REQ is not received periodically. In case network is not found, //the period between 2 MPHC_RXLEV_REQ increases and can be as high as 360 seconds (Max Value) // To enable MADC periodically, the function l1dmacro_adc_read_rx_cs_mode0; is called #if (CODE_VERSION != SIMULATION) #if (L1_MADC_ON ==1) if (l1a_l1s_com.mode == CS_MODE0) l1dmacro_adc_read_rx_cs_mode0(); else l1dmacro_adc_read_rx(); // ADC performed into a rx scenario to have BULON and BULENA signals off so maintaining // low power consumption on ABB #else l1dmacro_adc_read_rx(); // ADC performed into a rx scenario to have BULON and BULENA signals off so maintaining // low power consumption on ABB #endif // End of L1_MADC_ON == 1 #else l1dmacro_adc_read_rx(); // ADC performed into a rx scenario to have BULON and BULENA signals off so maintaining // low power consumption on ABB #endif l1s.task_status[ADC_CSMODE0].current_status = INACTIVE; if (l1a_l1s_com.adc_mode & ADC_NEXT_CS_MODE0) // performe ADC only one time { l1a_l1s_com.adc_mode &= ADC_MASK_RESET_IDLE; // reset in order to have only one ADC measurement in CS_MODE0 l1a_l1s_com.l1s_en_task[ADC_CSMODE0] = TASK_DISABLED; // disable the ADC task in case of one shot } // Set "CTRL_MS" flag in the controle flag register. l1s.tpu_ctrl_reg |= CTRL_ADC; } #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 /*-------------------------------------------------------*/ /* l1s_abort() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* task ABORT. When the L1S merge manager routine, */ /* "l1s_merge_manager()", finds a conflict between a */ /* running task and a pending task, it can come to */ /* aborting the running one to start executing the */ /* pending. Here is the routine which resets the comm. */ /* between the MCU and the DSP and TPU. The DSP is also */ /* signaled to abort any ongoing task. Here is a summary */ /* of the execution: */ /* */ /* - Traces for debug. */ /* - Reset MCU/DSP and MCU/TPU communications. */ /* - Signals the ABORT process to the DSP. */ /* - Flag DSP programmation. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1s.tpu_offset" */ /* OFFSET/SYNCHRO registers value for current serving */ /* cell setting. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.dsp_ctrl_reg" */ /* bit register used to know at the end of L1S if */ /* something has been programmed on the MCU/DSP */ /* interface. This is used mainly to swap then the */ /* com. page at the end of a control frame. */ /* -> set CTRL_ABORT bit in the register. */ /* */ /*-------------------------------------------------------*/ void l1s_abort(UWORD8 param1, UWORD8 param2) { // Traces for debug. // ****************** #if (TRACE_TYPE==5) trace_fct(CST_L1S_ABORT, l1a_l1s_com.Scell_info.radio_freq); #endif #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1S_ABORT_W0_R0, (UWORD32)(-1));//OMAPS00090550 #endif #if (TRACE_TYPE==1) || (TRACE_TYPE==4) if (trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_L1S_DEBUG) Trace_L1s_Abort(trace_info.abort_task); #endif // Reset MCU/DSP and MCU/TPU communications. // ****************************************** // Reset Hardware... // Set "tpu_reset_bit" to 1. // Reset DSP write/read page. // Reset communication pointers. // Immediate Reload offset with Serving one. l1d_reset_hw(l1s.tpu_offset); l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Signals the ABORT process to the DSP. // ************************************** // Set "b_abort" to TRUE, dsp will reset current and pending tasks. l1s_dsp_com.dsp_db_w_ptr->d_ctrl_system |= (1 << B_TASK_ABORT); // Tasks are aborted on DSP side => forbid measurements during ABORT l1s.forbid_meas = 1; // Flag DSP programmation. // ************************ // Set "CTRL_ABORT" flag in the controle flag register. l1s.dsp_ctrl_reg |= CTRL_ABORT; #if (FF_L1_FAST_DECODING == 1) /* Reset fast decoding */ l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_NONE; l1a_apihisr_com.fast_decoding.contiguous_decoding = FALSE; #endif /* #if (FF_L1_FAST_DECODING == 1) */ } //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #endif /*-------------------------------------------------------*/ /* l1s_ctrl_msagc() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: BCCHN,FBNEW,SB1,SB2,SBCONF. This function is */ /* the control function for making a power measurement */ /* for refreshing the AGC for those tasks. It programs */ /* the DSP and the TPU for making 1 measurement in the */ /* next frame. Here is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Get the cell information structure. */ /* - Traces and debug. */ /* - Programs DSP for measurement task. */ /* - Programs TPU for measurement task. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* BCCHN, BCCH Neighbor reading task. */ /* FBNEW, Frequency Burst detection task in Idle mode. */ /* SB1, Synchro Burst reading task in Idle mode. */ /* SB2, Synchro Burst detection task in Idle mode. */ /* SBCONF, Synchro Burst confirmation task in Idle */ /* mode. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1s.afc" */ /* current AFC value to be applied for FBNEW and SB2 */ /* tasks in Cell Selection only. */ /* */ /* "l1a_l1s_com.task_param" */ /* task semaphore bit register. Used to skip this */ /* control if L1A has changed or is changing some of */ /* the task parameters. */ /* */ /* "l1a_l1s_com.Ncell_info.bcch" */ /* "l1a_l1s_com.Ncell_info.acquis" */ /* "l1a_l1s_com.Ncell_info.acquis" */ /* "l1a_l1s_com.Ncell_info.conf" */ /* cell information structure used for BCCHN,FBNEW, */ /* SB1/SB2,SBCONF respectively. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.tpu_win" */ /* each frame is composed with a maximum of 3 */ /* working/TPU windows (typically RX/TX/PW). This is */ /* a counter used to count the number of windows */ /* used. */ /* -> incremented. */ /* */ /* "l1s.tpu_ctrl_reg" */ /* bit register used to know at the end of L1S if */ /* something has been programmed on the MCU/TPU */ /* interface. 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 */ /* interface. 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 l1s_ctrl_msagc(UWORD8 task, UWORD8 param2) { #if (RF_FAM == 61) UWORD16 dco_algo_ctl_pw = 0; UWORD8 if_ctl = 0; //OMAPS00090550 UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; #endif if(!(l1a_l1s_com.task_param[task])) // 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. { T_NCELL_SINGLE *cell_info_ptr = NULL; #if (L1_GPRS) T_NCELL_SINGLE pbcchn_cell_info; #endif #if ((REL99 == 1) && (FF_BHO == 1)) T_NCELL_SINGLE bho_cell_info; #endif // Get the cell information structure. // ************************************ switch(task) { case BCCHN: cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_norm];break; case BCCHN_TOP:cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_top];break; case FBNEW: cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id]; break; case SB2: cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id]; break; case SBCONF: cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sbconf_id];break; #if ((REL99 == 1) && (FF_BHO == 1)) case FBSB: { cell_info_ptr = &bho_cell_info; bho_cell_info.radio_freq = l1a_l1s_com.nsync_fbsb.radio_freq; bho_cell_info.fn_offset = l1a_l1s_com.nsync_fbsb.fn_offset; } break; #endif #if (L1_GPRS) case PBCCHN_IDLE: { cell_info_ptr = &pbcchn_cell_info; pbcchn_cell_info.radio_freq = l1pa_l1ps_com.pbcchn.bcch_carrier; pbcchn_cell_info.fn_offset = l1pa_l1ps_com.pbcchn.fn_offset; } break; #endif default: return; } // Traces and debug. // ****************** #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_MSAGC, cell_info_ptr->radio_freq); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Programs DSP for measurement task. // *********************************** // Dsp pgm... (2 measurement). #if L1_GPRS switch (l1a_l1s_com.dsp_scheduler_mode) { case GPRS_SCHEDULER: { l1pddsp_meas_ctrl(2,0); } break; case GSM_SCHEDULER: { l1ddsp_load_monit_task(2, 0); } break; } #else l1ddsp_load_monit_task(2, 0); #endif #if (RF_FAM == 61) #if (PWMEAS_IF_MODE_FORCE == 0) cust_get_if_dco_ctl_algo (&dco_algo_ctl_pw, &if_ctl, (UWORD8) L1_IL_INVALID, 0, cell_info_ptr->radio_freq,C_IF_ZERO_LOW_THRESHOLD_GSM);//OMAPS00090550 #else if_ctl = IF_120KHZ_DSP; dco_algo_ctl_pw = DCO_IF_0KHZ; #endif // Duplicate the outcome of DCO control as there are 2 PM dco_algo_ctl_pw = (((dco_algo_ctl_pw<<2) & 0x0C) | (dco_algo_ctl_pw & 0x03)); // 0000ZLZL l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw); #endif // Programs TPU for measurement task. // *********************************** // tpu pgm: measurement only. if (task == FBNEW) { l1dtpu_meas(cell_info_ptr->radio_freq, l1_config.params.high_agc, 0, // 0 is set for lna_off = 0 l1s.tpu_win, l1s.tpu_offset, INACTIVE #if(RF_FAM == 61) ,L1_AFC_NONE ,if_ctl #endif ); } else { l1dtpu_meas(cell_info_ptr->radio_freq, l1_config.params.high_agc, 0, // 0 is set for lna_off = 0 l1s.tpu_win, l1s.tpu_offset, INACTIVE #if(RF_FAM == 61) ,L1_AFC_SCRIPT_MODE ,if_ctl #endif ); } #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH) buffer_trace(4, l1s.actual_time.fn, cell_info_ptr->radio_freq, cell_info_ptr->fn_offset, l1s.tpu_win); #endif #endif if (task == FBNEW) { // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD); // tpu pgm: measurement only. l1dtpu_meas(cell_info_ptr->radio_freq, l1_config.params.low_agc, 0, // 0 is set for lna_off = 0 l1s.tpu_win, l1s.tpu_offset, INACTIVE #if(RF_FAM == 61) ,L1_AFC_SCRIPT_MODE ,if_ctl #endif ); } else { // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD); // tpu pgm: measurement only. l1dtpu_meas(cell_info_ptr->radio_freq, l1_config.params.low_agc, 0, // 0 is set for lna_off = 0 l1s.tpu_win, l1s.tpu_offset, INACTIVE #if(RF_FAM == 61) ,L1_AFC_SCRIPT_MODE ,if_ctl #endif ); } // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD); } // Flag DSP and TPU programmation. // ******************************** // Set "CTRL_MS" flag in the controle flag register. l1s.tpu_ctrl_reg |= CTRL_MS; l1s.dsp_ctrl_reg |= CTRL_MS; // 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[task].size; } /*-------------------------------------------------------*/ /* l1s_ctrl_fb() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: FBNEW,FB51. This function is the control */ /* function for making a frequency burst acquisition on */ /* a neighbor cell. It programs the DSP and the TPU for */ /* making 1 attempt in reading the frequency burst.Here */ /* is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Traces and debug. */ /* - Programs DSP for FB acquisition task. */ /* - Programs TPU for FB acquisition task. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* FBNEW, Frequency Burst detection task in Idle mode. */ /* FB51, Frequency Burst detection task in Dedicated */ /* mode. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.task_param" */ /* task semaphore bit register. Used to skip this */ /* control if L1A has changed or is changing some of */ /* the task parameters. */ /* */ /* "l1a_l1s_com.Ncell_info.acquis" */ /* cell information structure used for FBNEW and FB51 */ /* tasks. */ /* */ /* "l1a_l1s_com.fb_mode" */ /* the frequency burst detection algorithm implemented */ /* in the DSP uses 2 different modes. The mode to use */ /* is indicated by this global variable and is passed */ /* to the DSP. */ /* */ /* 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 */ /* interface. 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 */ /* interface. 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 l1s_ctrl_fb(UWORD8 task, UWORD8 param2) { WORD8 agc; UWORD8 lna_off; BOOL en_task; BOOL task_param; UWORD32 dsp_task; #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif // 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 enable flag. The control body is executed only // when the task semaphore is 0 and enable flag is 1. The semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. The enable can be // reset to 0 when the task is no more enabled. { T_NCELL_SINGLE *cell_info_ptr = NULL; // Get the cell information structure. // ************************************ cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id]; // Traces and debug. // ****************** #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_FB, cell_info_ptr->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 + 13) ; // Programs DSP for required task. // ******************************** // dsp pgm... dsp_task = l1s_swap_iq_dl(cell_info_ptr->radio_freq,task); l1ddsp_load_monit_task(dsp_task, l1a_l1s_com.fb_mode); // Programs TPU for required task. // ******************************** #if (L1_FF_MULTIBAND == 0) // Get AGC to be applied. agc = Cust_get_agc_from_IL(cell_info_ptr->radio_freq,l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, AV_ID); // lna_off flag is updated ONLY in case of l1ctl_pgc2 control algo lna_off = l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].lna_off; #else // L1_FF_MULTIBAND = 1 below operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(cell_info_ptr->radio_freq ); // lna_off flag is updated ONLY in case of l1ctl_pgc2 control algo lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; // Get AGC to be applied. agc = Cust_get_agc_from_IL(cell_info_ptr->radio_freq,l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, AV_ID); #endif // #if (L1_FF_MULTIBAND == 0) else // tpu pgm... l1dtpu_neig_fb(cell_info_ptr->radio_freq, agc, lna_off); } // 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. // Rem: Only FB51 task starts from this ctrl function. if(task==FB51) l1s.forbid_meas = TASK_ROM_MFTAB[task].size; } /*-------------------------------------------------------*/ /* l1s_ctrl_fbsb() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: FBSB. This function is the control */ /* function for making a frequency + synchro burst */ /* on a neighbor cell in case of blind handover */ /* It programs the DSP and the TPU for */ /* making 1 attempt in reading the frequency & synchro */ /* burst */ /* Here is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Traces and debug. */ /* - Programs DSP for FB+SB acquisition task. */ /* - Programs TPU for FB+SB acquisition task. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* FBSB, Frequency + Synchro burst detection task in */ /* blind handover */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.task_param" */ /* task semaphore bit register. Used to skip this */ /* control if L1A has changed or is changing some of */ /* the task parameters. */ /* */ /* "l1a_l1s_com.nsync_fbsb" */ /* cell information structure used for FBSB tasks. */ /* */ /* 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 */ /* interface. 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 */ /* interface. This is used mainly to swap then the */ /* com. page at the end of a control frame. */ /* -> set CTRL_RX bit in the register. */ /* */ /*-------------------------------------------------------*/ #if ((REL99 == 1) && (FF_BHO == 1)) void l1s_ctrl_fbsb(UWORD8 task, UWORD8 param2) { WORD8 agc; UWORD8 lna_off; UWORD32 dsp_task; //added by sajal for DCXO UWORD8 input_level; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_sb = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; #endif #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif // Traces and debug. // ****************** #if (TRACE_TYPE!=0) // trace_fct(CST_L1S_CTRL_FBSB, l1a_l1s_com.nsync_fbsb.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 + 13) ; // Programs DSP for required task. // ******************************** // dsp pgm... dsp_task = l1s_swap_iq_dl(l1a_l1s_com.nsync_fbsb.radio_freq, task); l1ddsp_load_monit_task(dsp_task, 1); #if (L1_FF_MULTIBAND == 0) input_level = l1a_l1s_com.last_input_level[l1a_l1s_com.nsync_fbsb.radio_freq - l1_config.std.radio_freq_index_offset].input_level; #else operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.nsync_fbsb.radio_freq); input_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; #endif #if (RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_sb, &if_ctl, (UWORD8) L1_IL_VALID , input_level, l1a_l1s_com.nsync_fbsb.radio_freq,if_threshold); l1ddsp_load_dco_ctl_algo_sb(dco_algo_ctl_sb); #endif // Programs TPU for required task. // ******************************** #if (L1_FF_MULTIBAND == 0) // lna_off flag is updated ONLY in case of l1ctl_pgc2 control algo lna_off = l1a_l1s_com.last_input_level[l1a_l1s_com.nsync_fbsb.radio_freq - l1_config.std.radio_freq_index_offset].lna_off; // Get AGC to be applied. agc = Cust_get_agc_from_IL(l1a_l1s_com.nsync_fbsb.radio_freq, l1a_l1s_com.last_input_level[l1a_l1s_com.nsync_fbsb.radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, AV_ID); #else // L1_FF_MULTIBAND = 1 below /*operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(l1a_l1s_com.nsync_fbsb.radio_freq);*/ // lna_off flag is updated ONLY in case of l1ctl_pgc2 control algo lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; // Get AGC to be applied. agc = Cust_get_agc_from_IL(l1a_l1s_com.nsync_fbsb.radio_freq, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, AV_ID); #endif // #if (L1_FF_MULTIBAND == 0) else // tpu pgm... l1dtpu_neig_fbsb(l1a_l1s_com.nsync_fbsb.radio_freq, agc, lna_off); // Disable Task // FTH l1a_l1s_com.l1s_en_task[FBSB] = TASK_DISABLED; // 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; } #endif //#if ((REL99 == 1) && (FF_BHO == 1)) /*-------------------------------------------------------*/ /* l1s_ctrl_sbgen() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: SB1,SB2,SB51,SBCONF,SBCNF51. This function is */ /* the control function for making a synchro burst */ /* reading on a neighbor cell in Cell Selection, Idle */ /* mode and dedicated mode SDCCH. It programs the DSP */ /* and the TPU for making 1 attempt in reading the */ /* synchro burst. Here is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Get the cell information structure. */ /* - Traces and debug. */ /* - Programs DSP for SB reading task. */ /* - Programs TPU for SB reading task. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* SB1, Synchro Burst reading task in Idle mode. */ /* SB2, Synchro Burst detection task in Idle mode. */ /* SBCONF, Synchro Burst confirmation task in Idle */ /* mode. */ /* SB51, Synchro Burst reading task in Dedicated mode. */ /* SBCNF51, Synchro Burst confirmation task in */ /* Dedicated mode. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.task_param" */ /* task semaphore bit register. Used to skip this */ /* control if L1A has changed or is changing some of */ /* the task parameters. */ /* */ /* "l1a_l1s_com.Ncell_info.acquis" */ /* cell information structure used for SB1, SB2 and */ /* SB51 tasks. */ /* */ /* "l1a_l1s_com.Ncell_info.conf" */ /* cell information structure used for SBCONF and */ /* SBCNF51 tasks. */ /* */ /* "l1s.tpu_offset" */ /* value for SYNCHRO and OFFSET register in the TPU */ /* for current serving cell setting. It is used here */ /* by the synchro burst reading TPU driver since this */ /* driver changes the OFFSET register. At the end of */ /* the task it restores the serving cell offset value. */ /* */ /* 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 l1s_ctrl_sbgen(UWORD8 task, UWORD8 attempt) { UWORD8 reload_serv_offset = TRUE; // Default: offset serving reloaded. WORD8 agc; UWORD8 lna_off; BOOL en_task; BOOL task_param; UWORD32 dsp_task; UWORD8 input_level; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_sb = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; #endif #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif // 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 enable flag. The control body is executed only // when the task semaphore is 0 and enable flag is 1. The semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. The enable can be // reset to 0 when the task is no more enabled. { T_NCELL_SINGLE *cell_info_ptr = NULL; switch(task) { case SB2: { // Get the cell information structure. // ************************************ cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id]; if(attempt == 1) reload_serv_offset = FALSE; // Offset serving not reloaded on 1st CTRL. #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_SB2, cell_info_ptr->radio_freq); #endif } break; case SB51: { // Get the cell information structure. // ************************************ cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id]; #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_SB51, cell_info_ptr->radio_freq); #endif } break; case SBCONF: case SBCNF51: { // Get the cell information structure. // ************************************ cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sbconf_id]; #if (TRACE_TYPE!=0) if(task == SBCONF) trace_fct(CST_L1S_CTRL_SBCONF, cell_info_ptr->radio_freq); else trace_fct(CST_L1S_CTRL_SBCNF51, cell_info_ptr->radio_freq); #endif #if (L1_EOTD==1) // We need to trigger the TOA tracking / adjustment period // which logs all TOA updates after E-OTD has started... if(l1a_l1s_com.nsync.eotd_meas_session == TRUE) { if( (l1a_l1s_com.nsync.eotd_toa_phase == 0) && (l1a_l1s_com.nsync.active_sbconf_id == 12) ) { l1a_l1s_com.nsync.eotd_toa_tracking = 0; l1a_l1s_com.nsync.eotd_toa_phase = 1; } l1a_l1s_com.nsync.eotd_cache_toa_tracking = l1a_l1s_com.nsync.eotd_toa_tracking; } #endif } break; default: return; } // Traces and debug. // ****************** #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 + 3) ; // Programs DSP for required task. // ******************************** // dsp pgm... dsp_task = l1s_swap_iq_dl(cell_info_ptr->radio_freq,task); l1ddsp_load_monit_task(dsp_task, 0); #if (L1_FF_MULTIBAND == 0) input_level = l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].input_level; #else // L1_FF_MULTIBAND = 1 below operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(cell_info_ptr->radio_freq); input_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; #endif //#if (L1_FF_MULTIBAND == 0) else #if (RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_sb, &if_ctl, (UWORD8) L1_IL_VALID , input_level, cell_info_ptr->radio_freq,if_threshold); // This is a work-around for a DSP problem (OMAPS00117845) // The problem happens during neighbor FB/SB, when there is an // IDLE frame between neighbor FB and SB. // Neighbor cell SB(SB2) is different from other kind of SB decode. // For SB2 we open the RF window for 2 frames (2 C W W R) // For both Control, l1s_dsp_com.dsp_db_common_w_ptr->d_dco_algo_ctrl_sb is updated. // However DSP copies DB value to NDB and this value is copied only once. // At the end of the first SB, DSP right shifts the NDB variable. // The fix below replicates the DCO control information 4 times // so that DSP has correct information even after right shifting during first SB. if(task == SB2) { dco_algo_ctl_sb *= 0x55; } l1ddsp_load_dco_ctl_algo_sb(dco_algo_ctl_sb); #endif // Programs TPU for required task. // ******************************** #if (L1_FF_MULTIBAND == 0) // Get AGC to be applied. agc = Cust_get_agc_from_IL(cell_info_ptr->radio_freq, input_level >> 1, AV_ID); // lna_off flag is ONLY updated in case of l1ctl_pgc2 control algorithm lna_off = l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].lna_off; #else // L1_FF_MULTIBAND = 0 below operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(cell_info_ptr->radio_freq); // lna_off flag is ONLY updated in case of l1ctl_pgc2 control algorithm lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; // Get AGC to be applied. agc = Cust_get_agc_from_IL(cell_info_ptr->radio_freq, input_level >> 1, AV_ID); #endif // #if (L1_FF_MULTIBAND == 0) else // tpu pgm... l1dtpu_neig_sb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, reload_serv_offset, attempt #if (RF_FAM == 61) ,if_ctl #endif ); #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH) buffer_trace(4, l1s.actual_time.fn, cell_info_ptr->radio_freq, cell_info_ptr->time_alignmt,l1s.tpu_offset); #endif #endif } else // The task has been disabled or some parameters have changed, the serving tpu offset // must be restored. { if(attempt==2) { l1dmacro_offset(l1s.tpu_offset,IMM); } } // 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. // Rem: Only SB51/SBCNF51 tasks start from this ctrl function. if((task==SB51)||(task==SBCNF51)) 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 /*-------------------------------------------------------*/ /* l1s_ctrl_fb26() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: FB26. This function is the control function */ /* for making a frequency burst acquisition attempt on */ /* a neighbor cell in dedicated mode TCH. It programs */ /* the DSP and the TPU for making 1 attempt in reading */ /* the frequency burst.Here is a summary of the */ /* execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Traces and debug. */ /* - Programs DSP for FB acquisition task. */ /* - Programs TPU for FB acquisition task. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.Ncell_info.acquis" */ /* cell information structure used for FB26 task. */ /* */ /* "l1s.tpu_offset" */ /* value for SYNCHRO and OFFSET register in the TPU */ /* for current serving cell setting. It is used here */ /* by the frequency burst reading TPU driver since */ /* this driver changes the OFFSET register. At the end */ /* of the task it restores the serving cell offset */ /* value. */ /* */ /* 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 l1s_ctrl_fb26(UWORD8 param1, UWORD8 param2) { WORD8 agc; BOOL lna_off; UWORD32 dsp_task; UWORD16 radio_freq = 0; #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif #if (L1_12NEIGH ==1) BOOL en_task; BOOL task_param; // Get "enable" task flag and "synchro semaphore" for current task. en_task = l1a_l1s_com.l1s_en_task[param1]; task_param = l1a_l1s_com.task_param[param1]; if((en_task) && !(task_param)) // Check the task semaphore and enable flag. The control body is executed only // when the task semaphore is 0 and enable flag is 1. The semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. The enable can be // reset to 0 when the task is no more enabled. #else if(!(l1a_l1s_com.task_param[FB26] == SEMAPHORE_SET)) #endif // 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. { #if (L1_12NEIGH ==1) T_NCELL_SINGLE *cell_info_ptr = NULL; cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id]; radio_freq = cell_info_ptr->radio_freq; #else radio_freq = l1a_l1s_com.nsync.list[0].radio_freq; #endif // Traces and debug. // ****************** #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_FB26, radio_freq); #endif #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[FB26].name); #endif // Programs DSP for FB26 task. // **************************** // dsp pgm... dsp_task = l1s_swap_iq_dl(radio_freq,FB26); l1ddsp_load_monit_task(dsp_task, 1); // Programs TPU for FB26 task. // **************************** #if (L1_FF_MULTIBAND == 0) // agc is just computed from last stored IL agc = Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, AV_ID); lna_off = l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].lna_off; #else // L1_FF_MULTIBAND = 1 below operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(radio_freq); lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; // agc is just computed from last stored IL agc = Cust_get_agc_from_IL(radio_freq, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, AV_ID); #endif // #if (L1_FF_MULTIBAND == 1) else // tpu pgm... l1dtpu_neig_fb26(radio_freq, agc, lna_off, l1s.tpu_offset); } // 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. // Special case: we set forbid_meas to skip the measurements in the frames // FN%26=24 or 25. l1s.forbid_meas = 3; } //#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_ctrl_sb26() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: SB1,SB2,SB51,SBCONF,SBCNF51. This function is */ /* the control function for making a synchro burst */ /* reading on a neighbor cell in Cell Selection, Idle */ /* mode and dedicated mode SDCCH. It programs the DSP */ /* and the TPU for making 1 attempt in reading the */ /* synchro burst. Here is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Get the cell information structure. */ /* - Traces and debug. */ /* - Programs DSP for SB reading task. */ /* - Programs TPU for SB reading task. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* SB26, Synchro Burst reading task in Dedicated mode, */ /* TCH. */ /* SBCNF26, Synchro Burst confirmation task in Dedic. */ /* mode TCH. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.Ncell_info.acquis" */ /* cell information structure used for SB26 task. */ /* */ /* "l1a_l1s_com.Ncell_info.conf" */ /* cell information structure used for SBCNF26 task. */ /* */ /* "l1s.tpu_offset" */ /* value for SYNCHRO and OFFSET register in the TPU */ /* for current serving cell setting. It is used here */ /* by the synchro burst reading TPU driver since this */ /* driver changes the OFFSET register. At the end of */ /* the task it restores the serving cell offset value. */ /* */ /* 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 l1s_ctrl_sb26(UWORD8 task, UWORD8 param2) { UWORD32 nb_nop = 0; WORD8 agc; BOOL lna_off; UWORD32 dsp_task; UWORD8 input_level; UWORD32 temp; #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif #if (L1_12NEIGH ==1) BOOL en_task; BOOL task_param; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_sb = 0; UWORD8 if_ctl = 0 ; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; #endif // 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)) #else if(!(l1a_l1s_com.task_param[task])) #endif // 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 = 0; UWORD32 time_alignmt = 0; #if (L1_12NEIGH ==1) T_NCELL_SINGLE *cell_info_ptr; if (task == SB26) cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id]; if (task == SBCNF26) { #if (L1_EOTD==1) // We need to trigger the TOA tracking / adjustment period // which logs all TOA updates after E-OTD has started... if(l1a_l1s_com.nsync.eotd_meas_session == TRUE) { if( (l1a_l1s_com.nsync.eotd_toa_phase == 0) && (l1a_l1s_com.nsync.active_sbconf_id == 12) ) { l1a_l1s_com.nsync.eotd_toa_tracking = 0; l1a_l1s_com.nsync.eotd_toa_phase = 1; } l1a_l1s_com.nsync.eotd_cache_toa_tracking = l1a_l1s_com.nsync.eotd_toa_tracking; } #endif cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sbconf_id]; } radio_freq = cell_info_ptr->radio_freq; time_alignmt = cell_info_ptr->time_alignmt; #else // Get the cell information. // ************************** radio_freq = l1a_l1s_com.nsync.list[0].radio_freq; time_alignmt = l1a_l1s_com.nsync.list[0].time_alignmt; #endif // Traces and debug. // ****************** #if (TRACE_TYPE!=0) switch(task) { case SB26: trace_fct(CST_L1S_CTRL_SB26, radio_freq); break; case SBCNF26: trace_fct(CST_L1S_CTRL_SBCNF26, radio_freq); break; } #endif #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[task].name); #endif // Programs DSP for required task. // ******************************** // dsp pgm... dsp_task = l1s_swap_iq_dl(radio_freq,task); l1ddsp_load_monit_task(dsp_task, 0); // Programs TPU for required task. // ******************************** temp = (UWORD32)(l1_config.params.fb26_anchoring_time - EPSILON_SYNC); #if (L1_12NEIGH ==1) if((cell_info_ptr->sb26_offset == 1) && (time_alignmt >= temp)) //omaps00090550 #else if((l1a_l1s_com.nsync.list[0].sb26_offset == 1) && (time_alignmt >= temp)) //omaps00090550 #endif // SB is in the 2nd frame of the search slot... // ...and SB is at the very end of the slot. // We insert a nop in the tpu scenario to // be able to jump the 1st frame. { nb_nop = 1; } #if (L1_FF_MULTIBAND == 0) // agc is just computed from last stored IL input_level = l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].input_level; agc = Cust_get_agc_from_IL(radio_freq, input_level >> 1, AV_ID); lna_off = l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].lna_off; #else // L1_FF_MULTIBAND = 1 below operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(radio_freq); // agc is just computed from last stored IL input_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; agc = Cust_get_agc_from_IL(radio_freq, input_level >> 1, AV_ID); #endif // #if (L1_FF_MULTIBAND == 0) else #if (RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_sb, &if_ctl, (UWORD8) L1_IL_VALID, input_level, radio_freq,if_threshold); l1ddsp_load_dco_ctl_algo_sb(dco_algo_ctl_sb); #endif // tpu pgm... l1dtpu_neig_sb26(radio_freq, agc, lna_off, time_alignmt, nb_nop, l1s.tpu_offset #if (RF_FAM == 61) ,if_ctl #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. // Special case: we set forbid_meas to skip the measurements in the frames // FN%26=24 or 25. l1s.forbid_meas = 3; } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM /*-------------------------------------------------------*/ /* l1s_ctrl_smscb() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: SMSCB. This function is the control function */ /* for reading a CBCH burst on the serving cell. It */ /* shifts the OFFSET register to match the normal burst */ /* receive task with the CBCH timeslot number (0,1,2 or */ /* 3), programs a normal burst reading and restores the */ /* OFFSET to the serving cell timeslot 0. On the last */ /* control (4th burst), the SYNCHRO/OFFSET registers are */ /* shifted back to the normal idle mode PCH reading */ /* setting. Here is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Traces and debug. */ /* - Programs DSP for SMSCB task, reading 1 burst. */ /* - Programs TPU for SMSCB task, reading 1 burst. */ /* - Shift TPU SYNCHRO/OFFSET registers back to the */ /* PAGING TASK timeslot. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* SMSCB, Short Message Service Cell Broadcast. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.cbch_desc" */ /* Cell Broadcast CHannel description structure. */ /* */ /* "l1a_l1s_com.Scell_info.bsic" */ /* BSIC of the serving cell. It is used here to pass */ /* the training sequence number (part of BSIC) to the */ /* DSP. */ /* */ /* "l1s.afc" */ /* current AFC value to be applied for SMSCB reading */ /* task. */ /* */ /* "l1a_l1s_com.offset_tn0" */ /* value to load in the OFFSET register to shift then */ /* any receive task to the timeslot 0 of the serving */ /* cell. This is the default setting to restore after */ /* any CBCH burst reading. */ /* */ /* "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 CBCH 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 l1s_ctrl_smscb(UWORD8 task, UWORD8 burst_id) { UWORD16 rx_radio_freq; UWORD32 offset_smscb; WORD8 agc; UWORD8 lna_off; UWORD32 dsp_task; static WORD32 new_tpu_offset; static BOOL change_synchro; #if 0 /* FreeCalypso TCS211 reconstruction */ UWORD8 input_level; #endif #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif #if (NEW_SNR_THRESHOLD == 1) UWORD8 saic_flag=0; #endif /* NEW_SNR_THRESHOLD */ #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; // By default we choose the hardware filter UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER; #endif // Needed for simulated DSP GRPS scheduler #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((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 = l1a_l1s_com.dedic_set.radio_freq; // Traces and debug. // ****************** #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[task].name); #endif #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_SMSCB, rx_radio_freq); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Programs DSP for SMSCB task according to the DSP scheduler used // **************************************************************** #if L1_GPRS 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,l1a_l1s_com.cbch_desc.tsc); } break; // dsp pgm is made using GPRS scheduler... case GPRS_SCHEDULER: { #if FF_L1_IT_DSP_USF l1pddsp_idle_rx_nb(burst_id,l1a_l1s_com.cbch_desc.tsc,rx_radio_freq,0,FALSE,FALSE); #else l1pddsp_idle_rx_nb(burst_id,l1a_l1s_com.cbch_desc.tsc,rx_radio_freq,0,FALSE); #endif } break; } #else dsp_task = l1s_swap_iq_dl(rx_radio_freq, task); // dsp pgm... l1ddsp_load_rx_task(dsp_task,burst_id,l1a_l1s_com.cbch_desc.tsc); #endif // Check if "Synchro" change is needed. // ************************************* // If so the synchro is changed by 4 timeslots. if(burst_id == BURST_1) { // 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[task].size; change_synchro = l1a_l1s_com.change_synchro_cbch; 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(l1_config.params.rx_change_synchro_time, new_tpu_offset); } else { new_tpu_offset = l1s.tpu_offset; } } // Programs TPU for SMSCB task, reading 1 burst. // ********************************************** offset_smscb = new_tpu_offset + l1a_l1s_com.tn_smscb * TN_WIDTH; if (offset_smscb >= TPU_CLOCK_RANGE) offset_smscb -= TPU_CLOCK_RANGE; #if 1 /* FreeCalypso match TCS211 */ // agc is set with the input_level computed from PAGC algo agc = Cust_get_agc_from_IL(l1a_l1s_com.Scell_info.radio_freq, l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, MAX_ID); lna_off = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].lna_off; #elif (L1_FF_MULTIBAND == 0) // agc is set with the input_level computed from PAGC algo input_level = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].input_level; agc = Cust_get_agc_from_IL(l1a_l1s_com.Scell_info.radio_freq,input_level >> 1, MAX_ID); lna_off = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].lna_off; #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); input_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; agc = Cust_get_agc_from_IL(l1a_l1s_com.Scell_info.radio_freq,input_level >> 1, MAX_ID); #endif // #if (L1_FF_MULTIBAND == 0) else #if(RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID, input_level, l1a_l1s_com.Scell_info.radio_freq,if_threshold); l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); #endif // Store IL used for current CTRL in order to be able to buil IL from pm // in READ phase. #if 1 /* FreeCalypso match TCS211 */ l1a_l1s_com.Scell_used_IL.input_level = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].input_level; l1a_l1s_com.Scell_used_IL.lna_off = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].lna_off; #elif (L1_FF_MULTIBAND == 0) l1a_l1s_com.Scell_used_IL.input_level = input_level; l1a_l1s_com.Scell_used_IL.lna_off = l1a_l1s_com.last_input_level[l1a_l1s_com.Scell_info.radio_freq - l1_config.std.radio_freq_index_offset].lna_off; #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); l1a_l1s_com.Scell_used_IL.input_level = input_level; l1a_l1s_com.Scell_used_IL.lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; #endif // #if (L1_FF_MULTIBAND == 1) else #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function 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... l1dtpu_serv_rx_nb(rx_radio_freq, agc, lna_off, new_tpu_offset, offset_smscb, TRUE, FALSE #if (RF_FAM == 61) ,csf_filter_choice ,if_ctl #endif #if (NEW_SNR_THRESHOLD == 1) ,saic_flag #endif /* NEW_SNR_THRESHOLD */ ); } // 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 (P)CCCH one). // **************************************************************************************** // When the CBCH reading control is completed (4 burst controled), // the SYNCHRO/OFFSET registers are shifted back to the normal idle // setting used for (P)CCCH 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. #if L1_GPRS 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". #else l1s.actual_time = l1s.next_time; l1s_increment_time(&(l1s.next_time), 1); // Increment "next time". #endif #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) trace_fct(CST_L1S_ADJUST_TIME, (UWORD32)(-1));//OMAPS00090550 #endif l1s.tpu_ctrl_reg |= CTRL_SYCB; l1s.dsp_ctrl_reg |= CTRL_SYNC; } } // 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; } #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 #if 0 /* FreeCalypso TCS211 reconstruction */ UWORD32 qual_acc_idle1[2]; #endif /*-------------------------------------------------------*/ /* l1s_ctrl_snb_dl() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* serving cell normal burst reading tasks: NP, EP, */ /* BCCHS, ALLC, DDL and ADL. This function is the control*/ /* function for reading a normal burst on the serving */ /* cell. It programs the DSP and the TPU for reading a */ /* normal burst without change on the TPU OFFSET */ /* register and flags the reading of the normal paging */ /* burst. This flag is used by the measurement manager */ /* "l1s_meas_manager()" at the end of L1S. Here 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 Normal Paging burst. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* NP, Normal paging reading task. */ /* EP, Extended paging reading task. */ /* BCCHS, BCCH Serving reading task. */ /* ALLC, All serving cell CCCH reading task. */ /* */ /* DDL, SDCCH DOWNLINK reading task. */ /* ADL, SACCH DOWNLINK (associated with SDCCH)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.dedic_set" */ /* Dedicated channel parameter structure. It is used */ /* to get the ARFCN to use for SDCCH (DDL, ADL). This */ /* ARFCN comes from the HOPPING algorithm called just */ /* before calling this function. */ /* */ /* "l1a_l1s_com.Scell_info" */ /* Serving cell information structure. */ /* .radio_freq, serving cell beacon frequency. */ /* .bsic, BSIC of the serving cell. It is used here */ /* to pass the training sequence number (part */ /* of BSIC) to the DSP. */ /* */ /* "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: */ /* --------------------------------- */ /* "l1s.np_ctrl" */ /* Flag set when a normal paging burst reading is */ /* controled. This flag is used by the measurement */ /* manager "l1s_meas_manager()", at the end of L1S, to */ /* scheduling the neighbor cell measurements. */ /* -> set to 1. */ /* */ /* "l1s.tpu_win" */ /* each frame is composed with a maximum of 3 */ /* working/TPU windows (typically RX/TX/PW). This is */ /* a counter used to count the number of windows */ /* used. */ /* -> incremented. */ /* */ /* "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 l1s_ctrl_snb_dl(UWORD8 task, UWORD8 burst_id) { UWORD8 lna_off; WORD8 agc; UWORD16 rx_radio_freq; UWORD8 tsc; T_INPUT_LEVEL *IL_info_ptr; UWORD32 dsp_task; static BOOL change_synchro; UWORD8 adc_active = INACTIVE; #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif /*L1_FF_MULTIBAND*/ #if L1_GPRS static BOOL algo_change_synchro_active = FALSE; static BOOL BCCHS_in_transfert = FALSE; #endif #if 0 /* FreeCalypso match TCS211 */ UWORD8 input_level = 0; //omaps00090550 #endif #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; // 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. { // Catch ARFCN and set CIPHERING reduced frame number. // Catch Training sequence. // **************************************************** if((task == DDL) || (task == ADL)) // Dedicated mode SDCCH downlink. { // Get ARFCN to be used for current control. rx_radio_freq = l1a_l1s_com.dedic_set.radio_freq; if (rx_radio_freq==l1a_l1s_com.Scell_info.radio_freq) // we are working on a beacon freq. IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas_beacon; else IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas;// we are working on a daughter freq // Catch training sequence code from the channel description. tsc = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->tsc; // Set CIPHERING reduced frame number. #if (AMR == 1) #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), SIG_ONLY_MODE, l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type, #if !FF_L1_IT_DSP_DTX 0, 0, 0, 0, 0, 0); #else 0, 0, 0, 0, 0, 0, 0); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), SIG_ONLY_MODE, l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type, #if !FF_L1_IT_DSP_DTX 0, 0, 0, 0); #else 0, 0, 0, 0, 0); #endif #endif #else #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), SIG_ONLY_MODE, l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type, #if !FF_L1_IT_DSP_DTX 0, 0, 0, 0, 0); #else 0, 0, 0, 0, 0, 0); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), SIG_ONLY_MODE, l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type, #if !FF_L1_IT_DSP_DTX 0, 0, 0); #else 0, 0, 0, 0); #endif #endif #endif // for SDCCH we use DPAGC algorithm. #if DPAGC_MAX_FLAG agc = Cust_get_agc_from_IL(rx_radio_freq, IL_info_ptr->input_level >> 1, MAX_ID); #else agc = Cust_get_agc_from_IL(rx_radio_freq, IL_info_ptr->input_level >> 1, AV_ID); #endif lna_off = IL_info_ptr->lna_off; // Store input_level and lna_off field used for current CTRL in order to be able to build IL // from pm in READ phase. l1a_l1s_com.Scell_used_IL = *IL_info_ptr; } // end if (task == DDL) || (task == ADL) else { rx_radio_freq = l1a_l1s_com.Scell_info.radio_freq; // Catch training sequence code from serving cell BCC (part of BSIC). tsc = l1a_l1s_com.Scell_info.bsic & 0x0007; // for PCH/E_PCH/Serving BCCH and All CCCH we use // PAGC algorithm. #if 1 /* FreeCalypso match TCS211 */ agc = Cust_get_agc_from_IL(rx_radio_freq, l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, MAX_ID); lna_off = l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset].lna_off; // Store input_level and lna_off fields used for current CTRL in order to be able // to build IL from pm in READ phase. l1a_l1s_com.Scell_used_IL = l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset]; #elif (L1_FF_MULTIBAND == 0) input_level = l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset].input_level ; lna_off = l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset].lna_off; agc = Cust_get_agc_from_IL(rx_radio_freq, input_level >> 1, MAX_ID); // Store input_level and lna_off fields used for current CTRL in order to be able // to build IL from pm in READ phase. l1a_l1s_com.Scell_used_IL = l1a_l1s_com.last_input_level[rx_radio_freq - l1_config.std.radio_freq_index_offset]; #else // L1_FF_MULTIBAND = 1 below operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(rx_radio_freq); input_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level ; lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; agc = Cust_get_agc_from_IL(rx_radio_freq, input_level >> 1, MAX_ID); // Store input_level and lna_off fields used for current CTRL in order to be able // to build IL from pm in READ phase. l1a_l1s_com.Scell_used_IL = l1a_l1s_com.last_input_level[operative_radio_freq]; #endif // #if (L1_FF_MULTIBAND == 0) else } #if(RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID , input_level, rx_radio_freq,if_threshold); l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); #endif //RF_FAM =61 #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function 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 //L1_SAIC != 0 // ADC measurement // *************** // check if during the 1st burst of the bloc an ADC measurement must be performed if ((burst_id == BURST_1) && (task == NP)) { #if L1_GPRS //In case of network mode of operation II or III, CCCH reading is possible //in packet idle mode and in packet transfer mode. //ADC measurements are already managed by comlex function of Packet idle tasks if (!((l1a_l1s_com.l1s_en_task[PNP] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[PEP] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[PALLC] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED))) #endif { adc_active = l1s_ADC_decision_on_NP(); } } // end if (burst_id == BURST_1) && (task == NP) if (task == ADL) { // ADC measurement for SACCH DL // **************************** // check if during the SACCH 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; 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 ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_traffic_period) // wait for the period { adc_active = ACTIVE; l1a_l1s_com.adc_cpt = 0; } } } // Traces and debug. // ****************** #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[task].name); #endif #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1S_CTRL_SNB_DL_BURST0 + burst_id, (UWORD32)(-1));//OMAPS00090550 #endif #if (TRACE_TYPE==5) trace_fct(CST_L1S_CTRL_SNB_DL, rx_radio_freq); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // the l1a_l1s_com.mode variable could change during the block: So test this variable only on the 1st block // See BUG2237 (mode change from Idle to Transfert during BCCHS task) #if (L1_GPRS) if (burst_id == BURST_1) BCCHS_in_transfert = ((l1a_l1s_com.mode == PACKET_TRANSFER_MODE) && ((task == EBCCHS) || (task == NBCCHS))); #endif // Programs DSP according to the DSP scheduler used // ************************************************* #if (L1_GPRS) switch(l1a_l1s_com.dsp_scheduler_mode) { // dsp pgm is made using GSM scheduler... case GSM_SCHEDULER: #if (FF_L1_FAST_DECODING == 1) l1ddsp_load_fast_dec_task(task,burst_id); #endif dsp_task = l1s_swap_iq_dl(rx_radio_freq,task); l1ddsp_load_rx_task(dsp_task, burst_id, tsc); break; // dsp pgm is made using GPRS scheduler... case GPRS_SCHEDULER: #if (FF_L1_FAST_DECODING == 1) l1ddsp_load_fast_dec_task(task,burst_id); #endif #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; } #else #if (FF_L1_FAST_DECODING == 1) l1ddsp_load_fast_dec_task(task,burst_id); #endif dsp_task = l1s_swap_iq_dl(rx_radio_freq,task); l1ddsp_load_rx_task(dsp_task, burst_id, tsc); #endif // update the TPU with the new TOA if necessary l1ctl_update_TPU_with_toa(); // Programs TPU for required task. // ******************************** #if (L1_GPRS) //In case of network mode of operation II or III, CCCH reading is possible //in packet idle mode and in packet transfer mode. // if (TS(CCCH) - TS(current task))%8 >= 4 synchro change is required // if not, OFFSET change is required // if (((task == EP) || (task == NP)) && ((l1a_l1s_com.l1s_en_task[PNP] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[PEP] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[PALLC] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED))) { UWORD32 new_offset; WORD32 new_synchro; UWORD32 ts_ccch; ts_ccch = (l1a_l1s_com.ccch_group * 2); //timeslot CCCH burts new_offset = (ts_ccch - l1a_l1s_com.dl_tn + 8) % 8; //dl_tn is the current time slot from previous task if (burst_id == BURST_1) l1s.forbid_meas = TASK_ROM_MFTAB[task].size; if (new_offset >= 4) algo_change_synchro_active = TRUE; if (algo_change_synchro_active) { // compute TPU offset for "current timeslot + 4 timeslot" new_synchro = l1s.tpu_offset + (4 * TN_WIDTH); if(new_synchro >= TPU_CLOCK_RANGE) new_synchro -= TPU_CLOCK_RANGE; //compute new offset new_offset = (((ts_ccch + 4 - l1a_l1s_com.dl_tn)%8) * TN_WIDTH) + new_synchro; } //no synchro change required, but new offset is computed else { new_synchro = l1s.tpu_offset; new_offset = (new_offset * TN_WIDTH) + new_synchro; } if (new_offset >= TPU_CLOCK_RANGE) new_offset -= TPU_CLOCK_RANGE; // tpu pgm... l1dtpu_serv_rx_nb(rx_radio_freq, agc, lna_off, new_synchro, new_offset, TRUE, adc_active #if (RF_FAM == 61) ,csf_filter_choice ,if_ctl #endif #if (NEW_SNR_THRESHOLD == 1) ,saic_flag #endif /*NEW_SNR_THRESHOLD */ ); } // end if (task == EP) || (task == NP) in packet Idle // in case of EBCCHS and NBCCHS in packet transfer a change synchro is performed else if (BCCHS_in_transfert) { UWORD32 new_offset; WORD32 new_synchro; change_synchro = ((l1a_l1s_com.dl_tn > 0) && (l1a_l1s_com.dl_tn < 5 )); // if change synchro is needed if(change_synchro) // TS= [1,2,3,4] { // the synchro is changed by 4 timeslots. new_synchro = l1s.tpu_offset + (4 * TN_WIDTH); if(new_synchro >= TPU_CLOCK_RANGE) new_synchro -= TPU_CLOCK_RANGE; // the TPU offset is changed according to the PDTCH time slot // because of the new synchro above with a shift of 4TS, // 4TS are substract to the offset new_offset = (8 - 4 - l1a_l1s_com.dl_tn) * TN_WIDTH; } else { // the synchro is unchanged new_synchro = l1s.tpu_offset; // the TPU offset is changed according to the PDTCH time slot new_offset = (8 - l1a_l1s_com.dl_tn) * TN_WIDTH; } new_offset += new_synchro; if (new_offset >= TPU_CLOCK_RANGE) new_offset -= TPU_CLOCK_RANGE; // tpu pgm... #if (RF_FAM == 61) l1dtpu_serv_rx_nb(rx_radio_freq, agc, lna_off, new_synchro, new_offset, TRUE, adc_active, csf_filter_choice, if_ctl #if (NEW_SNR_THRESHOLD == 1) ,saic_flag #endif /*NEW_SNR_THRESHOLD */ ); #endif #if(RF_FAM != 61) l1dtpu_serv_rx_nb(rx_radio_freq, agc, lna_off, new_synchro, new_offset, TRUE, adc_active); #endif } // end if (task == EBCCHS) || (task == NBCCHS) in packet Idle else #endif { // tpu pgm... #if (RF_FAM == 61) l1dtpu_serv_rx_nb(rx_radio_freq, agc, lna_off, l1s.tpu_offset, l1s.tpu_offset, FALSE, adc_active, csf_filter_choice, if_ctl #if (NEW_SNR_THRESHOLD == 1) ,saic_flag #endif /*NEW_SNR_THRESHOLD */ ); #endif #if (RF_FAM != 61) l1dtpu_serv_rx_nb(rx_radio_freq, agc, lna_off, l1s.tpu_offset, l1s.tpu_offset, FALSE, adc_active); #endif } // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + RX_LOAD); // GSM DSP scheduler is not able to handle PWR too close to RX normal burst. // We have to oblige a min of 1 burst period between RX and PWR if(l1_config.params.rx_synth_load_split < BP_SPLIT) l1s.tpu_win += BP_SPLIT - l1_config.params.rx_synth_load_split; #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH) buffer_trace(4, l1s.actual_time.fn, rx_radio_freq, l1s.tpu_win,l1s.tpu_offset); #endif #endif } #if (L1_GPRS) //In case of network mode of operation II or III, CCCH reading is possible //in packet idle mode and in packet transfer mode. if (((task == EP) || (task == NP)) && ((l1a_l1s_com.l1s_en_task[PNP] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[PEP] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[PALLC] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED))) { if((burst_id == BURST_4) && algo_change_synchro_active) { // 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; l1s.ctrl_synch_before = FALSE; algo_change_synchro_active = FALSE; #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) trace_fct(CST_L1S_ADJUST_TIME, (UWORD32)(-1));//OMAPS00090550 #endif } } // in case of EBCCHS and NBCCHS in packet transfer a change synchro is performed else if (BCCHS_in_transfert) { // Shift TPU SYNCHRO/OFFSET registers back to the default timeslot . // **************************************************************** // When the E/NBCCHS reading control is completed , // the SYNCHRO/OFFSET registers are shifted back to the normal // 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) // TS= [1,2,3,4] { // 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". #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) trace_fct(CST_L1S_ADJUST_TIME, (UWORD32)(-1));//OMAPS00090550 #endif l1s.tpu_ctrl_reg |= CTRL_SYCB; l1s.dsp_ctrl_reg |= CTRL_SYNC; } } // 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) l1s.forbid_meas = TASK_ROM_MFTAB[task].size; } #endif // Flag the reading of a Normal Paging burst. // ******************************************* // Set flag "NP contoled !!". Used in "l1_synch()" to generate meas. controles. if(task == NP) l1a_l1s_com.ba_list.np_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; } //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #endif /*-------------------------------------------------------*/ /* l1s_ctrl_snb_ul() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* serving cell normal burst sending tasks: DUL, AUL. */ /* This function is the control function for sending a */ /* burst on a SDCCH channel. It programs the DSP and the */ /* TPU for sending a normal burst taking into account */ /* the timing adavance. Here is a summary of the */ /* execution: */ /* */ /* - Catch ARFCN. */ /* - Traces and debug. */ /* - Programs DSP for required task. */ /* - Catch UL data block from DLL and gives it to DSP. */ /* - Programs TPU for required task. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* DUL, SDCCH UPLINK sending task. */ /* AUL, SACCH UPLINK (associated with SDCCH)sending */ /* 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.dedic_set" */ /* Dedicated channel parameter structure. It is used */ /* to get the ARFCN to use for SDCCH (DUL, AUL). This */ /* ARFCN comes from the HOPPING algorithm called just */ /* before calling this function. */ /* */ /* "l1a_l1s_com.Scell_info" */ /* Serving cell information structure. */ /* .bsic, BSIC of the serving cell. It is used here */ /* to pass the training sequence number (part */ /* of BSIC) to the DSP. */ /* */ /* "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 restore this value in the OFFSET register after */ /* the TX burst programming. */ /* */ /* "l1s.applied_txpwr" */ /* Applied transmit power. */ /* */ /* "l1s.reported_txpwr" */ /* Transmit power to report in the L1 header of the */ /* SACCH data block. */ /* */ /* "l1a_l1s_com.dedic_set.aset" */ /* Active dedicated mode parameter set. */ /* .timing_advance, Timing advance to apply to the UL */ /* burst transmission. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.tpu_win" */ /* each frame is composed with a maximum of 3 */ /* working/TPU windows (typically RX/TX/PW). This is */ /* a counter used to count the number of windows */ /* used. */ /* -> set to TDMA_WIN3. */ /* */ /* "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_TX 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_TX bit in the register. */ /* */ /*-------------------------------------------------------*/ void l1s_ctrl_snb_ul(UWORD8 task, UWORD8 burst_id) { T_RADIO_FRAME *tx_data = NULL; UWORD16 tx_radio_freq; UWORD32 dsp_task; UWORD8 adc_active_ul = INACTIVE; // Catch ARFCN. // ************* // Get ARFCN to be used for current control. tx_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) trace_fct(CST_L1S_CTRL_SNB_UL, tx_radio_freq); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Programs DSP for required task. // ******************************** // Set CIPHERING reduced frame number. #if (AMR == 1) #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), SIG_ONLY_MODE, l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type, #if !FF_L1_IT_DSP_DTX 0, 0, 0, 0, 0, 0); #else 0, 0, 0, 0, 0, 0, 0); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), SIG_ONLY_MODE, l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type, #if !FF_L1_IT_DSP_DTX 0, 0, 0, 0); #else 0, 0, 0, 0, 0); #endif #endif #else #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), SIG_ONLY_MODE, l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type, #if !FF_L1_IT_DSP_DTX 0, 0, 0, 0, 0); #else 0, 0, 0, 0, 0, 0); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), SIG_ONLY_MODE, l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type, #if !FF_L1_IT_DSP_DTX 0, 0, 0); #else 0, 0, 0, 0); #endif #endif #endif if(task == DUL) // SDCCH/UL task. { if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0) // "ho_acc_to_send" is a counter of Handover Access burst still to send. // This counter is set by "l1s_dedicated_mode_manager()" in L1S when a // Handover command is received from L3 through L1A. { // TX burst is a RACH. // ******************** // dsp and tpu pgm... l1s_ctrl_rach(RAHO,NO_PAR); // Decrement number of HO ACCESS burst still to be sent. // Rem: (-1) is used for Async. HO. if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != -1) l1a_l1s_com.dedic_set.aset->ho_acc_to_send --; if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send == 0) // Handover access procedure is completed. // -> send L1C_HANDOVER_FINISHED message with "cause = COMPLETED" to L1A. { l1s_send_ho_finished(HO_COMPLETE); } } else { // TX burst is a Normal Burst. // **************************** // dsp pgm... #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.applied_txpwr) #endif dsp_task = l1s_swap_iq_ul(tx_radio_freq,task); l1ddsp_load_tx_task(dsp_task, burst_id, l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->tsc); // tpu pgm... l1dtpu_serv_tx_nb(tx_radio_freq, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.tpu_offset, l1s.applied_txpwr,INACTIVE); // Catch UL data block from DLL and gives it to DSP. // ************************************************** // SDCCH info. if(burst_id == BURST_1) // perform "PH_DATA_REQ" from L2... { // Get SDCCH/UL data block from L2. tx_data = dll_read_dcch(SIG_ONLY_MODE); // Store the UL data block in MCU/DSP interface. if(tx_data != NULL) // NULL should never occur !!! { #if (TRACE_TYPE==1) || (TRACE_TYPE==4) RTTL1_FILL_UL_DCCH trace_info.facch_ul_count ++; #endif l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_cu, &(tx_data->A[0])); } } } // In any case set TXPWR. l1ddsp_load_txpwr(l1s.applied_txpwr, tx_radio_freq); } // End if(task == DUL) else // SACCH/UL task. { if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0) // "ho_acc_to_send" is a counter of Handover Access burst still to send. // This counter is set by "l1s_dedicated_mode_manager()" in L1S when a // Handover command is received from L3 through L1A. // Rem: it is not allowed to send HO ACCESS burst on SACCH/UL. We must // then avoid any normal burst transmission by setting txpwr=NO_TXPWR. The DSP // and TPU are controled normally. { // Set TXPWR. l1ddsp_load_txpwr(NO_TXPWR, tx_radio_freq); #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, NO_TXPWR) #endif } else { // Set TXPWR. l1ddsp_load_txpwr(l1s.applied_txpwr, tx_radio_freq); #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.applied_txpwr) #endif } //ADC Measurements // // Check if during the SACCH burst an ADC measurement shall be performed if (l1a_l1s_com.adc_mode & ADC_NEXT_TRAFFIC_UL) // perform ADC only one time { adc_active_ul = 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_ul = ACTIVE; l1a_l1s_com.adc_cpt = 0; } } } // In any case TX burst is a Normal Burst. // **************************************** // dsp pgm... dsp_task = l1s_swap_iq_ul(tx_radio_freq,task); l1ddsp_load_tx_task(dsp_task, burst_id, l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->tsc); // tpu pgm... l1dtpu_serv_tx_nb(tx_radio_freq, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.tpu_offset, l1s.applied_txpwr,adc_active_ul); // Catch UL data block from DLL and gives it to DSP. // ************************************************** // SACCH info. if(burst_id == BURST_1) // perform "PH_DATA_REQ" from L2... { #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) BOOL tx_data_flag = FALSE; //omaps00090550 #endif #if (FF_REPEATED_SACCH == 1) #if TESTMODE if(l1_config.repeat_sacch_enable != REPEATED_SACCH_ENABLE) /* disable the repeated sacch mode */ { l1s.repeated_sacch.sro = 0; /* set no repetition order */ l1s.repeated_sacch.buffer_empty = TRUE; /* set no buffer */ } #endif /* TESTMODE */ #endif /* (FF_REPEATED_SACCH == 1) */ #if (FF_REPEATED_SACCH == 1) /* Get data from PS if only no repetition order is required (1st condition) or no repetition candidate exists (2nd condition) */ if( (l1s.repeated_sacch.sro == 0) || (l1s.repeated_sacch.buffer_empty == TRUE) ) { #endif /* (FF_REPEATED_SACCH == 1) */ tx_data = dll_read_sacch(SIG_ONLY_MODE); if(tx_data != NULL) // NULL should never occur !!! { #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) tx_data_flag =TRUE; //omaps00090550 #endif // Set L1 Header... tx_data->A[0] = l1s.reported_txpwr; #if (FF_REPEATED_SACCH == 1) /* Include the SACCH Repetition Request (SRR) in the L1 Header */ tx_data->A[0] |= (l1s.repeated_sacch.srr <<6); #endif /* FF_REPEATED_SACCH */ tx_data->A[1] = l1a_l1s_com.dedic_set.aset->timing_advance; // Store the UL data block in MCU/DSP interface. l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_cu, &(tx_data->A[0])); #if (FF_REPEATED_SACCH == 1 ) /* Store the block data in case of a retransmission order */ /* Retransmission is done in case of a SAPI0 and not 3 */ if(((tx_data->A[2]&0x1C) >> 2) == SAPI_0) { l1s_store_sacch_buffer( &(l1s.repeated_sacch), &(tx_data->A[0])); } else // FIXME FIXME NOT sure whether this needs to be done { /* the SACCH repetition block occurrence will always come as a consecutive pair */ /* To handle DL UL | DL UL | DL UL */ /* - 0 | SRO 3 | - new data should be asked from PS old 0 cannot be repeated */ l1s.repeated_sacch.buffer_empty=TRUE; } #endif /* FF_REPEATED_SACCH */ }/* end of if(tx_data != NULL) */ #if (FF_REPEATED_SACCH == 1) } else if ((l1s.repeated_sacch.sro == 1) && (l1s.repeated_sacch.buffer_empty == FALSE)) { /* Put data block in MCU/DSP com. */ l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_cu, l1s.repeated_sacch.buffer ); l1s.repeated_sacch.buffer_empty = TRUE; /* Set that the buffer is now empty (only one repetition) */ } #endif /* FF_REPEATED_SACCH */ #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) RTTL1_FILL_UL_SACCH(tx_data_flag,l1a_l1s_com.dedic_set.aset->timing_advance, l1s.reported_txpwr) //omaps00090550 #endif } } // Set tpu window identifier for Power meas after TX. l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_nb_load_split + l1_config.params.rx_synth_load_split; // 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_nnb() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* neigbor cell normal burst reading tasks: BCCHN. */ /* This function is the control function for reading 4 */ /* normal bursts on a neighbor cell. It programs the DSP */ /* and the TPU for reading the 4 bursts taking into */ /* account the time difference between the serving and */ /* the neighbor cells. To this avail, it shifts the TPU */ /* OFFSET register according to this time difference and */ /* restores the serving offset value when the 4 burst */ /* reading are completed. Here is a summary of the */ /* execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Traces and debug. */ /* - Programs DSP for required task. */ /* - Programs TPU for required task. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* BCCHN, BCCH Neighbor reading task. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.Ncell_info.bcch" */ /* cell information structure used for BCCHN task. */ /* */ /* "l1a_l1s_com.l1s_en_task" */ /* L1S task enable bit register. Used here to check if */ /* the Full BCCH Reading task is enabled and then to */ /* take the decision to reloading the serving value */ /* in the TPU OFFSET register. */ /* */ /* "l1s.tpu_offset" */ /* value for SYNCHRO and OFFSET register in the TPU */ /* for current serving cell setting. At the end of */ /* the task this value is restored in the OFFSET */ /* register. */ /* */ /* 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 l1s_ctrl_nnb(UWORD8 task, UWORD8 param2) { UWORD8 lna_off; WORD8 agc; T_NCELL_SINGLE *cell_info_ptr = NULL; BOOL en_task; BOOL task_param; UWORD32 dsp_task; #if(L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; UWORD8 input_level; #endif #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; #endif // 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 enable flag. The control body is executed only // when the task semaphore is 0 and enable flag is 1. The semaphore can be set to // 1 whenever L1A makes some changes to the task parameters. The enable can be // reset to 0 when the task is no more enabled. { // Get the cell information structure. // ************************************ if (task == BCCHN) cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_norm]; else // BCCHN_TOP and BCCHN_TRAN tasks cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_top]; // Traces and debug. // ****************** #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_NNB, cell_info_ptr->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 + 6) ; // Programs DSP for required task. // ******************************** #if L1_GPRS switch(l1a_l1s_com.dsp_scheduler_mode) { // dsp pgm is made using GSM scheduler... case GSM_SCHEDULER: dsp_task = l1s_swap_iq_dl(cell_info_ptr->radio_freq,task); l1ddsp_load_rx_task(dsp_task, 0, cell_info_ptr->tsc); break; // dsp pgm is made using GPRS scheduler... case GPRS_SCHEDULER: l1pddsp_load_bcchn_task(cell_info_ptr->tsc, cell_info_ptr->radio_freq); break; } #else // dsp pgm... dsp_task = l1s_swap_iq_dl(cell_info_ptr->radio_freq,task); l1ddsp_load_rx_task(dsp_task, 0, cell_info_ptr->tsc); #endif // Programs TPU for required task. // ******************************** // We program 4 burst reading. The OFFSET register is used to // cope with the time difference between the serving and the // neighbor cells. The serving cell offset value (l1s.tpu_offset) // is restored at the end of the 4 burst reading. #if (L1_FF_MULTIBAND == 0) // agc is computed from PGC2 algo result. agc = Cust_get_agc_from_IL(cell_info_ptr->radio_freq, l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].input_level >> 1, AV_ID); lna_off = l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].lna_off; #else // L1_FF_MULTIBAND = 1 below operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(cell_info_ptr->radio_freq); lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; input_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; // agc is computed from PGC2 algo result. agc = Cust_get_agc_from_IL(cell_info_ptr->radio_freq, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, AV_ID); #endif // #if (L1_FF_MULTIBAND == 0) else #if(RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID, #if (L1_FF_MULTIBAND == 0) l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].input_level, #else input_level, #endif cell_info_ptr->radio_freq,if_threshold); //dco_algo_ctl has 0000 00ZL dco_algo_ctl_nb *= 0x55; // replicate 0000 00zL as ZLZL ZLZL l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); #endif #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH) buffer_trace(4, l1s.actual_time.fn, cell_info_ptr->radio_freq, cell_info_ptr->time_alignmt, cell_info_ptr->fn_offset); #endif #endif #if (RF_FAM == 61) if ( cell_info_ptr->time_alignmt >= TPU_CLOCK_RANGE - EPSILON_SYNC) { // Insert 1 NOP to correct the EPSILON_SYNC side effect l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, FALSE, 1, if_ctl #if (NEW_SNR_THRESHOLD == 1) ,SAIC_OFF #endif /* NEW_SNR_THRESHOLD == 1*/ ); } else { l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, FALSE, 0, if_ctl #if (NEW_SNR_THRESHOLD == 1) ,SAIC_OFF #endif /* NEW_SNR_THRESHOLD == 1*/ ); } l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, FALSE, 0, if_ctl #if (NEW_SNR_THRESHOLD == 1) ,SAIC_OFF #endif /* NEW_SNR_THRESHOLD == 1*/ ); l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, FALSE, 0, if_ctl #if (NEW_SNR_THRESHOLD == 1) ,SAIC_OFF #endif /* NEW_SNR_THRESHOLD == 1*/ ); l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, TRUE, 0, if_ctl #if (NEW_SNR_THRESHOLD == 1) ,SAIC_OFF #endif /* NEW_SNR_THRESHOLD == 1*/ ); #endif // RF_FAM == 61 #if (RF_FAM != 61) if ( cell_info_ptr->time_alignmt >= TPU_CLOCK_RANGE - EPSILON_SYNC) { // Insert 1 NOP to correct the EPSILON_SYNC side effect l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, FALSE, 1); } else { l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, FALSE, 0); } l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, FALSE, 0); l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, FALSE, 0); l1dtpu_neig_rx_nb(cell_info_ptr->radio_freq, agc, lna_off, cell_info_ptr->time_alignmt, l1s.tpu_offset, TRUE, 0); #endif // RF_FAM != 61 } // 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; #if L1_GPRS // This task is not compatible with Neigh. Measurement. Store task length // in "forbid_meas" to indicate when the task will last. if(task == BCCHN_TRAN) { // In IDLE mode, l1s.forbid_meas is setted by the AGC ctrl l1s.forbid_meas = TASK_ROM_MFTAB[task].size; } #endif } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM /*-------------------------------------------------------*/ /* l1s_ctrl_rach() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* serving cell Random Access burst sending tasks: RAAC, */ /* RAHO. This function is the control function for */ /* sending a random access burst to the serving cell. */ /* This sending is either a Channel Request (connection */ /* establishment) or a Handover Access burst (dedicated */ /* mode). It programs the DSP and the TPU for sending a */ /* random access burst with a null timing advance. */ /* Here is a summary of the execution: */ /* */ /* - Traces and debug. */ /* - Programs DSP for required task. */ /* - Build RACH data block and store in MCU/DSP com. */ /* - Programs TPU for required task. */ /* - Send confirmation msg to L1A. */ /* - Flag DSP and TPU programmation. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* RAAC, RACH sending task for Channel Request. */ /* RAHO, RACH sending task for Handover Access. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.Scell_info" */ /* Serving cell information structure. */ /* .bsic, BSIC of the serving cell. It is used here */ /* to pass the training sequence number (part */ /* of BSIC) to the DSP. */ /* .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 restore this value in the OFFSET register after */ /* the TX burst programming. */ /* */ /* "l1s.applied_txpwr" */ /* Applied transmit power. */ /* */ /* "l1a_l1s_com.ra_info" */ /* random access task parameters. */ /* .channel_request, random number sent in the case */ /* of Channel Request (RAAC). */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.tpu_win" */ /* each frame is composed with a maximum of 3 */ /* working/TPU windows (typically RX/TX/PW). This is */ /* a counter used to count the number of windows */ /* used. */ /* -> set to TDMA_WIN3. */ /* */ /* "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_TX 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_TX bit in the register. */ /* */ /*-------------------------------------------------------*/ void l1s_ctrl_rach(UWORD8 task, UWORD8 param2) { UWORD8 tx_data[2]; UWORD16 radio_freq=0; UWORD32 dsp_task; UWORD8 adc_active=INACTIVE; // Get ARFCN to be used for current control. // ******************************************* if(task == RAHO) // Handover Access... { // The ARFCN comes from the HOPPING algorithm called // prior to calling any CTRL function in the current frame. radio_freq = l1a_l1s_com.dedic_set.radio_freq; } else // Network Access... { #if TESTMODE if (l1_config.TestMode) { // A TX_TCH task has been enabled in TestMode with burst_type=access burst. // Thus set radio_freq to tch_arfcn . radio_freq = l1_config.tmode.rf_params.tch_arfcn; } else #endif { // The ARFCN is the BEACON frequency. radio_freq = l1a_l1s_com.Scell_info.radio_freq; } } // ADC measurement // *************** // check if during the RACH an ADC measurement must be performed if (task == RAACC) if (l1a_l1s_com.adc_mode & ADC_EACH_RACH) // perform ADC on each burst adc_active = ACTIVE; // 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 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("RA"); #endif #endif // Programs DSP for required task. // ******************************** // dsp pgm... dsp_task = l1s_swap_iq_ul(radio_freq,task); l1ddsp_load_ra_task(dsp_task); // Set TXPWR. l1ddsp_load_txpwr(l1s.applied_txpwr, radio_freq); // Build RACH data block and store in MCU/DSP com. // ************************************************ // RACH info. if(task == RAACC) // RACH data is only the "channel_request". (BYTE format data). { tx_data[0] = (l1a_l1s_com.Scell_info.bsic << 2); tx_data[1] = l1a_l1s_com.ra_info.channel_request; } else // RACH data is only the "handover access" (BYTE format data). { tx_data[0] = (l1a_l1s_com.Scell_info.bsic << 2); tx_data[1] = l1a_l1s_com.dedic_set.aset->ho_acc; } // Store data block in MCU/DSP com. l1ddsp_load_info(DSP_TASK_CODE[task], &(l1s_dsp_com.dsp_ndb_ptr->d_rach), &(tx_data[0])); // Programs TPU for required task. // ******************************** // tpu pgm... l1dtpu_serv_tx_ra(radio_freq, l1s.tpu_offset, l1s.applied_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; #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_AB(task, l1s.applied_txpwr) #endif // 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; } /*-------------------------------------------------------*/ /* l1s_ctrl_tchtd() */ /*-------------------------------------------------------*/ /* */ /* Description: This function controls the non transmitting slot in case of Half Rate TCH */ /* ------------ */ /* */ /*-------------------------------------------------------*/ void l1s_ctrl_tchtd(UWORD8 task, UWORD8 param2) { T_CHANNEL_DESCRIPTION *desc_ptr; #if FF_L1_IT_DSP_DTX BOOL dtx_dsp_interrupt = FALSE; #endif // Traces and debug. // ****************** #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[TCHD].name); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Catch channel description. // *************************** // Catch the active channel description used along the routine. // It contains: // "channel_type", {TCH_F, TCH_H, SDCCH_4, SDCCH_8}. // "subchannel", {0, 1}. 0 is the default value for TCH_F. desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; /**************************************************************************/ /* TCH/Dummy Receive... */ /**************************************************************************/ #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_TCHT_DUMMY__DL, l1a_l1s_com.dedic_set.radio_freq); #endif #if FF_L1_IT_DSP_DTX // Fast DTX active only in TCH AHS if ((l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AHS_MODE) && (l1a_l1s_com.dedic_set.aset->dtx_allowed == TRUE)) { // AHS0 if (desc_ptr->subchannel == 0) { // DTX interrupt request for B1 and B2 (no DTX uncertainty on B0 thanks to idle frame) if (l1s.next_time.fn_mod13 <= 7) dtx_dsp_interrupt = TRUE; } // AHS1 else { // DTX interrupt requested for ALL blocks (idle frame does not help) dtx_dsp_interrupt = TRUE; } } #endif /*--------------------------------------------*/ /* Program DSP... */ /*--------------------------------------------*/ // dsp pgm. l1ddsp_load_rx_task(DSP_TASK_CODE[task], 0, desc_ptr->tsc); /*--------------------------------------------*/ /* Flag DSP and TPU programmation... */ /*--------------------------------------------*/ // Set "CTRL_RX" flag in the controle flag register. l1s.dsp_ctrl_reg |= CTRL_RX; /*----------------------------------------------*/ /* Common for Dedicated mode: DSP parameters... */ /*----------------------------------------------*/ #if (AMR == 1) #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, 0, l1a_l1s_com.dedic_set.reset_sacch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.vocoder_on); #else l1a_l1s_com.dedic_set.vocoder_on, dtx_dsp_interrupt); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, #if !FF_L1_IT_DSP_DTX 0); #else 0, dtx_dsp_interrupt); #endif #endif #else #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, l1a_l1s_com.dedic_set.reset_sacch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.vocoder_on); #else l1a_l1s_com.dedic_set.vocoder_on, dtx_dsp_interrupt); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.sync_tch); #else l1a_l1s_com.dedic_set.sync_tch, dtx_dsp_interrupt); #endif #endif #endif // Clear "sync_tch" and "reset_sacch" flag to maintain normal TCH process. l1a_l1s_com.dedic_set.sync_tch = FALSE; #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1a_l1s_com.dedic_set.reset_sacch = FALSE; #endif // Set tpu window identifier for Power meas in case of dummy burst in Half-rate l1s.tpu_win = 0; } /*-------------------------------------------------------*/ /* l1s_ctrl_tchth() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* dedicated mode TCH task: TCHTH. This function is the */ /* control function for reading the DL burst and sending */ /* the UL burst. The UL burst can be a Normal Burst in */ /* normal case or an Access Burst when starting a */ /* Handover procedure. Both Half rate and Full rate TCH */ /* channel are handled. The DSP and the TPU are */ /* programmed for both the DL and UL bursts. The timing */ /* advance is taken into account for positionning the UL */ /* burst. */ /* */ /* This function accesses the L1/DLL and L1/DATA */ /* interface ("dll_read_dcch()", "tx_tch_data()" */ /* functions respectively) and passes then the returned */ /* data blocks to the DSP. */ /* */ /* Here is a summary of the execution: */ /* */ /* - Traces and debug. */ /* - Catch channel description and ARFCN. */ /* - TCH/T Receive... */ /* - Program DSP for RX. */ /* - Program TPU for RX. */ /* - Flag DSP and TPU programmation. */ /* - TCH/T Transmit... */ /* - If Any Handover Access burst to send */ /* - Call "l1s_ctrl_rach()". */ /* - Else */ /* - Get DATA block if required for TCH. */ /* - Program DSP for TX. */ /* - Program TPU for TX. */ /* - Flag DSP and TPU programmation. */ /* - Common for DL/UL: DSP parameters. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* TCHTH, Traffic Channel TCH Half rate. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.dedic_set" */ /* Dedicated channel parameter structure. */ /* .radio_freq, ARFCN value set by the Hopping algo. */ /* .aset, active dedicated parameter set. */ /* */ /* "l1a_l1s_com.Scell_info" */ /* Serving cell information structure. */ /* .bsic, BSIC of the serving cell. It is used here */ /* to pass the training sequence number (part */ /* of BSIC) to the DSP. */ /* */ /* "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. */ /* */ /* "l1s.applied_txpwr" */ /* Applied transmit power. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.tpu_win" */ /* each frame is composed with a maximum of 3 */ /* working/TPU windows (typically RX/TX/PW). This is */ /* a counter used to count the number of windows */ /* used. */ /* -> set to TDMA_WIN3. */ /* */ /* "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. */ /* -> set CTRL_TX 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. */ /* -> set CTRL_TX bit in the register. */ /* */ /*-------------------------------------------------------*/ void l1s_ctrl_tchth(UWORD8 task, UWORD8 param2) { UWORD16 radio_freq=0; T_CHANNEL_DESCRIPTION *desc_ptr; UWORD8 lna_off; WORD8 agc; T_INPUT_LEVEL *IL_info_ptr; UWORD32 dsp_task; UWORD32 fn_mod_52; UWORD8 input_level; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; // By default we choose the hardware filter UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER; #endif #if FF_L1_IT_DSP_DTX BOOL dtx_dsp_interrupt=FALSE; //omaps00090550 #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[TCHTH].name); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Catch channel description and ARFCN. // ************************************* // Catch the active channel description used along the routine. // It contains: // "channel_type", {TCH_F, TCH_H, SDCCH_4, SDCCH_8}. // "subchannel", {0, 1}. 0 is the default value for TCH_F. desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; // 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 (radio_freq == l1a_l1s_com.Scell_info.radio_freq) IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas_beacon; // we are working on a beacon freq. else IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas; // we are working on a daughter freq. #if FF_L1_IT_DSP_DTX // Skip RX DSP/RF programming part during DTX HISR if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) { #endif /**************************************************************************/ /* TCH/T Receive... */ /**************************************************************************/ #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_TCHTH__DL, radio_freq); #endif /*--------------------------------------------*/ /* Program DSP... */ /*--------------------------------------------*/ dsp_task = l1s_swap_iq_dl(radio_freq,task); // dsp pgm. l1ddsp_load_rx_task(dsp_task, 0, desc_ptr->tsc); // Set TXPWR. l1ddsp_load_txpwr(l1s.applied_txpwr, radio_freq); input_level = IL_info_ptr->input_level ; #if(RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID, input_level , radio_freq,if_threshold); l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); #endif /*--------------------------------------------*/ /* Program TPU... */ /*--------------------------------------------*/ // for TCHTH we use DPAGC algorithm. #if DPAGC_MAX_FLAG agc = Cust_get_agc_from_IL(radio_freq, input_level >> 1, MAX_ID); #else agc = Cust_get_agc_from_IL(radio_freq, input_level >> 1, AV_ID); #endif lna_off = IL_info_ptr->lna_off; // Store input_level and lna_off fields used for current CTRL in order to be able // to build IL from pm in READ phase. l1a_l1s_com.Scell_used_IL = *IL_info_ptr; #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function 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 // update the TPU with the new TOA if necessary l1ctl_update_TPU_with_toa(); // Program a serving cell normal burst reading in TPU. #if (RF_FAM == 61) l1dtpu_serv_rx_nb(radio_freq, agc, lna_off, l1s.tpu_offset, l1s.tpu_offset, FALSE,INACTIVE, csf_filter_choice, if_ctl #if (NEW_SNR_THRESHOLD == 1) ,saic_flag #endif /*NEW_SNR_THRESHOLD */ ); #endif #if (RF_FAM != 61) l1dtpu_serv_rx_nb(radio_freq, agc, lna_off, l1s.tpu_offset, l1s.tpu_offset, FALSE,INACTIVE); #endif // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + RX_LOAD); /*--------------------------------------------*/ /* 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; #if FF_L1_IT_DSP_DTX } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) #endif /**************************************************************************/ /* TCH/T Transmit... */ /**************************************************************************/ // Any Handover Access burst to send ? // ************************************ if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0) // "ho_acc_to_send" is a counter of Handover Access burst still to send. // This counter is set by "l1s_dedicated_mode_manager()" in L1S when a // Handover command is received from L3 through L1A. // We must then replace the TCH UL normal burst by a RACH and decrement // this counter. { if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != -1) l1a_l1s_com.dedic_set.aset->ho_acc_to_send --; l1s_ctrl_rach(RAHO,NO_PAR); if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send == 0) // Handover access procedure is completed. // -> send L1C_HANDOVER_FINISHED message with "cause = COMPLETED" to L1A. { l1s_send_ho_finished(HO_COMPLETE); } } else // TCH/UL is a normal burst. { UWORD8 channel_mode = l1a_l1s_com.dedic_set.aset->achan_ptr->mode; //omaps00090550 UWORD8 channel_type = desc_ptr->channel_type; UWORD8 subchannel = desc_ptr->subchannel; #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_TCHTH__UL, radio_freq); #endif #if FF_L1_IT_DSP_DTX // FACCH and IDS handled during L1S, have to be skipped during DTX HISR if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) { #endif /*--------------------------------------------*/ /* Get DATA block if required for TCH. */ /*--------------------------------------------*/ // Half rate traffic channel... { // Rem: time to get data block is // Subchannel 0: FN%26 in {0, 8, 17}. // Subchannel 1: FN%26 in {1, 9, 18}. // => normalised time: FN_normalised = FN%26 - subchannel, in {0, 8, 17}. // so CTL: must occur 2 TDMAs before, on // Subchannel 0: FN%26 in {23, 6, 15}. // Subchannel 1: FN%26 in {24, 7, 16}. UWORD8 normalised_fn = l1s.next_time.t2 - subchannel; // FN%26 - subchannel if((normalised_fn == 23) || (normalised_fn == 6) || (normalised_fn == 15)) // It is time to check if a FACCH/UL data block is available from DLL or // if a data block is available from the DATA interface. { T_RADIO_FRAME *tx_data = NULL; // Check if any FACCH to transmit. // Rem: when mode is "SIGNALLING ONLY" the "dll_read_dcch()" function // always give back a block of FACCH (true block or dummy one). tx_data = dll_read_dcch(channel_mode); if(tx_data != NULL) { // In DTX mode in HS, all 6 FACCH 1/2 bursts must always be transmitted. // Note: FACCH presence is checked 1 "control" before "control" of 1st burst of FACCH due to a DSP constraint // i.e. 3 bursts before FACCH interleaving boundary // So we must wait 1 control before controlling the transmission of 6 FACCH 1/2 bursts l1s.facch_bursts = 7; #if (TRACE_TYPE==1) || (TRACE_TYPE==4) RTTL1_FILL_UL_DCCH trace_info.facch_ul_count ++; #endif l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_fu, &(tx_data->A[0])); #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsptx(dltsk_trace[TCHTH].name); #endif } #if (AMR == 1) // Check if any DATA traffic info frame available. // This check is used for all full rate channels except when // this channel is in SIGNALLING ONLY mode or in Half Rate // Speech mode or in adaptative Half Rate mode. if((channel_mode != TCH_HS_MODE) && (channel_mode != TCH_AHS_MODE) && (channel_mode != SIG_ONLY_MODE)) #else // Check if any DATA traffic info frame available. // This check is used for all full rate channels except when // this channel is in SIGNALLING ONLY mode or in Half Rate // Speech mode. if((channel_mode != TCH_HS_MODE) && (channel_mode != SIG_ONLY_MODE)) #endif { UWORD8 *tx_data = NULL; tx_data = tx_tch_data(); if(tx_data != NULL) { // Store the DATA/UL data block in the MCU/DSP com. according // to the "subchannel". if(subchannel == 0) l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_0, tx_data); else l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_1, tx_data); #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsptx(dltsk_trace[TCHTH].name); #endif } } } } #if FF_L1_IT_DSP_DTX // Fast DTX active only in TCH AHS if ((l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AHS_MODE) && (l1a_l1s_com.dedic_set.aset->dtx_allowed == TRUE)) { // AHS0 if (desc_ptr->subchannel == 0) { // DTX interrupt request for B1 and B2 (no DTX uncertainty on B0 thanks to idle frame) if (l1s.next_time.fn_mod13 <= 7) dtx_dsp_interrupt = TRUE; // DTX uncertainty check if ((l1a_apihisr_com.dtx.fast_dtx_ready == TRUE) && // Fast DTX can be used ((l1s.next_time.fn_mod13 == 4) || (l1s.next_time.fn_mod13 == 8))) // new block boundary l1a_apihisr_com.dtx.dtx_status = DTX_AWAITED; } // AHS1 else { // DTX interrupt requested for ALL blocks (idle frame does not help) dtx_dsp_interrupt = TRUE; // DTX uncertainty check if ((l1a_apihisr_com.dtx.fast_dtx_ready == TRUE) && // Fast DTX can be used ((l1s.next_time.fn_mod13 == 1) || (l1s.next_time.fn_mod13 == 5)|| (l1s.next_time.fn_mod13 == 9))) // new block boundary l1a_apihisr_com.dtx.dtx_status = DTX_AWAITED; } } else l1a_apihisr_com.dtx.dtx_status = DTX_AVAILABLE; } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) // Postpone TPU/DSP programming when DTX status not available from DSP if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED) { BOOL tx_active =FALSE; //omaps00090550 #endif /*--------------------------------------------*/ /* Program DSP... */ /*--------------------------------------------*/ dsp_task = l1s_swap_iq_ul(radio_freq,task); l1ddsp_load_tx_task(dsp_task, 0, desc_ptr->tsc); /*--------------------------------------------*/ /* Program TPU... */ /*--------------------------------------------*/ fn_mod_52 = l1s.actual_time.fn % 52; l1s.facch_bursts--; if (l1s.facch_bursts < 0) l1s.facch_bursts = -1; #if FF_L1_IT_DSP_DTX // Condition for TX TPU programming channel mode dependant switch (channel_mode) { case SIG_ONLY_MODE: case TCH_24H_MODE: case TCH_48H_MODE: // DTX not supported tx_active = TRUE; break; case TCH_HS_MODE: if ((l1s.dtx_ul_on == FALSE) || // No DTX ((l1s.facch_bursts >= 0) && (l1s.facch_bursts <= 5)) || // FACCH in progress ((subchannel == 0) && ((fn_mod_52 == 51) || (/*(fn_mod_52 >= 0) && omaps00090550*/(fn_mod_52 <= 5)))) || // SID HS0 ((subchannel == 1) && (fn_mod_52 >= 13) && (fn_mod_52 <= 19)) // SID HS1 ) tx_active = TRUE; else tx_active = FALSE; break; case TCH_AHS_MODE: if (l1a_apihisr_com.dtx.tx_active) // DSP (Fast) DTX status tx_active = TRUE; else tx_active = FALSE; break; } // TPU TX burst programming if (tx_active) #else // In DTX mode, UL bursts should not be transmitted when no voice activity is detected // we must not call TPU scenario if dtx_on == TRUE in HS (See Technical Memo) // However, in DTX mode, several bursts must always be transmitted (See ETSI 05.08, 8.3) if ( (channel_mode != TCH_HS_MODE) || (l1s.dtx_ul_on == FALSE) || ( (l1s.facch_bursts >= 0) && (l1s.facch_bursts <= 5) ) || ( (subchannel == 0) && ((fn_mod_52 == 51) || ((fn_mod_52 >= 0) && (fn_mod_52 <= 5))) ) || ( (subchannel == 1) && (fn_mod_52 >= 13) && (fn_mod_52 <= 19) )) #endif { l1dtpu_serv_tx_nb(radio_freq, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.tpu_offset, l1s.applied_txpwr,INACTIVE); } #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.applied_txpwr) #endif #if FF_L1_IT_DSP_DTX } // if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED) #endif } // TCH/UL is a normal burst. #if FF_L1_IT_DSP_DTX // Postpone TPU/DSP programming when DTX status not available from DSP if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) { #endif /*----------------------------------------------*/ /* Common for Dedicated mode: DSP parameters... */ /*----------------------------------------------*/ #if (AMR == 1) #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, l1a_l1s_com.dedic_set.sync_amr, l1a_l1s_com.dedic_set.reset_sacch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.vocoder_on); #else l1a_l1s_com.dedic_set.vocoder_on, dtx_dsp_interrupt); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.sync_amr); #else l1a_l1s_com.dedic_set.sync_amr, dtx_dsp_interrupt); #endif #endif // Clear "sync_amr" flag to maintain normal TCH process. l1a_l1s_com.dedic_set.sync_amr = FALSE; #else #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, l1a_l1s_com.dedic_set.reset_sacch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.vocoder_on); #else l1a_l1s_com.dedic_set.vocoder_on, dtx_dsp_interrupt); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.sync_tch); #else l1a_l1s_com.dedic_set.sync_tch, dtx_dsp_interrupt); #endif #endif #endif // reset the FACCH header of the API buffer on the control following an ABORT to avoid decoding unwanted FACCH if (l1a_l1s_com.dedic_set.reset_facch == TRUE) { // Reset A_FD header. // B_FIRE1 =1, B_FIRE0 =0 , BLUD =0 l1s_dsp_com.dsp_ndb_ptr->a_fd[0] = (1<<B_FIRE1); l1s_dsp_com.dsp_ndb_ptr->a_fd[2] = 0xffff; } // Clear "sync_tch" and "reset_sacch" flag to maintain normal TCH process. l1a_l1s_com.dedic_set.sync_tch = FALSE; l1a_l1s_com.dedic_set.reset_facch = FALSE; #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1a_l1s_com.dedic_set.reset_sacch = FALSE; #endif // Set tpu window identifier for Power meas. l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_nb_load_split + l1_config.params.rx_synth_load_split; /*--------------------------------------------*/ /* 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 FF_L1_IT_DSP_DTX } //if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) #endif } /*-------------------------------------------------------*/ /* l1s_ctrl_tchtf() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* dedicated mode TCH task: TCHTF. This function is the */ /* control function for reading the DL burst and sending */ /* the UL burst. The UL burst can be a Normal Burst in */ /* normal case or an Access Burst when starting a */ /* Handover procedure. Both Half rate and Full rate TCH */ /* channel are handled. The DSP and the TPU are */ /* programmed for both the DL and UL bursts. The timing */ /* advance is taken into account for positionning the UL */ /* burst. */ /* */ /* This function accesses the L1/DLL and L1/DATA */ /* interface ("dll_read_dcch()", "tx_tch_data()" */ /* functions respectively) and passes then the returned */ /* data blocks to the DSP. */ /* */ /* Here is a summary of the execution: */ /* */ /* - Traces and debug. */ /* - Catch channel description and ARFCN. */ /* - TCH/T Receive... */ /* - Program DSP for RX. */ /* - Program TPU for RX. */ /* - Flag DSP and TPU programmation. */ /* - TCH/T Transmit... */ /* - If Any Handover Access burst to send */ /* - Call "l1s_ctrl_rach()". */ /* - Else */ /* - Get DATA block if required for TCH. */ /* - Program DSP for TX. */ /* - Program TPU for TX. */ /* - Flag DSP and TPU programmation. */ /* - Common for DL/UL: DSP parameters. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* TCHTF, Traffic Channel TCH Full rate. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.dedic_set" */ /* Dedicated channel parameter structure. */ /* .radio_freq, ARFCN value set by the Hopping algo. */ /* .aset, active dedicated parameter set. */ /* */ /* "l1a_l1s_com.Scell_info" */ /* Serving cell information structure. */ /* .bsic, BSIC of the serving cell. It is used here */ /* to pass the training sequence number (part */ /* of BSIC) to the DSP. */ /* */ /* "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. */ /* */ /* "l1s.applied_txpwr" */ /* Applied transmit power. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.tpu_win" */ /* each frame is composed with a maximum of 3 */ /* working/TPU windows (typically RX/TX/PW). This is */ /* a counter used to count the number of windows */ /* used. */ /* -> set to TDMA_WIN3. */ /* */ /* "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. */ /* -> set CTRL_TX 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. */ /* -> set CTRL_TX bit in the register. */ /* */ /*-------------------------------------------------------*/ void l1s_ctrl_tchtf(UWORD8 task, UWORD8 param2) { UWORD16 radio_freq=0; T_CHANNEL_DESCRIPTION *desc_ptr; UWORD8 lna_off; WORD8 agc; T_INPUT_LEVEL *IL_info_ptr; UWORD32 dsp_task; UWORD32 fn_mod_104; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb; UWORD8 if_ctl =0 ; //omaps00090550 UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; // By default we choose the hardware filter UWORD8 csf_filter_choice = L1_SAIC_HARDWARE_FILTER; #endif #if FF_L1_IT_DSP_DTX BOOL dtx_dsp_interrupt = FALSE; #endif #if (NEW_SNR_THRESHOLD == 1) UWORD8 saic_flag; #endif // Traces and debug. // ****************** #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsp_tpu(dltsk_trace[TCHTF].name); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Catch channel description and ARFCN. // ************************************* // Catch the active channel description used along the routine. // It contains: // "channel_type", {TCH_F, TCH_H, SDCCH_4, SDCCH_8}. // "subchannel", {0, 1}. 0 is the default value for TCH_F. desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; // 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 (radio_freq == l1a_l1s_com.Scell_info.radio_freq) IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas_beacon; // we are working on a beacon freq. else IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas; // we are working on a daughter freq. #if FF_L1_IT_DSP_DTX // Skip RX DSP/RF programming part during DTX HISR if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) { #endif /**************************************************************************/ /* TCH/T Receive... */ /**************************************************************************/ #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_TCHTF__DL, radio_freq); #endif /*--------------------------------------------*/ /* Program DSP... */ /*--------------------------------------------*/ // dsp pgm. dsp_task = l1s_swap_iq_dl(radio_freq,task); l1ddsp_load_rx_task(dsp_task, 0, desc_ptr->tsc); #if(RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID, IL_info_ptr->input_level , radio_freq,if_threshold); l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); #endif #if TESTMODE // if Normal Mode or // if TestMode DL+UL // NOTE: UL only true if DL is true in TCHTF! if ( !l1_config.TestMode || (l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK))) #endif { // Set TXPWR. l1ddsp_load_txpwr(l1s.applied_txpwr, radio_freq); } /*--------------------------------------------*/ /* Program TPU... */ /*--------------------------------------------*/ // for TCHTF we use DPAGC algorithm. #if DPAGC_MAX_FLAG agc = Cust_get_agc_from_IL(radio_freq, IL_info_ptr->input_level >> 1, MAX_ID); #else agc = Cust_get_agc_from_IL(radio_freq, IL_info_ptr->input_level >> 1, AV_ID); #endif lna_off = IL_info_ptr->lna_off; // Store input_level and lna_off fields used for current CTRL in order to be able // to build IL from pm in READ phase. l1a_l1s_com.Scell_used_IL = *IL_info_ptr; #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function 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 #if TESTMODE // Continuous mode: Rx TPU programmation only in NO_CONTINUOUS or START_RX_CONTINUOUS mode. if ((!l1_config.TestMode) || (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS) || (l1_config.tmode.rf_params.tmode_continuous == TM_START_RX_CONTINUOUS)) #endif { // update the TPU with the new TOA if necessary l1ctl_update_TPU_with_toa(); // Program a serving cell normal burst reading in TPU. l1dtpu_serv_rx_nb(radio_freq, agc, lna_off, l1s.tpu_offset, l1s.tpu_offset, FALSE,INACTIVE #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 DSP and TPU programmation... */ /*--------------------------------------------*/ // Set "CTRL_RX" flag in the controle flag register. #if TESTMODE // Continuous mode: swap TPU page for Rx only in NO_CONTINUOUS or START_RX_CONTINUOUS mode. if ((!l1_config.TestMode) || (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS) || (l1_config.tmode.rf_params.tmode_continuous == TM_START_RX_CONTINUOUS)) #endif { l1s.tpu_ctrl_reg |= CTRL_RX; } l1s.dsp_ctrl_reg |= CTRL_RX; #if FF_L1_IT_DSP_DTX } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) #endif /**************************************************************************/ /* TCH/T Transmit... */ /**************************************************************************/ // Any Handover Access burst to send ? // ************************************ if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0) // "ho_acc_to_send" is a counter of Handover Access burst still to send. // This counter is set by "l1s_dedicated_mode_manager()" in L1S when a // Handover command is received from L3 through L1A. // We must then replace the TCH UL normal burst by a RACH and decrement // this counter. { if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != -1) l1a_l1s_com.dedic_set.aset->ho_acc_to_send --; l1s_ctrl_rach(RAHO,NO_PAR); if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send == 0) // Handover access procedure is completed. // -> send L1C_HANDOVER_FINISHED message with "cause = COMPLETED" to L1A. { l1s_send_ho_finished(HO_COMPLETE); } } else // TCH/UL is a normal burst. { UWORD8 channel_mode = l1a_l1s_com.dedic_set.aset->achan_ptr->mode; //OMAPS00090550 UWORD8 channel_type = desc_ptr->channel_type; #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_TCHTF__UL, radio_freq); #endif #if FF_L1_IT_DSP_DTX // FACCH and IDS handled during L1S, have to be skipped during DTX HISR if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) { #endif /*--------------------------------------------*/ /* Get DATA block if required for TCH. */ /*--------------------------------------------*/ // Full rate traffic channel... { UWORD8 fn_report_mod13_mod4 = (l1s.next_time.fn_in_report % 13) % 4; if(fn_report_mod13_mod4 == 3) // It is time to check if a FACCH/UL data block is available from DLL or // if a data block is available from the DATA interface. { T_RADIO_FRAME *tx_data = NULL; // Check if any FACCH to transmit. // Rem: when mode is "SIGNALLING ONLY" the "dll_read_dcch()" function // always gives back a block of FACCH (true block or dummy one). // In ETM test mode, the protocol stack is not active and hence we do not require any FACCH data from L23 // But this change is applicable only when ETM scripts are run with PS-builds. In case of L1-SA, // dll_read_dcch() is called which is just a stub function (It just returns a NULL ptr for L1 SA) /* FreeCalypso: this logic is not present in TCS211 */ #if 0 #if TESTMODE #if (OP_L1_STANDALONE == 0) if(!l1_config.TestMode) #endif // (OP_L1_STANDALONE == 0) #endif // TESTMODE #endif { tx_data = dll_read_dcch(channel_mode); } if(tx_data != NULL) { // In DTX mode in FR and EFR, all 8 FACCH 1/2 bursts must always be transmitted. // Note: FACCH presence is checked 1 "control" before "control" of 1st burst of FACCH due to a DSP constraint // i.e. 2 bursts before FACCH interleaving boundary //So we must wait 1 burst before controlling the transmission of 8 FACCH 1/2 bursts l1s.facch_bursts = 9; #if (TRACE_TYPE==1) || (TRACE_TYPE==4) RTTL1_FILL_UL_DCCH trace_info.facch_ul_count ++; #endif // Store the FACCH/UL data block in the MCU/DSP com. #if TRACE_TYPE==3 if (l1_stats.type == PLAY_UL) { // load A_DU_1 in PLAY Uplink mode. l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_1, &(tx_data->A[0])); if (channel_mode == TCH_EFR_MODE) { WORD32 bit5word14, bit2word14, bit12word15, bit15word15; // clear CRC bits and repetition bits l1s_dsp_com.dsp_ndb_ptr->a_du_1[7] &= 0x807f; l1s_dsp_com.dsp_ndb_ptr->a_du_1[14] &= 0xfc24; l1s_dsp_com.dsp_ndb_ptr->a_du_1[15] &= 0x93ff; l1s_dsp_com.dsp_ndb_ptr->a_du_1[19] &= 0xff00; // read repetition bits bit5word14 = (l1s_dsp_com.dsp_ndb_ptr->a_du_1[14] >> 5)& 0x1; bit2word14 = (l1s_dsp_com.dsp_ndb_ptr->a_du_1[14] >> 2)& 0x1; bit12word15 = (l1s_dsp_com.dsp_ndb_ptr->a_du_1[15] >> 12) & 0x1; bit15word15 = (l1s_dsp_com.dsp_ndb_ptr->a_du_1[15] >> 15)& 0x1; // copy repetition bits l1s_dsp_com.dsp_ndb_ptr->a_du_1[14] |= (bit5word14 << 4 | bit5word14 << 3 | bit2word14 | bit2word14 << 1); l1s_dsp_com.dsp_ndb_ptr->a_du_1[15] |= (bit15word15 << 13 | bit12word15 << 14 | bit12word15 << 10 | bit15word15 << 11); } else { l1s_dsp_com.dsp_ndb_ptr->a_du_1[14] &= 0xfc3f; l1s_dsp_com.dsp_ndb_ptr->a_du_1[19] &= 0xff00; } // set PLAY Uplink bit ....... l1s_dsp_com.dsp_ndb_ptr->d_tch_mode |= (1 << B_PLAY_UL); } else l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_fu, &(tx_data->A[0])); #else l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_fu, &(tx_data->A[0])); #endif #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsptx(dltsk_trace[TCHTF].name); #endif } #if (AMR == 1) // Check if any DATA traffic info frame available. // This check is used for all full rate channels except when // this channel is in SIGNALLING ONLY mode or in Full Rate // Speech mode or adaptative full rate mode. if((channel_mode != TCH_FS_MODE) && (channel_mode != SIG_ONLY_MODE) && (channel_mode != TCH_EFR_MODE) && (channel_mode != TCH_AFS_MODE)) #else // Check if any DATA traffic info frame available. // This check is used for all full rate channels except when // this channel is in SIGNALLING ONLY mode or in Full Rate // Speech mode. if((channel_mode != TCH_FS_MODE) && (channel_mode != SIG_ONLY_MODE) && (channel_mode != TCH_EFR_MODE)) #endif { #if IDS { UWORD8 fn_report_mod26; API *data_ul; data_ul = l1s_dsp_com.dsp_ndb_ptr->a_du_0; fn_report_mod26 = l1s.next_time.fn_in_report%26; // Set flag for UL/DL block information: for TCH/F48 mode only if((channel_mode == TCH_48F_MODE) && ((fn_report_mod26 == 7) || (fn_report_mod26 == 16) || (fn_report_mod26 == 24))) l1s_dsp_com.dsp_ndb_ptr->d_ra_act |= (3 << B_F48BLK); else l1s_dsp_com.dsp_ndb_ptr->d_ra_act &= ~(3 << B_F48BLK); dll_data_ul(l1s_dsp_com.dsp_ndb_ptr->a_data_buf_ul, &l1s_dsp_com.dsp_ndb_ptr->d_ra_conf, &l1s_dsp_com.dsp_ndb_ptr->d_ra_act, &l1s_dsp_com.dsp_ndb_ptr->d_ra_test, &l1s_dsp_com.dsp_ndb_ptr->d_ra_statu, &l1s_dsp_com.dsp_ndb_ptr->d_fax); // Fill a_du_0 data block Header. // Note: a_du_0 header is fill when dummy block is filled as well when data block // is filled (buffer a_data_buf_ul data_ul[0] = (1 << B_BLUD); // 1st word: Set B_BLU bit. data_ul[1] = 0; // 2nd word: cleared. data_ul[2] = 0; // 3rd word: cleared. } #else { UWORD8 *tx_data = NULL; tx_data = tx_tch_data(); if(tx_data != NULL) { // Store the DATA/UL data block in the MCU/DSP com. #if TRACE_TYPE==3 if (l1_stats.type == PLAY_UL) { // load A_DU_1 in PLAY Uplink mode. l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_1, tx_data); if (channel_mode == TCH_48F_MODE) l1s_dsp_com.dsp_ndb_ptr->a_du_1[10] &= 0x00ff; if (channel_mode == TCH_24F_MODE) l1s_dsp_com.dsp_ndb_ptr->a_du_1[7] &= 0x00ff; // set PLAY Uplink bit ....... l1s_dsp_com.dsp_ndb_ptr->d_tch_mode |= (1 << B_PLAY_UL); } else l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_0, tx_data); #else l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_du_0, tx_data); #endif } #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsptx(dltsk_trace[TCHTF].name); #endif } #endif } } } #if FF_L1_IT_DSP_DTX // Fast DTX active only in TCH AFS, for TDMA3 from speech block = 0, 1 [MOD 3] if ((l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AFS_MODE) && (l1a_l1s_com.dedic_set.aset->dtx_allowed == TRUE)) { // DTX interrupt request for B1 and B2 (no DTX uncertainty on B0 thanks to idle frame) if (l1s.next_time.fn_mod13 <= 7) dtx_dsp_interrupt = TRUE; // DTX uncertainty check if ((l1a_apihisr_com.dtx.fast_dtx_ready == TRUE) && // Fast DTX can be used ((l1s.next_time.fn_mod13 == 4) || (l1s.next_time.fn_mod13 == 8))) // new block boundary l1a_apihisr_com.dtx.dtx_status = DTX_AWAITED; } else l1a_apihisr_com.dtx.dtx_status = DTX_AVAILABLE; } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) // Postpone TPU/DSP programming when DTX status not available from DSP if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED) { BOOL tx_active =FALSE; //omaps00090550 #endif #if TESTMODE // if Normal Mode or // if TestMode and UL+DL // NOTE: UL only true if DL is true in TCHTF! if ( !l1_config.TestMode || (l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK))) #endif { /*--------------------------------------------*/ /* Program DSP... */ /*--------------------------------------------*/ dsp_task = l1s_swap_iq_ul(radio_freq,task); l1ddsp_load_tx_task(dsp_task, 0, desc_ptr->tsc); /*--------------------------------------------*/ /* Program TPU... */ /*--------------------------------------------*/ fn_mod_104 = l1s.actual_time.fn % 104; #if TESTMODE if ((!l1_config.TestMode) || (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS) || (l1_config.tmode.rf_params.tmode_continuous == TM_START_TX_CONTINUOUS)) #endif { l1s.facch_bursts--; if (l1s.facch_bursts < 0) l1s.facch_bursts = -1; #if FF_L1_IT_DSP_DTX // Condition for TX TPU programming channel mode dependant switch (channel_mode) { case SIG_ONLY_MODE: case TCH_24F_MODE: case TCH_48F_MODE: case TCH_96_MODE: case TCH_144_MODE: // DTX not supported tx_active = TRUE; break; case TCH_FS_MODE: case TCH_EFR_MODE: if ((l1s.dtx_ul_on == FALSE) || // No DTX ((l1s.facch_bursts >= 0) && (l1s.facch_bursts <= 7)) || // FACCH in progress ((fn_mod_104 >= 51) && (fn_mod_104 <= 58)) // SID ) tx_active = TRUE; else tx_active = FALSE; break; case TCH_AFS_MODE: if (l1a_apihisr_com.dtx.tx_active) // DSP (Fast) DTX status tx_active = TRUE; else tx_active = FALSE; break; } // TPU TX burst programming if (tx_active) #else // In DTX mode, UL bursts should not be transmitted when no voice activity is detected // we must not call TPU scenario if dtx_on == TRUE in EFR and FR (See Technical Memo) // However, in DTX mode, bursts 52 to 59 (modulo 104) must always be transmitted // FACCH must also be transmitted but we must wait 1 bursts before transmitting 8 1/2 bursts if ( ((channel_mode != TCH_FS_MODE) && (channel_mode != TCH_EFR_MODE)) || (l1s.dtx_ul_on == FALSE) || ( (l1s.facch_bursts >= 0) && (l1s.facch_bursts <= 7) ) || ((fn_mod_104 >= 51) && (fn_mod_104 <= 58)) ) #endif { l1dtpu_serv_tx_nb(radio_freq, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.tpu_offset, l1s.applied_txpwr,INACTIVE); } } #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.applied_txpwr) #endif } #if FF_L1_IT_DSP_DTX } // if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED) #endif } // TCH/UL is a normal burst. #if FF_L1_IT_DSP_DTX // Postpone TPU/DSP programming when DTX status not available from DSP if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) { #endif /*----------------------------------------------*/ /* Common for Dedicated mode: DSP parameters... */ /*----------------------------------------------*/ #if (AMR == 1) #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, 0, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, l1a_l1s_com.dedic_set.sync_amr, l1a_l1s_com.dedic_set.reset_sacch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.vocoder_on); #else l1a_l1s_com.dedic_set.vocoder_on, dtx_dsp_interrupt); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, 0, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.sync_amr); #else l1a_l1s_com.dedic_set.sync_amr, dtx_dsp_interrupt); #endif #endif // Clear "sync_amr" flag to maintain normal TCH process. l1a_l1s_com.dedic_set.sync_amr = FALSE; #else #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, 0, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, l1a_l1s_com.dedic_set.reset_sacch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.vocoder_on); #else l1a_l1s_com.dedic_set.vocoder_on, dtx_dsp_interrupt); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, 0, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.sync_tch); #else l1a_l1s_com.dedic_set.sync_tch, dtx_dsp_interrupt); #endif #endif #endif // reset the FACCH header of the API buffer on the control following an ABORT to avoid decoding unwanted FACCH if (l1a_l1s_com.dedic_set.reset_facch == TRUE) { // Reset A_FD header. // B_FIRE1 =1, B_FIRE0 =0 , BLUD =0 l1s_dsp_com.dsp_ndb_ptr->a_fd[0] = (1<<B_FIRE1); l1s_dsp_com.dsp_ndb_ptr->a_fd[2] = 0xffff; } // Clear "sync_tch" and "reset_sacch" flag to maintain normal TCH process. l1a_l1s_com.dedic_set.sync_tch = FALSE; l1a_l1s_com.dedic_set.reset_facch = FALSE; #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1a_l1s_com.dedic_set.reset_sacch = FALSE; #endif // Set tpu window identifier for Power meas or FS/SB search. l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_nb_load_split + l1_config.params.rx_synth_load_split; /*--------------------------------------------*/ /* Flag DSP and TPU programmation... */ /*--------------------------------------------*/ #if TESTMODE // if Normal Mode or // if TestMode and UL+DL // NOTE: UL only true if DL is true in TCHTF! if ( !l1_config.TestMode || ( l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK))) #endif { #if TESTMODE // Continuous mode: swap TPU page for Tx in NO_CONTINUOUS or START_TX_CONTINUOUS mode. if ((!l1_config.TestMode) || (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS) || (l1_config.tmode.rf_params.tmode_continuous == TM_START_TX_CONTINUOUS)) #endif { l1s.tpu_ctrl_reg |= CTRL_TX; } l1s.dsp_ctrl_reg |= CTRL_TX; } #if TESTMODE // Continuous mode: if end of control of START_RX/TX: go to CONTINUOUS state if (l1_config.TestMode && (l1_config.tmode.rf_params.tmode_continuous != TM_NO_CONTINUOUS)) l1_config.tmode.rf_params.tmode_continuous = TM_CONTINUOUS; #endif #if FF_L1_IT_DSP_DTX } //if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) #endif } /*-------------------------------------------------------*/ /* l1s_ctrl_tcha() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* dedicated mode TCH task: TCHA. This function is the */ /* control function for reading the DL burst and sending */ /* the UL burst on the Slow Associated Channel (SACCH) */ /* associated with the traffic channel. The UL burst can */ /* be a Normal Burst in normal case or an Access Burst */ /* when starting a Handover procedure. Both Half rate */ /* and Full rate TCH channel are handled. The DSP and */ /* the TPU are programmed for both the DL and UL bursts. */ /* The timing advance is taken into account for */ /* positionning the UL burst. */ /* */ /* This function accesses the L1/DLL interface */ /* ("dll_read_sacch()" function) and passes then the */ /* returned data blocks to the DSP after having set the */ /* L1 header part of the block. */ /* */ /* Here is a summary of the execution: */ /* */ /* - Traces and debug. */ /* - Catch channel description and ARFCN. */ /* - TCH/SACCH Receive... */ /* - Program DSP for RX. */ /* - Program TPU for RX. */ /* - Flag DSP and TPU programmation. */ /* - TCH/SACCH Transmit... */ /* - If Any Handover Access burst to send */ /* - Call "l1s_ctrl_rach()". */ /* - Else */ /* - Get DATA block from DLL if required. */ /* - Program DSP for TX. */ /* - Program TPU for TX. */ /* - Flag DSP and TPU programmation. */ /* - Common for DL/UL: DSP parameters. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* TCHA, Associated channel task when dedicated/TCH. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.dedic_set" */ /* Dedicated channel parameter structure. */ /* .radio_freq, ARFCN value set by the Hopping algo. */ /* .aset, active dedicated parameter set. */ /* */ /* "l1a_l1s_com.Scell_info" */ /* Serving cell information structure. */ /* .bsic, BSIC of the serving cell. It is used here */ /* to pass the training sequence number (part */ /* of BSIC) to the DSP. */ /* */ /* "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. */ /* */ /* "l1s.applied_txpwr" */ /* Applied transmit power. */ /* */ /* "l1s.reported_txpwr" */ /* Transmit power to report in the L1 header of the */ /* SACCH data block. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1s.tpu_win" */ /* each frame is composed with a maximum of 3 */ /* working/TPU windows (typically RX/TX/PW). This is */ /* a counter used to count the number of windows */ /* used. */ /* -> set to TDMA_WIN3. */ /* */ /* "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. */ /* -> set CTRL_TX 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. */ /* -> set CTRL_TX bit in the register. */ /* */ /*-------------------------------------------------------*/ void l1s_ctrl_tcha(UWORD8 task, UWORD8 param2) { UWORD16 radio_freq=0; T_CHANNEL_DESCRIPTION *desc_ptr; UWORD8 lna_off =0;//omaps00090550 WORD8 agc =0; //omaps00090550 T_INPUT_LEVEL *IL_info_ptr; UWORD32 dsp_task; UWORD8 adc_active_ul = INACTIVE; UWORD8 adc_active_dl = INACTIVE; #if (RF_FAM == 61) UWORD16 dco_algo_ctl_nb = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = C_IF_ZERO_LOW_THRESHOLD_GSM; // 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[TCHA].name); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Catch channel description and ARFCN. // ************************************* // Catch the active channel description used along the routine. // It contains: // "channel_type", {TCH_F, TCH_H, SDCCH_4, SDCCH_8}. // "subchannel", {0, 1}. 0 is the default value for TCH_F. desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; // Get ARFCN to be used for current control. radio_freq = l1a_l1s_com.dedic_set.radio_freq; if (radio_freq == l1a_l1s_com.Scell_info.radio_freq) IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas_beacon; // we are working on a beacon freq. else IL_info_ptr = &l1a_l1s_com.Scell_info.traffic_meas; // we are working on a daughter freq. /**************************************************************************/ /* SACCH Receive... */ /**************************************************************************/ // ADC measurement // *************** // check if during the SACCH burst an ADC measurement must be performed if (l1a_l1s_com.adc_mode & ADC_NEXT_TRAFFIC_DL) // perform ADC only one time { adc_active_dl = 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_DL) // perform ADC on each period bloc if (l1s.next_time.fn_in_report == 12) //periodic with each 1st SACCH burst if ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_traffic_period) // wait for the period { adc_active_dl = ACTIVE; l1a_l1s_com.adc_cpt = 0; } #if TESTMODE // if Normal Mode or // if TestMode and DL-only or DL+UL if ( !l1_config.TestMode || (l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_DOWNLINK))) #endif { #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_TCHA___DL, radio_freq); #endif /*--------------------------------------------*/ /* Program DSP... */ /*--------------------------------------------*/ // dsp pgm. dsp_task = l1s_swap_iq_dl(radio_freq,task); l1ddsp_load_rx_task(dsp_task, 0, desc_ptr->tsc); #if(RF_FAM == 61) // Locosto DCO cust_get_if_dco_ctl_algo(&dco_algo_ctl_nb, &if_ctl, (UWORD8) L1_IL_VALID , IL_info_ptr->input_level , radio_freq,if_threshold); l1ddsp_load_dco_ctl_algo_nb(dco_algo_ctl_nb); #endif /*--------------------------------------------*/ /* Program TPU... */ /*--------------------------------------------*/ // for TCHA we use DPAGC algorithm. #if DPAGC_MAX_FLAG agc = Cust_get_agc_from_IL(radio_freq, IL_info_ptr->input_level >> 1, MAX_ID); #else agc = Cust_get_agc_from_IL(radio_freq, IL_info_ptr->input_level >> 1, AV_ID); #endif lna_off = IL_info_ptr->lna_off; // Store input_level and lna_off fields used for current CTRL in order to be able // to build IL from pm in READ phase. l1a_l1s_com.Scell_used_IL = *IL_info_ptr; #if (L1_SAIC != 0) // If SAIC is enabled, call the low level SAIC control function 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 #if TESTMODE // Continuous mode: Rx TPU programmation only in NO_CONTINUOUS or START_RX_CONTINUOUS mode. if ((!l1_config.TestMode) || (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS) || (l1_config.tmode.rf_params.tmode_continuous == TM_START_RX_CONTINUOUS)) #endif { // update the TPU with the new TOA if necessary l1ctl_update_TPU_with_toa(); // Program a serving cell normal burst reading in TPU. l1dtpu_serv_rx_nb(radio_freq, agc, lna_off, l1s.tpu_offset, l1s.tpu_offset, FALSE,adc_active_dl #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); // Set "CTRL_RX" flag in the control flag register. #if TESTMODE // Continuous mode: swap TPU page for Rx only in NO_CONTINUOUS or START_RX_CONTINUOUS mode. if ((!l1_config.TestMode) || (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS) || (l1_config.tmode.rf_params.tmode_continuous == TM_START_RX_CONTINUOUS)) #endif { l1s.tpu_ctrl_reg |= CTRL_RX; } l1s.dsp_ctrl_reg |= CTRL_RX; } /**************************************************************************/ /* TCH/T Transmit... */ /**************************************************************************/ // Any Handover Access burst to send ? --> TXPWR management // ************************************ if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0) // "ho_acc_to_send" is a counter of Handover Access burst still to send. // This counter is set by "l1s_dedicated_mode_manager()" in L1S when a // Handover command is received from L3 through L1A. // When Handover access is in progress, nothing but RACH can be transmitted. // RACH is not allowed on SACCH therefore TX is avoided by setting // the txpwr to NO_TXPWR !!! { #if 0 /* LoCosto code */ // NOTE: The spec says RACH bursts on SACCH UL is optional. hence it should not be counted // Refer spec 04.08 l1s_ctrl_rach(RAHO,NO_PAR); #else /* TCS211 reconstruction, code taken from TSM30 */ // Set TXPWR. l1ddsp_load_txpwr(NO_TXPWR, radio_freq); #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, NO_TXPWR) #endif #endif } else // TCH/UL is a normal burst. // TX power must be the normal one { // Set TXPWR. l1ddsp_load_txpwr(l1s.applied_txpwr, radio_freq); #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_UL_NB(task, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.applied_txpwr) #endif // 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_ul = 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 (l1s.next_time.fn_in_report == 12) //periodic with each 1st SACCH burst if ((++l1a_l1s_com.adc_cpt)>=l1a_l1s_com.adc_traffic_period) // wait for the period { adc_active_ul = ACTIVE; l1a_l1s_com.adc_cpt = 0; } #if 1 /* FreeCalypso TCS211 reconstruction */ } // End of "TCH/UL is a normal burst" #endif // In any case (normal TX or no TX due to Handover Access process) // the full TCHA task must be controled for TPU and DSP. { T_RADIO_FRAME *tx_data = NULL; #if (TRACE_TYPE!=0) trace_fct(CST_L1S_CTRL_TCHA___UL, radio_freq); #endif /*--------------------------------------------*/ /* Get DATA block if required for SACCH. */ /*--------------------------------------------*/ if(l1s.next_time.fn_in_report == 12) // It is time to get a SACCH data block from DLL. // Call "dll_read_sacch()" to perform "PH_DATA_REQ" and pass // the data block to the DSP.. { #if ((FF_REPEATED_SACCH) && ( TESTMODE)) if(l1_config.repeat_sacch_enable != REPEATED_SACCH_ENABLE) { l1s.repeated_sacch.sro = 0; l1s.repeated_sacch.buffer_empty = TRUE; } #endif /* #if ((FF_REPEATED_SACCH) && ( TESTMODE)) */ #if FF_REPEATED_SACCH /* Get data from PS if only no repetition order is required (1st condition) */ /* or no repetition candidate exists (2nd condition) */ if((l1s.repeated_sacch.sro == 0) || (l1s.repeated_sacch.buffer_empty == TRUE)) #endif /* FF_REPEATED_SACCH */ { tx_data = dll_read_sacch(SIG_ONLY_MODE); if(tx_data != NULL) { // Set L1 Header... tx_data->A[0] = l1s.reported_txpwr; tx_data->A[1] = l1a_l1s_com.dedic_set.aset->timing_advance; #if FF_REPEATED_SACCH /* Include the SACCH Repetition Request (SRR) in the L1 Header */ tx_data->A[0] |= (l1s.repeated_sacch.srr <<6); #endif /* FF_REPEATED_SACCH */ // Put data block in MCU/DSP com. l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_cu, &(tx_data->A[0])); #if (FF_REPEATED_SACCH == 1 ) if(((tx_data->A[2]&0x1C) >> 2) == SAPI_0) /* Store the block data in case of a retransmission order */ { l1s_store_sacch_buffer( &(l1s.repeated_sacch), &(tx_data->A[0])); /* Stores the buffer and turns of the buffer_empty flag as false */ } else { /* the SACCH repetition block occurrence will always come as a consecutive pair */ /* To handle DL UL | DL UL | DL UL */ /* - 0 | SRO 3 | - new data should be asked from PS old 0 cannot be repeated */ l1s.repeated_sacch.buffer_empty=TRUE; } #endif /* FF_REPEATED_SACCH */ } /* if(tx_data != NULL) */ #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dsptx(dltsk_trace[TCHA].name); #endif }/* if((l1s.repeated_sacch.sro == 0) || (l1s.repeated_sacch.buffer_empty == TRUE))*/ #if FF_REPEATED_SACCH else if ((l1s.repeated_sacch.sro == 1) && (l1s.repeated_sacch.buffer_empty == FALSE)) { /* Put data block in MCU/DSP com. */ l1ddsp_load_info(DSP_TASK_CODE[task], l1s_dsp_com.dsp_ndb_ptr->a_cu, l1s.repeated_sacch.buffer ); l1s.repeated_sacch.buffer_empty = TRUE; /* Set that the buffer is now empty (only one repetition) */ } /* end else repetition */ #endif /* FF_REPEATED_SACCH */ // check to be removed } /*--------------------------------------------*/ /* Program DSP... */ /*--------------------------------------------*/ #if TESTMODE // UL-only... // Use SPI to write to Omega uplink buffer, do NOT use DSP if (l1_config.TestMode && l1_config.tmode.rf_params.down_up == TMODE_UPLINK) { #if (CODE_VERSION != SIMULATION) // For Calyso+ & Before... #if (RF_FAM == 12) ABB_Write_Register_on_page(PAGE0, AUXAPC, Cust_get_pwr_data(l1s.applied_txpwr, radio_freq #if(REL99 && FF_PRF) ,1 #endif )); l1tm_fill_burst(l1_config.tmode.tx_params.burst_data, &TM_ul_data[0]); ABB_Write_Uplink_Data(&TM_ul_data[0]); #endif //For UppCosto, Tx Data Write is via PLD to DRP & Ramp is via the ABB Driver #if (RF_FAM == 60) ABB_Write_Register_on_page(PAGE0, AUXAPC, Cust_get_pwr_data(l1s.applied_txpwr, radio_freq #if(REL99 && FF_PRF) ,1 #endif )); l1tm_fill_burst(l1_config.tmode.tx_params.burst_data, &TM_ul_data[0]); PLD_Write_Uplink_Data(&TM_ul_data[0]); #endif #if (RF_FAM == 61) // For DRP we use the DSP to write the TX Power via a new variable apclev in API // A new variable is required in API as DSP copies the tx_power_ctl (which is // normally used to pass the APCLEV value to DSP) to APCLEV ONLY when there is a // burst to be transmitted l1ddsp_apc_load_apclev(Cust_get_pwr_data(l1s.applied_txpwr, radio_freq #if(REL99 && FF_PRF) ,1 #endif )); l1tm_fill_burst(l1_config.tmode.tx_params.burst_data, &TM_ul_data[0]); DRP_Write_Uplink_Data(&TM_ul_data[0]); #endif #endif } // Use DSP... // if Normal Mode or // if TestMode and DL+UL else if ( !l1_config.TestMode || (l1_config.TestMode && l1_config.tmode.rf_params.down_up == (TMODE_DOWNLINK|TMODE_UPLINK))) { dsp_task = l1s_swap_iq_ul(radio_freq,task); l1ddsp_load_tx_task(dsp_task, 0, desc_ptr->tsc); } #else dsp_task = l1s_swap_iq_ul(radio_freq,task); l1ddsp_load_tx_task(dsp_task, 0, desc_ptr->tsc); #endif /*--------------------------------------------*/ /* Program TPU... */ /*--------------------------------------------*/ #if TESTMODE // if Normal Mode or // if TestMode and UL-only or DL+UL if ( !l1_config.TestMode || (l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK) && (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS || l1_config.tmode.rf_params.tmode_continuous == TM_START_TX_CONTINUOUS))) #endif { l1dtpu_serv_tx_nb(radio_freq, l1a_l1s_com.dedic_set.aset->timing_advance, l1s.tpu_offset, l1s.applied_txpwr, adc_active_ul); } } #if 0 /* FreeCalypso TCS211 reconstruction */ } // End of "TCH/UL is a normal burst" #endif /*----------------------------------------------*/ /* Common for Dedicated mode: DSP parameters... */ /*----------------------------------------------*/ #if (AMR == 1) #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, l1a_l1s_com.dedic_set.sync_amr, l1a_l1s_com.dedic_set.reset_sacch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.vocoder_on); #else l1a_l1s_com.dedic_set.vocoder_on, 0); #endif #else // FF_L1_TCH_VOCODER_CONTROL l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.sync_amr); #else l1a_l1s_com.dedic_set.sync_amr, 0); #endif #endif // FF_L1_TCH_VOCODER_CONTROL l1a_l1s_com.dedic_set.sync_amr = FALSE; #else // AMR #if (FF_L1_TCH_VOCODER_CONTROL == 1) l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, l1a_l1s_com.dedic_set.sync_tch, l1a_l1s_com.dedic_set.reset_sacch, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.vocoder_on); #else l1a_l1s_com.dedic_set.vocoder_on, 0); #endif #else l1ddsp_load_tch_param(&(l1s.next_time), l1a_l1s_com.dedic_set.aset->achan_ptr->mode, desc_ptr->channel_type, desc_ptr->subchannel, l1a_l1s_com.dedic_set.aset->achan_ptr->tch_loop, #if !FF_L1_IT_DSP_DTX l1a_l1s_com.dedic_set.sync_tch); #else l1a_l1s_com.dedic_set.sync_tch, 0); #endif #endif #endif // AMR // Clear "sync_tch" flag to maintain normal TCH process. l1a_l1s_com.dedic_set.sync_tch = FALSE; #if (FF_L1_TCH_VOCODER_CONTROL) l1a_l1s_com.dedic_set.reset_sacch = FALSE; #endif #if 0 /* FreeCalypso TCS211 reconstruction */ if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send == 0) { #endif // Set tpu window identifier for Power meas or FS/SB search. l1s.tpu_win = (3 * BP_SPLIT) + l1_config.params.tx_nb_load_split + l1_config.params.rx_synth_load_split; /*--------------------------------------------*/ /* Flag DSP and TPU programmation... */ /*--------------------------------------------*/ #if TESTMODE // if Normal Mode or // if TestMode and UL-only or DL+UL if ( !l1_config.TestMode || (l1_config.TestMode && (l1_config.tmode.rf_params.down_up & TMODE_UPLINK))) #endif { #if TESTMODE // Continuous mode: swap TPU page for Tx in NO_CONTINUOUS or START_TX_CONTINUOUS mode. if ((!l1_config.TestMode) || (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS) || (l1_config.tmode.rf_params.tmode_continuous == TM_START_TX_CONTINUOUS)) #endif { l1s.tpu_ctrl_reg |= CTRL_TX; } l1s.dsp_ctrl_reg |= CTRL_TX; } #if TESTMODE // Continuous mode: if end of control of START_RX/TX: go to CONTINUOUS state if (l1_config.TestMode && (l1_config.tmode.rf_params.tmode_continuous != TM_NO_CONTINUOUS)) l1_config.tmode.rf_params.tmode_continuous = TM_CONTINUOUS; #endif #if 0 /* FreeCalypso TCS211 reconstruction */ } #endif } #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_hopping_algo() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* dedicated mode tasks: DDL, DUL, ADL, AUL, TCHTH/F and */ /* TCHA. This function performs the Hopping Sequence */ /* generation. It computes the ARFCN to use on the next */ /* frame. When the channel does not hop, it returns */ /* the fixe ARFCN provided in the channel description. */ /* */ /* If the channel is hopping and the ARFCN result is the */ /* BEACON frequency, an indication flag is set to warn */ /* the DSP ("b_bcch_freq_ind"). */ /* */ /* (see GSM05.02 $6.2.3) */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.dedic_set.aset" */ /* Active set of Dedicated channel parameters. */ /* */ /* "l1s.l1s.next_time" */ /* frame number and derived numbers for next frame. */ /* */ /* Returned parameter in globals: */ /* ------------------------------ */ /* */ /* "l1a_l1s_com.dedic_set.radio_freq" */ /* ARFCN to be used on the next frame. */ /* */ /*-------------------------------------------------------*/ void l1s_hopping_algo(UWORD8 task, UWORD8 param2) { UWORD8 mai; T_CHN_SEL *chan_sel; T_MOBILE_ALLOCATION *alist_ptr; UWORD16 *ma; UWORD8 n; UWORD8 hsn; UWORD8 maio; UWORD16 *radio_freq_ptr; UWORD16 *beacon_channel_ptr=&l1a_l1s_com.Scell_info.radio_freq; // beacon channel of the serving cell T_TIME_INFO *time_ptr; T_TIME_INFO next_neighbor_time; switch(task) { #if L1_GPRS case PTCCH: { chan_sel = &(l1pa_l1ps_com.transfer.aset->freq_param.chan_sel); alist_ptr = &(l1pa_l1ps_com.transfer.aset->freq_param.freq_list); radio_freq_ptr = &l1pa_l1ps_com.transfer.ptcch.radio_freq; time_ptr = &l1s.next_time; } break; case PDTCH: case SINGLE: // For PDTCH, set pointers to the PACKET parameter structures. { chan_sel = &(l1pa_l1ps_com.transfer.aset->freq_param.chan_sel); alist_ptr = &(l1pa_l1ps_com.transfer.aset->freq_param.freq_list); radio_freq_ptr = &l1a_l1s_com.dedic_set.radio_freq; time_ptr = &l1s.next_time; } break; case PALLC: case PNP: case PEP: { chan_sel = &l1pa_l1ps_com.pccch.packet_chn_desc.chan_sel; alist_ptr = &l1pa_l1ps_com.pccch.frequency_list; radio_freq_ptr = &l1pa_l1ps_com.p_idle_param.radio_freq; time_ptr = &l1s.next_time; } break; case POLL: { // Load adequat freq. list according to the current mode: // SINGLE (i.e. 2 phase access) else Packet Access or Packet Idle if(l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED) { chan_sel = &(l1pa_l1ps_com.transfer.aset->freq_param.chan_sel); alist_ptr = &(l1pa_l1ps_com.transfer.aset->freq_param.freq_list); radio_freq_ptr = &l1a_l1s_com.dedic_set.radio_freq; } else { chan_sel = &l1pa_l1ps_com.pccch.packet_chn_desc.chan_sel; alist_ptr = &l1pa_l1ps_com.pccch.frequency_list; radio_freq_ptr = &l1pa_l1ps_com.p_idle_param.radio_freq; } time_ptr = &l1s.next_time; } break; case PBCCHS: { chan_sel = &l1pa_l1ps_com.pbcchs.packet_chn_desc.chan_sel; alist_ptr = &l1pa_l1ps_com.pbcchs.frequency_list; radio_freq_ptr = &l1pa_l1ps_com.p_idle_param.radio_freq; // If PBCCHS controlled one frame in advance --> correct Frame Number when PBCCH block is read if (l1pa_l1ps_com.pbcchs.control_offset) time_ptr = &l1s.next_plus_time; else time_ptr = &l1s.next_time; } break; case PBCCHN_IDLE: case PBCCHN_TRAN: { WORD32 next_neighbor_time_fn; chan_sel = &l1pa_l1ps_com.pbcchn.packet_chn_desc.chan_sel; alist_ptr = &l1pa_l1ps_com.pbcchn.frequency_list; radio_freq_ptr = &l1pa_l1ps_com.p_idle_param.radio_freq; beacon_channel_ptr = &l1pa_l1ps_com.pbcchn.bcch_carrier; time_ptr = &next_neighbor_time; // To review (is there any better solution?)........... next_neighbor_time_fn = l1s.next_time.fn + l1pa_l1ps_com.pbcchn.fn_offset; #if 0 /* correct code (corrected by TI for LoCosto) */ if (next_neighbor_time_fn > ((WORD32)MAX_FN))//OMAPS00090550 #else /* wrong code to match TCS211 disassembly */ if (next_neighbor_time_fn > MAX_FN) #endif next_neighbor_time.fn = (UWORD32) (next_neighbor_time_fn - MAX_FN); else if (next_neighbor_time_fn < 0) next_neighbor_time.fn = (UWORD32) (next_neighbor_time_fn + MAX_FN); else next_neighbor_time.fn = (UWORD32) (next_neighbor_time_fn); next_neighbor_time.t1 = next_neighbor_time.fn / (26L*51L); // T1 = FN div 26*51 next_neighbor_time.t2 = next_neighbor_time.fn % 26; // T2 = FN % 26. next_neighbor_time.t3 = next_neighbor_time.fn % 51; // T3 = FN % 51. } break; case ITMEAS: { // Packet transfer mode if (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) { // We use the active TBF frequency parameters chan_sel = &(l1pa_l1ps_com.transfer.aset->freq_param.chan_sel); alist_ptr = &(l1pa_l1ps_com.transfer.aset->freq_param.freq_list); } // Packet idle mode else { // We use the frequency parameters given in the MPHP_INT_MEAS_REQ message chan_sel = &(l1pa_l1ps_com.itmeas.packet_intm_freq_param.chan_sel); alist_ptr = &(l1pa_l1ps_com.itmeas.packet_intm_freq_param.freq_list); } radio_freq_ptr = &l1pa_l1ps_com.itmeas.radio_freq; time_ptr = &l1s.next_plus_time; } break; #endif case SMSCB: // For SMSCB, set pointers to the SMSCB parameter structures. { chan_sel = &l1a_l1s_com.cbch_desc.chan_sel; alist_ptr = &l1a_l1s_com.cbch_freq_list; radio_freq_ptr = &l1a_l1s_com.dedic_set.radio_freq; // If SMSCB is controlled one frame in advance --> correct Frame Number when SMSCB block is read if (l1a_l1s_com.pre_scheduled_cbch) time_ptr = &l1s.next_plus_time; else time_ptr = &l1s.next_time; } break; default: // For SDCCH/TCH, set pointers to the active channel description. { chan_sel = &(l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->chan_sel); alist_ptr = l1a_l1s_com.dedic_set.aset->ma.alist_ptr; radio_freq_ptr = &l1a_l1s_com.dedic_set.radio_freq; time_ptr = &l1s.next_time; } } // End of switch(task) // Set local variables. ma = &(alist_ptr->rf_chan_no.A[0]); n = alist_ptr->rf_chan_cnt; hsn = chan_sel->rf_channel.hopping_rf.hsn; maio = chan_sel->rf_channel.hopping_rf.maio; if(chan_sel->h == FALSE) // Single RF channel, NOT HOPPING. { *radio_freq_ptr = chan_sel->rf_channel.single_rf.radio_freq; } else // Hopping channel... { /**************************************************/ /* Perform the HOPPING algorithm. */ /**************************************************/ if(hsn == 0) // Cyclic hopping... { mai = (time_ptr->fn + maio) % n; } else { UWORD8 i = 0; UWORD8 m; UWORD8 mp; UWORD8 nbin; UWORD8 tp; UWORD8 s; UWORD8 t1r = (UWORD8)(time_ptr->t1 % 64); while(i<=6) { if((n >> i) > 0) nbin = i; i++; } nbin++; m = time_ptr->t2 + RNTABLE[(hsn ^ t1r) + time_ptr->t3]; mp = m % (1L << nbin); tp = time_ptr->t3 % (1L << nbin); if(mp < n) s = mp; else s = (mp + tp) % n; mai = (s + maio) % n; } *radio_freq_ptr = ma[mai]; } if(*radio_freq_ptr == *beacon_channel_ptr) // If ARFCN is the BEACON... { // Set "b_bcch_freq_ind" to TRUE. l1s_dsp_com.dsp_db_w_ptr->d_ctrl_system |= (1 << B_BCCH_FREQ_IND); } } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM //===============================================================================================// #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 /*-------------------------------------------------------*/ /* l1s_read_dummy() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* task: ABORT. Since this task just aborts any ongoing */ /* DSP task, there is no result returned by the DSP to */ /* the MCU when this abort is completed, but the MCU/DSP */ /* com. read page must be switched properly. This the */ /* only reason why we have created this function. */ /* */ /* Modified parameter in globals: */ /* ------------------------------ */ /* */ /* "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. */ /* */ /*-------------------------------------------------------*/ void l1s_read_dummy(UWORD8 task, UWORD8 param2) { l1_check_com_mismatch(task); #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1S_READ_DUMMY ,(UWORD32)(-1));//OMAPS00090550 #endif // task is completed, make it INACTIVE (only in case of TCHD). if(task == TCHD) l1s.task_status[task].current_status = INACTIVE; #if FF_L1_IT_DSP_DTX // Fast DTX status update if(task == TCHD) { UWORD8 subchannel = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->subchannel; // Currently used for TCH-AHS only if (((subchannel == 0) && (l1s.actual_time.fn_mod13_mod4 == 0)) || // FN%13 = 4, 8 and 12 for TCH/H0 (no Read on FN%13=0) ((subchannel == 1) && (l1s.actual_time.fn_mod13_mod4 == 1))) // FN%13 = 1, 5 and 9 for TCH/H1 { // Latch TX activity status if DTX allowed if ((l1a_l1s_com.dedic_set.aset->dtx_allowed == FALSE) || // No DTX allowed (l1s_dsp_com.dsp_ndb_ptr->d_fast_dtx_enc_data ) || // DTX allowed but not used (l1a_apihisr_com.dtx.fast_dtx_ready == FALSE)) // Fast DTX status is invalid l1a_apihisr_com.dtx.tx_active = TRUE; else l1a_apihisr_com.dtx.tx_active = FALSE; } } #endif // Set flag used to change the read page at the end of "l1_synch". l1s_dsp_com.dsp_r_page_used = TRUE; } //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #endif /*-------------------------------------------------------*/ /* l1s_read_msagc() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: BCCHN,FBNEW,SB1,SB2,SBCONF. This function is */ /* the reading result function used for reading a power */ /* measurement result used then to refreshing the AGC */ /* for those tasks. Here is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low. */ /* - Get the cell information structure. */ /* - Traces and debug. */ /* - Read receive level result from MCU/DSP interface.*/ /* - Flag the use of the MCU/DSP dual page read */ /* interface. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* BCCHN, BCCH Neighbor reading task. */ /* FBNEW, Frequency Burst detection task in Idle mode. */ /* SB1, Synchro Burst reading task in Idle mode. */ /* SB2, Synchro Burst detection task in Idle mode. */ /* SBCONF, Synchro Burst confirmation task in Idle */ /* mode. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "l1a_l1s_com.Ncell_info.bcch" */ /* "l1a_l1s_com.Ncell_info.acquis" */ /* "l1a_l1s_com.Ncell_info.acquis" */ /* "l1a_l1s_com.Ncell_info.conf" */ /* cell information structure used for BCCHN,FBNEW, */ /* SB1/SB2,SBCONF respectively. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "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. */ /* */ /*-------------------------------------------------------*/ void l1s_read_msagc(UWORD8 task, UWORD8 param2) { BOOL en_task; BOOL task_param; UWORD8 pm_level[2]; #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif // 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. { T_NCELL_SINGLE *cell_info_ptr = NULL; #if (L1_GPRS) T_NCELL_SINGLE pbcchn_cell_info; #endif #if ((REL99 == 1) && (FF_BHO == 1)) T_NCELL_SINGLE bho_cell_info; #endif // Get the cell information structure. // ************************************ switch(task) { case BCCHN_TOP: cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_top ]; break; case BCCHN: cell_info_ptr = &l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_norm ]; break; case FBNEW: cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id]; break; case SB2: cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id]; break; case SBCONF: cell_info_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sbconf_id]; break; #if ((REL99 == 1) && (FF_BHO == 1)) case FBSB: { cell_info_ptr = &bho_cell_info; bho_cell_info.radio_freq = l1a_l1s_com.nsync_fbsb.radio_freq; bho_cell_info.fn_offset = l1a_l1s_com.nsync_fbsb.fn_offset; } break; #endif #if (L1_GPRS) case PBCCHN_IDLE: { cell_info_ptr = &pbcchn_cell_info; pbcchn_cell_info.radio_freq = l1pa_l1ps_com.pbcchn.bcch_carrier; pbcchn_cell_info.fn_offset = l1pa_l1ps_com.pbcchn.fn_offset; } break; #endif default: return; } // Traces and debug. // ****************** #if (TRACE_TYPE!=0) trace_fct(CST_L1S_READ_MSAGC , cell_info_ptr->radio_freq); #endif #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH) buffer_trace(4, l1s.actual_time.fn, cell_info_ptr->radio_freq, cell_info_ptr->fn_offset, pm); #endif #endif l1_check_com_mismatch(MS_AGC_ID); // Read receive level result from MCU/DSP interface. // ************************************************** // Read 2 received levels... #if L1_GPRS switch (l1a_l1s_com.dsp_scheduler_mode) { case GPRS_SCHEDULER: { // Call the reading driver using GPRS scheduler l1pddsp_meas_read(2, pm_level); } break; case GSM_SCHEDULER: { // Call the reading driver using GSM scheduler l1ddsp_meas_read(2, pm_level); } break; } #else l1ddsp_meas_read(2, pm_level); #endif // Power Measurement performed during last l1s_ctrl_msagc with HIGH_AGC // returned in pm_level[0] // Power measurement performed during last l1s_ctrl_msagc with LOW_AGC // returned in pm_level[1] l1_check_pm_error(pm_level[0], MS_AGC_ID); l1_check_pm_error(pm_level[1], MS_AGC_ID); l1ctl_pgc2(pm_level[0], pm_level[1], cell_info_ptr->radio_freq); #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_LNA) #if (L1_FF_MULTIBAND == 0) buffer_trace (4, 22, cell_info_ptr->radio_freq, l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].input_level, l1a_l1s_com.last_input_level[cell_info_ptr->radio_freq - l1_config.std.radio_freq_index_offset].lna_off); #else // L1_FF_MULTIBAND = 1 below operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(cell_info_ptr->radio_freq); buffer_trace (4, 22, cell_info_ptr->radio_freq, l1a_l1s_com.last_input_level[cell_info_ptr->agc_index].input_level, l1a_l1s_com.last_input_level[cell_info_ptr->agc_index].lna_off); #endif // #if (L1_FF_MULTIBAND == 0) else #endif #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; } #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_mon_result() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: FBNEW,SB1,SB2,SBCONF,SB51,SBCNF51,SB26,SBCNF26.*/ /* This function is the reading result function used for */ /* reading the neighbor cell monitoring results. Here is */ /* a summary of the execution: */ /* */ /* - Traces and debug. */ /* - Get task result from MCU/DSP read interface. */ /* */ /* - case: FBNEW/FB51. */ /* - If SEMAPHORE(task) is low. */ /* - Update AFC if required. */ /* - Read FB detection results. */ /* - Reports results to L1A. */ /* - Disactivate and Disable task. */ /* - Reset buffers and flags in NDB. */ /* */ /* - case: FB26. */ /* - Read FB detection results. */ /* - Reports results to L1A. */ /* - Disactivate task. */ /* */ /* - case: SB26/SBCNF26. */ /* - Read SB reading results. */ /* - Reports results to L1A. */ /* - Disactivate task. */ /* */ /* - case: SB1/SB2/SB51/SBCONF/SBCNF51. */ /* - If SEMAPHORE(task) is low. */ /* - Update AFC if required. */ /* - Read FB detection results. */ /* - Reports results to L1A. */ /* - Disactivate task when required. */ /* */ /* - Flag the use of the MCU/DSP dual page read */ /* interface. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* FBNEW, Frequency Burst detection task in Idle mode. */ /* SB1, Synchro Burst reading task in Idle mode. */ /* SB2, Synchro Burst detection task in Idle mode. */ /* SBCONF, Synchro Burst confirmation task in Idle */ /* mode. */ /* SB51, Synchro Burst reading task in SDCCH Dedicated */ /* mode. */ /* SBCNF51, Synchro Burst confirmation task in SDCCH */ /* Dedicated mode. */ /* SB26, Synchro Burst reading task in TCH Dedicated */ /* mode. */ /* SBCNF26, Synchro Burst confirmation task in TCH */ /* Dedicated mode. */ /* */ /* "attempt_for_sb2" */ /* Since SB2 calls twice this function, this parameter */ /* tells the function which call it it. Used mainly */ /* to know when to DISACTIVATE the task. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "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. */ /* */ /* Modified parameters from globals: */ /* --------------------------------- */ /* "l1a_l1s_com.l1s_en_task" */ /* L1S task enable bit register. */ /* -> disable FBNEW,FB51 task. */ /* */ /* "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 l1s_read_mon_result(UWORD8 task, UWORD8 attempt) { UWORD32 flag=0; UWORD32 toa; UWORD32 pm; UWORD32 angle; UWORD32 snr; #if TESTMODE UWORD32 pm_fullres; #endif API *data; BOOL en_task; BOOL task_param; UWORD32 fb_abort_flag=0; /*-------------------------------------------------------------------------------*/ /* READ MONITORING TASK RESULTS FROM MCU/DSP INTERFACE... */ /*-------------------------------------------------------------------------------*/ // 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]; // Traces and debug. // ****************** #if (TRACE_TYPE!=0)&& (TRACE_TYPE !=5) trace_fct(CST_L1S_READ_MON_RESULT,(UWORD32)(-1)); #endif if(!(en_task) || (task_param)) { #if (TRACE_TYPE!=0) // Current task is no more alive, L1A changed the task parameters. // -> Trace "ABORT" on log file and screen. trace_fct(CST_TASK_KILLED, (UWORD32)(-1)); #endif } else // Current task is still alive, check task identifier and debug number... { #if (TRACE_TYPE!=0) if((task != FB26) && (task != SB26) && (task != SBCNF26)) // DB cannot be used for FB26/SB26/SBCNF26 result. if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_md & 0xffff) != (UWORD32)DSP_TASK_CODE[task]) // Task id. different than the one expected... trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND,(UWORD32)(-1)); #endif if((task != FB26) && (task != SB26) && (task != SBCNF26) && (attempt==12) #if ((REL99 == 1) && (FF_BHO == 1)) && (task != FBSB) #endif ) // DB cannot be used for FB26/SB26/SBCNF26 result. { l1_check_com_mismatch(task); } } // Get task result from MCU/DSP read interface. // ********************************************* switch(task) { case FBNEW : case FB51 : /*---------------------------------------------------*/ /* Frequency burst detection result... */ /*---------------------------------------------------*/ { 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. { flag = l1s_dsp_com.dsp_ndb_ptr->d_fb_det & 0xffff; // 1 means FOUND. toa = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA] & 0xffff; // Unit is BIT. pm = (l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff) >> 5; // WARNING... to be used!!! #if TESTMODE pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff; // F26.6 #endif angle = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_ANGLE] & 0xffff; // WARNING... to be used!!! snr = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_SNR] & 0xffff; // WARNING... to be used!!! // Check FB detection flag and attempt: // If no detection and attempt < 12 than continue FB search // Attempt=11: special case: wait for next (last) read, as // other task may already be programmed in MFTAB (do not flush !!!) if(((!flag) && (attempt < 11)) || (attempt==11)) break; // If FB detection occurs before 11th attempt, abort FB search if((flag == TRUE) && (attempt < 11)) fb_abort_flag=TRUE; if (fb_abort_flag == TRUE) { if ((l1s_dsp_com.dsp_db_r_ptr->d_debug & 0xffff) != ((l1s.debug_time + (12 - attempt)) % 65536)) l1_check_com_mismatch(task); } // l1_check_pm_error(pm, task); #if TRACE_TYPE==3 stats_samples_fb(flag,toa,pm,angle,snr); #endif #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace(FB51); #endif // Update AFC: Call AFC control function (KALMAN filter). #if AFC_ALGO #if TESTMODE if (l1_config.afc_enable) #endif { WORD16 old_afc=l1s.afc; if((flag == TRUE) && (l1a_l1s_com.mode == CS_MODE)) { #if (VCXO_ALGO == 0) l1s.afc = l1ctl_afc(AFC_OPEN_LOOP, &l1s.afc_frame_count, (WORD16)angle, 0, l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq); #else l1s.afc = l1ctl_afc(AFC_OPEN_LOOP, &l1s.afc_frame_count, (WORD16)angle, 0, l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq,l1a_l1s_com.mode); #endif #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_AFC_OPEN) buffer_trace (4,(WORD16)angle,old_afc,l1s.afc,0); #endif #endif } } #endif // Call FB report function (send report msg to L1A). #if TESTMODE if (l1_config.TestMode) l1s_read_fb(task, flag, toa, attempt, pm_fullres, angle, snr); else l1s_read_fb(task, flag, toa, attempt, pm, angle, snr); #else l1s_read_fb(task, flag, toa, attempt, pm, angle, snr); #endif // The Frequency Burst detection task in Idle (FBNEW) and // Dedicated/SDCCH (FB51) are 1 shot tasks, they must be // disabled in L1S when they are completed. Disable it. l1a_l1s_com.l1s_en_task[task] = TASK_DISABLED; // the status is not used in D51 and D26 modes if (task != FB51 ) { l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].status = NSYNC_COMPLETED; } } if ((fb_abort_flag == TRUE) || (attempt==12)) { // FB task is completed, make it INACTIVE. l1s.task_status[task].current_status = INACTIVE; // Reset buffers and flags in NDB ... l1s_dsp_com.dsp_ndb_ptr->d_fb_det = FALSE; l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA] = 0; // This task is not compatible with Neigh. Measurement. // Clear "forbid_meas" to indicate when the task is complete. l1s.forbid_meas = 0; } // FB search finished before 11th attempt: // -reset DSP R/W pages, DSP tasks and TPU // -flush MFTAB and reset frame count // -adjust debug time if(fb_abort_flag) { l1d_reset_hw(l1s.tpu_offset); l1s.tpu_ctrl_reg |= CTRL_FB_ABORT; // set CTRL bit -> tpu_end_scenario l1s_clear_mftab(l1s.mftab.frmlst); l1s.frame_count = 0; #if 0 /* FreeCalypso TCS211 reconstruction */ // This task is not compatible with Neigh. Measurement. // Clear "forbid_meas" to indicate when the task is complete. l1s.forbid_meas = 0; #endif } } break; case FB26 : /*---------------------------------------------------*/ /* Frequency burst detection result... */ /*---------------------------------------------------*/ { UWORD8 neigh_id; // read cell identifier. neigh_id = l1a_l1s_com.nsync.active_fb_id; 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. { flag = l1s_dsp_com.dsp_ndb_ptr->d_fb_det & 0xffff; // 1 means FOUND. toa = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA] & 0xffff; // Unit is BIT. pm = (l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff) >> 5; // WARNING... to be used!!! #if TESTMODE pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff; // F10.6 #endif // CQ 19836: do not check PM on FB26 //l1_check_pm_error(pm, task); angle = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_ANGLE] & 0xffff; // WARNING... to be used!!! snr = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_SNR] & 0xffff; // WARNING... to be used!!! // Call FB report function (send report msg to L1A). #if TESTMODE if (l1_config.TestMode) l1s_read_fb(task, flag, toa, NO_PAR, pm_fullres, angle, snr); else l1s_read_fb(task, flag, toa, NO_PAR, pm, angle, snr); #else l1s_read_fb(task, flag, toa, NO_PAR, pm, angle, snr); #endif } #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace(FB26); #endif // The Frequency Burst detection task in Dedicated/TCH // is composed with several attempts managed in L1A. // -> task is completed: set INACTIVE. l1s.task_status[task].current_status = INACTIVE; // Reset buffers and flags in NDB ... l1s_dsp_com.dsp_ndb_ptr->d_fb_det = FALSE; l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA] = 0; } break; case SB26 : case SBCNF26 : /*---------------------------------------------------*/ /* Synchro. burst detection result... */ /*---------------------------------------------------*/ { 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. { flag = !(((l1s_dsp_com.dsp_ndb_ptr->a_sch26[0] & 0xffff) & (1<<B_SCH_CRC)) >> B_SCH_CRC); // 1 means ERROR. toa = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA] & 0xffff; // Unit is BIT. pm = (l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff) >> 5; // WARNING... to be used!!! #if TESTMODE pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff; // F26.6 #endif angle = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_ANGLE] & 0xffff; snr = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_SNR] & 0xffff; data = &(l1s_dsp_com.dsp_ndb_ptr->a_sch26[3]); // Set data block pointer (skip header). l1_check_pm_error(pm, task); // Call SB report function (send report msg to L1A). #if TESTMODE if (l1_config.TestMode) l1s_read_sb(task, flag, data, toa, attempt, pm_fullres, angle, snr); else l1s_read_sb(task, flag, data, toa, attempt, pm, angle, snr); #else l1s_read_sb(task, flag, data, toa, attempt, pm, angle, snr); #endif } #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace(SB26); #endif // The Synchro Burst detection (SB26) and confirmation (SBCNF26) // tasks in Dedicated/TCH are enabling/disabling are fully // managed by L1A. // -> task is completed: set INACTIVE. l1s.task_status[task].current_status = INACTIVE; // Reset buffers and flags in NDB ... l1s_dsp_com.dsp_ndb_ptr->a_sch26[0] = (1<<B_SCH_CRC); } break; case SB2 : case SBCONF : case SB51 : case SBCNF51 : /*---------------------------------------------------*/ /* Synchro. burst detection result... */ /*---------------------------------------------------*/ { 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. { UWORD8 neigh_id; if((task == SB2) || (task == SB51)) neigh_id = l1a_l1s_com.nsync.active_sb_id; else neigh_id = l1a_l1s_com.nsync.active_sbconf_id; flag = !(((l1s_dsp_com.dsp_db_r_ptr->a_sch[0] & 0xffff) & (1<<B_SCH_CRC)) >> B_SCH_CRC); // 1 means ERROR. toa = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA] & 0xffff; // Unit is BIT. pm = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM] & 0xffff) >> 5; // WARNING... to be used!!! #if TESTMODE pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff; // F26.6 #endif 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; data = &(l1s_dsp_com.dsp_db_r_ptr->a_sch[3]); // Set data block pointer (skip header). #if (L1_DEBUG_IQ_DUMP == 1) l1ddsp_read_iq_dump(task); #endif l1_check_pm_error(pm, task); // CQ30474. In case SNR is too low, the SB shall be considered as failed. // This is valuable for code running on target with DSP 3606. /* * FreeCalypso: despite the above comment, * this code is NOT present in TCS211. */ #if 0 #if (CODE_VERSION == NOT_SIMULATION) if ( snr < MIN_ACCEPTABLE_SNR_FOR_SB ) flag = FALSE; #endif #endif #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH) buffer_trace(4, l1s.actual_time.fn, toa,pm, l1s_dsp_com.dsp_db_r_ptr->a_sch[0] & 0xffff); #endif #endif #if TRACE_TYPE==3 stats_samples_sb(flag,toa,pm,angle,snr); #endif #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) if (task == SBCONF) uart_trace(SBCONF); else uart_trace(SB2); // display result code... #endif // Update AFC: Call AFC control function (KALMAN filter). #if AFC_ALGO #if TESTMODE if (l1_config.afc_enable) #endif { WORD16 old_afc=l1s.afc; if((flag == TRUE) && (l1a_l1s_com.mode == CS_MODE)) { #if (VCXO_ALGO == 0) l1s.afc = l1ctl_afc(AFC_OPEN_LOOP, &l1s.afc_frame_count, (WORD16)angle, 0, l1a_l1s_com.nsync.list[neigh_id].radio_freq); #else l1s.afc = l1ctl_afc(AFC_OPEN_LOOP, &l1s.afc_frame_count, (WORD16)angle, 0, l1a_l1s_com.nsync.list[neigh_id].radio_freq,l1a_l1s_com.mode); #endif #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_AFC_OPEN) buffer_trace (4,(WORD16)angle,old_afc,l1s.afc,1); #endif #endif } } #endif // Call SB report function (send report msg to L1A). #if TESTMODE if (l1_config.TestMode) l1s_read_sb(task, flag, data, toa, attempt, pm_fullres, angle, snr); else l1s_read_sb(task, flag, data, toa, attempt, pm, angle, snr); #else l1s_read_sb(task, flag, data, toa, attempt, pm, angle, snr); #endif // the status is not used in D51 and D26 modes if ((task != SBCNF51 ) && (task != SB51)) { // SB2 activity completed for this neighbour cell. if((task != SB2) || ((task == SB2) && (attempt == 2))) l1a_l1s_com.nsync.list[neigh_id].status = NSYNC_COMPLETED; } } // All tasks are completed by this function except SB2 which // calls it twice. SB2 is then completed only when making the // second execution of this function. // -> task is completed: set INACTIVE. if((task != SB2) || (task == SB2) && (attempt == 2)) { l1s.task_status[task].current_status = INACTIVE; l1a_l1s_com.l1s_en_task[task] = TASK_DISABLED; } } break; #if ((REL99 == 1) && (FF_BHO == 1)) case FBSB : /*---------------------------------------------------*/ /* Frequency + Synchro burst detection result... */ /*---------------------------------------------------*/ { BOOL abort_flag = FALSE; if (l1a_l1s_com.nsync_fbsb.fb_found_attempt == 0) // Looking for FB { flag = l1s_dsp_com.dsp_ndb_ptr->d_fb_det & 0xffff; // flag = TRUE means FOUND. toa = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_TOA] & 0xffff; // Unit is BIT. pm = (l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff) >> 5; #if TESTMODE pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff; // F26.6 #endif angle = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_ANGLE] & 0xffff; snr = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_SNR] & 0xffff; if (flag) // FB detected { // Store toa and attempt for future use l1a_l1s_com.nsync_fbsb.fb_toa = toa; l1a_l1s_com.nsync_fbsb.fb_found_attempt = attempt; #if (TRACE_TYPE == 3) stats_samples_fb(flag, toa, pm, angle, snr); #endif #if (TRACE_TYPE == 2 ) || (TRACE_TYPE == 3) // uart_trace(FBSB); #endif } else { if (attempt < 12) { // FB not found, some attempts remaining break; } else { // FB not found, no attempt remaining // Call FBSB report function (send report msg to L1A). #if TESTMODE if (l1_config.TestMode) l1s_read_fbsb(task, attempt, FALSE, FALSE, (API *)NULL, toa, pm, angle, snr); else #endif l1s_read_fbsb(task, attempt, FALSE, FALSE, (API *)NULL, toa, pm, angle, snr); abort_flag = TRUE; } } } else // if (l1a_l1s_com.nsync_fbsb.fb_found_attempt == 0) // Looking for SB { flag = !(((l1s_dsp_com.dsp_db_r_ptr->a_sch[0] & 0xffff) & (1<<B_SCH_CRC)) >> B_SCH_CRC); // // flag = TRUE means FOUND. toa = l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_TOA] & 0xffff; // Unit is BIT. pm = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM] & 0xffff) >> 5; #if TESTMODE pm_fullres = l1s_dsp_com.dsp_ndb_ptr->a_sync_demod[D_PM] & 0xffff; // F26.6 #endif 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; data = &(l1s_dsp_com.dsp_db_r_ptr->a_sch[3]); // Set data block pointer (skip header). if (flag) // SB detected { // SB found report SUCCESS #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH) buffer_trace(4, l1s.actual_time.fn, toa,pm, l1s_dsp_com.dsp_db_r_ptr->a_sch[0] & 0xffff); #endif #endif #if (TRACE_TYPE == 3) stats_samples_sb(flag, toa, pm, angle, snr); #endif #if (TRACE_TYPE == 2 ) || (TRACE_TYPE == 3) // uart_trace(FBSB); // display result code... #endif // Call FBSB report function (send report msg to L1A). #if TESTMODE if (l1_config.TestMode) l1s_read_fbsb(task, attempt, TRUE, TRUE, data, toa, pm, angle, snr); else #endif l1s_read_fbsb(task, attempt, TRUE, TRUE, data, toa, pm, angle, snr); abort_flag = TRUE; } else // if (flag) { if (attempt < (l1a_l1s_com.nsync_fbsb.fb_found_attempt + 2)) { // SB not found, one attempt remaining break; } else { // SB not found, no attempt remaining // Call FBSB report function (send report msg to L1A). #if TESTMODE if (l1_config.TestMode) l1s_read_fbsb(task, attempt, TRUE, FALSE, (API *)NULL, toa, pm, angle, snr); else #endif l1s_read_fbsb(task, attempt, TRUE, FALSE, (API *)NULL, toa, pm, angle, snr); abort_flag = TRUE; } } } // if(l1a_l1s_com.nsync_fbsb.fb_found_attempt == 0) if(abort_flag == TRUE) { // -> task is completed: set INACTIVE. l1s.task_status[task].current_status = INACTIVE; l1a_l1s_com.l1s_en_task[task] = TASK_DISABLED; if (attempt < 14) { // FBSB search finished before last attempt: // -reset DSP R/W pages, DSP tasks and TPU // -flush MFTAB and reset frame count // -adjust debug time l1d_reset_hw(l1s.tpu_offset); l1s.tpu_ctrl_reg |= CTRL_FBSB_ABORT; // set CTRL bit -> tpu_end_scenario l1s_clear_mftab(l1s.mftab.frmlst); l1s.frame_count = 0; } } } #endif // #if ((REL99 == 1) && (FF_BHO == 1)) } // 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" only if not // in dedicated/TCH mode (FB26,SB26,SBCNF26). Those task are not following the // common principle. They use only the NDB part of the MCU/DSP interface, no // page swapping is then needed. #if ((REL99 == 1) && (FF_BHO == 1)) if(((task != FB26) && (task != SB26) && (task != SBCNF26) && (task != FBNEW) && (task != FB51) && (task != FBSB)) || #else if(((task != FB26) && (task != SB26) && (task != SBCNF26) && (task != FBNEW) && (task != FB51)) || #endif // #if ((REL99 == 1) && (FF_BHO == 1)) ((!fb_abort_flag) && (attempt==12))) l1s_dsp_com.dsp_r_page_used = TRUE; } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM #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 /*-------------------------------------------------------*/ /* l1s_read_snb_dl() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: BCCHS,NP,EP,ALLC,SMSCB. */ /* This function is the reading result function used for */ /* reading a serving cell burst acquisition result in */ /* any mode except dedicated mode. 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" */ /* NP, Normal paging reading task. */ /* EP, Extended paging reading task. */ /* BCCHS, BCCH Serving reading task. */ /* ALLC, All serving cell CCCH reading task. */ /* SMSCB, Short Message Service Cell Broadcast 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.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. */ /* */ /* "l1a_l1s_com.l1s_en_task" */ /* L1S task enable bit register. */ /* */ /* 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 l1s_read_snb_dl(UWORD8 task, UWORD8 burst_id) { UWORD32 toa; UWORD32 pm; UWORD32 angle; UWORD32 snr; BOOL en_task; BOOL task_param; UWORD16 radio_freq=0; static UWORD16 pwr_level; #if L1_FF_MULTIBAND == 1 UWORD16 operative_radio_freq; #endif #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. // ****************** #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1S_READ_SNB_DL , (UWORD32)(-1));//OMAPS00090550 #endif #if (TRACE_TYPE!=0) #if L1_GPRS if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER) { // Check task identifier... if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_d & 0xffff) != (UWORD32)DSP_TASK_CODE[task]) trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1));//OMAPS00090550 // Check burst identifier... if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_burst_d & 0xffff) != burst_id) trace_fct(CST_DL_BURST_DOES_NOT_CORRESPOND, (UWORD32)(-1));//OMAPS00090550 } else // GPRS scheduler { // Check burst identifier... if(l1ps_dsp_com.pdsp_db_r_ptr->d_burst_nb_gprs != burst_id) trace_fct(CST_DL_BURST_DOES_NOT_CORRESPOND, (UWORD32)(-1)); } #else // Check task identifier... if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_d & 0xffff) != (UWORD32)DSP_TASK_CODE[task]) trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1)); // Check burst identifier... if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_burst_d & 0xffff) != burst_id) trace_fct(CST_DL_BURST_DOES_NOT_CORRESPOND,(UWORD32)( -1)); #endif #endif l1_check_com_mismatch(task); // Read control results and feed control algorithms. // ************************************************** // Read control information. #if L1_GPRS 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; } #else 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; #endif l1_check_pm_error(pm, task); // Update AGC: Call PAGC algorithm radio_freq = l1a_l1s_com.Scell_info.radio_freq; #if (L1_FF_MULTIBAND == 0) l1a_l1s_com.Scell_IL_for_rxlev = l1ctl_pagc((UWORD8)pm, radio_freq, &l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset]); #else // L1_FF_MULTIBAND = 1 below operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(radio_freq); l1a_l1s_com.Scell_IL_for_rxlev = l1ctl_pagc((UWORD8)pm, radio_freq, &l1a_l1s_com.last_input_level[operative_radio_freq]); #endif // #if (L1_FF_MULTIBAND == 0) else #if (FF_L1_FAST_DECODING == 1) if (skipped_bursts>0) { l1ctl_pagc_missing_bursts(skipped_bursts); } #endif /* if (FF_L1_FAST_DECODING == 1) */ #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_LNA) #if (L1_FF_MULTIBAND == 0) buffer_trace (4, 33, radio_freq, l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].input_level, l1a_l1s_com.last_input_level[radio_freq - l1_config.std.radio_freq_index_offset].lna_off); #else // L1_FF_MULTIBAND = 1 below buffer_trace (4, 33, radio_freq, l1a_l1s_com.last_input_level[operative_radio_freq].input_level, l1a_l1s_com.last_input_level[operative_radio_freq].lna_off); #endif // #if (L1_FF_MULTIBAND == 0) else #endif #endif #if TRACE_TYPE==3 stats_samples_nb(toa,pm,angle,snr,burst_id,task); #endif // Update AFC: Call AFC control function (KALMAN filter). #if AFC_ALGO #if TESTMODE if (l1_config.afc_enable) #endif { #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_AFC_OPEN)//omaps00090550 WORD16 old_afc = l1s.afc; WORD16 old_count= l1s.afc_frame_count; #endif #endif #if (VCXO_ALGO == 0) l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq); #else l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, 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 #if (DEBUG_TRACE == BUFFER_TRACE_TOA) if (task == NP || task == EP) buffer_trace(5, l1s.debug_time, 0xf1, i, l1s.afc, angle ); #endif #endif } #endif //Feed TOA histogram. #if (TOA_ALGO != 0) if (task != SMSCB) { #if (TOA_ALGO == 2) if(l1s.toa_var.toa_snr_mask == 0) #else if(l1s.toa_snr_mask == 0) #endif #if (RF_FAM == 2) // RF 2 #if (TOA_ALGO == 2) if(l1a_l1s_com.Scell_IL_for_rxlev < IL_FOR_RXLEV_SNR) { l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa); } else { l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa); } #else 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) , skipped_bursts #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) , skipped_bursts #endif ); } #endif #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_TOA ) if (task == NP || task == EP) buffer_trace(5, l1s.debug_time, 0xf0, toa, snr, l1s.tpu_offset ); #endif #endif #else // RF 2 #if (TOA_ALGO == 2) if(l1a_l1s_com.Scell_IL_for_rxlev < IL_FOR_RXLEV_SNR) { l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr, toa); } else { l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa); } #else 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) , skipped_bursts #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) , skipped_bursts #endif ); } #endif #endif // RF 2 } #else // TOA_ALGO #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_TOA) if (task == NP || task == EP) buffer_trace(5, l1s.debug_time, 0xf0, toa, snr, l1s.tpu_offset ); #endif #endif #endif // TOA_ALGO #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) #endif #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) && HAVE_L1_TRACE_BURST_PARAM l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, l1a_l1s_com.Scell_IL_for_rxlev); #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); #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 (task == NP) { toa_tab[burst_id] = toa; } #if 0 /* FreeCalypso TCS211 reconstruction */ // added Enhanced RSSI if(l1s_dsp_com.dsp_ndb_ptr->a_cd[2] != 0xffff) { qual_acc_idle1[0] += l1s_dsp_com.dsp_ndb_ptr->a_cd[2]; //RX Qual value reporting- total number of decoded bits qual_acc_idle1[1] += 1; } #endif #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 */ { UWORD8 i; #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace(task); #endif // the data power bloc = pwr_level/4. #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*/ #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 L1_GPRS 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); #else l1s_read_l3frm(pwr_level,&(l1s_dsp_com.dsp_ndb_ptr->a_cd[0]), task); #endif #if L1_GPRS if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER) #endif { // reset buffers and flags in NDB ... // reset nerr.... // reset A_CD contents....... l1s_dsp_com.dsp_ndb_ptr->a_cd[2] = 0xffff; for (i=0;i<12;i++) l1s_dsp_com.dsp_ndb_ptr->a_cd[3+i] = 0x0000; } } // End if... } // End if... // The NP/EP task was enabled and could cancel a PTCCH burst // This incomplete PTCCH decoding block cause DSP troubles and so COM/PM errors // and then a recovery => in this case restart the PTCCH from the burst 0 #if L1_GPRS if((task == NP)||(task == EP)) if(l1a_l1s_com.l1s_en_task[PTCCH] == TASK_ENABLED) if(l1pa_l1ps_com.transfer.ptcch.activity & PTCCH_DL) // a PTCCH DL task is running if((l1s.actual_time.t2 >= 13) && (l1s.actual_time.t2 <= 17)) // only if the NP/EP remove a PTCCH activity { // Restart PTCCH DL task from the begining (i.e BURST 0). l1pa_l1ps_com.transfer.ptcch.activity ^= PTCCH_DL; // disable PTCCH_DL activity running l1pa_l1ps_com.transfer.ptcch.request_dl = TRUE; // restart PTCCH DL from the Burst0 } #endif // Deactivate task. // ****************** // End of task -> task must become INACTIVE. // Rem: some TASKS (ALLC) can be pipelined and therefore must stay active if // they have already reentered the flow. #if (FF_L1_FAST_DECODING == 1) 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 == NP) || (task == NBCCHS)) { 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; } } /* end if tsk == NP */ #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) { /* Successful decode before the 4th burst, no other control/read activities are needed */ 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 (L1_DEBUG_IQ_DUMP == 1) 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 GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #endif /*-------------------------------------------------------*/ /* l1s_read_nnb() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: BCCHN. */ /* This function is the reading result function used for */ /* reading a neighbor cell block acquisition result in */ /* idle mode. Here is a summary of the execution: */ /* */ /* - If SEMAPHORE(task) is low and task still enabled. */ /* - Traces and debug. */ /* - Read DL DATA block from MCU/DSP interface. */ /* - Disactivate task. */ /* - Flag the use of the MCU/DSP dual page read */ /* interface. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* BCCHN, BCCH Neighbor reading task. */ /* */ /* Input parameters from globals: */ /* ------------------------------ */ /* "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. */ /* */ /* "l1a_l1s_com.l1s_en_task" */ /* L1S task enable bit register. */ /* */ /* 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 l1s_read_nnb(UWORD8 task, UWORD8 param) { BOOL en_task; BOOL task_param; UWORD16 neigh_radio_freq; UWORD16 pwr_level; UWORD8 active_neigh_id; #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif /*--------------------------------------------------------*/ /* READ NEIGBOR CELL RECEIVE TASK RESULTS... */ /*--------------------------------------------------------*/ /* Rem: the full result is present in the mcu<-dsp */ /* communication buffer. */ /*--------------------------------------------------------*/ // 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. // ****************** #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1S_READ_NNB ,(UWORD32)(-1)); #endif #if (TRACE_TYPE!=0) // Check task identifier... #if L1_GPRS switch(l1a_l1s_com.dsp_scheduler_mode) { case GSM_SCHEDULER: { if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_d & 0xffff) != (UWORD32)DSP_TASK_CODE[task]) trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1)); } break; case GPRS_SCHEDULER: { if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_md & 0xffff) != (UWORD32)DSP_TASK_CODE[task]) trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1)); } break; } #else if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_d & 0xffff) != (UWORD32)DSP_TASK_CODE[task]) trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1)); #endif #endif l1_check_com_mismatch(task); #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace(task); #endif if(task == BCCHN) active_neigh_id = l1a_l1s_com.bcchn.active_neigh_id_norm; else // BCCHN_TRAN and BCCHN_TOP tasks active_neigh_id = l1a_l1s_com.bcchn.active_neigh_id_top; // the mean power level is impossible for the neighbor bloc, so the las input level is used. neigh_radio_freq = l1a_l1s_com.bcchn.list[active_neigh_id].radio_freq; #if 1 /* FreeCalypso TCS211 reconstruction */ pwr_level = l1a_l1s_com.last_input_level[neigh_radio_freq].input_level; #elif (L1_FF_MULTIBAND == 0) pwr_level = l1a_l1s_com.last_input_level[neigh_radio_freq - l1_config.std.radio_freq_index_offset].input_level; #else operative_radio_freq = l1_multiband_radio_freq_convert_into_operative_radio_freq(neigh_radio_freq); pwr_level = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; #endif // Read downlink DATA block from MCU/DSP interface. // ************************************************* // Read L3 frame block and send msg to L1A. #if L1_GPRS 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); #else l1s_read_l3frm(pwr_level,&(l1s_dsp_com.dsp_ndb_ptr->a_cd[0]), task); #endif // Disable the served TC from the TC bitmap. if(task == BCCHN) l1a_l1s_com.bcchn.list[active_neigh_id].bcch_blks_req ^= ((UWORD16)(1L << l1a_l1s_com.bcchn.active_neigh_tc_norm)); else // BCCHN_TRAN and BCCHN_TOP tasks l1a_l1s_com.bcchn.list[active_neigh_id].bcch_blks_req ^= ((UWORD16)(1L << l1a_l1s_com.bcchn.active_neigh_tc_top)); } // The BCCHN task was enabled and could cancel a PTCCH burst // This incomplete PTCCH decoding block cause DSP troubles and so COM/PM errors // and then a recovery (seen with ULYSS) => in this case restart the PTCCH from the burst 0 #if L1_GPRS if (task == BCCHN_TRAN) if(l1a_l1s_com.l1s_en_task[PTCCH] == TASK_ENABLED) if(l1pa_l1ps_com.transfer.ptcch.activity & PTCCH_DL) // a PTCCH DL task is running if ((l1s.actual_time.t2 >= 13) && (l1s.actual_time.t2 <= 18)) // only if the BCCHN remove a PTCCH activity { // Restart PTCCH DL task from the begining (i.e BURST 0). l1pa_l1ps_com.transfer.ptcch.activity ^= PTCCH_DL; // disable PTCCH_DL activity running l1pa_l1ps_com.transfer.ptcch.request_dl = TRUE; // restart PTCCH DL from the Burst0 } #endif // Disactivate task. // ****************** // End of task -> task must become INACTIVE. l1s.task_status[task].current_status = INACTIVE; #if (L1_DEBUG_IQ_DUMP == 1) 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; } /*-------------------------------------------------------*/ /* l1s_read_dedic_dl() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is a "COMPLEX" function used by the L1S */ /* tasks: DDL,ADL,TCHTH,TCHTF,TCHA. */ /* This function is the reading result function used for */ /* dedicated mode. Here is a summary of the execution: */ /* */ /* - Traces and debug. */ /* - Read control results and feed control algo. */ /* - Read DL DATA block from MCU/DSP interface. */ /* - Flag the use of the MCU/DSP dual page read */ /* interface. */ /* */ /* Input parameters: */ /* ----------------- */ /* "task" */ /* DDL, SDCCH DOWNLINK reading task. */ /* ADL, SACCH DOWNLINK (associated with SDCCH)reading */ /* task. */ /* TCHTH, TCH channel task when dedicated/TCH Half rate*/ /* TCHTF, TCH channel task when dedicated/TCH Full rate*/ /* TCHA, Associated channel task when dedicated/TCH. */ /* */ /* "burst_id" (used only by DDL/ADL tasks). */ /* 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.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. */ /* */ /* "l1a_l1s_com.l1s_en_task" */ /* L1S task enable bit register. */ /* */ /* 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. */ /* */ /* RXQUAL : */ /* 1) SDCCH : for RXQUAL_FULL and RXQUAL_SUB we accumu- */ /* -late number of estimated errors (a_cd[2]) */ /* for ALL SACCH and SDCCH TDMA frames. */ /* 2) TCH : for RXQUAL_FULL in TCH_FS_MODE and */ /* TCH_24F_MODE, we accumulate number of */ /* estimated errors for ALL FACCH (a_fd[2]) */ /* TDMA frames and ALL speech (a_dd_0[2]) */ /* TDMA frames. */ /* for RXQUAL_FULL in all data modes (except */ /* TCH_24F_MODE, see above) we accumulate */ /* number of errors for ALL FACCH (a_fd[2]) */ /* TDMA frames and ALL data (a_dd_0[2]) */ /* TDMA frames. */ /* for RXQUAL_SUB in TCH_FS_MODE and */ /* TCH_24F_MODE, we only accumulate number of */ /* estimated errors for FACCH (a_fd[2]) TDMA */ /* frames and speech (a_dd_0[2]) TDMA frames */ /* at SID block boundary position. */ /* for RXQUAL_SUB in all data modes (except */ /* TCH_24F_MODE, see above) we only accumulate*/ /* number of estimated errors for FACCH */ /* (a_fd[2]) TDMA frames at SID block boundary*/ /* position. The GSM specification 5.08 $8.4 */ /* is not clear about data block at SID block */ /* boundary position. Do we need to accumulate*/ /* if L2/fill frame at this SID block boundary*/ /* position. */ /* Note: before accumulating FACCH TDMA frame we only */ /* check b_blud value, we don't mind about b_fire. */ /*-------------------------------------------------------*/ void l1s_read_dedic_dl(UWORD8 task, UWORD8 burst_id) { UWORD32 toa; UWORD32 pm; UWORD32 angle; UWORD32 snr; BOOL beacon; T_INPUT_LEVEL *IL_info_ptr; UWORD16 radio_freq=0; #if TESTMODE UWORD32 pm_fullres =0;//omaps00090550 #endif #if REL99 #if FF_EMR T_EMR_PARAMS emr_params; // strucutre to store pre-calculated parameter /*--------------------------------------------------------*/ /* INITIALIZATION OF EMR params.. */ /*--------------------------------------------------------*/ emr_params.task = task; emr_params.burst_id = burst_id; emr_params.facch_present = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD; emr_params.facch_fire1 = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_FIRE1)) >> B_FIRE1; emr_params.a_dd_0_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD; emr_params.a_dd_0_bfi = ((l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0])&(1<<B_BFI)) >> B_BFI; // 3rd bit tells the BAD frame emr_params.a_dd_1_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_BLUD)) >> B_BLUD; emr_params.a_dd_1_bfi = ((l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0])&(1<<B_BFI)) >> B_BFI; // 3rd bit tells the BAD frame emr_params.b_m1 = ((l1s_dsp_com.dsp_ndb_ptr->a_data_buf_dl[1]) &(1<<B_M1)) >> B_M1; // = 1 if second half frame for data 14.4 emr_params.b_f48blk_dl = ((l1s_dsp_com.dsp_ndb_ptr->d_ra_act) &(1<<B_F48BLK_DL)) >> B_F48BLK_DL; // = 1 if second half frame for data 4.8 emr_params.b_ce = (((l1s_dsp_com.dsp_ndb_ptr->d_ra_conf) & (1<<B_CE)) >> B_CE); emr_params.a_ntd = (((l1s_dsp_com.dsp_ndb_ptr->a_data_buf_dl[1]) & (1<<B_FCS_OK)) >> B_FCS_OK); emr_params.a_cd_fire1 = (l1s_dsp_com.dsp_ndb_ptr->a_cd[0] & (1<<B_FIRE1)) >> B_FIRE1; emr_params.sid_present_sub0 = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_SID1)) >> B_SID1; // find out whether sid1 is 0/1 emr_params.sid_present_sub1 = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_SID1)) >> B_SID1; // find out whether sid1 is 0/1 #if (AMR == 1) emr_params.amr_facch_present= (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD; emr_params.amr_facch_fire1 = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_FIRE1)) >> B_FIRE1; emr_params.b_ratscch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & (1<<B_BLUD)) >> B_BLUD; emr_params.ratscch_rxtype = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT; emr_params.amr_rx_type_sub0 = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT; emr_params.amr_rx_type_sub1 = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT; #endif //(AMR == 1) #endif //FF_EMR #endif //REL99 /*--------------------------------------------------------*/ /* READ DEDICATED CHANNEL DL RESULTS... */ /*--------------------------------------------------------*/ // Traces and debug. // ****************** #if (TRACE_TYPE!=0) && (TRACE_TYPE !=5) trace_fct(CST_L1S_READ_DEDIC_DL, -1); #endif #if (TRACE_TYPE!=0) // Check task identifier... if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_d & 0xffff) != (UWORD32)DSP_TASK_CODE[task]) trace_fct(CST_DL_TASKS_DO_NOT_CORRESPOND, (UWORD32)(-1)); #endif #if (TESTMODE) // WARNING! // Don't trace MCU-DSP mismatches during UL-only in TestMode. The DSP is not working // in that case so it is normal. However, if tracing happens the CPU overloads if (l1_config.TestMode && l1_config.tmode.rf_params.down_up & TMODE_DOWNLINK) #endif { l1_check_com_mismatch(task); } radio_freq = l1a_l1s_com.dedic_set.radio_freq_dd; 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; } #if (AMR == 1) { // RATSCCH detection UWORD16 ratscch_dl_header=l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0]; UWORD16 b_ratscch_dl_blud = (ratscch_dl_header & (1<<B_BLUD)) >> B_BLUD; if(b_ratscch_dl_blud==TRUE) { UWORD8 rx_type = (ratscch_dl_header & RX_TYPE_MASK) >> RX_TYPE_SHIFT; if(rx_type==C_RATSCCH_GOOD) { // RATSCCH block detected l1s_amr_update_from_ratscch(&l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0]); } } } #endif // AMR switch(task) { case DDL : case ADL : /*---------------------------------------------------*/ /* Dedicated mode: SDCCH receive task. */ /* Rem: only a partial result is present in the */ /* mcu<-dsp communication buffer. The BLOCK content */ /* itself is in the last comm. (BURST_4) */ /*---------------------------------------------------*/ { UWORD8 i, IL_for_rxlev; #if (TRACE_TYPE!=0) // Check burst identifier... if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_burst_d & 0xffff) != burst_id) trace_fct(CST_DL_BURST_DOES_NOT_CORRESPOND, (UWORD32)(-1)); #endif // Read control results and feed control algorithms. // ************************************************** // Read control information. 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; l1_check_pm_error(pm, task); // Update AGC: Call DPAGC algorithm IL_for_rxlev = l1ctl_dpagc(0,beacon,(UWORD8)pm,radio_freq,IL_info_ptr); // dtx_on = 0 // Dedicated mode serving cell measurement reading. #if REL99 #if FF_EMR // only task,burst_id is valid in structure pointed by *emr_params l1s_read_dedic_scell_meas(IL_for_rxlev, 1, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 1); #endif #if TRACE_TYPE==3 stats_samples_nb(toa,pm,angle,snr,burst_id,task); #endif // Update AFC: Call AFC control function (KALMAN filter). #if AFC_ALGO #if TESTMODE if (l1_config.afc_enable) #endif { #if (VCXO_ALGO == 0) l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq); #else l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq,l1a_l1s_com.mode); #endif } #endif //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 1 /* FreeCalypso TCS211 reconstruction */ if (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); else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count); #else UWORD32 snr_temp; snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0; #if (TOA_ALGO == 2) l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa); #else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING ==1) ,0 #endif ); #endif #endif } #endif #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev) #endif #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) && HAVE_L1_TRACE_BURST_PARAM l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev); #endif #if (BURST_PARAM_LOG_ENABLE == 1) l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev); #endif // Read downlink DATA block from MCU/DSP interface. // ************************************************* if(burst_id == BURST_4) { #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace(task); #endif if(task == DDL) { // Read DCCH DL data block from DSP, pass it to L2. l1s_read_dcch_dl(l1s_dsp_com.dsp_ndb_ptr->a_cd, task); } else { // Read L2 frame block and send msg to L1A. l1s_read_sacch_dl(l1s_dsp_com.dsp_ndb_ptr->a_cd, task); } // RXQUAL_FULL/RXQUAL_SUB : number of estimated errors, this value is contained // in a_cd[2] field, for every SACCH and SDDCH blocks l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_cd[2]&0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += A_D_BLEN; l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_cd[2]&0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += A_D_BLEN; // TEMPORARY : reset buffers and flags in NDB ... // reset nerr.... // reset A_CD contents....... l1s_dsp_com.dsp_ndb_ptr->a_cd[0] = (1<<B_FIRE1); // B_FIRE1=1,B_FIRE0=0,BLUD=0. l1s_dsp_com.dsp_ndb_ptr->a_cd[2] = 0xffff; for (i=0; i<12 ;i++) l1s_dsp_com.dsp_ndb_ptr->a_cd[3+i] = 0x0000; // task is completed, make it INACTIVE. l1s.task_status[task].current_status = INACTIVE; } } break; case TCHTH: /*---------------------------------------------------*/ /* Dedicated mode: TCHTH receive task. */ /* HALF RATE */ /*---------------------------------------------------*/ { UWORD32 b_blud; UWORD8 channel_mode; //OMAPS00090550 UWORD8 channel_type; UWORD8 subchannel; UWORD32 l1_mode; UWORD32 fn_mod_104; UWORD32 fn_mod_52; //OMAPS00090550 UWORD32 fn_report_mod13_mod4; UWORD32 normalised_fn_report_mod13_mod4; UWORD32 normalised_fn_report_mod26; UWORD8 IL_for_rxlev = 0; //omaps00090550 #if (AMR == 1) UWORD8 rx_type; UWORD8 b_ratscch_blud,b_facch_blud; UWORD8 voco_type; BOOL facch_present = FALSE; #if REL99 #if FF_EMR emr_params.amr_facch_present = FALSE; emr_params.amr_facch_fire1 = FALSE; #endif #endif #endif // Read control results and feed control algorithms. // ************************************************** // Read control information. 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; l1_check_pm_error(pm, task); #if TRACE_TYPE==3 stats_samples_tch(toa,pm,angle,snr); #endif #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace(TCHTH); #endif // Update AFC: Call AFC control function (KALMAN filter). #if AFC_ALGO #if TESTMODE if (l1_config.afc_enable) #endif { #if (VCXO_ALGO == 0) l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq); #else l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq,l1a_l1s_com.mode); #endif } #endif // Increment number of burst not sent due to DTX. if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_u & 0xffff) == TCH_DTX_UL) { l1a_l1s_com.Smeas_dedic.dtx_used++; l1s.dtx_ul_on = TRUE; } else { l1s.dtx_ul_on = FALSE; } // Check SID frame subset... channel_mode = l1a_l1s_com.dedic_set.aset->achan_ptr->mode; //OMAPS00090550 channel_type = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type; subchannel = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->subchannel; fn_mod_104 = l1s.actual_time.fn % 104; fn_mod_52 = l1s.actual_time.fn % 52; #if REL99 #if FF_EMR // Compute FN in reporting period % 13 % 4 = (((FN-subchannel)+ 13) %13) %4 normalised_fn_report_mod13_mod4 = ((l1s.actual_time.fn - subchannel + 13) % 13) % 4; // Compute FN in reporting period % 26 independently of the considered subchannel. normalised_fn_report_mod26 = (l1s.actual_time.fn - subchannel + 26) % 26; emr_params.channel_mode = channel_mode; emr_params.subchannel = subchannel; emr_params.normalised_fn_mod13_mod4 = normalised_fn_report_mod13_mod4; #endif //FF_EMR #endif //REL99 #if (AMR == 1) // Check if we're in AMR DTX mode if(channel_mode==TCH_AHS_MODE && ( (((l1s.actual_time.fn_mod13 % 4)==3) && (subchannel==0)) || // AHS0: block is decoded on DSP side at fn%13%4=2 (((l1s.actual_time.fn_mod13 % 4)==0) && (subchannel==1)) )) // AHS1: block is decoded on DSP side at fn%13%4=3 { if(subchannel==0) { b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD; rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT; } else { b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_BLUD)) >> B_BLUD; rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT; } b_ratscch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & (1<<B_BLUD)) >> B_BLUD; b_facch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD; // Check if AMR DTX mode is on if((((rx_type==SID_FIRST) || (rx_type==SID_UPDATE) || (rx_type==SID_BAD)) && b_blud==TRUE) || (rx_type==AMR_NO_DATA && b_blud==FALSE)) { l1s.dtx_amr_dl_on=TRUE; } else if(b_ratscch_blud==FALSE && b_facch_blud==FALSE) { l1s.dtx_amr_dl_on=FALSE; } } #endif #if (AMR == 1) if (channel_mode != TCH_AHS_MODE) { // This AGC and TOA update isn't applied to the adaptative half rate mode. if(((channel_mode == TCH_HS_MODE) && (subchannel == 0) && (fn_mod_52 > 0) && (fn_mod_52 <= 7)) || ((channel_mode == TCH_HS_MODE) && (subchannel == 1) && (fn_mod_52 > 14) && (fn_mod_52 <= 21)) || ((channel_mode != TCH_HS_MODE) && (subchannel == 0) && (fn_mod_104 > 56) && (fn_mod_104 <= 76)) || ((channel_mode != TCH_HS_MODE) && (subchannel == 1) && (fn_mod_104 > 66) && (fn_mod_104 <= 86))) #else if(((channel_mode == TCH_HS_MODE) && (subchannel == 0) && (fn_mod_52 > 0) && (fn_mod_52 <= 7)) || ((channel_mode == TCH_HS_MODE) && (subchannel == 1) && (fn_mod_52 > 14) && (fn_mod_52 <= 21)) || ((channel_mode != TCH_HS_MODE) && (subchannel == 0) && (fn_mod_104 > 56) && (fn_mod_104 <= 76)) || ((channel_mode != TCH_HS_MODE) && (subchannel == 1) && (fn_mod_104 > 66) && (fn_mod_104 <= 86))) #endif // Current results are from the TDMA frame subset always received (GSM05.08, $8.3). // -> pwr meas. must be used for SUB set result. // -> TOA filtering can be fed with SNR/TOA. // WARNING: TCH/H in signalling only is here processed like TCH/H data. GSM spec is // ======== unclear !!!!!!!!!!!!!!!1 { // Update AGC: Call DPAGC algorithm IL_for_rxlev = l1ctl_dpagc(1,beacon,(UWORD8)pm, radio_freq, IL_info_ptr); // Dedicated mode serving cell measurement reading, indicate "SUB". #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 1,&emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 1); #endif //Feed TOA histogram. #if (TOA_ALGO != 0) // When in 1/2 rate data, we are working on 14 SID frames (instead // of 12 otherwise), so we need to increment length of the histogram // filling period from 36 to 42. if (channel_mode != TCH_HS_MODE) l1_mode=DEDIC_MODE_HALF_DATA; else l1_mode=l1a_l1s_com.mode; #if (TOA_ALGO == 2) if(l1s.toa_var.toa_snr_mask == 0) #else if(l1s.toa_snr_mask == 0) #endif { #if 1 /* FreeCalypso TCS211 reconstruction */ if (IL_for_rxlev < IL_FOR_RXLEV_SNR) l1s.toa_shift = l1ctl_toa(TOA_RUN, l1_mode, snr, toa, &l1s.toa_update, &l1s.toa_period_count); else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1_mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count); #else UWORD32 snr_temp; snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0; #if (TOA_ALGO == 2) l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1_mode, snr_temp, toa); #else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1_mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING == 1) ,0 #endif ); #endif #endif } #endif } // if(((channel_mode == TCH_HS_MODE) && (subchannel == 0) && else { // Update AGC: Call DPAGC algorithm IL_for_rxlev = l1ctl_dpagc(0,beacon,(UWORD8)pm,radio_freq,IL_info_ptr); // Dedicated mode serving cell measurement reading, full set only. #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 0); #endif } #if (AMR == 1) } // if (channel_mode != TCH_AHS_MODE) #endif #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev) #endif #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) && HAVE_L1_TRACE_BURST_PARAM l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev); #endif #if (BURST_PARAM_LOG_ENABLE == 1) l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev); #endif // Read downlink DATA block from MCU/DSP interface. // ************************************************* // Compute FN % 13 % 4 //OMAPS00090550 fn_report_mod13_mod4 = (l1s.actual_time.fn_mod13) % 4; // Compute normalised FN % 13 %4 = (((FN-subchannel)+ 13) %13) %4 normalised_fn_report_mod13_mod4 = ((l1s.actual_time.fn - subchannel + 13) % 13) % 4; // Compute normalised FN %26 = ((FN - subchannel)+ 26) %26 normalised_fn_report_mod26 = (l1s.actual_time.fn - subchannel + 26) % 26; if((normalised_fn_report_mod26 == 16)|| (normalised_fn_report_mod26 == 24)|| (normalised_fn_report_mod26 == 7)) // It is time to get FACCH/H data block. { // FACCH: Check A_FD information block. //------------------------------------- UWORD8 temp; b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD; #if ((REL99) && (AMR == 1)) #if FF_EMR emr_params.amr_facch_fire1 = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_FIRE1)) >> B_FIRE1; #endif #endif if(b_blud == TRUE) { // Read FACCH DL data block from DSP, pass it to L2. #if ( FF_REPEATED_DL_FACCH == 1 ) #if (TRACE_TYPE == 1 || TRACE_TYPE == 4) trace_info.facch_dl_count_all++; #endif // if the current block is a repetition reports NULL to L2 otherwise reports the current block l1s_read_dcch_dl((API*)l1s_repeated_facch_check(l1s_dsp_com.dsp_ndb_ptr->a_fd), task); #else l1s_read_dcch_dl(l1s_dsp_com.dsp_ndb_ptr->a_fd, task); #endif #if (AMR == 1) if (channel_mode != TCH_AHS_MODE) { #endif // RXQUAL_SUB : In case of data taffic channels, accumulate number of // estimated errors, this value is contained in a_fd[2] field, only // for SID TDMA frames received as FACCH frames. (GSM 5.08 $8.4) if (((fn_mod_104==59) && (channel_mode==TCH_HS_MODE) && (subchannel==0)) || ((fn_mod_104==73) && (channel_mode==TCH_HS_MODE) && (subchannel==1)) || ((fn_mod_104==76) && ((channel_mode==TCH_48H_MODE)|| (channel_mode==TCH_24H_MODE)) && (subchannel==0)) || ((fn_mod_104==86) && ((channel_mode==TCH_48H_MODE)|| (channel_mode==TCH_24H_MODE)) && (subchannel==1))) // last SID TDMA frame received as FACCH frames. { l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_fd[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_F_D_BLEN; } #if (AMR == 1) } // if (channel_mode != TCH_AHS_MODE) else { // Indicate to AMR specific processing that burst was a FACCH facch_present = TRUE; #if ((REL99) && (AMR == 1)) #if FF_EMR emr_params.amr_facch_present = facch_present; #endif #endif // Update AGC: Call DPAGC algorithm IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr); // Dedicated mode serving cell measurement reading, indicate "FULL". #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 0); #endif } #endif // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_fd[2] field, for each TCHT block. // The same for AMR #if (AMR == 1) // in AMR, l1s.dtx_amr_dl_on is FALSE if DTX mode is off // in non AMR TCH, l1s.dtx_amr_dl_on is always FALSE // In AMR DTX, DSP patch sometimes reports FACCH blocks which ARE NOT FACCH blocks // therefore they shouldn't be taken into account in the RXQUALL_FULL computation if(l1s.dtx_amr_dl_on==FALSE) #endif { l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_fd[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_F_D_BLEN; } // Reset A_FD header. // B_FIRE1 =1, B_FIRE0 =0 , BLUD =0 l1s_dsp_com.dsp_ndb_ptr->a_fd[0] = (1<<B_FIRE1); l1s_dsp_com.dsp_ndb_ptr->a_fd[2] = 0xffff; // Rem: when FACCH is received, we must reset A_DD_0 header also. // Reset A_DD_0 header in NDB. #if (AMR == 1) if ((channel_mode==TCH_AHS_MODE) && (subchannel==0)) { l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] &= (API)(RX_TYPE_MASK); } else #endif { l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0; } l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff; // Rem: when FACCH is received, we must reset A_DD_1 header also. // Reset A_DD_0 header in NDB. #if (AMR == 1) if ((channel_mode==TCH_AHS_MODE) && (subchannel==1)) { l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] &= (API)(RX_TYPE_MASK); } else #endif { l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] = 0; } l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff; } // if(b_blud == TRUE) else // No FACCH received at FACCH boundary frame. Nevertheless, need to read dummy // FACCH DL data block. { // Dummy: Read FACCH DL data block from DSP, pass it to L2. // Rem: this is an upper layer requirement to call this // function at every FACCH DL boundary. l1s_read_dcch_dl(NULL, task); } } // if((normalised_fn_report_mod26 == 16)|| ... // else we are not at FACCH boundary frame // We must check for the presence of a TCH/H block (even if it does fall on a FACCH boundary) // We use the b_blud bit to confirm presence of TCH/H (or FACCH) if((normalised_fn_report_mod13_mod4 == 3) && (channel_mode==TCH_HS_MODE)) // It is time to get TCH/HS data block. { #if TRACE_TYPE==3 if (l1_stats.type == PLAY_UL && (channel_mode == TCH_HS_MODE)) play_trace(); #endif // Check A_DD_0 information block only if no FACCH. if (subchannel==0) b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD; else b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_BLUD)) >> B_BLUD; if(b_blud == TRUE) { if (subchannel==0) { // RXQUAL_SUB : In case of speech traffic channels, accumulate number of // estimated errors, this value is contained in a_dd_0[2] field, only // for SID TDMA frames. (GSM 5.08 $8.4) if (fn_mod_104==59) { l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_HS_BLEN; } // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_dd_0[2] field, for each TCHT block. l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff; } // if (subchannel==0) else { // RXQUAL_SUB : In case of speech traffic channels, accumulate number of // estimated errors, this value is contained in a_dd_1[2] field, only // for SID TDMA frames. (GSM 5.08 $8.4) if (fn_mod_104==73) { l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_HS_BLEN; } l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff; // Reset A_DD_1 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff; } l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_HS_BLEN; } // if(b_blud == TRUE) } // if((normalised_fn_report_mod13_mod4 == 3) && (channel_mode==TCH_HS_MODE)) #if (AMR == 1) if(((normalised_fn_report_mod26 == 20) || (normalised_fn_report_mod26 == 3) || (normalised_fn_report_mod26 == 11)) && ((channel_mode == TCH_48H_MODE) || (channel_mode == TCH_24H_MODE))) #else if(((normalised_fn_report_mod26 == 20) || (normalised_fn_report_mod26 == 3) || (normalised_fn_report_mod26 == 11)) && (channel_mode!=TCH_HS_MODE)) #endif // It is time to get TCH/H4.8 or TCH/H2.4 data block. { // Check A_DD_0 information block only if no FACCH. if (subchannel==0) b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD; else b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_BLUD)) >> B_BLUD; if(b_blud == TRUE) { if (subchannel==0) { // RXQUAL_SUB : In case of speech traffic channels, accumulate number of // estimated errors, this value is contained in a_dd_0[2] field, only // for SID TDMA frames. (GSM 5.08 $8.4) if (fn_mod_104==76) { l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_F_D_BLEN; } // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_dd_0[2] field, for each TCHT block. l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff; } else { // RXQUAL_SUB : In case of speech traffic channels, accumulate number of // estimated errors, this value is contained in a_dd_1[2] field, only // for SID TDMA frames. (GSM 5.08 $8.4) if (fn_mod_104==86) { l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_F_D_BLEN; } l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff; // Reset A_DD_1 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff; } // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_dd_1[2] field, for each TCHT block. l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_F_D_BLEN; // WARNING: sequence number is not implemented in DATA half rate // TO BE DEFINED...... } // if(b_blud == TRUE) } // if(((normalised_fn_report_mod26 == 20) || ... #if (AMR == 1) if ((channel_mode == TCH_AHS_MODE) && (facch_present == FALSE)) { // the channel is a TCH/AHS and it's time to receive a new block if (subchannel == 0) { // Load the bit to check if the block is valid b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD; } else // subchannel 1 { // Load the bit to check if the block is valid b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & (1<<B_BLUD)) >> B_BLUD; } b_ratscch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & (1<<B_BLUD)) >> B_BLUD; // All frames except NO_DATA (b_blud = FALSE) and FACCH, i.e AMR speech/SID block or a RATSCCH block if(b_ratscch_blud==TRUE) { // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_ratscch_dl[2] field, for each TCHT block. l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[2] & 0xffff; // Reset the A_RATSCCH_DL header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[2] = 0xffff; // RXQUAL_FULL : the number of bits examined for errors on serving cell depends on // the block received. l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += RATSCCH_BLEN; IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr); #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 0); #endif } else if(b_blud==TRUE) { if (subchannel == 0) { // Load the type of the block received rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT; // Load the type of vocoder currently used voco_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & VOCODER_TYPE_MASK) >> VOCODER_TYPE_SHIFT; #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1) Trace_dedic_tch_block_stat(rx_type, l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2], voco_type); #endif // RXQUAL_SUB : In case of adaptative traffic channel, accumulate number of estimated errors // is contained in the a_dd_0[2] value but the accumulation is made with SID_UPDATE frame only. if((rx_type==SID_UPDATE) || (rx_type==SID_BAD)) { l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += SID_UPDATE_BLEN; } // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_dd_0[2] field, for each TCHT block. l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] &= (API)(RX_TYPE_MASK); l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff; } else // subchannel ==1 { // Load the type of the block received rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT; // Load the type of vocoder currently used voco_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] & VOCODER_TYPE_MASK) >> VOCODER_TYPE_SHIFT; #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1) Trace_dedic_tch_block_stat(rx_type, l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2], voco_type); #endif // RXQUAL_SUB : In case of adaptative traffic channel, accumulate number of estimated errors // is contained in the a_dd_1[2] value but the accumulation is made with SID_UPDATE block only. if((rx_type==SID_UPDATE) || (rx_type==SID_BAD)) { l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += SID_UPDATE_BLEN; } // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_dd_1[2] field, for each TCHT block. l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff; // Reset A_DD_1 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] &= (API)(RX_TYPE_MASK); l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff; } // subchannel == 1 // RXQUAL_FULL : the number of bits examined for errors on serving cell depends on // the block received. if((rx_type==SPEECH_GOOD) || (rx_type==SPEECH_DEGRADED) || (rx_type==SPEECH_BAD)) { // The block length depens on the vocoder type switch (voco_type) { case AMR_CHANNEL_7_95: { // TCH-AHS 7.95 l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_7_95_BLEN; } break; case AMR_CHANNEL_7_4: { // TCH-AHS 7.4 l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_7_4_BLEN; } break; case AMR_CHANNEL_6_7: { // TCH-AHS 6.7 l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_6_7_BLEN; } break; case AMR_CHANNEL_5_9: { // TCH-AHS 5.9 l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_5_9_BLEN; } break; case AMR_CHANNEL_5_15: { // TCH-AHS 5.15 l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_5_15_BLEN; } break; case AMR_CHANNEL_4_75: { // TCH-AHS 4.75 l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_4_75_BLEN; } break; } // switch } // if ( (rx_type == SPEECH_GOOD) || ... else if((rx_type == SID_UPDATE) || (rx_type == SID_BAD)) { // the block is a SID UPDATE l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += SID_UPDATE_BLEN; } // AGC, TOA update for AMR... SUB FIFO only for SID_UPDATE frame if((rx_type == SID_UPDATE) || (rx_type == SID_BAD)) { IL_for_rxlev = l1ctl_dpagc_amr(1,beacon,(UWORD8)pm, radio_freq, IL_info_ptr); #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 1, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 1); #endif #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 1 /* FreeCalypso TCS211 reconstruction */ if (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); else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count); #else UWORD32 snr_temp; snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0; #if (TOA_ALGO == 2) l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa); #else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING == 1) ,0 #endif ); #endif #endif } #endif } else { IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr); #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 0); #endif } } // if (b_blud == TRUE) // simple burst or NO_DATA frame else { // NO_DATA is considered a bad frame if (normalised_fn_report_mod13_mod4 == 3) { l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AHS_4_75_BLEN; if (subchannel == 0) { l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1) Trace_dedic_tch_block_stat(AMR_NO_DATA, l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2], 0); #endif // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] &= (API)(RX_TYPE_MASK); l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff; } else { l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] & 0xffff; #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1) Trace_dedic_tch_block_stat(AMR_NO_DATA, l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2], 0); #endif // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] &= (API)(RX_TYPE_MASK); l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff; } } // Update AGC: Call DPAGC AMR algorithm in order to fill the G_all buffer IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm,radio_freq,IL_info_ptr); // Dedicated mode serving cell measurement reading, full set only. #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 0); #endif } } // if ((channel_mode == TCH_AHS_MODE) && (facch_present == FALSE)) #endif // task is completed, make it INACTIVE. l1s.task_status[task].current_status = INACTIVE; } break; case TCHTF: /*---------------------------------------------------*/ /* Dedicated mode: TCHTF receive task. */ /* FULL RATE */ /*---------------------------------------------------*/ { UWORD8 IL_for_rxlev = 0; //omaps00090550 UWORD32 b_blud; UWORD8 channel_mode; //OMAPS00090550 UWORD8 channel_type; UWORD32 fn_mod_104; //OMAPS00090550 UWORD32 fn_mod_52; UWORD32 fn_report_mod13_mod4; #if (AMR == 1) UWORD8 rx_type; UWORD8 b_ratscch_blud,b_facch_blud; BOOL facch_present = FALSE; #endif #if TESTMODE xSignalHeaderRec *msg; #endif // Read control results and feed control algorithms. // ************************************************** // Read control information. 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; l1_check_pm_error(pm, task); #if TRACE_TYPE==3 stats_samples_tch(toa,pm,angle,snr); #endif #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace(TCHTF); #endif // Update AFC: Call AFC control function (KALMAN filter). #if AFC_ALGO #if TESTMODE if (l1_config.afc_enable) #endif { #if (VCXO_ALGO == 0) l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq); #else l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq,l1a_l1s_com.mode); #endif } #endif // Check SID frame subset... channel_mode = l1a_l1s_com.dedic_set.aset->achan_ptr->mode; //OMAPS00090550 channel_type = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type; fn_mod_104 = l1s.actual_time.fn % 104; //OMAPS00090550 fn_mod_52 = l1s.actual_time.fn % 52; #if (AMR == 1) // Check if we're in AMR DTX mode if(channel_mode==TCH_AFS_MODE && (l1s.actual_time.fn_mod13 % 4)==0) // AFS: block is decoded on DSP side at fn%13%4=3 { b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD; rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT; b_ratscch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & (1<<B_BLUD)) >> B_BLUD; b_facch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD; // Check if AMR DTX mode is on if((((rx_type==SID_FIRST) || (rx_type==SID_UPDATE) || (rx_type==SID_BAD)) && b_blud==TRUE) || (rx_type==AMR_NO_DATA && b_blud==FALSE)) { l1s.dtx_amr_dl_on=TRUE; } else if(b_ratscch_blud==FALSE && b_facch_blud==FALSE) { l1s.dtx_amr_dl_on=FALSE; } } #endif #if REL99 #if FF_EMR emr_params.channel_mode = channel_mode; // emr_params.fn_mod13_mod4 = l1s.actual_time.fn_mod13_mod4; #if (AMR == 1) emr_params.amr_facch_present = FALSE; emr_params.amr_facch_fire1 = FALSE; #endif #endif #endif // Increment number of burst not sent due to DTX. if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_u & 0xffff) == TCH_DTX_UL) { l1a_l1s_com.Smeas_dedic.dtx_used++; l1s.dtx_ul_on = TRUE; } else { // Some bursts are always sent in DTX mode. d_task_u does not give DTX_UL // so we must keep previous value of dtx_on if (! ((fn_mod_104 > 52) && (fn_mod_104 <= 60)) ) l1s.dtx_ul_on = FALSE; } #if FF_L1_IT_DSP_DTX // Currently used for TCH-AFS only if (l1s.actual_time.fn_mod13_mod4 == 0) // FN%13 = 4, 8 and 12 (no TCH/F Read on FN%13=0) { // Latch TX activity status if DTX allowed if ((l1a_l1s_com.dedic_set.aset->dtx_allowed == FALSE) || // No DTX allowed (l1s_dsp_com.dsp_ndb_ptr->d_fast_dtx_enc_data) || // DTX allowed but not used (l1a_apihisr_com.dtx.fast_dtx_ready == FALSE)) // Fast DTX status is invalid l1a_apihisr_com.dtx.tx_active = TRUE; else l1a_apihisr_com.dtx.tx_active = FALSE; } #endif #if (AMR == 1) if (channel_mode != TCH_AFS_MODE) { // This AGC and TOA update isn't applied to the adaptative full rate mode #endif if((fn_mod_104 > 52) && (fn_mod_104 <= 60)) // Current results are from the TDMA frame subset always received (GSM05.08, $8.3). // -> pwr meas. must be used for SUB set result. // -> TOA filtering can be fed with SNR/TOA. // This DTX is only applied to the mode EFR, FR and data. { // Update AGC: Call DPAGC algorithm IL_for_rxlev = l1ctl_dpagc(1,beacon,(UWORD8)pm, radio_freq, IL_info_ptr); // Dedicated mode serving cell measurement reading, indicate "SUB". #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 1, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 1); #endif //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 1 /* FreeCalypso TCS211 reconstruction */ if (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); else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count); #else UWORD32 snr_temp; snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0; #if (TOA_ALGO == 2) l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa); #else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING == 1) ,0 #endif ); #endif #endif } #endif } else { // Update AGC: Call DPAGC algorithm IL_for_rxlev = l1ctl_dpagc(0,beacon,(UWORD8)pm,radio_freq,IL_info_ptr); // Dedicated mode serving cell measurement reading, full set only. #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 0); #endif } #if (AMR == 1) } // if (channel_mode != TCH_AFS_MODE) #endif #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev) #endif #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) && HAVE_L1_TRACE_BURST_PARAM l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev); #endif #if (BURST_PARAM_LOG_ENABLE == 1) l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev); #endif // Read downlink DATA block from MCU/DSP interface. // ************************************************* // Compute FN in reporting period % 13 % 4. fn_report_mod13_mod4 = (l1s.actual_time.fn_mod13) % 4; if(fn_report_mod13_mod4 == 0) // It is time to get FACCH/F or TCH/F2.4 or TCH/(E)FS data block. { UWORD8 temp; #if TRACE_TYPE==3 if (l1_stats.type == PLAY_UL && (channel_mode == TCH_FS_MODE || channel_mode == TCH_24F_MODE || channel_mode == TCH_EFR_MODE)) play_trace(); #endif // FACCH: Check A_FD information block. //------------------------------------- b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_BLUD)) >> B_BLUD; #if ((REL99) && (AMR == 1)) #if FF_EMR emr_params.amr_facch_fire1 = (l1s_dsp_com.dsp_ndb_ptr->a_fd[0] & (1<<B_FIRE1)) >> B_FIRE1; #endif #endif if(b_blud == TRUE) { // Read FACCH DL data block from DSP, pass it to L2. #if ( FF_REPEATED_DL_FACCH == 1 ) #if (TRACE_TYPE == 1 || TRACE_TYPE == 4) trace_info.facch_dl_count_all++; #endif /* if the current block is a repetition reports NULL to L2 otherwise reports the current block */ l1s_read_dcch_dl((API*)l1s_repeated_facch_check(l1s_dsp_com.dsp_ndb_ptr->a_fd), task); #else /* UWORD8 error_flag =*/ l1s_read_dcch_dl(l1s_dsp_com.dsp_ndb_ptr->a_fd, task); #endif /* ( FF_REPEATED_DL_FACCH == 1 ) */ #if (AMR == 1) // Non AMR FACCH handling if (channel_mode != TCH_AFS_MODE) { #endif // RXQUAL_SUB : In case of data taffic channels, accumulate number of // estimated errors, this value is contained in a_fd[2] field, only // for SID TDMA frames received as FACCH frames. (GSM 5.08 $8.4) if (fn_mod_104==60) { l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_fd[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_F_D_BLEN; } #if (AMR == 1) } else { // AGC, RXLEV_FULL // Indicate to AMR specific processing that burst was a FACCH facch_present = TRUE; #if ((REL99) && (AMR == 1)) #if FF_EMR emr_params.amr_facch_present = facch_present; #endif #endif // Update AGC: Call DPAGC algorithm IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr); // Dedicated mode serving cell measurement reading, indicate "FULL". #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 0); #endif } #endif // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_fd[2] field, for each TCHT block. #if (AMR == 1) // in AMR, l1s.dtx_amr_dl_on is FALSE if DTX mode is off // in non AMR TCH, l1s.dtx_amr_dl_on is always FALSE // In AMR DTX, DSP patch sometimes reports FACCH blocks which ARE NOT FACCH blocks // therefore they shouldn't be taken into account in the RXQUALL_FULL computation if(l1s.dtx_amr_dl_on==FALSE) #endif { l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_fd[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_F_D_BLEN; } // Reset A_FD header. // B_FIRE1 =1, B_FIRE0 =0 , BLUD =0 l1s_dsp_com.dsp_ndb_ptr->a_fd[0] = (1<<B_FIRE1); l1s_dsp_com.dsp_ndb_ptr->a_fd[2] = 0xffff; // Rem: when FACCH is received, we must reset A_DD_0 header also. // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff; // Rem: when FACCH is received, we must reset A_DD_1 header also. // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_1[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_dd_1[2] = 0xffff; #if TESTMODE if (l1_config.TestMode) { pm_fullres = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM] & 0xffff); // F26.6 // Allocate result message. msg = os_alloc_sig(sizeof(T_TMODE_TCH_INFO)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = TMODE_TCH_INFO; ((T_TMODE_TCH_INFO *)(msg->SigP))->pm_fullres = pm_fullres; // F26.6 ((T_TMODE_TCH_INFO *)(msg->SigP))->snr = snr; ((T_TMODE_TCH_INFO *)(msg->SigP))->toa = toa; ((T_TMODE_TCH_INFO *)(msg->SigP))->angle = (WORD16) angle; // signed ((T_TMODE_TCH_INFO *)(msg->SigP))->qual_full = l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; ((T_TMODE_TCH_INFO *)(msg->SigP))->qual_nbr_meas_full = TCH_FS_BLEN; // send TMODE_TCH_INFO message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } #endif } // if (b_blud == TRUE) else // (if (b_blud == TRUE) FACCH { // No FACCH received. // Dummy: Read FACCH DL data block from DSP, pass it to L2. // Rem: this is an upper layer requirement to call this // function at every FACCH DL boundary. l1s_read_dcch_dl(NULL, task); #if (AMR == 1) if (channel_mode != TCH_AFS_MODE) { #endif // Check A_DD_0 information block for TCH/F2.4 or TCH/FS. // TCH/F2.4 or TCH/FS: Check A_DD_0 information block. //---------------------------------------------------- b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD; if(b_blud == TRUE) { // RXQUAL_SUB : In case of speech traffic channels, accumulate number of // estimated errors, this value is contained in a_dd_0[2] field, only // for SID TDMA frames. (GSM 5.08 $8.4) if (fn_mod_104==60) { l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += TCH_FS_BLEN; } // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_dd_0[2] field, for each TCHT block. l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_FS_BLEN; #if TESTMODE if (l1_config.TestMode) { pm_fullres = (l1s_dsp_com.dsp_db_r_ptr->a_serv_demod[D_PM] & 0xffff); // F26.6 // Allocate result message. msg = os_alloc_sig(sizeof(T_TMODE_TCH_INFO)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = TMODE_TCH_INFO; ((T_TMODE_TCH_INFO *)(msg->SigP))->pm_fullres = pm_fullres; // F26.6 ((T_TMODE_TCH_INFO *)(msg->SigP))->snr = snr; ((T_TMODE_TCH_INFO *)(msg->SigP))->toa = toa; ((T_TMODE_TCH_INFO *)(msg->SigP))->angle = (WORD16) angle; // signed ((T_TMODE_TCH_INFO *)(msg->SigP))->qual_full = l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; ((T_TMODE_TCH_INFO *)(msg->SigP))->qual_nbr_meas_full = TCH_FS_BLEN; // send TMODE_TCH_INFO message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } #endif if(channel_mode == TCH_24F_MODE) { #if IDS // Integrated Data Services implementation { dll_data_dl(l1s_dsp_com.dsp_ndb_ptr->a_data_buf_dl, &l1s_dsp_com.dsp_ndb_ptr->d_ra_act, &l1s_dsp_com.dsp_ndb_ptr->d_ra_statd); } #else { // DATA traffic. // Pass data block to DATA ADAPTOR. // REM: Data packet is always given to the DATA ADAPTOR. // There is no RX quality check !! { rx_tch_data(&l1s_dsp_com.dsp_ndb_ptr->a_dd_0[3], channel_mode, 0); } } #endif } // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff; } // if(b_blud == TRUE) #if (AMR == 1) } // if (channel_mode != TCH_AFS_MODE) #endif } // if (b_blud == TRUE) FACCH (else) #if (FF_REPEATED_DL_FACCH == 1) #if 1 temp=l1s.repeated_facch.counter_candidate; l1s.repeated_facch.counter_candidate=l1s.repeated_facch.counter; l1s.repeated_facch.counter=temp; #else if (l1s.repeated_facch.counter_candidate == 1) l1s.repeated_facch.counter_candidate = 0 ; else if (l1s.repeated_facch.counter_candidate == 0 ) l1s.repeated_facch.counter_candidate = 0 ; l1s.repeated_facch.counter++ ; if (l1s.repeated_facch.counter == 4) { l1s.repeated_facch.counter = 0; l1s.repeated_facch.pipeline[0].buffer_empty=l1s.repeated_facch.pipeline[1].buffer_empty=TRUE; } #endif #endif/*(FF_REPEATED_DL_FACCH == 1)*/ /* FACCH Full rate */ } // if(fn_report_mod13_mod4 == 0) else // if(fn_report_mod13_mod4 == 0) #if (AMR == 1) if ((fn_report_mod13_mod4 == 2) && (channel_mode != TCH_AFS_MODE)) #else if(fn_report_mod13_mod4 == 2) #endif // It is time to get TCH/F4.8 or TCH/F9.6 data block. { #if TRACE_TYPE==3 if (l1_stats.type == PLAY_UL && (channel_mode == TCH_48F_MODE || channel_mode == TCH_96_MODE || channel_mode == TCH_144_MODE)) play_trace(); #endif // Check A_DD_0 information block only if no FACCH. b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD; if(b_blud == TRUE) { // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_dd_0[2] field, for each TCHT block. l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_F_D_BLEN; if((channel_mode == TCH_48F_MODE) || (channel_mode == TCH_96_MODE) || (channel_mode == TCH_144_MODE)) { #if IDS // Integrated Data Services implementation { dll_data_dl(l1s_dsp_com.dsp_ndb_ptr->a_data_buf_dl, &l1s_dsp_com.dsp_ndb_ptr->d_ra_act, &l1s_dsp_com.dsp_ndb_ptr->d_ra_statd); } #else { // DATA traffic. // Pass data block to DATA ADAPTOR. // REM: Data packet is always given to the DATA ADAPTOR. // There is no RX quality check !! { UWORD8 sequence_number; UWORD8 fn_report_mod26 = l1s.actual_time.fn_in_report % 26; // Catch sequence number. This is used in TCH/F4.8 to distinguish // data blocks (see GSM 5.02) received on B0,B2,B4 (sequence number 0) // and data blocks received on B1,B2,B3 (sequence number 1). if((fn_report_mod26 == 23) || (fn_report_mod26 == 6) || (fn_report_mod26 == 15)) sequence_number = 0; else sequence_number = 1; rx_tch_data(&l1s_dsp_com.dsp_ndb_ptr->a_dd_0[3], channel_mode, sequence_number); } } #endif } // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff; } // if(b_blud == TRUE) } // if(fn_report_mod13_mod4 == 2) #if (AMR == 1) if ((channel_mode == TCH_AFS_MODE) && (facch_present == FALSE)) { // Load the bit to check if the block is valid b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & (1<<B_BLUD)) >> B_BLUD; // Load the bit to check if the block is a RATSCCH in case of rx_type = NO_DATA b_ratscch_blud = (l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] & (1<<B_BLUD)) >> B_BLUD; // All detected AMR frames except NO_DATA (b_blud = 0) and FACCH are handled here, i.e. speech/SID/RATSCCH if(b_ratscch_blud==TRUE) { // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_ratscch_dl[2] field, for each TCHT block. l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[2] & 0xffff; // Reset the A_RATSCCH_DL header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_ratscch_dl[2] = 0xffff; // RXQUAL_FULL : the number of bits examined for errors on serving cell depends on // the block received. l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += RATSCCH_BLEN; IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr); #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 0); #endif } else if(b_blud==TRUE) { // Load the type of the block received rx_type = (l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] & RX_TYPE_MASK) >> RX_TYPE_SHIFT; #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1) Trace_dedic_tch_block_stat(rx_type, l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2], 0); #endif // RXQUAL_SUB : In case of adaptative traffic channel, accumulate number of estimated errors // is contained in the a_dd_0[2] value but the accumulation is made with SID_UPDATE frame only. // Note: SID_UPDATE frame corresponds to rx_type SID_UPDATE (b_ratscch_blud = FALSE) or SID_BAD (See Memo) if((rx_type==SID_UPDATE) || (rx_type==SID_BAD)) { l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += SID_UPDATE_BLEN; } // RXQUAL_FULL : accumulate number of estimated errors, this value is // contained in a_dd_0[2] field, for each TCHT block. // Frames, which have no class1 bit (so no quality meas is possible), have d_nerr = 0 // so we can add them l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff; // RXQUAL_FULL : the number of bits examined for errors on serving cell depends on // the block received. if((rx_type==SPEECH_GOOD) || (rx_type==SPEECH_DEGRADED) || (rx_type==SPEECH_BAD)) { // It's a speech block // Note: in AFS, the d_nerr value doesn't depend on the vocoder currently use l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AFS_BLEN; } else if((rx_type==SID_UPDATE) || (rx_type==SID_BAD)) { // the block is a SID UPDATE frame l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += SID_UPDATE_BLEN; } // AGC, TOA, RXLEV for AMR. SUB queues only for SID_UPDATE frames if((rx_type==SID_UPDATE) || (rx_type==SID_BAD)) { IL_for_rxlev = l1ctl_dpagc_amr(1,beacon,(UWORD8)pm, radio_freq, IL_info_ptr); #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 1, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 1); #endif #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 1 /* FreeCalypso TCS211 reconstruction */ if (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); else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count); #else UWORD32 snr_temp; snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0; #if (TOA_ALGO == 2) l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa); #else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING == 1) ,0 #endif ); #endif #endif } #endif } else { IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm, radio_freq, IL_info_ptr); #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 0); #endif } } // if(b_blud==TRUE) // NO_DATA block detected or simple burst else { if (fn_report_mod13_mod4 == 0) { l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += TCH_AFS_BLEN; #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1) Trace_dedic_tch_block_stat(AMR_NO_DATA, l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2], 0); #endif // Reset A_DD_0 header in NDB. l1s_dsp_com.dsp_ndb_ptr->a_dd_0[0] = 0; l1s_dsp_com.dsp_ndb_ptr->a_dd_0[2] = 0xffff; } // Update AGC: Call DPAGC AMR algorithm in order to fill the G_all buffer IL_for_rxlev = l1ctl_dpagc_amr(0,beacon,(UWORD8)pm,radio_freq,IL_info_ptr); // Dedicated mode serving cell measurement reading, full set only. #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 0, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 0); #endif } } // if ((channel_mode == TCH_AFS_MODE) && (facch_present == FALSE)) #endif // task is completed, make it INACTIVE. l1s.task_status[task].current_status = INACTIVE; } break; case TCHA: /*---------------------------------------------------*/ /* Dedicated mode: SACCH receive task. */ /*---------------------------------------------------*/ { UWORD8 IL_for_rxlev; UWORD32 b_blud; // Read control results and feed control algorithms. // ************************************************** // Read control information. 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; #if TESTMODE if (l1_config.TestMode && l1_config.tmode.rf_params.down_up == TMODE_UPLINK) { // For UL-only tasks, TCHA is scheduled in every frame. TCH_INFO message is only // used to count loops; no stats are collected. xSignalHeaderRec *msg; // Allocate result message. msg = os_alloc_sig(sizeof(T_TMODE_TCH_INFO)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = TMODE_TCH_INFO; // send TMODE_TCH_INFO message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } // WARNING! // Don't trace PM=0 during UL-only in TestMode. The DSP is not working // in that case so it is normal. However, if tracing happens the CPU overloads if (l1_config.TestMode && l1_config.tmode.rf_params.down_up & TMODE_DOWNLINK) #endif { l1_check_pm_error(pm, task); } #if TRACE_TYPE==3 stats_samples_tch_sacch(toa,pm,angle,snr); #endif #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace(task); #endif // Update AGC: Call DPAGC algorithm IL_for_rxlev = l1ctl_dpagc(1,beacon,(UWORD8)pm,radio_freq,IL_info_ptr); // dtx_on = 1 // Dedicated mode serving cell measurement reading, indicate "SUB". #if REL99 #if FF_EMR l1s_read_dedic_scell_meas(IL_for_rxlev, 1, &emr_params); #endif #else l1s_read_dedic_scell_meas(IL_for_rxlev, 1); #endif // Update AFC: Call AFC control function (KALMAN filter). #if AFC_ALGO #if TESTMODE if (l1_config.afc_enable) #endif { #if (VCXO_ALGO == 0) l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq); #else l1s.afc = l1ctl_afc(AFC_CLOSED_LOOP, &l1s.afc_frame_count, (WORD16)angle, snr, radio_freq,l1a_l1s_com.mode); #endif } #endif //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 1 /* FreeCalypso TCS211 reconstruction */ if (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); else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, 0, toa, &l1s.toa_update, &l1s.toa_period_count); #else UWORD32 snr_temp; snr_temp = (IL_for_rxlev < IL_FOR_RXLEV_SNR)? snr: 0; #if (TOA_ALGO == 2) l1s.toa_var.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa); #else l1s.toa_shift = l1ctl_toa(TOA_RUN, l1a_l1s_com.mode, snr_temp, toa, &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING == 1) ,0 #endif ); #endif #endif } #endif #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_DL_BURST(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev) #endif #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) && HAVE_L1_TRACE_BURST_PARAM l1_trace_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev); #endif #if (BURST_PARAM_LOG_ENABLE == 1) l1_log_burst_param(angle, snr, l1s.afc, task, pm, toa, IL_for_rxlev); #endif // Read downlink DATA block from MCU/DSP interface. // ************************************************* if(l1s.actual_time.fn_in_report == 91) // It's time to read a SACCH DL result from DSP. { // Check A_CD information block. b_blud = (l1s_dsp_com.dsp_ndb_ptr->a_cd[0] & (1<<B_BLUD)) >> B_BLUD; if(b_blud == TRUE) { #if W_A_DSP1 // Temporary correction to fix a known DSP problem. SACCH deinterleaver not // initialized on HO. // if (old_sacch_DSP_bug == TRUE) { // Invalidate the current sacch block - indicate it cannot be decoded l1s_dsp_com.dsp_ndb_ptr->a_cd[0] = (1<<B_FIRE1); // B_FIRE1=1,B_FIRE0=0,BLUD=0. old_sacch_DSP_bug = FALSE; } #endif // Read data block and send msg to L1A. l1s_read_sacch_dl(l1s_dsp_com.dsp_ndb_ptr->a_cd, task); // RXQUAL_FULL/RXQUAL_SUB : Accumulate number of estimated errors, this value // is contained in a_cd[2] field, for every SACCH block. l1a_l1s_com.Smeas_dedic.qual_acc_full += l1s_dsp_com.dsp_ndb_ptr->a_cd[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full += A_D_BLEN; l1a_l1s_com.Smeas_dedic.qual_acc_sub += l1s_dsp_com.dsp_ndb_ptr->a_cd[2] & 0xffff; l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub += A_D_BLEN; // TEMPORARY : reset buffers and flags in NDB ... // reset nerr.... // reset A_CD contents....... l1s_dsp_com.dsp_ndb_ptr->a_cd[0] = (1<<B_FIRE1); // B_FIRE1=1,B_FIRE0=0,BLUD=0. l1s_dsp_com.dsp_ndb_ptr->a_cd[2] = 0xffff; } } #if W_A_DSP1 else if (l1s.actual_time.fn_in_report == 13) // TF 5/8/98 - DSP fix { // As this is the first SACCH burst the known DSP bug cannot occur on a new channel. old_sacch_DSP_bug = FALSE; } #endif // task is completed, make it INACTIVE. l1s.task_status[task].current_status = INACTIVE; } break; } // End switch... #if (L1_DEBUG_IQ_DUMP == 1) 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; } /*-------------------------------------------------------*/ /* l1s_read_tx_result() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : */ /*-------------------------------------------------------*/ void l1s_read_tx_result(UWORD8 task, UWORD8 burst_id) { /*--------------------------------------------------------*/ /* READ TRANSMIT TASK RESULTS... */ /*--------------------------------------------------------*/ #if (TRACE_TYPE!=0) if(task==RAACC) { if((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_ra & 0xffff) != (UWORD32)DSP_TASK_CODE[task]) trace_fct(CST_UL_TASKS_DO_NOT_CORRESPOND, -1); } else { if(((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_u & 0xffff) != (UWORD32)DSP_TASK_CODE[task]) && ((UWORD32)(l1s_dsp_com.dsp_db_r_ptr->d_task_u & 0xffff) != TCH_DTX_UL)) trace_fct(CST_UL_TASKS_DO_NOT_CORRESPOND, -1); } #endif l1_check_com_mismatch(task); switch(task) { case RAACC: /*---------------------------------------------------*/ /* Serving Cell: Random Access TX task. */ /*---------------------------------------------------*/ // Rem: confirmation message is sent at "CTRL" to be able to give FN%42432. { // 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_MPHC_RA_CON)); DEBUGMSG(status,NU_ALLOC_ERR) if (l1s.actual_time.fn == 0) ((T_MPHC_RA_CON *)(msg->SigP))->fn = MAX_FN - 1; else ((T_MPHC_RA_CON *)(msg->SigP))->fn = l1s.actual_time.fn - 1; ((T_MPHC_RA_CON *)(msg->SigP))->channel_request = l1a_l1s_com.ra_info.channel_request; msg->SignalCode = L1C_RA_DONE; os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) // Desactivate the RAACC task. l1s.task_status[task].current_status = INACTIVE; #if (TRACE_TYPE!=0) trace_fct(CST_L1S_READ_RA, l1a_l1s_com.Scell_info.radio_freq); #endif } break; case DUL: /*---------------------------------------------------*/ /* Serving Cell: SDCCH up link. */ /*---------------------------------------------------*/ { // Desactivate UL task. if(burst_id == BURST_4) { l1s.task_status[task].current_status = INACTIVE; #if (TRACE_TYPE == 5) // in simulation only the 4th burst is traced trace_fct(CST_L1S_READ_TX_NB__DUL, l1a_l1s_com.Scell_info.radio_freq); #endif } #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1S_READ_TX_NB__DUL, l1a_l1s_com.Scell_info.radio_freq); #endif } break; case AUL: /*---------------------------------------------------*/ /* Serving Cell: SACCH up link. */ /*---------------------------------------------------*/ { // Desactivate UL task. if(burst_id == BURST_4) { l1s.task_status[task].current_status = INACTIVE; #if (TRACE_TYPE == 5) // in simulation only the 4th burst is traced trace_fct(CST_L1S_READ_TX_NB__AUL, l1a_l1s_com.Scell_info.radio_freq); #endif } #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1S_READ_TX_NB__AUL, l1a_l1s_com.Scell_info.radio_freq); #endif } break; case TCHA: case TCHTF: /*---------------------------------------------------*/ /* Serving Cell: TCH link. */ /*---------------------------------------------------*/ { #if (TRACE_TYPE==5) if(burst_id == BURST_4) // in simulation only the 4th burst is traced trace_fct(CST_L1S_READ_TX_NB__TCHF, l1a_l1s_com.Scell_info.radio_freq); #endif #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1S_READ_TX_NB__TCHF, l1a_l1s_com.Scell_info.radio_freq); #endif } break; case TCHTH: /*---------------------------------------------------*/ /* Serving Cell: TCH link. */ /*---------------------------------------------------*/ { #if (TRACE_TYPE==5) if(burst_id == BURST_2) // in simulation only lates burst is traced trace_fct(CST_L1S_READ_TX_NB__TCHH, l1a_l1s_com.Scell_info.radio_freq); #endif #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_L1S_READ_TX_NB__TCHH, l1a_l1s_com.Scell_info.radio_freq); #endif } break; } // Set flag used to change the read page at the end of "l1_synch". l1s_dsp_com.dsp_r_page_used = TRUE; } /*-------------------------------------------------------*/ /* l1s_read_dedic_scell_meas() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : */ /*-------------------------------------------------------*/ #if REL99 #if FF_EMR void l1s_read_dedic_scell_meas(UWORD8 input_level, UWORD8 sub_flag, T_EMR_PARAMS *emr_params) { UWORD8 task; UWORD8 burst_id; UWORD8 b_blud; UWORD8 counter; UWORD8 bfi; // band frame indicator UWORD8 channel_mode; // current channel type //OMAPS00090550 UWORD8 fn_report_mod_26; UWORD8 subchannel; // half rate sub channel UWORD8 sid_present; // indication for sid block UWORD16 rx_type; UWORD32 normalised_fn_mod13_mod4; UWORD16 mean_bep_lsb = 0; //l1s_dsp_com.dsp_ndb_ptr->d_mean_bep_block_lsb; UWORD16 mean_bep_msb = 0; //l1s_dsp_com.dsp_ndb_ptr->d_mean_bep_block_msb; UWORD32 mean_bep = 0; //((mean_bep_msb<<WORD_SHIFT)|(mean_bep_lsb)) >> MEAN_BEP_FORMAT; UWORD16 cv_bep = 0; //(l1s_dsp_com.dsp_ndb_ptr->d_cv_bep_block) >> CV_BEP_FORMAT; static WORD16 last_corr_decoded_burst[8] = {0, 0, 0, 0, 0, 0, 0, 0}; static UWORD16 cv_bep_tch4_8f_144[2] = {0, 0}; static UWORD32 mean_bep_tch4_8f_144[2] = {0, 0}; WORD16 rxlev = l1s_encode_rxlev(input_level); if (l1s_dsp_com.dsp_r_page == 1) { cv_bep = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_0[D_CV_BEP]; mean_bep_msb = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_0[D_MEAN_BEP_MSW]; mean_bep_lsb = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_0[D_MEAN_BEP_LSW]; } else { cv_bep = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_1[D_CV_BEP]; mean_bep_msb = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_1[D_MEAN_BEP_MSW]; mean_bep_lsb = l1s_dsp_com.dsp_ndb_ptr->a_mean_cv_bep_page_1[D_MEAN_BEP_LSW]; } mean_bep = ((mean_bep_msb<<WORD_SHIFT)|(mean_bep_lsb)) >> MEAN_BEP_FORMAT; cv_bep = cv_bep >> CV_BEP_FORMAT; // EMR : Copy of Legacy code begins // Measurement must be rejected if channel is hopping, hopped on // the beacon frequency and PWRC is TRUE (see GSM05.08, $8.1.3). if(!((l1a_l1s_com.dedic_set.pwrc == TRUE) && (l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->chan_sel.h == TRUE) && (l1a_l1s_com.dedic_set.radio_freq_dd == l1a_l1s_com.Scell_info.radio_freq))) { // Add to FULL set meas. l1a_l1s_com.Scell_info.meas.nbr_meas++; l1a_l1s_com.Scell_info.meas.acc += rxlev; if(sub_flag == TRUE) { // Add to SUB set meas. l1a_l1s_com.Smeas_dedic.nbr_meas_sub++; l1a_l1s_com.Smeas_dedic.acc_sub += rxlev; } // if(sub_flag == TRUE) // EMR : Copy of Legacy code ends } // if(!((l1a_l1s_com.dedic_set.pwrc == TRUE) && .... // new rxlev is received. remove the oldest rxlev. for(counter=0;counter<=6;counter++) last_corr_decoded_burst[counter] = last_corr_decoded_burst[counter+1]; // store new rxlev. last_corr_decoded_burst[7] = rxlev; task = emr_params->task; burst_id = emr_params->burst_id; channel_mode = emr_params->channel_mode; normalised_fn_mod13_mod4 = emr_params->normalised_fn_mod13_mod4; // TCH FS and TCH EFR if((task == TCHTF) && (l1s.actual_time.fn_mod13_mod4 == 0) && ((channel_mode == TCH_FS_MODE) || (channel_mode == TCH_EFR_MODE) || (channel_mode == SIG_ONLY_MODE))) { if(emr_params->facch_present == TRUE) { // FACCH if(emr_params->facch_fire1 == FALSE) { // FACCH correctly decoded l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; if(channel_mode == SIG_ONLY_MODE) // accumulation of correctly decoded blocks excluding SACCH and SID frames FACCH only for sig only mode l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } // if(facch_fire1 == FALSE) } // if(facch_present == TRUE ) else { // NOT FACCH, if (emr_params->a_dd_0_blud == TRUE) { if (emr_params->a_dd_0_bfi == FALSE) { // speech correctly decoded l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; if (emr_params->sid_present_sub0 == FALSE) { // accumulation of correctly decoded blocks excluding SACCH FACCH and SID frames l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } // if(sid_present == FALSE) } // if(bfi == FALSE) } // if(b_blud == TRUE) } // else part of if(facch_present == TRUE ) } // TCH FS and TCH EFR // TCH 2.4F if((task == TCHTF) && (l1s.actual_time.fn_mod13_mod4 == 0) && (channel_mode == TCH_24F_MODE)) { if(emr_params->facch_present == TRUE) { if(emr_params->facch_fire1 == FALSE) { // FACCH correctly decoded l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; } } // if(facch_present == TRUE) else { // NOT FACCH check whether the data buffer is updated!! if(emr_params->a_dd_0_blud == TRUE) { // Check if transparent data or not if(emr_params->b_ce == TRUE)// Non Transparent { //check if correctly decoded or not if(emr_params->a_ntd == FALSE)//good frame detected { l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; // accumulation of correctly decoded blocks excluding SACCH FACCH frames l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } // if(a_ntd == FALSE) } // if(b_ce == TRUE) else { // 2.4F transperent data (always considered as correctly decoded) l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; // accumulation of decoded blocks excluding SACCH FACCH and SID frames l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } // if(b_ce == TRUE) } // if(b_blud == TRUE) } // else part of if(facch_present == TRUE) } // TCH 2.4F // TCH 9.6F if((task == TCHTF) && (l1s.actual_time.fn_mod13_mod4 == 0) && (channel_mode == TCH_96_MODE)) { if(emr_params->facch_present == TRUE) { if(emr_params->facch_fire1 == FALSE) { // FACCH correctly decoded l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; } //if(fire1 == FALSE) } //if(facch_present == TRUE) } // if(fn_mod13_mod4 == 0) if((task == TCHTF) && (l1s.actual_time.fn_mod13_mod4 == 2) && (channel_mode == TCH_96_MODE)) { if(emr_params->a_dd_0_blud == TRUE) { // Check if transparent data or not if(emr_params->b_ce == TRUE)// Non Transparent { //check if correctly decoded or not if(emr_params->a_ntd == FALSE)//good frame detected { l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; // accumulation of correctly decoded blocks excluding SACCH FACCH frames l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } // if(a_ntd == FALSE) } // if(b_ce == TRUE) else { // transparent data (always correctly decoded) l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; // accumulation of decoded blocks excluding SACCH FACCH frames l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } // transparent data } // if(b_blud == TRUE) } // TCH F9.6 // TCH 4.8F/14.4F if((task == TCHTF) && (l1s.actual_time.fn_mod13_mod4 == 0) && ((channel_mode == TCH_48F_MODE) || (channel_mode == TCH_144_MODE)) ) { if(emr_params->facch_present == TRUE) { if(emr_params->facch_fire1 == FALSE) { // FACCH correctly decoded l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4;// 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; } //if(fire1 == FALSE) } //if(facch_present == TRUE) } // if(fn_mod13_mod4 == 0) if((task == TCHTF) && (l1s.actual_time.fn_mod13_mod4 == 2) && ((channel_mode == TCH_48F_MODE) || (channel_mode == TCH_144_MODE)) ) { // block end add new value of mean_bep and cv_bep value to mean_bep_tch4_8f_144 and // cv_bep_tch4_8f_144. remove the oldest value. mean_bep_tch4_8f_144[0] = mean_bep_tch4_8f_144[1]; cv_bep_tch4_8f_144[0] = cv_bep_tch4_8f_144[1]; mean_bep_tch4_8f_144[1] = mean_bep; cv_bep_tch4_8f_144[1] = cv_bep; if ( ((emr_params->a_dd_0_blud == TRUE) && (emr_params->b_m1) && (channel_mode == TCH_144_MODE)) || ((emr_params->a_dd_0_blud == TRUE) && (emr_params->b_f48blk_dl) && (channel_mode == TCH_48F_MODE)) ) { // Check if transparent data or not if(emr_params->b_ce == TRUE) // Non transparent { //check if correctly decoded or not. Accumulate last 8 slots if(emr_params->a_ntd == FALSE) //good frame detected { // two blocks are accumulated at a time, increment by 2. l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas+=8; // 8 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep_tch4_8f_144[0] + mean_bep_tch4_8f_144[1]; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep_tch4_8f_144[0] + cv_bep_tch4_8f_144[1]; // two blocks are accumulated at a time, increment by 2. l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num += 2; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num+=2; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[0] + last_corr_decoded_burst[1] + last_corr_decoded_burst[2] + last_corr_decoded_burst[3] + last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; // accumulation of correctly decoded blocks excluding SACCH FACCH frames l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks +=2; } // if(a_ntd == FALSE) } // if(b_ce == TRUE) else { // transparent data l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=8; // 8 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep_tch4_8f_144[0] + mean_bep_tch4_8f_144[1]; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep_tch4_8f_144[0] + cv_bep_tch4_8f_144[1]; // two blocks are accumulated at a time, increment by 2. l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num+=2; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num += 2; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[0] + last_corr_decoded_burst[1] + last_corr_decoded_burst[2] + last_corr_decoded_burst[3] + last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; // accumulation of correctly decoded blocks excluding SACCH FACCH frames l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks +=2; } // Transparent data } // if(b_blud == TRUE) } // TCH 4.8F/14.4 // TCH HS if((task == TCHTH) && ((channel_mode == TCH_HS_MODE)||(channel_mode == SIG_ONLY_MODE))&& (normalised_fn_mod13_mod4 == 3) ) { UWORD8 norm_fn_mod26; subchannel = emr_params->subchannel; norm_fn_mod26 = ((l1s.actual_time.fn - subchannel + 26) % 26); if(subchannel == 0) { b_blud = emr_params->a_dd_0_blud; bfi = emr_params->a_dd_0_bfi; // 3rd bit tells the BAD frame. sid_present = emr_params->sid_present_sub0; // find out whether sid1 is 0/1, 1 mean } else { b_blud = emr_params->a_dd_1_blud; bfi = emr_params->a_dd_1_bfi; // 3rd bit tells the BAD frame. sid_present = emr_params->sid_present_sub1; // find out whether sid1 is 0/1, 1 mean } if(norm_fn_mod26 == 7 || norm_fn_mod26 == 16|| norm_fn_mod26 == 24 ) { // FACCH: Check A_FD information block. if(emr_params->facch_present == TRUE) { // FACCH correctly decoded if(emr_params->facch_fire1 == FALSE) { // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated if((channel_mode == SIG_ONLY_MODE)) // accumulation of correctly decoded blocks excluding SACCH // and SID frames FACCH only for sig only mode l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } //if(fire1 == FALSE) } //if(facch_present ==....) else { // No Facch at this positions 7,16,24 if (b_blud == TRUE) { if(bfi == FALSE) { l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[7] + last_corr_decoded_burst[6] + last_corr_decoded_burst[5] + last_corr_decoded_burst[4] ; //as per standard 05.08 section 8.3 //sid_present can become true only at (fn modulo 26) == 6 //sid_present will be false at all other points if(sid_present == FALSE) // accumulation of correctly decoded blocks excluding SACCH // FACCH and SID frames l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } // if(bfi == FALSE) } // if (b_blud == TRUE) } // else facch_present } //if(norm_fn_report_mod26 == 7 || norm_fn_report_mod26 == 16|| norm_fn_report_mod26 == 24 ) else { //norm_fn_report_mod26 == 3 || norm_fn_report_mod26 == 11|| norm_fn_report_mod26 == 20 if (b_blud == TRUE) { if(bfi == FALSE) { l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[7] + last_corr_decoded_burst[6] + last_corr_decoded_burst[5] + last_corr_decoded_burst[4] ; //as per standard 05.08 section 8.3 //sid_present can become true only at (fn modulo 26) == 6 //sid_present will be false at all other points if(sid_present == FALSE) // accumulation of correctly decoded blocks excluding SACCH // FACCH and SID frames l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } //if(bfi == FALSE) } // if (b_blud == TRUE) } //else }//task == TCHTH..... // SACCH of TCH if((task == TCHA)) { //unconditionnal accumulation of rxlev_val l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas++; l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += rxlev; if(l1s.actual_time.fn_in_report == 91) { // Set detection flag. if(emr_params->a_cd_fire1 == FALSE) { // rec 05.08 8.2.3: BEP value need to be accumulated on correctly received blocks // rec 05.08 8.4.8.2 : for SACCH of TCH, no accumulation for CV_BEP and nbr_rcvd_blocks l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; } // if(fire1 == FALSE) } // if(l1s.actual_time.fn_in_report == 91) } // // SACCH of TCH // SDCCH and SACCH of SDCCH if (((task == DDL) || (task == ADL)) && (burst_id == BURST_4)) { //unconditional accumulation of Rxlev_val l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; // rec 05.08 8.2.3: in SDCCH, BEP value need to be accumulated on correctly received blocks if(emr_params->a_cd_fire1 == FALSE) { l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; } } // SDCCH //AMR FS #if (AMR == 1) if((task == TCHTF) && (channel_mode == TCH_AFS_MODE) && (l1s.actual_time.fn_mod13_mod4 == 0)) { if(emr_params->amr_facch_present == TRUE) { // FACCH present // FACCH correctly decoded ? if(emr_params->amr_facch_fire1 == FALSE) { l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; } // if(fire1 == FALSE) } // if(facch_present == TRUE) else { // NOT FACCH if ((emr_params->b_ratscch_blud == TRUE) && (emr_params->ratscch_rxtype == RATSCCH_GOOD)) { //RATSCCH correctly decoded l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; } // if(b_ratscch_blud == TRUE) else if(emr_params->a_dd_0_blud == TRUE) { // Good speech frame. if((emr_params->amr_rx_type_sub0 == SPEECH_GOOD) || (emr_params->amr_rx_type_sub0 == SPEECH_DEGRADED) || (emr_params->amr_rx_type_sub0 == SID_UPDATE)) { l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc += mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc += cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; if ((emr_params->amr_rx_type_sub0 == SPEECH_GOOD) || (emr_params->amr_rx_type_sub0 == SPEECH_DEGRADED)) //Number of correctly decoded blocks excluding SACCH FACCH RATSCCH and SID frames. l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } // if((rx_type == SPEECH_GOOD) || (rx_type == SID_UPDATE)) } // else if(b_blud == TRUE) } // else of if(facch_present == TRUE) } //AMR FS //AMR HS //TCH AHS if((task == TCHTH) && (channel_mode == TCH_AHS_MODE)&& (normalised_fn_mod13_mod4 == 3)) { UWORD8 norm_fn_mod26; subchannel = emr_params->subchannel; if (subchannel == 0) { // Load the bit to check if the block is valid b_blud = emr_params->a_dd_0_blud; rx_type = emr_params->amr_rx_type_sub0; } else // subchannel 1 { // Load the bit to check if the block is valid b_blud = emr_params->a_dd_1_blud; rx_type = emr_params->amr_rx_type_sub1; } norm_fn_mod26 = (l1s.actual_time.fn - subchannel +26) % 26; if(norm_fn_mod26 == 7 || norm_fn_mod26 == 16|| norm_fn_mod26 == 24 ) { // FACCH: Check A_FD information block. if(emr_params->amr_facch_present == TRUE) { // FACCH present // FACCH correctly decoded ? if(emr_params->amr_facch_fire1 == FALSE) { l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc +=mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc +=cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc += last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; } // if(fire1 == FALSE) } // if(facch_present == TRUE) else { // NOT FACCH // Load the bit to check if the block is a RATSCCH in caseof rx_type = NO_DATA //In half rate, there are 2 consecutive frames called RATSCCH_MARKER and //RATSCCH_DATA, MARKER doesn't contain any CRC. So we cannot make a decision //whether RATSCCH_MARKER is correctly decoded. Hence ratscch_rxtype_prev //is not valid. Hence the inner check has to be based only on ratscch_rxtype. //ratscch_rxtype is updated based on the CRC of RATSCCH_DATA. //The following are the decisions on the outer check "if (b_ratscch_blud == TRUE).... //b_ratscch_blud is updated based on RATSCCH_DATA. Hence it is a valid check //b_ratscch_blud_prev would have been accumulated based on RATSCCH_MARKER. //The assumption here is that when RATSCCH_MARKER is detected, the b_blud bit of //a_ratscch_dl will be updated. if ( ((emr_params->b_ratscch_blud == TRUE) && (emr_params->ratscch_rxtype == RATSCCH_GOOD)) || ((b_blud==TRUE) && (rx_type == SID_UPDATE)) || ((b_blud == TRUE)&&(rx_type == SPEECH_DEGRADED)) || ((b_blud == TRUE)&&(rx_type == SPEECH_GOOD)) ) { //RATSCCH or SID Update or Speech block correctly decoded, increment the counter l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc +=mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc +=cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc +=last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; if (((rx_type == SPEECH_GOOD) || (rx_type == SPEECH_DEGRADED)) && (emr_params->ratscch_rxtype != RATSCCH_GOOD)) l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } } // else part of if(facch_present == TRUE) }//fnmod26 == 7||16 || 24 else { //if (norm_fn_mod26 ==3 || norm_fn_mod26 == 11 || //norm_fn_mod26 == 20) if ( ((emr_params->b_ratscch_blud == TRUE) && (emr_params->ratscch_rxtype == RATSCCH_GOOD)) || ((b_blud==TRUE) && (rx_type == SID_UPDATE)) || ((b_blud == TRUE)&&(rx_type == SPEECH_DEGRADED)) || ((b_blud == TRUE)&&(rx_type == SPEECH_GOOD)) ) { //RATSCCH or SID Update or Speech block correctly decoded, increment the counter l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas +=4; // 4 bursts are accumulated // Accumulate BEP l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc +=mean_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc +=cv_bep; l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num++; l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num++; //accumulation of the correctly decoded block l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc +=last_corr_decoded_burst[4] + last_corr_decoded_burst[5] + last_corr_decoded_burst[6] + last_corr_decoded_burst[7]; if (((rx_type == SPEECH_GOOD) || (rx_type == SPEECH_DEGRADED)) && (emr_params->ratscch_rxtype != RATSCCH_GOOD)) l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks++; } } //else fn = 3,11,20 }//task == TCHTH..... #endif //(AMR == 1) } #endif //FF_EMR #else //REL99 void l1s_read_dedic_scell_meas(UWORD8 input_level, UWORD8 sub_flag) { WORD16 rxlev = l1s_encode_rxlev(input_level); // Measurement must be rejected if channel is hopping, hopped on // the beacon frequency and PWRC is TRUE (see GSM05.08, $8.1.3). if(!((l1a_l1s_com.dedic_set.pwrc == TRUE) && (l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->chan_sel.h == TRUE) && (l1a_l1s_com.dedic_set.radio_freq_dd == l1a_l1s_com.Scell_info.radio_freq))) { // Add to FULL set meas. l1a_l1s_com.Scell_info.meas.nbr_meas++; l1a_l1s_com.Scell_info.meas.acc += rxlev; if(sub_flag == TRUE) { // Add to SUB set meas. l1a_l1s_com.Smeas_dedic.nbr_meas_sub++; l1a_l1s_com.Smeas_dedic.acc_sub += rxlev; } } } #endif //REL99 /*-------------------------------------------------------*/ /* l1s_dedic_reporting() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : */ /*-------------------------------------------------------*/ void l1s_dedic_reporting() { xSignalHeaderRec *msg; UWORD8 i; UWORD32 nbr_carrier = l1a_l1s_com.ba_list.nbr_carrier; // Allocate L1C_MEAS_DONE message... msg = os_alloc_sig(sizeof(T_MPHC_MEAS_REPORT)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = L1C_MEAS_DONE; // Fill miscelaneous parameters //============================= ((T_MPHC_MEAS_REPORT*)(msg->SigP))->ba_id = l1a_l1s_com.ba_list.ba_id; //timing_advance... //txpwr... //meas_valid... // Fill msg for Neighbor Cells //============================ for(i=0;i<nbr_carrier;i++) { T_MEAS_INFO *ba_ptr = &l1a_l1s_com.ba_list.A[i]; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->ncell_meas.A[i].bcch_freq = ba_ptr->radio_freq; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->ncell_meas.A[i].rxlev_acc = ba_ptr->acc; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->ncell_meas.A[i].rxlev_nbr_meas = ba_ptr->nbr_meas; // Reset BA. ba_ptr->acc = 0; ba_ptr->nbr_meas = 0; } ((T_MPHC_MEAS_REPORT*)(msg->SigP))->no_of_ncell_meas = nbr_carrier; // Fill msg for Serving Cell //========================== ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_full_acc = l1a_l1s_com.Scell_info.meas.acc; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_full_nbr_meas = l1a_l1s_com.Scell_info.meas.nbr_meas; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_sub_acc = l1a_l1s_com.Smeas_dedic.acc_sub; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_sub_nbr_meas = l1a_l1s_com.Smeas_dedic.nbr_meas_sub; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxqual_full_acc_errors = l1a_l1s_com.Smeas_dedic.qual_acc_full; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxqual_full_nbr_bits = l1a_l1s_com.Smeas_dedic.qual_nbr_meas_full; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxqual_sub_acc_errors = l1a_l1s_com.Smeas_dedic.qual_acc_sub; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxqual_sub_nbr_bits = l1a_l1s_com.Smeas_dedic.qual_nbr_meas_sub; #if REL99 #if FF_EMR ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_val_acc = l1a_l1s_com.Smeas_dedic_emr.rxlev_val_acc; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->rxlev_val_nbr_meas = l1a_l1s_com.Smeas_dedic_emr.rxlev_val_nbr_meas; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->nbr_rcvd_blocks = l1a_l1s_com.Smeas_dedic_emr.nbr_rcvd_blocks; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->mean_bep_block_acc = l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_acc; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->cv_bep_block_acc = l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_acc; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->mean_bep_block_num = l1a_l1s_com.Smeas_dedic_emr.mean_bep_block_num; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->cv_bep_block_num = l1a_l1s_com.Smeas_dedic_emr.cv_bep_block_num; #endif #endif if(l1a_l1s_com.dedic_set.aset->dtx_allowed == TRUE) // Set "dtx_used" flag according to DSP transmit report result only if // DTX is allowed. { if(l1a_l1s_com.Smeas_dedic.dtx_used > 0) ((T_MPHC_MEAS_REPORT*)(msg->SigP))->dtx_used = TRUE; // Set the dtx_used flag in the case of TCHF/ no signaling else if ((l1a_l1s_com.dedic_set.aset->chan1.mode == SIG_ONLY_MODE) &&(l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type==TCH_F)) ((T_MPHC_MEAS_REPORT*)(msg->SigP))->dtx_used = TRUE; else ((T_MPHC_MEAS_REPORT*)(msg->SigP))->dtx_used = FALSE; } else { ((T_MPHC_MEAS_REPORT*)(msg->SigP))->dtx_used = FALSE; } // Reset Serving Cell measurement variables. l1s_reset_dedic_serving_meas(); // Give miscellaneous info to L3 (just for indication/debug). //=========================================================== ((T_MPHC_MEAS_REPORT*)(msg->SigP))->timing_advance = l1a_l1s_com.dedic_set.aset->timing_advance; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->txpwr_used = l1s.reported_txpwr; #if (TRACE_TYPE==1) || (TRACE_TYPE==4) ((T_MPHC_MEAS_REPORT*)(msg->SigP))->facch_dl_count = trace_info.facch_dl_count; ((T_MPHC_MEAS_REPORT*)(msg->SigP))->facch_ul_count = trace_info.facch_ul_count; #if (FF_REPEATED_DL_FACCH == 1) ((T_MPHC_MEAS_REPORT*)(msg->SigP))->facch_dl_combined_good_count = trace_info.facch_dl_combined_good_count; /* No of good blocks after combining */ ((T_MPHC_MEAS_REPORT*)(msg->SigP))->facch_dl_repetition_block_count = trace_info.facch_dl_repetition_block_count; #endif/* (FF_REPEATED_DL_FACCH == 1) */ trace_info.facch_dl_fail_count_trace = trace_info.facch_dl_fail_count; trace_info.facch_dl_count = 0; trace_info.facch_ul_count = 0; trace_info.facch_dl_fail_count = 0; #if ( FF_REPEATED_DL_FACCH == 1 ) /* Reseting the values */ trace_info.facch_dl_combined_good_count = 0; trace_info.facch_dl_repetition_block_count = 0; #endif/* (FF_REPEATED_DL_FACCH == 1) */ #endif // send L1C_MEAS_DONE message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } #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_fb() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : this function sends L1C_FB_INFO to L1A*/ /*-------------------------------------------------------*/ void l1s_read_fb(UWORD8 task, UWORD32 fb_flag, UWORD32 toa, UWORD32 attempt, UWORD32 pm, UWORD32 angle, UWORD32 snr) { xSignalHeaderRec *msg; WORD32 modif_toa = 0; WORD32 ntdma; UWORD32 fn_offset; // For detail of the here below equation cf. BUG1558 #define MAX_TOA_FOR_SB (D_NSUBB_DEDIC*48)+DL_ABB_DELAY/4-(SB_BURST_DURATION+DL_ABB_DELAY+SB_MARGIN)/4-2 #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dspres(dltsk_trace[task].name); #endif #if (TRACE_TYPE!=0) switch(task) { case FBNEW: trace_fct(CST_L1S_READ_FB, l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq);break; case FB51: trace_fct(CST_L1S_READ_FB51, l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq);break; case FB26: trace_fct(CST_L1S_READ_FB26, l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq);break; default: trace_fct(CST_UNKNOWN_FB, l1a_l1s_com.nsync.list[0].radio_freq);break; } #endif if(fb_flag == TRUE) { switch (task) { case FBNEW: case FB51: // Compute NTDMA & TOA taking into account the 23 bit guard for next SB receive window. { modif_toa = toa - (SB_MARGIN/4); // Rem: unit is "BIT". } break; case FB26: // Compute TOA taking into account the 23 bit guard for next SB receive window // and the time diff. between a the fb search and a normal serving RX slot.. // Rem: TOA cannot be less than "SB_MARGIN/4". { // Saturate TOA to MAX_TOA_FOR_SB since it is the last position compatible with the // SB26 tpu programming. MAX_TOA_FOR_SB + 1 would reject the TCHT/frame0 one frame later due // to an overlap of TPU scenarios. if(toa >= MAX_TOA_FOR_SB) toa = MAX_TOA_FOR_SB; modif_toa = toa + ((l1_config.params.fb26_anchoring_time + PROVISION_TIME - START_RX_FB)/4) - (SB_MARGIN/4); // Rem: unit is "BIT". } break; } // End of switch. if(modif_toa < 0) { modif_toa = (modif_toa + (TPU_CLOCK_RANGE/4)) * 4; // Unit is changed from bit to qbit. ntdma = - 1; } else { ntdma = modif_toa / (TPU_CLOCK_RANGE/4); modif_toa = (modif_toa - ntdma * (TPU_CLOCK_RANGE/4)) * 4; // Unit is changed from bit to qbit. } switch (task) { case FBNEW: // Compute NTDMA & TOA taking into account the 23 bit guard for next SB receive window. { // "fn_offset" loaded with serving frame number corresponding to FB. // Keep a %51 format to prepare SB scheduling. fn_offset = (l1s.actual_time.fn - attempt + ntdma + MAX_FN) % 51; } break; case FB51: // Compute NTDMA & TOA taking into account the 23 bit guard for next SB receive window. { // "fn_offset" loaded with serving frame number corresponding to FB. // Keep a full frame number to allow scheduling of SB, 2 MF51 later. fn_offset = (l1s.actual_time.fn - attempt + ntdma + MAX_FN) % MAX_FN; } break; case FB26: { // "fn_offset" loaded with serving frame number corresponding to CTL(SB26). fn_offset = (l1s.actual_time.fn + 52 - 3) % MAX_FN; if(ntdma == 1) // 2nd frame... l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].sb26_offset = 1; else l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].sb26_offset = 0; } break; } // End of switch. } // End if. // Store TOA and FN offset in neighbor cell structure. l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].time_alignmt = modif_toa; l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].fn_offset = fn_offset; // Create message T_L1C_FB_INFO. msg = os_alloc_sig(sizeof(T_L1C_FB_INFO)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = L1C_FB_INFO; // Fill msg fields. ((T_L1C_FB_INFO *) (msg->SigP))->fb_flag = fb_flag; ((T_L1C_FB_INFO *) (msg->SigP))->ntdma = ntdma; ((T_L1C_FB_INFO *) (msg->SigP))->neigh_id = l1a_l1s_com.nsync.active_fb_id; // Debug info or testmode ((T_L1C_FB_INFO *) (msg->SigP))->pm = pm; ((T_L1C_FB_INFO*)(msg->SigP))->toa = toa; ((T_L1C_FB_INFO*)(msg->SigP))->angle = angle; ((T_L1C_FB_INFO*)(msg->SigP))->snr = snr; ((T_L1C_FB_INFO *) (msg->SigP))->radio_freq = l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_fb_id].radio_freq; os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } //#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_sb() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : this function sends L1C_SB_INFO to L1A*/ /*-------------------------------------------------------*/ void l1s_read_sb(UWORD8 task, UWORD32 flag, API *data, UWORD32 toa, UWORD8 attempt, UWORD32 pm, UWORD32 angle, UWORD32 snr) { xSignalHeaderRec *msg; UWORD8 bsic=0; UWORD32 sb; WORD32 modif_toa = 0; UWORD32 fn_offset = 0; WORD32 time_alignmt = 0; T_NCELL_SINGLE *cell_ptr = NULL; //omaps00090550 NULL; UWORD32 SignalCode=0; UWORD8 fn_delay = 2; // SB result read with 2 frames delay. UWORD8 neigh_id=0; UWORD32 fn; switch(task) { case SB2 : case SB51 : case SB26 : // Get Neighbour cell ptr. cell_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sb_id]; neigh_id = l1a_l1s_com.nsync.active_sb_id; #if (TRACE_TYPE!=0) trace_fct(CST_L1S_READ_SB, cell_ptr->radio_freq); #endif SignalCode = L1C_SB_INFO; if(task == SB26) fn_delay = 3 - l1a_l1s_com.nsync.list[neigh_id].sb26_offset; break; case SBCONF : case SBCNF51 : case SBCNF26 : // Get Neighbour cell ptr. cell_ptr = &l1a_l1s_com.nsync.list[l1a_l1s_com.nsync.active_sbconf_id]; neigh_id = l1a_l1s_com.nsync.active_sbconf_id; #if (TRACE_TYPE!=0) trace_fct(CST_L1S_READ_SBCONF, cell_ptr->radio_freq); #endif SignalCode = L1C_SBCONF_INFO; if(task == SBCNF26) fn_delay = 3 - l1a_l1s_com.nsync.list[neigh_id].sb26_offset; break; } #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dspres(dltsk_trace[task].name); #endif // Compute NTDMA & TOA taking into account the 23 bit guard for next SB receive window. modif_toa = (toa - (SB_MARGIN/4)) * 4; // Rem: unit is "QBIT". // Read SB content,. sb = data[0] & 0xffff | ((data[1] & 0xffff) << 16); if (flag == TRUE) // SB has been found... // We synchronized with a NEIGHBOUR cell. { UWORD32 t1, t2, t3, t3p; // extract BSIC, T1, T2, T3. Compute FN. // bsic contains NCC & BCC (GSM05.02, p9) bsic = (UWORD8) ((sb & 0x000000fc) >> 2); t1 = ((sb & 0x00800000) >> 23 | // t1 low (sb & 0x0000ff00) >> 7 | // t1 midle (sb & 0x00000003) << 9); // t1 high t2 = (sb & 0x007c0000) >> 18; t3p = ((sb & 0x01000000) >> 24 | // t3p low (sb & 0x00030000) >> 15); // t3p high t3 = (10*(t3p) +1); fn = (51 * ((t3 - t2 + 26) % 26) + t3 + (26 * 51 * t1)); // Due to pipeline effect (CTRL.WORK.WORK.READ), sb content is taken into account // "fn_delay" TDMA later: that's why we use "fn + fn_delay..." in the offset computation. // // NEIGHBOUR DOMAIN: // ----------------- // | |<----- 1 TDMA ----->| SB | | // | | |XXXX | | // | | | | | // | | | FN_neighbour(SB) | FN_neighbour(SB)+1 | FN_neighbour(SB)+2 // | | | | | // offset | // + | // BOB | // |<----------->| // MS DOMAIN: | // ---------- | | | | // | CTRL | WORK | WORK | READ | // | | | | | // // offset = FN_neighbour(SB)+ fn_delay - FN_serving(READ). // Bob: fine timing difference between the Neighbour timing and the MS internal timing. // fn_offset = (fn + fn_delay + MAX_FN - l1s.actual_time.fn) % MAX_FN; // "time_alignmt" must be corrected (use "modif_toa" from the SB read). // Check that "time_alignmt" do not become bigger than "TPU_CLOCK_RANGE". // If so, "fn_offset" must be decremented. time_alignmt = cell_ptr->time_alignmt + modif_toa; if(time_alignmt >= TPU_CLOCK_RANGE) { time_alignmt -= TPU_CLOCK_RANGE; // qbp for sim. Normal value is 1250; fn_offset -= 1; // WARNING....to be checked!!!!!! } else if(time_alignmt < 0) { time_alignmt += TPU_CLOCK_RANGE; // qbp for sim. Normal value is 1250; fn_offset += 1; // WARNING....to be checked!!!!!! } } #if L1_RECOVERY if(flag) { // recovery flag is reseted because the system works fine // this check is performed in all modes. l1a_l1s_com.recovery_flag = FALSE; // Reset error flags and counter l1s.recovery.frame_count = 0; } #endif // In all mode send result message to L1 Async. msg = os_alloc_sig(sizeof(T_MPHC_NCELL_SYNC_IND)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = SignalCode; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->sb_flag = flag; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->radio_freq = cell_ptr->radio_freq; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->bsic = bsic; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->fn_offset = fn_offset; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->time_alignmt = time_alignmt; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->neigh_id = neigh_id; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->attempt = attempt; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->pm = pm; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->toa = toa; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->angle = angle; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->snr = snr; #if (L1_EOTD == 1) // In EOTD mode read additional results if (l1a_l1s_com.nsync.eotd_meas_session == TRUE) { UWORD8 i; WORD16 d_eotd_first; WORD16 d_eotd_max; UWORD32 d_eotd_nrj; API *data = &(l1s_dsp_com.dsp_ndb_ptr->a_eotd_crosscor[0]); UWORD32 fn_sb_neigh; d_eotd_first = l1s_dsp_com.dsp_ndb_ptr->d_eotd_first & 0xffff; d_eotd_max = l1s_dsp_com.dsp_ndb_ptr->d_eotd_max & 0xffff; fn_sb_neigh = (l1s.actual_time.fn - fn_delay + MAX_FN) % MAX_FN; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->fn_sb_neigh = fn_sb_neigh; d_eotd_nrj = (l1s_dsp_com.dsp_ndb_ptr->d_eotd_nrj_low & 0xffff) | ((l1s_dsp_com.dsp_ndb_ptr->d_eotd_nrj_high & 0x00ff) << 16); // L1 SW : // CPS Cursor expects the accumulated signal level of the cross // correlation (d_eotd_nrj) to be 16bit format. The DSP reports // it as 24bit format (lsb aligned in a 32bit word). // We scale the DSP result by right shifting by 8, hence preserving // the MSBs d_eotd_nrj >>= 8; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->eotd_data_valid = TRUE; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->d_eotd_first = d_eotd_first; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->d_eotd_max = d_eotd_max; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->d_eotd_nrj = d_eotd_nrj; ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->fn_in_SB = fn; for (i=0; i<18; i++) ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->a_eotd_crosscor[i] = data[i] & 0xffff;; if(task == SBCNF26) { ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->toa_correction = l1a_l1s_com.nsync.eotd_cache_toa_tracking; } else { ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->toa_correction = 0; } } else ((T_MPHC_NCELL_SYNC_IND*)(msg->SigP))->eotd_data_valid = FALSE; #endif os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } //#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_fbsb() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : sends L1C_FBSB_INFO to L1A */ /*-------------------------------------------------------*/ #if ((REL99 == 1) && (FF_BHO == 1)) void l1s_read_fbsb(UWORD8 task, UWORD8 attempt, BOOL fb_flag, BOOL sb_flag, API *data, UWORD32 toa, UWORD32 pm, UWORD32 angle, UWORD32 snr) { xSignalHeaderRec *msg; UWORD8 bsic = 0; UWORD32 fn_offset = 0; UWORD32 time_alignmt = 0; #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dspres(dltsk_trace[task].name); #endif #if (TRACE_TYPE!=0) // trace_fct(CST_L1S_READ_FBSB, l1a_l1s_com.nsync_fbsb.radio_freq); #endif if ((fb_flag == TRUE) && (sb_flag == TRUE)) { UWORD32 toa_qbit, sb, fn, fn2, t1, t2, t3, t3p; UWORD8 ntdma; // Read SB content,. sb = data[0] & 0xffff | ((data[1] & 0xffff) << 16); // extract BSIC, T1, T2, T3. Compute FN. // bsic contains NCC & BCC (GSM05.02, p9) bsic = (UWORD8) ((sb & 0x000000fc) >> 2); t1 = ((sb & 0x00800000) >> 23 | // t1 low (sb & 0x0000ff00) >> 7 | // t1 midle (sb & 0x00000003) << 9); // t1 high t2 = (sb & 0x007c0000) >> 18; t3p = ((sb & 0x01000000) >> 24 | // t3p low (sb & 0x00030000) >> 15); // t3p high t3 = (10*(t3p) +1); fn = (51 * ((t3 - t2 + 26) % 26) + t3 + (26 * 51 * t1)); // _|-----------------------------------|___ : TPU WINDOW // |FB| |SB| // _|---------------->|--------->|->| // toa_fb 1 frame toa_sb // // we also need to take into account the 23 bit guard for SB receive window. toa_qbit = (l1a_l1s_com.nsync_fbsb.fb_toa + toa) * 4 + TPU_CLOCK_RANGE - SB_MARGIN; ntdma = toa_qbit / TPU_CLOCK_RANGE; fn_offset = (fn - l1s.actual_time.fn + attempt - ntdma + (2 * MAX_FN))% MAX_FN; time_alignmt = toa_qbit - (ntdma * TPU_CLOCK_RANGE); } // Create message T_L1C_FBSB_INFO. msg = os_alloc_sig(sizeof(T_L1C_FB_INFO)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = L1C_FBSB_INFO; // Fill msg fields. ((T_L1C_FBSB_INFO *) (msg->SigP))->fb_flag = fb_flag; ((T_L1C_FBSB_INFO *) (msg->SigP))->sb_flag = sb_flag; ((T_L1C_FBSB_INFO *) (msg->SigP))->bsic = bsic; ((T_L1C_FBSB_INFO *) (msg->SigP))->fn_offset = fn_offset; ((T_L1C_FBSB_INFO *) (msg->SigP))->time_alignmt = time_alignmt; ((T_L1C_FBSB_INFO *) (msg->SigP))->pm = pm; ((T_L1C_FBSB_INFO *) (msg->SigP))->toa = toa; ((T_L1C_FBSB_INFO *) (msg->SigP))->angle = angle; ((T_L1C_FBSB_INFO *) (msg->SigP))->snr = snr; os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } #endif // #if ((REL99 == 1) && (FF_BHO == 1)) //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM #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 /*-------------------------------------------------------*/ /* l1s_read_l3frm() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : reads NB data */ /* and formate MPHC_DATA_IND message */ /*-------------------------------------------------------*/ void l1s_read_l3frm(UWORD8 pwr_level, API *info_address, UWORD32 task_rx) { xSignalHeaderRec *msg; UWORD32 i,j; UWORD32 word32; UWORD32 rx_fail_flag; //OMAPS00090550 UWORD32 b_fire0; UWORD32 b_fire1; UWORD8 tc = l1s.actual_time.tc; // Default: tc loaded with current serving TC. UWORD16 radio_freq = l1a_l1s_com.Scell_info.radio_freq; // Default: radio_freq load with serving cell #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dspres(dltsk_trace[task_rx].name); #endif // Allocate result message. #if (GSM_IDLE_RAM == 1) // GPF not modified for GSM_IDLE_RAM -> enable Traffic Controller in L1S if (!READ_TRAFFIC_CONT_STATE) CSMI_TrafficControllerOn(); #endif msg = os_alloc_sig(sizeof(T_MPHC_DATA_IND)); DEBUGMSG(status,NU_ALLOC_ERR) switch(task_rx) { case NP: #if (TRACE_TYPE!=0) trace_fct(CST_L1S_READ_L3FRM__NP, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code and L2 channel. msg->SignalCode = L1C_NP_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_PCH; break; case EP: #if (TRACE_TYPE!=0) trace_fct(CST_L1S_READ_L3FRM__EP, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code and L2 channel. msg->SignalCode = L1C_EP_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_EPCH; break; case NBCCHS: #if (TRACE_TYPE!=0) trace_fct(CST_L1S_READ_L3FRM__NBCCHS, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code and L2 channel. msg->SignalCode = L1C_BCCHS_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_NBCCH; break; case EBCCHS: #if (TRACE_TYPE!=0) trace_fct(CST_L1S_READ_L3FRM__EBCCHS, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code and L2 channel. msg->SignalCode = L1C_BCCHS_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_EBCCH; break; case BCCHN: #if L1_GPRS case BCCHN_TRAN: #endif case BCCHN_TOP: #if (TRACE_TYPE!=0) if (task_rx == BCCHN) trace_fct(CST_L1S_READ_L3FRM__BCCHN, l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_norm].radio_freq); else // BCCHN_TRAN and BCCHN_TOP tasks trace_fct(CST_L1S_READ_L3FRM__BCCHN, l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_top].radio_freq); #endif // Fill msg signal code, L2 channel and get neighbour TC. msg->SignalCode = L1C_BCCHN_INFO; // Save neighbour ID. // With TC and Neighbour ID, L1A can manage the remaining BCCH requests. if (task_rx == BCCHN) { ((T_MPHC_DATA_IND *)(msg->SigP))->neigh_id = l1a_l1s_com.bcchn.active_neigh_id_norm; tc = l1a_l1s_com.bcchn.active_neigh_tc_norm; radio_freq = l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_norm].radio_freq; } else // BCCHN_TRAN and BCCHN_TOP tasks { ((T_MPHC_DATA_IND *)(msg->SigP))->neigh_id = l1a_l1s_com.bcchn.active_neigh_id_top; tc = l1a_l1s_com.bcchn.active_neigh_tc_top; radio_freq = l1a_l1s_com.bcchn.list[l1a_l1s_com.bcchn.active_neigh_id_top].radio_freq; } if(tc >= 8) { // Reading Extended BCCH. tc -= 8; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_EBCCH; } else { // Reading Normal BCCH. ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_NBCCH; } break; case ALLC: #if (TRACE_TYPE!=0) trace_fct(CST_L1S_READ_L3FRM__ALLC, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code, L2 channel and get neighbour TC. msg->SignalCode = L1C_ALLC_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_CCCH; break; case SMSCB: #if (TRACE_TYPE!=0) trace_fct(CST_L1S_READ_L3FRM__CB, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code, L2 channel and get neighbour TC. msg->SignalCode = L1C_CB_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_CBCH; break; #if L1_GPRS case PNP: #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_L3FRM__PNP, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code and L2 channel. msg->SignalCode = L1P_PNP_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PPCH; tc = l1pa_l1ps_com.pbcchs.rel_pos_to_report; break; case PEP: #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_L3FRM__PEP, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code and L2 channel. msg->SignalCode = L1P_PEP_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PEPCH; tc = l1pa_l1ps_com.pbcchs.rel_pos_to_report; break; case PALLC: #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_L3FRM__PALLC, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code and L2 channel. msg->SignalCode = L1P_PALLC_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PCCCH; tc = l1pa_l1ps_com.pbcchs.rel_pos_to_report; break; case PBCCHS: #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_L3FRM__PBCCHS, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code and L2 channel. msg->SignalCode = L1P_PBCCHS_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PBCCH; tc = l1pa_l1ps_com.pbcchs.rel_pos_to_report; break; case PBCCHN_IDLE: case PBCCHN_TRAN: #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_L3FRM__PBCCHN, l1pa_l1ps_com.pbcchn.bcch_carrier); #endif // Fill msg signal code and L2 channel. msg->SignalCode = L1P_PBCCHN_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PBCCH; tc = l1pa_l1ps_com.pbcchn.relative_position; radio_freq = l1pa_l1ps_com.pbcchn.bcch_carrier; break; case SINGLE: #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_L3FRM__SINGLE, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill L2 channel. msg->SignalCode = L1P_PACCH_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_PCHANNEL_PACCH; tc = l1pa_l1ps_com.pbcchs.rel_pos_to_report; break; #endif // WARNING !!! to be removed (for CBCH debugging). default: #if (TRACE_TYPE!=0) trace_fct(CST_L1PS_READ_L3FRM__UNKNOWN, l1a_l1s_com.Scell_info.radio_freq); #endif // Fill msg signal code, L2 channel and get neighbour TC. msg->SignalCode = L1C_CB_INFO; ((T_MPHC_DATA_IND *)(msg->SigP))->l2_channel = L2_CHANNEL_CCCH; } #if L1_GPRS if (l1a_l1s_com.dsp_scheduler_mode == GSM_SCHEDULER) #endif { // Compute detection flag. //OMAPS00090550 b_fire0 = ((info_address[0] & 0xffff) & (1<<B_FIRE0)) >> B_FIRE0; b_fire1 = ((info_address[0] & 0xffff) & (1<<B_FIRE1)) >> B_FIRE1; if(b_fire1 != 1) rx_fail_flag = FALSE; // information block received successfully. else rx_fail_flag = TRUE; // information block reception failled. // Get 23 bytes info. from DSP. for (j=0, i=0; i<11; i++) { word32 = info_address[3 + i]; // Get info word, rem: skip info. header. ((T_MPHC_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x000000ff); ((T_MPHC_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x0000ff00) >> 8; } ((T_MPHC_DATA_IND *)(msg->SigP))->l2_frame.A[22] = (info_address[14] & 0x000000ff); // reset buffers and flags in NDB ... // B_FIRE1 =1, B_FIRE0 =0 , BLUD =0 info_address[0] = (1<<B_FIRE1); } #if L1_GPRS else // GPRS scheduler { // Compute detection flag. rx_fail_flag = ((*info_address & 0x0100) >> 8); // 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++) { // Data downloaded from a_dd_gprs[0][]... word32 = info_address[4 + i]; // Get info word, rem: skip info. header. #if 0 /* FreeCalypso TCS211 reconstruction */ if(j<23) #endif ((T_MPHC_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x000000ff); #if 0 /* FreeCalypso TCS211 reconstruction */ if(j<23) #endif ((T_MPHC_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x0000ff00) >> 8; } // reset buffers and flags in NDB ... // reset CS_TYPE info_address[0] = CS_NONE_TYPE; } #endif // Report detection flag. if((l1s_dsp_com.dsp_db_r_ptr->d_debug & 0xffff ) != (l1s.debug_time & 0xffff )) // in case of COM error the block is false ((T_MPHC_DATA_IND *)(msg->SigP))->error_flag = TRUE; else ((T_MPHC_DATA_IND *)(msg->SigP))->error_flag = rx_fail_flag; // be careful: radio_freq is setted at the beging of the code and may be modified inside the "case" ((T_MPHC_DATA_IND *)(msg->SigP))->radio_freq = radio_freq; // be careful: tc is setted at the beging of the code and may be modified inside the "case" ((T_MPHC_DATA_IND *)(msg->SigP))->tc = tc; // convert in ETSI format and send it back to L3 ((T_MPHC_DATA_IND *)(msg->SigP))->ccch_lev = l1s_encode_rxlev(pwr_level); #if (FF_L1_FAST_DECODING == 1) // Update the fn according to the number of the last decoded burst (2, 3 or 4) in case of fast paging: alignment with a block boudary if(l1a_l1s_com.last_fast_decoding == 0) // fast decoding was not not used ((T_MPHC_DATA_IND *)(msg->SigP))->fn = l1s.actual_time.fn; else // fast decoding done, fn is incremented up to 2 frames (if fast decoding with 2 bursts), 0 if fast decoding with 4 bursts (normal decoding) ((T_MPHC_DATA_IND *)(msg->SigP))->fn = l1s.actual_time.fn + BURST_4 + 1 - l1a_l1s_com.last_fast_decoding; #else ((T_MPHC_DATA_IND *)(msg->SigP))->fn = l1s.actual_time.fn; #endif // send message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #endif /*-------------------------------------------------------*/ /* l1s_read_sacch_dl() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : reads NB data */ /*-------------------------------------------------------*/ void l1s_read_sacch_dl(API *info_address, UWORD32 task_rx) { xSignalHeaderRec *msg; UWORD32 i,j; UWORD32 word32; UWORD32 rx_fail_flag; //OMAPS00090550 UWORD32 b_fire0; UWORD32 b_fire1; #if (FF_REPEATED_SACCH == 1) BOOL b_joint= 0; /* The flag to read the DSP response on combining */ static BOOL prevfail = 0; #endif /* (FF_REPEATED_SACCH == 1) */ // Traces. #if (TRACE_TYPE==5) && FLOWCHART trace_flowchart_dspres(dltsk_trace[task_rx].name); #endif #if (TRACE_TYPE!=0) if(task_rx == ADL) trace_fct(CST_L1S_READ_SACCH_DL__ADL, l1a_l1s_com.dedic_set.radio_freq_dd); if(task_rx == TCHA) trace_fct(CST_L1S_READ_SACCH_DL__TCHA, l1a_l1s_com.dedic_set.radio_freq_dd); #endif #if (((TRACE_TYPE==1) || (TRACE_TYPE==4)) && ((FF_REPEATED_SACCH == 1))) trace_info.repeat_sacch.dl_count ++; /* It is a SACCH downlink block */ #endif // Compute detection flag. //OMAPS00090550 b_fire0 = ((info_address[0] & 0xffff) & (1<<B_FIRE0)) >> B_FIRE0; b_fire1 = ((info_address[0] & 0xffff) & (1<<B_FIRE1)) >> B_FIRE1; if(b_fire1 != 1) rx_fail_flag = FALSE; // information block received successfully. else rx_fail_flag = TRUE; // information block reception failled. #if (FF_REPEATED_SACCH == 1) b_joint = (BOOL)(((info_address[0] & 0xffff) & (1<<B_JOINT)) >> B_JOINT); #endif /* (FF_REPEATED_SACCH == 1) */ // Clear 1st word of header. info_address[0] = 0; #if ((TESTMODE) && ((FF_REPEATED_SACCH == 1)) ) if(l1_config.repeat_sacch_enable != REPEATED_SACCH_ENABLE) { l1s.repeated_sacch.srr = 0; #if (TRACE_TYPE == 1 || TRACE_TYPE == 4) trace_info.repeat_sacch.dl_buffer_empty = TRUE; #endif /* TRACE_TYPE*/ } else { #endif /* ((TESTMODE) && ((FF_REPEATED_SACCH == 1))) */ #if (FF_REPEATED_SACCH == 1) if( (b_joint==TRUE) || (rx_fail_flag==TRUE )) { /* chase combining occurred or the current block was unsuccessfully decoded.*/ l1s.repeated_sacch.srr = 1; } else { l1s.repeated_sacch.srr = 0; // debug } #endif /* (FF_REPEATED_SACCH == 1) */ #if ((TESTMODE) && ((FF_REPEATED_SACCH == 1)) ) } /* end else l1_config.repeat_sacch_enable */ #endif /* ((TESTMODE) && ((FF_REPEATED_SACCH == 1))) */ #if ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH)) trace_info.repeat_sacch.srr = l1s.repeated_sacch.srr; if(b_joint == TRUE && b_fire1!=1) { trace_info.repeat_sacch.dl_combined_good_count ++; if (prevfail == 1) trace_info.repeat_sacch.dl_error_count--; } #endif /* ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH)) */ #if ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH)) trace_info.repeat_sacch.srr = l1s.repeated_sacch.srr; if( rx_fail_flag == TRUE) /* Information reception failed */ { trace_info.repeat_sacch.dl_error_count ++; } #endif /* ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH)) */ #if TESTMODE // Continunous mode: the SAACH data aren't valid. Therefore don't send to L1A. if ((!l1_config.TestMode) || ((l1_config.TestMode) && (l1_config.tmode.rf_params.tmode_continuous == TM_NO_CONTINUOUS))) #endif { // Allocate result message. msg = os_alloc_sig(sizeof(T_PH_DATA_IND)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = L1C_SACCH_INFO; ((T_PH_DATA_IND *)(msg->SigP))->l2_channel_type = L2_CHANNEL_SACCH; // Catch L1 Header if SACCH/DL data block successfully received. if(rx_fail_flag == FALSE) { UWORD8 supplied_txpwr = info_address[3] & 0x0000001f; UWORD8 supplied_ta = (info_address[3] & 0x00007f00) >> 8; #if (FF_REPEATED_SACCH == 1) //Set SRO parameter to transmit to the UL l1s.repeated_sacch.sro = (info_address[3] & 0x00000040) >> 6; /* 7 | 6 | 5 | 4 3 2 1 0 Spare | SRO| FPC EPC | Ordered MS power level | Ordered timing advance */ #endif /* (FF_REPEATED_SACCH == 1) */ // Check max transmit power (min txpwr) according to powerclass. supplied_txpwr = l1a_clip_txpwr(supplied_txpwr,l1a_l1s_com.dedic_set.radio_freq); #if TESTMODE // Update txpwr and ta only during Normal Mode if (!l1_config.TestMode) #endif { l1a_l1s_com.dedic_set.aset->new_target_txpwr = supplied_txpwr; // Check if supplied TA is valid, if not keep previous value. if(supplied_ta < 64) l1a_l1s_com.dedic_set.aset->new_timing_advance = supplied_ta; } #if ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH)) l1s_check_sacch_dl_block(info_address); trace_info.repeat_sacch.sro = l1s.repeated_sacch.sro; #endif /* ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH)) */ } /* end if rx_fail_flag */ else { #if ((TRACE_TYPE==1 || TRACE_TYPE == 4) && (FF_REPEATED_SACCH)) trace_info.repeat_sacch.dl_buffer_empty = TRUE; #endif } // Get 23 bytes info. from DSP. for (j=0, i=0; i<11; i++) { word32 = info_address[3 + i]; // Get info word, rem: skip info. header. ((T_PH_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x000000ff); ((T_PH_DATA_IND *)(msg->SigP))->l2_frame.A[j++] = (word32 & 0x0000ff00) >> 8; } ((T_PH_DATA_IND *)(msg->SigP))->l2_frame.A[22] = (info_address[14] & 0x000000ff); // Fill msg header... ((T_PH_DATA_IND *)(msg->SigP))->rf_chan_num = l1a_l1s_com.Scell_info.radio_freq; ((T_PH_DATA_IND *)(msg->SigP))->error_cause = rx_fail_flag; ((T_PH_DATA_IND *)(msg->SigP))->bsic = l1a_l1s_com.Scell_info.bsic; ((T_PH_DATA_IND *)(msg->SigP))->tc = l1s.actual_time.tc; // send message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) #if (TRACE_TYPE==1) || (TRACE_TYPE==4) trace_info.sacch_d_nerr = info_address[2] & 0x00ff; #endif #if (FF_REPEATED_SACCH == 1) prevfail= rx_fail_flag ; #endif /* (FF_REPEATED_SACCH == 1) */ } } /*-------------------------------------------------------*/ /* l1s_read_dcch_dl() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : reads FACCH DL data block. */ /*-------------------------------------------------------*/ void l1s_read_dcch_dl(API *info_address, UWORD32 task_rx) { UWORD8 rx_valid_flag = FALSE; UWORD8 timing_advance = 255; BOOL b_joint ; /* DSP indicator to Chase Combining */ #if (L1_SAGEM_INTERFACE == 1) UWORD8 channel_type = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type; #endif #if (FF_REPEATED_DL_FACCH == 1) b_joint = (BOOL) (((info_address[0] & 0xffff) & (1<<B_JOINT)) >> B_JOINT); #if TESTMODE if(l1_config.repeat_facch_dl_enable != REPEATED_FACCHDL_ENABLE) /* repeated FACCH mode is disabled */ b_joint = FALSE; #endif /* TESTMODE */ #endif /* (FF_REPEATED_DL_FACCH == 1) */ if(info_address != NULL) // A data block must be passed to L2. { UWORD32 b_fire1; #if (TRACE_TYPE!=0) if(task_rx == DDL) trace_fct(CST_L1S_READ_DCCH_DL__DDL, l1a_l1s_com.dedic_set.radio_freq_dd); if(task_rx == TCHTF) trace_fct(CST_L1S_READ_DCCH_DL__TCHTF, l1a_l1s_com.dedic_set.radio_freq_dd); if(task_rx == TCHTH) trace_fct(CST_L1S_READ_DCCH_DL__TCHTH, l1a_l1s_com.dedic_set.radio_freq_dd); #endif // Set detection flag. b_fire1 = ((info_address[0] & 0xffff) & (1<<B_FIRE1)) >> B_FIRE1; if(b_fire1 != 1) rx_valid_flag = TRUE; // information block received successfully. else rx_valid_flag = FALSE; // information block reception failled. if((rx_valid_flag == TRUE) && (l1a_l1s_com.dedic_set.aset->t3124 != 0)) // T3124 running... // Check for PHYSICAL INFORMATION message from FACCH. { UWORD32 message_type = info_address[5] & 0x00ff; if(message_type == 0x2D) // FACCH message is a PHYSICAL INFORMATION message. { // Catch TIMING ADVANCE information. timing_advance = (UWORD8)((info_address[5] & 0xff00) >> 8); l1a_l1s_com.dedic_set.aset->new_timing_advance = timing_advance; l1a_l1s_com.dedic_set.aset->timing_advance = timing_advance; // Reset T3124. l1a_l1s_com.dedic_set.aset->t3124 = 0; // Stop sending Handover Access burst. l1a_l1s_com.dedic_set.aset->ho_acc_to_send = 0; // Handover access procedure is completed. // -> send L1C_HANDOVER_FINISHED message with "cause = COMPLETED" to L1A. l1s_send_ho_finished(HO_COMPLETE); } } // Clear 1st word of header. info_address[0] = 0; // Shift data block pointer to skip DSP header. info_address = &(info_address[3]); if (rx_valid_flag == TRUE) { #if (TRACE_TYPE==1) || (TRACE_TYPE==4) trace_info.facch_dl_count ++; #endif #if (FF_REPEATED_DL_FACCH == 1) /*Fire code is correct and information recieved successfully */ l1s_store_facch_buffer(l1s.repeated_facch, info_address); #endif /* trace for FER calculation (Repeated FACCH mode): */ /* nb of DL FACCH blocks correctly decoded which is not a repetition */ #if ((TRACE_TYPE==1|| TRACE_TYPE==4) && (FF_REPEATED_DL_FACCH)) trace_info.facch_dl_good_block_reported++; if(b_joint == TRUE) /* The combined block is successfully decoded */ trace_info.facch_dl_combined_good_count++; #endif /* ((TRACE_TYPE==1|| TRACE_TYPE==4) && (FF_REPEATED_DL_FACCH)) */ #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1) Trace_dedic_tch_block_stat(FACCH_GOOD, l1s_dsp_com.dsp_ndb_ptr->a_fd[2], 0); #endif } else { #if (TRACE_TYPE==1) || (TRACE_TYPE==4) trace_info.facch_dl_fail_count ++; #endif #if (DEBUG_DEDIC_TCH_BLOCK_STAT == 1) Trace_dedic_tch_block_stat(FACCH_BAD, l1s_dsp_com.dsp_ndb_ptr->a_fd[2], 0); #endif } } #if (FF_REPEATED_DL_FACCH == 1) if(rx_valid_flag == FALSE) { l1s.repeated_facch.pipeline[l1s.repeated_facch.counter_candidate].buffer_empty=TRUE; } #endif /* (FF_REPEATED_DL_FACCH == 1) */ #if (TRACE_TYPE==1) || (TRACE_TYPE==4) RTTL1_FILL_DL_DCCH(rx_valid_flag, timing_advance) #endif // Pass data block to L2. #if (SEND_FN_TO_L2_IN_DCCH==1) #if (L1_SAGEM_INTERFACE == 1) dll_dcch_downlink(info_address, rx_valid_flag, l1s.actual_time.fn, channel_type); #else dll_dcch_downlink(info_address, rx_valid_flag, l1s.actual_time.fn); #endif #else #if (L1_SAGEM_INTERFACE == 1) dll_dcch_downlink(info_address, rx_valid_flag, channel_type); #else dll_dcch_downlink(info_address, rx_valid_flag); #endif #endif } #if (CHIPSET==15) /*-------------------------------------------------------*/ /* l1s_reset_tx_ptr() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : Reset the TX data pointer for DRP */ /* after ABORT */ /*-------------------------------------------------------*/ #define L1_DRP_TX_PTR_RESET_SET (0x00000020) #define L1_DRP_TX_PTR_RESET_RESET (~(L1_DRP_TX_PTR_RESET_SET)) void l1s_reset_tx_ptr(UWORD8 param1, UWORD8 param2) { volatile UWORD32 *ptr_drp_init32; ptr_drp_init32 = (UWORD32 *) (DRP_API_BASE_ADDRESS + DRP_REG_SRM_CW_ADDR); //0xFFFF1E00; // Set the TX_PTR_RESET bit to 1 to reset TX RD and WR pointers (*ptr_drp_init32) = (*ptr_drp_init32)|(L1_DRP_TX_PTR_RESET_SET); // Reset the bit to zero as aslong as the bit is 1, pointers are in reset state (*ptr_drp_init32) = (*ptr_drp_init32)&(L1_DRP_TX_PTR_RESET_RESET); } #endif