FreeCalypso > hg > tcs211-l1-reconst
view chipsetsw/layer1/cfile/l1_sync.c @ 315:27a933036b4f
l1p_ctl.c: l1pctl_dpcmb_agc_read() reconstructed
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 04 Oct 2017 04:03:00 +0000 |
parents | 9113e3ab9911 |
children |
line wrap: on
line source
/************* Revision Controle System Header ************* * GSM Layer 1 software * L1_SYNC.C * * Filename l1_sync.c * Copyright 2003 (C) Texas Instruments * ************* Revision Controle System Header *************/ //#pragma DUPLICATE_FOR_INTERNAL_RAM_START #include "l1_macro.h" #include "l1_confg.h" //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #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 #define L1_SYNC_C //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #endif //#pragma DUPLICATE_FOR_INTERNAL_RAM_START #if (CODE_VERSION == SIMULATION) #include "nucleus.h" #include <string.h> #if (AUDIO_TASK == 1) #include "l1audio_const.h" #include "l1audio_cust.h" #include "l1audio_defty.h" #if (L1_VOCODER_IF_CHANGE == 1) #include "l1audio_signa.h" #endif // L1_VOCODER_IF_CHANGE == 1 #endif // AUDIO_TASK #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 // TESTMODE #if (L1_GTT == 1) #include "l1gtt_const.h" #include "l1gtt_defty.h" #endif #if (L1_MP3 == 1) #include "l1mp3_defty.h" #endif #if (L1_MIDI == 1) #include "l1midi_defty.h" #endif #include "l1_defty.h" #include "cust_os.h" #include "l1_msgty.h" #include "l1_varex.h" #include "l1_proto.h" #include "l1_mftab.h" #include "l1_tabs.h" #include "ulpd.h" #if L2_L3_SIMUL #include "hw_debug.h" #endif // L2_L3 SIMUL #if L1_GPRS #include "l1p_cons.h" #include "l1p_msgt.h" #include "l1p_deft.h" #include "l1p_vare.h" #include "l1p_mfta.h" #include "l1p_tabs.h" #include "l1p_macr.h" #include "l1p_sign.h" #endif // L1_GPRS #include <stdio.h> #include "sim_cfg.h" #include "sim_cons.h" #include "sim_def.h" #include "sim_var.h" extern NU_TASK L1S_task; #if (FF_L1_IT_DSP_USF == 1) || (FF_L1_IT_DSP_DTX == 1) extern NU_TASK API_MODEM_task; #endif #else // NO SIMULATION #include <string.h> #include "l1_types.h" #include "sys_types.h" #include "l1_const.h" #include "l1_time.h" #include "l1_signa.h" #if TESTMODE #include "l1tm_defty.h" #endif // TESTMODE #if (AUDIO_TASK == 1) #include "l1audio_const.h" #include "l1audio_cust.h" #include "l1audio_defty.h" #if (L1_VOCODER_IF_CHANGE == 1) #include "l1audio_signa.h" #endif // L1_VOCODER_IF_CHANGE == 1 #endif // AUDIO_TASK #if (L1_GTT == 1) #include "l1gtt_const.h" #include "l1gtt_defty.h" #endif #if (L1_MP3 == 1) #include "l1mp3_defty.h" #endif #if (L1_MIDI == 1) #include "l1midi_defty.h" #endif #include "l1_defty.h" #include "cust_os.h" #include "l1_msgty.h" #include "l1_varex.h" #include "l1_proto.h" #include "l1_mftab.h" #include "l1_tabs.h" #include "tpudrv.h" #include "l1_trace.h" #if L2_L3_SIMUL #include "hw_debug.h" #endif // L2_L3 SIMUL #include "ulpd.h" #include "mem.h" #include "inth.h" #include "iq.h" #if L1_GPRS #include "l1p_cons.h" #include "l1p_msgt.h" #include "l1p_deft.h" #include "l1p_vare.h" #include "l1p_mfta.h" #include "l1p_tabs.h" #include "l1p_macr.h" #include "l1p_sign.h" #endif // L1_GPRS #endif // NO SIMULATION #if(RF_FAM == 61) #include "l1_rf61.h" #endif #define W_A_DSP_PR20037 1 /* FreeCalypso */ #if (GSM_IDLE_RAM != 0) #if (OP_L1_STANDALONE == 1) #include "csmi_simul.h" #else #include "csmi/sleep.h" #endif #endif #if (CHIPSET >= 12) #include "sys_conf.h" #endif #if (OP_L1_STANDALONE != 1) && (WCP_PROF == 1) #include "prf/prf_api.h" #endif #if 0 /* FreeCalypso TCS211 reconstruction */ //Enhanced RSSI -OMAPS00075410 #define TOTAL_NO_OF_BITS_IDLE_MEAS 625 extern UWORD32 qual_acc_idle1[2]; #endif #if (RF_FAM == 61) #include "tpudrv61.h" #endif #if W_A_DSP1 UWORD8 old_sacch_DSP_bug = FALSE; #endif #if (TRACE_TYPE == 6) #define TIMER_RESET_VALUE (0xFFFF) #define TICKS_PER_TDMA (2144) #endif #if (TRACE_TYPE == 2) || (TRACE_TYPE == 3) extern void L1_trace_string(char *s); extern void L1_trace_char (char s); #endif #if (TRACE_TYPE == 4) #define TIMER_RESET_VALUE (0xFFFF) #endif #if (L1_GTT == 1) /**************************************/ /* External GTT prototypes */ /**************************************/ extern void l1s_gtt_manager (void); #endif #if(L1_DYN_DSP_DWNLD == 1) extern void l1s_dyn_dwnld_manager(void); #endif #if (AUDIO_TASK == 1) /**************************************/ /* External audio prototypes */ /**************************************/ extern void l1s_audio_manager (void); #endif /*-------------------------------------------------------*/ /* Prototypes of external functions used in this file. */ /*-------------------------------------------------------*/ void l1ddsp_meas_read (UWORD8 nbmeas, UWORD8 *pm); #if L1_GPRS void l1ps_transfer_mode_manager (void); void l1ps_reset_db_mcu_to_dsp (T_DB_MCU_TO_DSP_GPRS *page_ptr); void l1pddsp_meas_ctrl (UWORD8 nbmeas, UWORD8 pm_pos); void l1pddsp_meas_read (UWORD8 nbmeas, UWORD8 *pm_read); void l1ps_meas_manager (void); void l1ps_transfer_meas_manager (void); void l1ps_macs_rlc_downlink_call (void); #endif #if (TRACE_TYPE==7) // CPU_LOAD extern void l1_cpu_load_start(void); extern void l1_cpu_load_stop(void); extern void l1_cpu_load_interm(void); #endif //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #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 (CODE_VERSION==SIMULATION) // for verification of the suspend procedure STATUS status; /*-------------------------------------------------------*/ /* frit_task() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function simulates the TPU scheduling task, the */ /* BTS behavior and shedules the l1 IT (for the L1S).This*/ /* task as the same priority (10) as the L2, L3, L1a */ /* tasks. This function calls the main function of the */ /* simulator "sim_main()" */ /*-------------------------------------------------------*/ void frit_task(UWORD32 argc, void *argv) { while(1) { sim_main(); os_NU_Relinquish(); // give back hand to OS... } } /*-------------------------------------------------------*/ /* l1s_task() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function simulates the L1S task. This task is */ /* called by the main task (frit task). The L1S task has */ /* the highest priority (5) under nucleus and calls the */ /* "sim_l1_int()" function. This task can suspend itsef */ /* in case of deep/big sleep simulation */ /*-------------------------------------------------------*/ void l1s_task(UWORD32 argc, void *argv) { while(1) { sim_l1_int(); status = NU_Suspend_Task(&L1S_task); // check status value... if (status) { #if (TRACE_TYPE==5) printf("Error somewhere in the L1S suspend task \n"); #endif EXIT; } } } #if (FF_L1_IT_DSP_USF == 1) || (FF_L1_IT_DSP_DTX == 1) /*-------------------------------------------------------*/ /* api_modem_task() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function simulates the USF/DTX IT. This task is */ /* called by the main task (frit task). It task has */ /* the same priority as L1S under nucleus and calls the */ /* "sim_api_modem_int()" function. */ /*-------------------------------------------------------*/ void api_modem_task(UWORD32 argc, void *argv) { while(1) { extern void sim_api_modem_int(void); sim_api_modem_int(); status = NU_Suspend_Task(&API_MODEM_task); // check status value... if (status) { #if (TRACE_TYPE==5) printf("Error somewhere in the API MODEM suspend task \n"); #endif EXIT; } } } #endif #else // SIMULATION /*-------------------------------------------------------*/ /* hisr() High Interrupt service routine */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is the ISR corresponding to the frame */ /* interrupt coming from the TPU every TDMA frame. It */ /* activates the Layer 1 synchronous part "l1s_synch()". */ /* */ /*-------------------------------------------------------*/ extern unsigned short layer_1_sync_end_time; void hisr(void) { /* * FreeCalypso TCS211 reconstruction: the LoCosto version * of this function had a whole bunch of junk here * which we have removed in order to match the TCS211 * binary object. */ // stop the gauging.This function must be called at the // begining of the HISR in order to have the IT_GAUGING // executed before the Deep sleep decision. // GOAL: reduce the wake up time by 1 frame l1s_gauging_task_end(); // check if an IT DSP stills pending => it means a CPU load error in the MCU #if (TRACE_TYPE==1) || (TRACE_TYPE==4) if (TPU_check_IT_DSP()==TRUE) { #if (GSM_IDLE_RAM == 0) l1_trace_IT_DSP_error(); #else l1_trace_IT_DSP_error_intram(); #endif } #endif /******************************************************/ // Synchronous Cpu load measurement */ // Log LISR -> hisr() entry cpu time */ // Start HW timer for hisr() measurement */ /******************************************************/ #if (TRACE_TYPE==7) // CPU_LOAD l1_cpu_load_interm(); l1_cpu_load_start(); #endif if ((l1_config.pwr_mngt == PWR_MNGT) && (l1s.pw_mgr.frame_adjust)) { /******************************************************/ // 1 Frame Adjust. after unscheduled wake-up */ /******************************************************/ l1s_wakeup_adjust(); } else { // increment time counter used for debug and by L3 scenario... l1s.debug_time ++; /***************************************************/ /* Frame counters management. */ /***************************************************/ // Time... // "Actual time" loaded with previous "next time". #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 (GSM_IDLE_RAM != 0) // Decrement counters l1s.gsm_idle_ram_ctl.os_load--; l1s.gsm_idle_ram_ctl.hw_timer--; #endif // Multiframe table... // Increment active frame % mftab size. IncMod(l1s.afrm, 1, MFTAB_SIZE); // Control function counters... // Increment frame count from last AFC update. l1s.afc_frame_count++; // Decrement time to next L1S task. if(l1a_l1s_com.time_to_next_l1s_task > 0 && l1a_l1s_com.time_to_next_l1s_task < MAX_FN) l1a_l1s_com.time_to_next_l1s_task--; } /******************************************************/ /* Call layer 1 synchronous part. */ /******************************************************/ l1s_synch(); /* * The following double invokation of l1s_synch() * is NOT present in the TCS211 version. */ #if 0 if(l1s.pw_mgr.sleep_performed == CLOCK_STOP && (l1s.pw_mgr.wakeup_type == WAKEUP_FOR_L1_TASK || l1s.pw_mgr.wakeup_type == WAKEUP_ASYNCHRONOUS_ULPD_0 || l1s.pw_mgr.wakeup_type == WAKEUP_FOR_OS_TASK || l1s.pw_mgr.wakeup_type == WAKEUP_FOR_HW_TIMER_TASK || l1s.pw_mgr.wakeup_type == WAKEUP_FOR_GAUGING_TASK)) { l1s_synch(); } #endif // Be careful:in case of asynchronous wake-up after sleep // an IT_TDMA may be unmasked and executed just after l1s_sleep_manager(); // In order to avoid issues with the execution of hisr() inside hisr() // do not add code here after !!! #if (TRACE_TYPE == 6) { UWORD16 layer_1_sync_end_time; UWORD8 cpu_load; layer_1_sync_end_time = TIMER_RESET_VALUE - TM_ReadTimer(2); cpu_load = (100 * layer_1_sync_end_time) / TICKS_PER_TDMA; l1_trace_cpu_load(cpu_load); } #endif /* used to be #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) in LoCosto */ #if (TRACE_TYPE == 1) /* TSM30 code has it this way */ // CPU load for TRACE_TYPE == 1 and 4 only if((trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_L1S_CPU_LOAD) && (trace_info.sleep_performed == FALSE)) { Trace_L1S_CPU_load(); #if (WCP_PROF == 1) #define TICKS_PER_TDMA (1875) prf_LogCPULoadL1S((unsigned char)((100 * layer_1_sync_end_time) / TICKS_PER_TDMA)); #endif } trace_info.sleep_performed = FALSE; #endif /******************************************************/ // Synchronous Cpu load measurement */ // Stop HW timer; compute results; output on uart */ // if FN%13 = 11 */ /******************************************************/ #if (TRACE_TYPE==7) // CPU_LOAD l1_cpu_load_stop(); #endif } #endif // NO SIMULATION //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #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_synch() // Description: // This function is the core of L1S. Here is a summary // of the execution: // - Frame counters management. // - Get current communication page pointers. // - RESET internal variables. // - RESET MCU->DSP DB communication page. // - TOA update management. // - L1 task manager, // - Dedicated_mode_manager. // - Task_scheduler. // - Execute_frame. // - Neighbor cells measurement manager. // - End manager. void l1s_synch() { #if (CODE_VERSION==SIMULATION) // increment time counter used for debug and by L3 scenario... l1s.debug_time ++; /***************************************************/ /* Frame counters management. */ /***************************************************/ // Time... #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 // Multiframe table... // Increment active frame % mftab size. IncMod(l1s.afrm, 1, MFTAB_SIZE); // Increment active frame % mftab size. // Control function counters... // Increment frame count from last AFC update. l1s.afc_frame_count++; // this function is called in the HISR and must be call here in Simulation l1s_gauging_task_end(); // Decrement time to next L1S task. if(l1a_l1s_com.time_to_next_l1s_task > 0 && l1a_l1s_com.time_to_next_l1s_task < MAX_FN) l1a_l1s_com.time_to_next_l1s_task--; #endif /* l1s.tcr_prog_done=0; */ #if (FF_L1_FAST_DECODING == 1) /* If a fast decoding IT is expected AND a deferred control is scheduled */ /* then it means that a fast decoding IT is still awaited from previous */ /* TDMA. */ if ( (l1a_apihisr_com.fast_decoding.status == C_FAST_DECODING_AWAITED) && (l1a_apihisr_com.fast_decoding.deferred_control_req == TRUE) ) { l1_trace_IT_DSP_error(IT_DSP_ERROR_FAST_DECODING); } #endif /* #if (FF_L1_FAST_DECODING == 1) */ #if L1_GPRS /* l1s.tcr_prog_done=0; */ // Increment TOA period counter used in packet tranfer mode if (l1a_l1s_com.mode == PACKET_TRANSFER_MODE) { // TOA update period in packet transfer mode = 4*78 frames // At least one block needs to be transmitted by the BTS every 78 frames // Taking into account fading probability at least one good block (4 TOA values) // is input to the TOA algorithm within the TOA update period #if (TOA_ALGO == 2) #else l1s.toa_period_count++; if (l1s.toa_period_count >= 4*78) { l1s.toa_update = TRUE; // set TOA update flag => TOA shift will be updated upon next call to l1ctl_toa } #endif } #endif #if (TOA_ALGO == 2) { #if L1_GPRS if((l1a_l1s_com.mode == I_MODE) || (l1a_l1s_com.mode == CON_EST_MODE1) || (l1a_l1s_com.mode == CON_EST_MODE2) || (l1a_l1s_com.mode == DEDIC_MODE) || (l1a_l1s_com.mode == PACKET_TRANSFER_MODE)) #else if((l1a_l1s_com.mode == I_MODE) || (l1a_l1s_com.mode == CON_EST_MODE1) || (l1a_l1s_com.mode == CON_EST_MODE2) || (l1a_l1s_com.mode == DEDIC_MODE)) #endif { if( (l1s.actual_time.fn >= l1s.toa_var.toa_update_fn) && ((l1s.actual_time.fn - l1s.toa_var.toa_update_fn) < L1_TOA_UPDATE_TIME) ) { // TOA needs to be updated every 'L1_TOA_UPDATE_TIME' frames l1s.toa_var.toa_update_fn = l1s.actual_time.fn + L1_TOA_UPDATE_TIME; if(l1s.toa_var.toa_update_fn >= MAX_FN) { l1s.toa_var.toa_update_fn-= MAX_FN; } // Set TOA idle update = TRUE; l1s.toa_var.toa_update_flag = TRUE; } } else { // TOA needs to be updated every 'L1_TOA_UPDATE_TIME' frames l1s.toa_var.toa_update_fn = l1s.actual_time.fn + L1_TOA_UPDATE_TIME; if(l1s.toa_var.toa_update_fn >= MAX_FN) { l1s.toa_var.toa_update_fn-=MAX_FN; } } } #endif #if (L1_DYN_DSP_DWNLD ==1) #if L1_GPRS if((l1a_l1s_com.l1a_activity_flag == TRUE) || (l1a_l1s_com.time_to_next_l1s_task == 0) || (l1s.frame_count != 0) || (l1s.pw_mgr.gauging_task == ACTIVE) || (l1s_get_next_gauging_in_Packet_Idle()==0) || (l1s.dyn_dwnld_state != 0)) #else if((l1a_l1s_com.l1a_activity_flag == TRUE) || (l1a_l1s_com.time_to_next_l1s_task == 0) || (l1s.frame_count != 0) || (l1s.pw_mgr.gauging_task == ACTIVE) || (l1s.dyn_dwnld_state != 0)) #endif // L1_GPRS #else #if L1_GPRS if((l1a_l1s_com.l1a_activity_flag == TRUE) || (l1a_l1s_com.time_to_next_l1s_task == 0) || (l1s.frame_count != 0) || (l1s.pw_mgr.gauging_task == ACTIVE) || (l1s_get_next_gauging_in_Packet_Idle()==0) ) #else if((l1a_l1s_com.l1a_activity_flag == TRUE) || (l1a_l1s_com.time_to_next_l1s_task == 0) || (l1s.frame_count != 0) || (l1s.pw_mgr.gauging_task == ACTIVE)) #endif // L1_GPRS #endif // L1_DYN_DSP_DWNLD //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // L1A has been executed, or // It's time to execute next task, or // A task is still in the MFTAB, or // a gauging will be performed in Packet Idle mode // ==> execute L1 core. //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% { BOOL l1s_task_allowed = TRUE; /* * FreeCalypso TCS211 reconstruction: the following code * fails to compile because the wakeup_time structure member * is not present in TCS211 headers. Let's try omitting it * so we can get a successful compile and start diffing the * compilation results. */ #if 0 /* This is not required in Locosto after merge of deep-sleep * initialization and control frame */ #if (CHIPSET != 15) // SETUP_AFC_AND_RF+1 frames shall pass since last wakeup // from deep sleep before scheduling any tasks due to RF wakeup. if ((l1_config.pwr_mngt == PWR_MNGT) // PWR management enabled && ((l1s.pw_mgr.mode_authorized == DEEP_SLEEP) || (l1s.pw_mgr.mode_authorized == ALL_SLEEP)) // deep sleep is still authorized && (l1s.pw_mgr.sleep_performed == CLOCK_STOP) // previous sleep was deep sleep && (((l1s.actual_time.fn_mod42432 - l1s.pw_mgr.wakeup_time + 42432) % 42432) <= l1_config.params.setup_afc_and_rf) #if L1_GPRS && (l1a_l1s_com.mode != DEDIC_MODE) && (l1a_l1s_com.mode != PACKET_TRANSFER_MODE)) //check that board is not in dedicated or transfer #else && (l1a_l1s_com.mode != DEDIC_MODE) ) //check that board is not in dedicated #endif { l1s_task_allowed = FALSE; } else { l1s.pw_mgr.sleep_performed = DO_NOT_SLEEP; // In case l1s is executed, initialize sleep performed in order to avoid reentry in part above 42432 frames later l1s_task_allowed = TRUE; } #else l1s.pw_mgr.sleep_performed = DO_NOT_SLEEP; // In case l1s is executed, initialize sleep performed in order to avoid reentry in part above 42432 frames later l1s_task_allowed = TRUE; #endif #endif if (l1s_task_allowed == TRUE) { // Reset L1A activity flag. l1a_l1s_com.l1a_activity_flag = FALSE; // Set default value in frame count to next task. l1a_l1s_com.time_to_next_l1s_task = MAX_FN; /*************************************************************/ /* Get current communication page pointers. */ /*************************************************************/ // init pointer in DB according to "dsp read page" number #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) if (l1s_dsp_com.dsp_r_page == 0) { if (l1s_dsp_com.dsp_w_page == 0) trace_fct(CST_NEW_FRAME_PAGE_R0_W0, (UWORD32)(-1)); else trace_fct(CST_NEW_FRAME_PAGE_R0_W1, (UWORD32)(-1)); } else { if (l1s_dsp_com.dsp_w_page == 0) trace_fct(CST_NEW_FRAME_PAGE_R1_W0, (UWORD32)(-1)); else trace_fct(CST_NEW_FRAME_PAGE_R1_W1, (UWORD32)(-1)); } #endif #if (CODE_VERSION == SIMULATION) l1s_dsp_com.dsp_db_r_ptr = (T_DB_DSP_TO_MCU *) &(buf.mcu_rd[l1s_dsp_com.dsp_r_page]); l1s_dsp_com.dsp_db_w_ptr = (T_DB_MCU_TO_DSP *) &(buf.mcu_wr[l1s_dsp_com.dsp_w_page]); #if (DSP == 38) || (DSP == 39) l1s_dsp_com.dsp_db_common_w_ptr = (T_DB_COMMON_MCU_TO_DSP *) &(buf.mcu_wr_common[l1s_dsp_com.dsp_w_page]); #endif #else if (l1s_dsp_com.dsp_r_page == 0) l1s_dsp_com.dsp_db_r_ptr = (T_DB_DSP_TO_MCU *) DB_R_PAGE_0; else l1s_dsp_com.dsp_db_r_ptr = (T_DB_DSP_TO_MCU *) DB_R_PAGE_1; if (l1s_dsp_com.dsp_w_page == 0) l1s_dsp_com.dsp_db_w_ptr = (T_DB_MCU_TO_DSP *) DB_W_PAGE_0; else l1s_dsp_com.dsp_db_w_ptr = (T_DB_MCU_TO_DSP *) DB_W_PAGE_1; #if (DSP == 38) || (DSP == 39) if (l1s_dsp_com.dsp_w_page == 0) l1s_dsp_com.dsp_db_common_w_ptr = (T_DB_COMMON_MCU_TO_DSP*) DB_COMMON_W_PAGE_0; else l1s_dsp_com.dsp_db_common_w_ptr = (T_DB_COMMON_MCU_TO_DSP *) DB_COMMON_W_PAGE_1; #endif #endif #if (L1_GPRS) #if (CODE_VERSION == SIMULATION) l1ps_dsp_com.pdsp_db_r_ptr = &(buf.mcu_rd_gprs[l1s_dsp_com.dsp_r_page]); l1ps_dsp_com.pdsp_db_w_ptr = &(buf.mcu_wr_gprs[l1s_dsp_com.dsp_w_page]); #else if (l1s_dsp_com.dsp_r_page == 0) l1ps_dsp_com.pdsp_db_r_ptr = (T_DB_DSP_TO_MCU_GPRS *) DB_R_PAGE_0_GPRS; else l1ps_dsp_com.pdsp_db_r_ptr = (T_DB_DSP_TO_MCU_GPRS *) DB_R_PAGE_1_GPRS; if (l1s_dsp_com.dsp_w_page == 0) l1ps_dsp_com.pdsp_db_w_ptr = (T_DB_MCU_TO_DSP_GPRS *) DB_W_PAGE_0_GPRS; else l1ps_dsp_com.pdsp_db_w_ptr = (T_DB_MCU_TO_DSP_GPRS *) DB_W_PAGE_1_GPRS; #endif #endif #if (DSP_DEBUG_TRACE_ENABLE == 1) if (l1s_dsp_com.dsp_r_page == 0) { l1s_dsp_com.dsp_db2_current_r_ptr = (T_DB2_DSP_TO_MCU *) DB2_R_PAGE_0; l1s_dsp_com.dsp_db2_other_r_ptr = (T_DB2_DSP_TO_MCU *) DB2_R_PAGE_1; } else { l1s_dsp_com.dsp_db2_current_r_ptr = (T_DB2_DSP_TO_MCU *) DB2_R_PAGE_1; l1s_dsp_com.dsp_db2_other_r_ptr = (T_DB2_DSP_TO_MCU *) DB2_R_PAGE_0; } #endif #if (D_ERROR_STATUS_TRACE_ENABLE == 1) if (trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_L1S_DEBUG) // check d_error_status variable #if (GSM_IDLE_RAM == 0) Trace_d_error_status(); #else Trace_d_error_status_intram(); #endif #endif /*************************************************************/ /* RESET internal variables... */ /* Must be performed after having set the current com. pages */ /*************************************************************/ l1s.tpu_win = 0; // Reset resources for driver and sub tasks... l1s_dsp_com.dsp_r_page_used = FALSE; // Init. flag for MCU<-DSP comm. l1s.tpu_ctrl_reg = NO_CTRL; // Reset MCU->TPU comm. task register (tx, rx, pw tasks). l1s.dsp_ctrl_reg = NO_CTRL; // Reset MCU->DSP comm. task register (tx, rx, pw tasks). /*************************************************************/ /* RESET MCU->DSP DB communication page. */ /*************************************************************/ l1s_reset_db_mcu_to_dsp(l1s_dsp_com.dsp_db_w_ptr); #if (DSP == 38) || (DSP == 39) l1s_reset_db_common_mcu_to_dsp(l1s_dsp_com.dsp_db_common_w_ptr); #endif #if (L1_GPRS) l1ps_reset_db_mcu_to_dsp(l1ps_dsp_com.pdsp_db_w_ptr); #endif /********************************************************************/ /* Reset DSP IT ENABLE bit Satu/Hyp/Dione TO BE REMOVED in HERCULES */ /********************************************************************/ #if (W_A_ITFORCE) (*(volatile UWORD16 *) TPU_INT_CTRL) &= ~TPU_INT_ITD_F; #endif /*************************************************************/ /* TOA UPDATE MANAGEMENT. */ /*************************************************************/ #if (TOA_ALGO != 0) if(l1a_l1s_com.toa_reset == TRUE) // TOA algo must be initialized { #if (TOA_ALGO == 2) l1s.toa_var.toa_shift = l1ctl_toa(TOA_INIT, 0, 0, 0); #else l1s.toa_shift = l1ctl_toa(TOA_INIT, 0, 0, 0, &l1s.toa_update, &l1s.toa_period_count #if (FF_L1_FAST_DECODING == 1) ,0 #endif /* FF_L1_FAST_DECODING */ ); #endif l1a_l1s_com.toa_reset = FALSE; } // Decrement mask counter for TOA. // Rem: this counter is used to mask the SNR/TOA results for 2 // frames immediatly following an update of TOA. #if (TOA_ALGO == 2) if(l1s.toa_var.toa_snr_mask > 0) l1s.toa_var.toa_snr_mask--; #else if(l1s.toa_snr_mask > 0) l1s.toa_snr_mask--; #endif #endif /*************************************************************/ /* L1 TASK MANAGER. */ /*************************************************************/ #if (TRACE_TYPE == 1) || (TRACE_TYPE==4) #if (defined RVM_RTT_SWE || (OP_L1_STANDALONE == 1)) trace_info.l1s_rtt_func.rtt_refresh_status(trace_info.l1s_trace_user_id); #endif RTTL1_FILL_FN(l1s.actual_time.fn) #endif #if (GSM_IDLE_RAM != 0) if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1) || (l1a_l1s_com.dedic_set.SignalCode != NULL)) { if (!READ_TRAFFIC_CONT_STATE) { CSMI_TrafficControllerOn(); #if (TRACE_TYPE==1) || (TRACE_TYPE==4) l1s_trace_mftab(); #endif } // Call routine: DEDICATED_MODE_MANAGER. l1s_dedicated_mode_manager(); } #else // GSM_IDLE_RAM l1s_dedicated_mode_manager(); #endif #if L1_GPRS #if (GSM_IDLE_RAM != 0) if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1)) { l1ps_transfer_mode_manager(); } else { if(!l1pa_l1ps_com.transfer.semaphore) { if ((l1pa_l1ps_com.transfer.fset[0]->SignalCode != NULL) || (l1pa_l1ps_com.transfer.fset[1]->SignalCode != NULL)) { if (!READ_TRAFFIC_CONT_STATE) { CSMI_TrafficControllerOn(); #if (TRACE_TYPE==1) || (TRACE_TYPE==4) l1s_trace_mftab(); #endif } // Call routine: TRANSFER_MODE_MANAGER. l1ps_transfer_mode_manager(); } } } #else // GSM_IDLE_RAM // Call routine: TRANSFER_MODE_MANAGER. l1ps_transfer_mode_manager(); #endif // GSM_IDLE_RAM #endif // L1_GPRS l1s_task_scheduler_process(); // Call routine: EXECUTE_FRAME. l1s_execute_frame(); #if L1_GPRS // Call routine: PACKET_MEAS_MANAGER. l1ps_meas_manager(); #if (GSM_IDLE_RAM != 0) if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1)) { if (l1a_l1s_com.l1s_en_task[PDTCH] != TASK_DISABLED) // <- Added in line with comment on l1s_meas_manager() : // Call routine: PACKET_TRANSFER_MODE_MANAGER // "Measurement manager not usefull in packet transfer mode l1ps_transfer_meas_manager(); // This permit to save CPU in packet transfer mode // Call routine: TASK_SCHEDULER." } #else l1ps_transfer_meas_manager(); // This permit to save CPU in packet transfer mode // Call routine: TASK_SCHEDULER." #endif //GSM_IDLE_RAM #endif //L1_GPRS #if L1_GPRS // Measurement manager not usefull in packet transfer mode // This permit to save CPU in packet transfer mode if (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_DISABLED) #endif // Call routine: MEAS_MANAGER. l1s_meas_manager(); #if (L1_GTT == 1) #if (GSM_IDLE_RAM != 0) if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1)) #endif //GSM_IDLE_RAM { // Call routine: GTT MANAGER. l1s_gtt_manager(); } #endif #if (AUDIO_TASK == 1) // Call routine: AUDIO MANAGER. #if (GSM_IDLE_RAM != 0) if ( l1s.gsm_idle_ram_ctl.l1s_full_exec == TRUE) { l1s_audio_manager(); } #else l1s_audio_manager(); #endif #else #if (GSM_IDLE_RAM != 0) l1s.gsm_idle_ram_ctl.l1s_full_exec = FALSE; #endif #endif // Triton Audio ON/OFF Changes #if (L1_AUDIO_MCU_ONOFF == 1) l1s_audio_onoff_manager(); #endif // L1_AUDIO_MCU_ONOFF #if(L1_DYN_DSP_DWNLD ==1) // Call routine: DSP DYNAMIC DOWNLOAD MANAGER l1s_dyn_dwnld_manager(); #endif // Call routine: END_MANAGER. l1s_end_manager(); } } #if ((TRACE_TYPE==1) || (TRACE_TYPE == 4)) Trace_PM_Equal_0_balance(); #endif #if (DSP_DEBUG_TRACE_ENABLE == 1) if (trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_DSP_DEBUG) #if (GSM_IDLE_RAM != 0) if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1)) #endif { #if(MELODY_E2 || L1_MP3 || L1_AAC || L1_DYN_DSP_DWNLD) // DSP Trace is output ONLY if melody e2, mp3 or dynamic download are not currently running if(trace_info.dsptrace_handler_globals.trace_flag_blocked == FALSE) #endif Trace_dsp_debug(); } #if (AMR == 1) if (trace_info.current_config->l1_dyn_trace & 1<<L1_DYN_TRACE_DSP_AMR_DEBUG) #if (GSM_IDLE_RAM != 0) if ((l1a_l1s_com.mode > I_MODE) || (l1_config.TestMode == 1)) #endif { #if(MELODY_E2 || L1_MP3 || L1_AAC || L1_DYN_DSP_DWNLD ) // DSP Trace is output ONLY if melody e2, mp3 or dynamic download are not currently running if(trace_info.dsptrace_handler_globals.trace_flag_blocked == FALSE) #endif Trace_dsp_amr_debug(); } #endif #endif // Vmemo/Reco sign-to-talk trace #if (TRACE_TYPE==2 ) || (TRACE_TYPE==3) uart_trace_multiframe(); #endif #if (TRACE_TYPE == 1) || (TRACE_TYPE==4) if (l1s.actual_time.fn_mod13 == 12) { RTTL1_EVENT(RTTL1_EVENT_FNMOD13_EQUAL_12, RTTL1_EVENT_SIZE_FNMOD13_EQUAL_12) } #endif /******************************************************/ /* if layer 1 ready to sleep, evaluate System loading.*/ /* */ /* Conditions are : */ /* - no RF/GSM task in progress */ /* - next RF/GSM task at min in 4 frames */ /* - Layer1 in Idle mode */ /******************************************************/ #if (GSM_IDLE_RAM != 0) if (((l1a_l1s_com.mode == I_MODE) || (l1a_l1s_com.mode == CS_MODE0)) && (l1_config.TestMode == 0)) { // Normally os_load and hw_timer shall be meaningful since last sleep phase without checking os - otherwise traffic controller is already on if ((l1s.gsm_idle_ram_ctl.os_load == 0) || (l1s.gsm_idle_ram_ctl.hw_timer == 0)) { if (!READ_TRAFFIC_CONT_STATE) { CSMI_TrafficControllerOn(); #if (TRACE_TYPE==1) || (TRACE_TYPE==4) l1s_trace_mftab(); #endif } } } #if (TRACE_TYPE==1) || (TRACE_TYPE==4) if (READ_TRAFFIC_CONT_STATE) { l1_intram_send_trace(); } #endif #endif if (l1_config.pwr_mngt == PWR_MNGT) { if ( (l1s.frame_count == 0) && (l1a_l1s_com.time_to_next_l1s_task > MIN_SLEEP_TIME) && (l1s.pw_mgr.gauging_task == INACTIVE) && ((l1a_l1s_com.mode == I_MODE)||(l1a_l1s_com.mode == CS_MODE0)) ) { // sleep mode is authorized by primitive .... if ( l1s.pw_mgr.mode_authorized >= BIG_SLEEP ) { l1s_sleep_manager(); } } #if 0 /* FreeCalypso TCS211 reconstruction */ else{ l1_trace_fail_sleep(FAIL_SLEEP_L1SYNCH,0,0); } #endif } #if (GSM_IDLE_RAM_DEBUG == 1) (*( volatile unsigned short* )(0xFFFE4802)) &= ~ (1 << 2); // GPIO-2=0 #endif // Be careful: The Deep sleep can be performed just above // Do not add something here !!!! } //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM #if ((GSM_IDLE_RAM != 0)) //omaps00090550 //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_START void l1s_keep_mftab_hist(void) { UWORD8 task_id, bit; WORD8 nb_bitmap; T_L1S_GSM_IDLE_INTRAM * gsm_idle_ram_ctl; gsm_idle_ram_ctl = &(l1s.gsm_idle_ram_ctl); bit=0; for(nb_bitmap=0; nb_bitmap<SIZE_TAB_L1S_MONITOR; nb_bitmap++) { gsm_idle_ram_ctl->mem_task_bitmap_idle_ram[nb_bitmap] = gsm_idle_ram_ctl->task_bitmap_idle_ram[nb_bitmap]; gsm_idle_ram_ctl->task_bitmap_idle_ram[nb_bitmap]=0; } nb_bitmap=0; for(task_id=0; task_id<NBR_DL_L1S_TASKS; task_id++) { gsm_idle_ram_ctl->task_bitmap_idle_ram[nb_bitmap] |= ((!(l1s.task_status[task_id].current_status == INACTIVE)) << bit); bit++; if ((bit == 32) || (task_id == (NBR_DL_L1S_TASKS -1))) { bit = 0; nb_bitmap++; } } } BOOL l1s_mftab_has_changed(void) { WORD8 nb_bitmap; UWORD32 diff_detected; T_L1S_GSM_IDLE_INTRAM * gsm_idle_ram_ctl; gsm_idle_ram_ctl = &(l1s.gsm_idle_ram_ctl); diff_detected=0; for(nb_bitmap=0; nb_bitmap<SIZE_TAB_L1S_MONITOR; nb_bitmap++) { diff_detected |= ((gsm_idle_ram_ctl->mem_task_bitmap_idle_ram[nb_bitmap] ^ gsm_idle_ram_ctl->task_bitmap_idle_ram[nb_bitmap])); } return (diff_detected != 0); } //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #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_task_scheduler_process() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is the task scheduler of L1S. It */ /* schedules any enabled task. When a task must start, */ /* it becomes PENDING. Since several tasks can become */ /* pending at the same time, the highest priority one */ /* is elected. The elected task compete then with the */ /* current running task. If they conflict, the highest */ /* priority one wins. If the winning is the new comer */ /* then the multiframe table is reset and the new coming */ /* task is installed. */ /* */ /*-------------------------------------------------------*/ void l1s_task_scheduler_process() { WORD32 pending_task; // Call routine: SCHEDULE_TASKS. l1s_schedule_tasks(&pending_task); // Call routine: MERGE_MANAGER (contains LOAD_MFTAB). l1s_merge_manager(pending_task); #if (GSM_IDLE_RAM != 0) l1s_keep_mftab_hist(); if (((l1a_l1s_com.mode == I_MODE) || (l1a_l1s_com.mode == CS_MODE0)) && (l1_config.TestMode == 0)) { l1s_adapt_traffic_controller(); } #endif } //#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_schedule_tasks() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function schedules all L1S tasks except measure- */ /* -ment tasks which are handled separately. */ /* */ /*-------------------------------------------------------*/ void l1s_schedule_tasks(WORD32 *best_pending_task) { UWORD8 task_id; T_TASK_STATUS *task_ptr = &(l1s.task_status[0]); #if ((TRACE_TYPE == 1)||(TRACE_TYPE == 4)) UWORD8 nb_bitmap = 0; UWORD8 bit = 0; #endif // Reset "new_status" for all L1S tasks: make them NOT_PENDING. for(task_id=0; task_id<NBR_DL_L1S_TASKS; task_id++) { task_ptr->new_status = NOT_PENDING; task_ptr->time_to_exec = MAX_FN; task_ptr++; #if ((TRACE_TYPE == 1)||(TRACE_TYPE == 4)) // L1S Task enabling trace trace_info.task_bitmap[nb_bitmap] |= l1a_l1s_com.l1s_en_task[task_id] << bit; bit++; if (bit == 32) { bit = 0; nb_bitmap++; } #endif } #if ((TRACE_TYPE == 1)||(TRACE_TYPE == 4)) if(SELECTED_BITMAP(RTTL1_ENABLE_L1S_TASK_ENABLE)) { // For the moment up to 64 tasks supported !!! if ((trace_info.task_bitmap[0] != trace_info.mem_task_bitmap[0]) || (trace_info.task_bitmap[1] != trace_info.mem_task_bitmap[1])) { RTTL1_FILL_L1S_TASK_ENABLE(trace_info.task_bitmap[0], trace_info.task_bitmap[1]) } trace_info.mem_task_bitmap[0] = trace_info.task_bitmap[0]; trace_info.mem_task_bitmap[1] = trace_info.task_bitmap[1]; trace_info.task_bitmap[0] = 0; trace_info.task_bitmap[1] = 0; } #endif #if ((REL99 == 1) && (FF_BHO == 1)) if ((l1a_l1s_com.l1s_en_task[FBSB] == TASK_ENABLED) && (l1s.task_status[FBSB].current_status == INACTIVE)) //---------------------------------- // FBSB task is ENABLED. //---------------------------------- { l1s.task_status[FBSB].time_to_exec = 0; } #endif // #if ((REL99 == 1) && (FF_BHO == 1)) if(l1a_l1s_com.l1s_en_task[SYNCHRO] == TASK_ENABLED) //-------------------------------------------- // Synchro (jump on new Cell) task is ENABLED. //-------------------------------------------- { // SYNCHRO task is not schedule if we are in the specific case: // L1A is touching SYNCHRO parameters (tn_difference, dl_tn and dsp_scheduler_mode) // and leave L1A to go in HISR (L1S) in middle of the update (cf. BUG1339) if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET) { // Save scheduling result. l1s.task_status[SYNCHRO].time_to_exec = 0; } } if (l1a_l1s_com.mode == CS_MODE0) if((l1a_l1s_com.l1s_en_task[ADC_CSMODE0] == TASK_ENABLED) && (l1s.task_status[ADC_CSMODE0].current_status == INACTIVE)) if ((l1a_l1s_com.l1s_en_meas & FSMS_MEAS) == 0) // avoid conflict with the Measurement campaign //-------------------------------- // ADC task is ENABLED in CS_MODE0. //-------------------------------- { UWORD32 time_to_adc; if (l1a_l1s_com.adc_mode & ADC_NEXT_CS_MODE0) { time_to_adc = 0; // ADC performed in the current frame } else if (l1a_l1s_com.adc_mode & ADC_EACH_CS_MODE0) // perform ADC on each "idle_period" * 102 { time_to_adc = (102 * l1a_l1s_com.adc_idle_period-1) - (l1s.actual_time.fn % (102 * l1a_l1s_com.adc_idle_period)); } // Save scheduling result. l1s.task_status[ADC_CSMODE0].time_to_exec = time_to_adc; } if((l1a_l1s_com.l1s_en_task[NP] == TASK_ENABLED) && (l1s.task_status[NP].current_status == INACTIVE)) //------------------------------- // Normal Paging task is ENABLED. //------------------------------- { UWORD8 mf51_for_ms_paging; UWORD32 np_position; UWORD32 paging_period; UWORD32 time_to_np; UWORD32 fn; fn = l1s.actual_time.fn; #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. //But the SYNCHRO task is not used anymore as opposite to CS mode for CCCH readings 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)) { // if CCCH timeslot is lower than current timeslot, it means that the scheduling // must be anticipated by 1 frame if((l1a_l1s_com.ccch_group * 2) < l1a_l1s_com.dl_tn) { fn = l1s.next_time.fn; l1s.ctrl_synch_before = TRUE; } else l1s.ctrl_synch_before = FALSE; } #endif // compute MF51 number (0 to 8) in a Paging Period which carries the Paging. mf51_for_ms_paging = l1a_l1s_com.page_group / l1a_l1s_com.nb_pch_per_mf51; np_position = (l1a_l1s_com.idle_task_info.pg_position - 1) + (mf51_for_ms_paging * 51); paging_period = l1a_l1s_com.bs_pa_mfrms * 51; time_to_np = (np_position + paging_period - (fn % paging_period)) % paging_period; // Save scheduling result. l1s.task_status[NP].time_to_exec = time_to_np; // Inform Gauging scheduler that NP task is pending.... if (time_to_np == 0) l1s.pw_mgr.paging_scheduled = TRUE; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[NP] = SEMAPHORE_RESET; } if((l1a_l1s_com.l1s_en_task[EP] == TASK_ENABLED) && (l1s.task_status[EP].current_status == INACTIVE)) //--------------------------------- // Extended Paging task is ENABLED. //--------------------------------- { UWORD8 mf51_for_ms_paging; UWORD32 ep_position; UWORD32 paging_period; UWORD32 time_to_ep; UWORD32 fn; fn = l1s.actual_time.fn; #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. //But the SYNCHRO task is not used anymore as opposite to CS mode for CCCH readings 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)) { // if CCCH timeslot is lower than current timeslot, it means that the scheduling // must be anticipated by 1 frame if((l1a_l1s_com.ccch_group * 2) < l1a_l1s_com.dl_tn) { fn = l1s.next_time.fn; l1s.ctrl_synch_before = TRUE; } else l1s.ctrl_synch_before = FALSE; } #endif // compute MF51 number (0 to 8) in a Paging Period which carries the Paging. mf51_for_ms_paging = ((l1a_l1s_com.page_group + 2) / l1a_l1s_com.nb_pch_per_mf51) % l1a_l1s_com.bs_pa_mfrms; ep_position = (l1a_l1s_com.idle_task_info.extpg_position - 1) + (mf51_for_ms_paging * 51); paging_period = l1a_l1s_com.bs_pa_mfrms * 51; time_to_ep = (ep_position + paging_period - (fn % paging_period)) % paging_period; // Save scheduling result. l1s.task_status[EP].time_to_exec = time_to_ep; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[EP] = SEMAPHORE_RESET; } if((l1a_l1s_com.l1s_en_task[NBCCHS] == TASK_ENABLED) && (l1s.task_status[NBCCHS].current_status == INACTIVE)) //------------------------------------- // Normal BCCH Serving task is ENABLED. //------------------------------------- { UWORD32 min_time_to_nbcchs = MAX_FN; WORD32 time_to_nbcchs; WORD16 time_in_mf51; WORD32 fn_div_51 = l1s.actual_time.fn / 51; UWORD8 i; UWORD16 modulus; WORD16 relative_position; WORD32 modulus_times_51; WORD16 current_mf51_position; // NBCCHS task starts in frame position "1" in the MF51. time_in_mf51 = 1 - l1s.actual_time.t3; #if (L1_GPRS) if(l1a_l1s_com.mode == PACKET_TRANSFER_MODE) { // In transfer mode, if l1a_l1s_com.dl_tn != 0, a change synchro is performed // So the CTRL must be compute the frame before if(l1a_l1s_com.dl_tn != 0) time_in_mf51 -- ; } #endif for(i=0;i<l1a_l1s_com.nbcchs.schedule_array_size;i++) { modulus = l1a_l1s_com.nbcchs.schedule_array[i].modulus; relative_position = l1a_l1s_com.nbcchs.schedule_array[i].relative_position; modulus_times_51 = modulus * 51; current_mf51_position = fn_div_51 % modulus; time_to_nbcchs = time_in_mf51 + (relative_position - current_mf51_position)*51; if(time_to_nbcchs < 0) time_to_nbcchs += modulus_times_51; else if(time_to_nbcchs >= modulus_times_51) time_to_nbcchs -= modulus_times_51; if(time_to_nbcchs < min_time_to_nbcchs) min_time_to_nbcchs = time_to_nbcchs; } // Save scheduling result. l1s.task_status[NBCCHS].time_to_exec = min_time_to_nbcchs; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[NBCCHS] = SEMAPHORE_RESET; } // End of "if / NBCCHS" if((l1a_l1s_com.l1s_en_task[EBCCHS] == TASK_ENABLED) && (l1s.task_status[EBCCHS].current_status == INACTIVE)) //--------------------------------------- // Extended BCCH Serving task is ENABLED. //--------------------------------------- { UWORD32 min_time_to_ebcchs = MAX_FN; WORD32 time_to_ebcchs; WORD16 time_in_mf51; WORD32 fn_div_51 = l1s.actual_time.fn / 51; UWORD8 i; UWORD16 modulus; WORD16 relative_position; WORD32 modulus_times_51; WORD16 current_mf51_position; // EBCCHS task starts in frame position "5" in the MF51. time_in_mf51 = 5 - l1s.actual_time.t3; #if (L1_GPRS) if(l1a_l1s_com.mode == PACKET_TRANSFER_MODE) { // 3 cases are considered: // => the l1a_l1s_com.dl_tn = {7,6,5,4,3,2,1} // the BCCHS burst is in the previous frame than the PDTCH, so the CTRL must be done // on the previous frame // => the l1a_l1s_com.dl_tn = {0} // the BCCHS burst is in the same frame than the PDTCH, so the CTRL must be done // on the same frame if(l1a_l1s_com.dl_tn != 0) time_in_mf51 -- ; // CTRL done on the previous frame } #endif for(i=0;i<l1a_l1s_com.ebcchs.schedule_array_size;i++) { modulus = l1a_l1s_com.ebcchs.schedule_array[i].modulus; relative_position = l1a_l1s_com.ebcchs.schedule_array[i].relative_position; modulus_times_51 = modulus * 51; current_mf51_position = fn_div_51 % modulus; time_to_ebcchs = time_in_mf51 + (relative_position - current_mf51_position)*51; if(time_to_ebcchs < 0) time_to_ebcchs += modulus_times_51; else if(time_to_ebcchs >= (WORD32)modulus_times_51) time_to_ebcchs -= modulus_times_51; if(time_to_ebcchs < (WORD32)min_time_to_ebcchs) min_time_to_ebcchs = time_to_ebcchs; } // Save scheduling result. l1s.task_status[EBCCHS].time_to_exec = min_time_to_ebcchs; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[EBCCHS] = SEMAPHORE_RESET; } // End of "if / EBCCHS" if(l1a_l1s_com.l1s_en_task[ALLC] == TASK_ENABLED) //--------------------------------- // ALL CCCH reading is ENABLED. //--------------------------------- { if(l1a_l1s_com.task_param[ALLC] == SEMAPHORE_RESET) { #define CCCH0_START_TIME 6 - 1 // CCCH block 0. #define CCCH1_START_TIME 12 - 1 // CCCH block 1. #define CCCH2_START_TIME 16 - 1 // CCCH block 2. #define CCCH3_START_TIME 22 - 1 // CCCH block 3. #define CCCH4_START_TIME 26 - 1 // CCCH block 4. #define CCCH5_START_TIME 32 - 1 // CCCH block 5. #define CCCH6_START_TIME 36 - 1 // CCCH block 6. #define CCCH7_START_TIME 42 - 1 // CCCH block 7. #define CCCH8_START_TIME 46 - 1 // CCCH block 8. UWORD32 min_time_to_allc = MAX_FN; if(l1s.actual_time.t3 <= CCCH0_START_TIME) min_time_to_allc = CCCH0_START_TIME - l1s.actual_time.t3; else if(l1s.actual_time.t3 <= CCCH1_START_TIME) min_time_to_allc = CCCH1_START_TIME - l1s.actual_time.t3; else if(l1s.actual_time.t3 <= CCCH2_START_TIME) min_time_to_allc = CCCH2_START_TIME - l1s.actual_time.t3; // CCCH3 to CCCH8 are considered only when MF51 is not combined. else if(l1a_l1s_com.bcch_combined == FALSE) { if(l1s.actual_time.t3 <= CCCH3_START_TIME) min_time_to_allc = CCCH3_START_TIME - l1s.actual_time.t3; else if(l1s.actual_time.t3 <= CCCH4_START_TIME) min_time_to_allc = CCCH4_START_TIME - l1s.actual_time.t3; else if(l1s.actual_time.t3 <= CCCH5_START_TIME) min_time_to_allc = CCCH5_START_TIME - l1s.actual_time.t3; else if(l1s.actual_time.t3 <= CCCH6_START_TIME) min_time_to_allc = CCCH6_START_TIME - l1s.actual_time.t3; else if(l1s.actual_time.t3 <= CCCH7_START_TIME) min_time_to_allc = CCCH7_START_TIME - l1s.actual_time.t3; else if(l1s.actual_time.t3 <= CCCH8_START_TIME) min_time_to_allc = CCCH8_START_TIME - l1s.actual_time.t3; // Attempt to read CCCH0. else min_time_to_allc = 51 + CCCH0_START_TIME - l1s.actual_time.t3; } // Attempt to read CCCH0. else min_time_to_allc = 51 + CCCH0_START_TIME - l1s.actual_time.t3; // Save scheduling result. l1s.task_status[ALLC].time_to_exec = min_time_to_allc; } else // Semaphore is Set, reset it when ALLC inactive. { if(l1s.task_status[ALLC].current_status == INACTIVE) l1a_l1s_com.task_param[ALLC] = SEMAPHORE_RESET; } } if(l1a_l1s_com.l1s_en_task[SMSCB] == TASK_ENABLED) //------------------------------------------------------ // Short Message Service Cell Broadcast task is ENABLED. //------------------------------------------------------ { if(l1s.task_status[SMSCB].current_status == INACTIVE) { WORD32 time_to_norm_smscb = MAX_FN; WORD32 time_to_ext_smscb = MAX_FN; WORD32 time_to_smscb_info = MAX_FN; UWORD32 min_time_to_smscb; if(l1a_l1s_com.cbch_info_req.next < l1a_l1s_com.cbch_info_req.cbch_num) { // Still some CBCH blocks to read from TB1/2/3/5/6/7, get next one. time_to_smscb_info = l1a_l1s_com.cbch_info_req.start_fn[l1a_l1s_com.cbch_info_req.next] + MAX_FN - l1s.actual_time.fn; if(time_to_smscb_info >= MAX_FN) time_to_smscb_info -= MAX_FN; // Check if passing 1 schedule position. if(time_to_smscb_info == 0) l1a_l1s_com.cbch_info_req.next++; } else { //%%%%%%%%%%%%%%%% // Normal CBCH... //%%%%%%%%%%%%%%%% // Check for scheduling info. if(l1a_l1s_com.norm_cbch_schedule.cbch_state == CBCH_SCHEDULED) { // CBCH header (TB0) reading is scheduled. if(l1a_l1s_com.norm_cbch_schedule.next < l1a_l1s_com.norm_cbch_schedule.cbch_num) { // Still some scheduled CBCH to read, get next one. time_to_norm_smscb = l1a_l1s_com.norm_cbch_schedule.first_block[l1a_l1s_com.norm_cbch_schedule.next] + MAX_FN - l1s.actual_time.fn; if(time_to_norm_smscb >= MAX_FN) time_to_norm_smscb -= MAX_FN; // Check if passing 1 schedule position. if(time_to_norm_smscb == 0) l1a_l1s_com.norm_cbch_schedule.next++; } else { // No more scheduled CBCH/TB0. l1a_l1s_com.norm_cbch_schedule.cbch_state = CBCH_CONTINUOUS_READING; } } if(l1a_l1s_com.norm_cbch_schedule.cbch_state == CBCH_CONTINUOUS_READING) { // CBCH header (TB0) reading is continuous. if(l1a_l1s_com.norm_cbch_schedule.start_continuous_fn != -1) { time_to_norm_smscb = l1a_l1s_com.norm_cbch_schedule.start_continuous_fn + MAX_FN - l1s.actual_time.fn; if(time_to_norm_smscb >= MAX_FN) time_to_norm_smscb -= MAX_FN; // Check for "CBCH continuous reading" starting frame number. if(time_to_norm_smscb == 0) l1a_l1s_com.norm_cbch_schedule.start_continuous_fn = -1; } else { // Continuous CBCH/TB0 reading is ongoing. WORD32 time_in_mf51; // No more scheduled CBCH to read, we must read all TB0. time_in_mf51 = l1a_l1s_com.cbch_start_in_mf51 - l1s.actual_time.t3; // Time to next TB0 CBCH block. time_to_norm_smscb = time_in_mf51 + (8-l1s.actual_time.tc)*51; if(time_to_norm_smscb < 0) time_to_norm_smscb += 8*51; if(time_to_norm_smscb >= 8*51) time_to_norm_smscb -= 8*51; } } //%%%%%%%%%%%%%%%%% // Extended CBCH... //%%%%%%%%%%%%%%%%% // Check for scheduling info. if(l1a_l1s_com.ext_cbch_schedule.cbch_state == CBCH_SCHEDULED) { // CBCH header (TB4) reading is scheduled. if(l1a_l1s_com.ext_cbch_schedule.next < l1a_l1s_com.ext_cbch_schedule.cbch_num) { // Still some scheduled CBCH to read, get next one. time_to_ext_smscb = l1a_l1s_com.ext_cbch_schedule.first_block[l1a_l1s_com.ext_cbch_schedule.next] + MAX_FN - l1s.actual_time.fn; if(time_to_ext_smscb >= MAX_FN) time_to_ext_smscb -= MAX_FN; // Check if passing 1 schedule position. if(time_to_ext_smscb == 0) l1a_l1s_com.ext_cbch_schedule.next++; // passing 1 schedule position. } else { // No more scheduled CBCH/TB4. l1a_l1s_com.ext_cbch_schedule.cbch_state = CBCH_CONTINUOUS_READING; } } if(l1a_l1s_com.ext_cbch_schedule.cbch_state == CBCH_CONTINUOUS_READING) { // Check for "CBCH continuous reading " starting frame number. if(l1a_l1s_com.ext_cbch_schedule.start_continuous_fn != -1) { time_to_ext_smscb = l1a_l1s_com.ext_cbch_schedule.start_continuous_fn + MAX_FN - l1s.actual_time.fn; if(time_to_ext_smscb >= MAX_FN) time_to_ext_smscb -= MAX_FN; // Check for "CBCH continuous reading" starting frame number. if(time_to_ext_smscb == 0) l1a_l1s_com.ext_cbch_schedule.start_continuous_fn = -1; } else { // Continuous CBCH/TB4 reading is ongoing. WORD32 time_in_mf51; // No more scheduled CBCH to read, we must read all TB4. time_in_mf51 = l1a_l1s_com.cbch_start_in_mf51 - l1s.actual_time.t3; // Time to next TB4 CBCH block. time_to_ext_smscb = time_in_mf51 + (4-l1s.actual_time.tc)*51; if(time_to_ext_smscb < 0) time_to_ext_smscb += 8*51; if(time_to_ext_smscb >= 8*51) time_to_ext_smscb -= 8*51; } } } // Choose closest one... if(time_to_norm_smscb < time_to_ext_smscb) min_time_to_smscb = time_to_norm_smscb; else min_time_to_smscb = time_to_ext_smscb; if(time_to_smscb_info < min_time_to_smscb) min_time_to_smscb = time_to_smscb_info; // Save scheduling result. l1s.task_status[SMSCB].time_to_exec = min_time_to_smscb; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SMSCB] = SEMAPHORE_RESET; } } //--------------------------------------------- // Random Access management for ACCESS phase. //--------------------------------------------- if(l1a_l1s_com.l1s_en_task[RAACC] == TASK_ENABLED) // Random Access (ACCESS mode) task is ENABLED. { // RAACC task requires to run L1S scheduler every frame. l1a_l1s_com.time_to_next_l1s_task = 0; if((l1a_l1s_com.bcch_combined == FALSE) || (COMBINED_RA_DISTRIB[l1s.actual_time.t3] == TRUE)) // Current frame is at a "slot" boundary -> decrement time to next RA. { if(l1a_l1s_com.ra_info.rand == 0) // It is time to controle a RACH transmit. { l1s.task_status[RAACC].new_status = PENDING; } // Decrement "rand" value after test to avoid a negative rand when L3 // specifies a rand = 0 l1a_l1s_com.ra_info.rand --; } } #if (L1_GPRS) // BCCHN task ENABLED and NBCCH task is INACTIVE if(((l1a_l1s_com.l1s_en_task[BCCHN ] == TASK_ENABLED) && (l1s.task_status[BCCHN ].current_status == INACTIVE)) || ((l1a_l1s_com.l1s_en_task[BCCHN_TOP ] == TASK_ENABLED) && (l1s.task_status[BCCHN_TOP ].current_status == INACTIVE)) || ((l1a_l1s_com.l1s_en_task[BCCHN_TRAN] == TASK_ENABLED) && (l1s.task_status[BCCHN_TRAN].current_status == INACTIVE))) #else // BCCHN task is ENABLED. if(((l1a_l1s_com.l1s_en_task[BCCHN ] == TASK_ENABLED) && (l1s.task_status[BCCHN ].current_status == INACTIVE)) || ((l1a_l1s_com.l1s_en_task[BCCHN_TOP] == TASK_ENABLED) && (l1s.task_status[BCCHN_TOP].current_status == INACTIVE))) #endif { { UWORD32 neigh_fn; UWORD8 neigh_tc; UWORD8 neigh_fn_mod51; WORD32 time_to_bcchn; WORD16 time_in_mf51; UWORD16 si_bitmap; UWORD8 first_possible_neigh_tc; UWORD8 i; UWORD8 tc_count; UWORD8 ext_bcch_start_time; UWORD8 bcchn_priority; //array in order to memorize for each priority the closest NBCCH // 3 priorities: TOP_PRIORITY, HIGH_PRIORITY, NORMAL_PRIORITY UWORD32 min_time_to_bcchn[3] = {MAX_FN,MAX_FN,MAX_FN}; UWORD8 best_neigh_id[3] = {0,0,0}; UWORD8 best_neigh_tc[3] = {0,0,0}; // Up to 6 pending Ncell BCCH reading. for(i=0;i<6;i++) { // Consider only the "in use" locations from the "6 neigh. list". if(l1a_l1s_com.bcchn.list[i].status != NSYNC_FREE) { // Get neighbor cell FN. neigh_fn = (l1s.actual_time.fn + l1a_l1s_com.bcchn.list[i].fn_offset) % MAX_FN; // Get neighbor cell TC. neigh_tc = (neigh_fn / 51) % 8; // Get neighbor cell TC. neigh_fn_mod51 = (neigh_fn % 51); //----------------- // Normal BCCH... //----------------- // Still some Normal BCCH to read. if(l1a_l1s_com.bcchn.list[i].bcch_blks_req & 0x00FF) { #if (L1_GPRS) // in case of packet transfer mode there is no measurement window if(l1a_l1s_com.l1s_en_task[BCCHN_TRAN] == TASK_ENABLED) { // Since Normal BCCH reading must start in FN_mod_51=50+2=1, current TC cannot // be read. First possible TC is therefore the next one. time_in_mf51 = 1 - neigh_fn_mod51; if(neigh_fn_mod51 > 1) first_possible_neigh_tc = neigh_tc + 1; else first_possible_neigh_tc = neigh_tc; } else { // Since Normal BCCH reading must start in FN_mod_51=50, current TC cannot // be read. First possible TC is therefore the next one. time_in_mf51 = 50 - neigh_fn_mod51; first_possible_neigh_tc = neigh_tc + 1; } #else // Since Normal BCCH reading must start in FN_mod_51=50, current TC cannot // be read. First possible TC is therefore the next one. time_in_mf51 = 50 - neigh_fn_mod51; first_possible_neigh_tc = neigh_tc + 1; #endif if(first_possible_neigh_tc >= 8) first_possible_neigh_tc -=8; // Get the duplicate version of the Normal BCCH si_bitmap. si_bitmap = l1a_l1s_com.bcchn.list[i].bcch_blks_req; // Look for 1st bit activated from current TC. tc_count = 0; while((!(si_bitmap & (1L << first_possible_neigh_tc))) && (tc_count < 8)) { tc_count++; first_possible_neigh_tc++; if(first_possible_neigh_tc >= 8) first_possible_neigh_tc -=8; } // Compute time to wait until NBCCH activation. #if (L1_GPRS) if(l1a_l1s_com.l1s_en_task[BCCHN_TRAN] == TASK_ENABLED) time_to_bcchn = time_in_mf51 + (first_possible_neigh_tc - neigh_tc )*51; else time_to_bcchn = time_in_mf51 + (first_possible_neigh_tc - neigh_tc - 1)*51; #else time_to_bcchn = time_in_mf51 + (first_possible_neigh_tc - neigh_tc - 1)*51; #endif // Prevent negative result. if(time_to_bcchn < 0) time_to_bcchn += 8*51; else if(time_to_bcchn >= 8*51) time_to_bcchn -= 8*51; // memorize the next BCCHN according to its priority // (TOP_PRIORITY or HIGH_PRIORITY or NORMAL_PRIORITY ) bcchn_priority = l1a_l1s_com.bcchn.list[i].gprs_priority ; if(time_to_bcchn < min_time_to_bcchn[bcchn_priority]) { min_time_to_bcchn[bcchn_priority] = time_to_bcchn; // Save Neighbour number best_neigh_id[bcchn_priority] = i; best_neigh_tc[bcchn_priority] = first_possible_neigh_tc; } } //----------------- // Extended BCCH... //----------------- // Still some Extended BCCH to read. if(l1a_l1s_com.bcchn.list[i].bcch_blks_req & 0xFF00) { #if (L1_GPRS) // in case of packet transfer mode there are no measurement windows if(l1a_l1s_com.l1s_en_task[BCCHN_TRAN] == TASK_ENABLED) ext_bcch_start_time=3+2; else ext_bcch_start_time=3; #else ext_bcch_start_time=3; #endif // Extended BCCH reading must start in FN_mod_51=ext_bcch_start_time. // Check if current TC could be read immediately. time_in_mf51 = ext_bcch_start_time - neigh_fn_mod51; if(neigh_fn_mod51 > ext_bcch_start_time) first_possible_neigh_tc = neigh_tc + 1; else first_possible_neigh_tc = neigh_tc; if(first_possible_neigh_tc >= 8) first_possible_neigh_tc -=8; // Offset TC by 8 to be within the EBCCH bitmap. first_possible_neigh_tc += 8; // Get the duplicate version of the Extended BCCH si_bitmap. si_bitmap = l1a_l1s_com.bcchn.list[i].bcch_blks_req; // Look for 1st bit activated from current TC. tc_count = 0; while((!(si_bitmap & (1L << first_possible_neigh_tc))) && (tc_count < 8)) { tc_count++; first_possible_neigh_tc++; if(first_possible_neigh_tc >= 16) first_possible_neigh_tc -=8; } // Compute time to wait until NBCCH activation. time_to_bcchn = time_in_mf51 + (first_possible_neigh_tc - neigh_tc - 8)*51; // Prevent negative result. if(time_to_bcchn < 0) time_to_bcchn += 8*51; else if(time_to_bcchn >= 8*51) time_to_bcchn -= 8*51; // memorize the next BCCHN according to its priority // (TOP_PRIORITY or HIGH_PRIORITY or NORMAL_PRIORITY ) bcchn_priority = l1a_l1s_com.bcchn.list[i].gprs_priority; if(time_to_bcchn < min_time_to_bcchn[bcchn_priority]) { min_time_to_bcchn[bcchn_priority] = time_to_bcchn; // Save Neighbour number best_neigh_id[bcchn_priority] = i; best_neigh_tc[bcchn_priority] = first_possible_neigh_tc; } } } } // Save scheduling result. #if L1_GPRS if(l1a_l1s_com.l1s_en_task[BCCHN_TRAN] == TASK_ENABLED) { // in packet transfer only task one task is allowed: BCCHN_TRAN with a TOP priority l1s.task_status[BCCHN_TRAN].time_to_exec = min_time_to_bcchn[TOP_PRIORITY]; l1a_l1s_com.bcchn.active_neigh_id_top = best_neigh_id[TOP_PRIORITY]; l1a_l1s_com.bcchn.active_neigh_tc_top = best_neigh_tc[TOP_PRIORITY]; l1a_l1s_com.task_param[BCCHN_TRAN] = SEMAPHORE_RESET; } else #endif { // in IDLE 2 tasks are allowed: BCCHN_TOP with a TOP priority or BCCHN with normal and high priorities // these 2 tasks may be enabled together. if((l1a_l1s_com.l1s_en_task[BCCHN_TOP] == TASK_ENABLED)&&(l1s.task_status[BCCHN_TOP].current_status == INACTIVE)) { // update only if the task is not being running. l1s.task_status[BCCHN_TOP].time_to_exec = min_time_to_bcchn[TOP_PRIORITY]; l1a_l1s_com.bcchn.active_neigh_id_top = best_neigh_id[TOP_PRIORITY]; l1a_l1s_com.bcchn.active_neigh_tc_top = best_neigh_tc[TOP_PRIORITY]; l1a_l1s_com.task_param[BCCHN_TOP] = SEMAPHORE_RESET; } if((l1a_l1s_com.l1s_en_task[BCCHN] == TASK_ENABLED) && (l1s.task_status[BCCHN].current_status == INACTIVE)) { // update only if the task is not being running. l1a_l1s_com.task_param[BCCHN] = SEMAPHORE_RESET; if(min_time_to_bcchn[HIGH_PRIORITY] < min_time_to_bcchn[NORMAL_PRIORITY] + BLOC_BCCHN_SIZE-1) { l1s.task_status[BCCHN].time_to_exec = min_time_to_bcchn[HIGH_PRIORITY]; l1a_l1s_com.bcchn.active_neigh_id_norm = best_neigh_id[HIGH_PRIORITY]; l1a_l1s_com.bcchn.active_neigh_tc_norm = best_neigh_tc[HIGH_PRIORITY]; } else { l1s.task_status[BCCHN].time_to_exec = min_time_to_bcchn[NORMAL_PRIORITY]; l1a_l1s_com.bcchn.active_neigh_id_norm = best_neigh_id[NORMAL_PRIORITY]; l1a_l1s_com.bcchn.active_neigh_tc_norm = best_neigh_tc[NORMAL_PRIORITY]; } } } } // End of "if / current_status" } // End of "if / BCCHN" #if (L1_GPRS) if((l1a_l1s_com.l1s_en_task[PNP] == TASK_ENABLED) || ((l1a_l1s_com.l1s_en_task[PEP] == TASK_ENABLED) && (l1s.task_status[PEP].current_status == INACTIVE))) //------------------------------------- // Packet Normal Paging task is ENABLED. //------------------------------------- { #define BS_PAG_BLKS l1pa_l1ps_com.pccch.bs_pag_blks_res #define BS_PBCCH_BLKS l1pa_l1ps_com.pccch.bs_pbcch_blks UWORD16 fn_mod; UWORD16 paging_group; UWORD8 mf52_index; UWORD32 m_index_dvd; UWORD32 m_index_rest; UWORD16 block_index_in_mf64x52; UWORD16 m_index_dvd_intermediate; UWORD8 mf52_for_ms_pg; UWORD8 mf52_for_ms_epg; UWORD8 pg_block_index; WORD16 time_to_pnp; WORD16 time_to_pep, time_to_pep_2; UWORD8 pnp_blk_position; UWORD8 pep_blk_position; UWORD16 m_index; WORD16 m_for_pep; UWORD16 pnp_position, pep_position_2 =0;//omaps00090550 static UWORD16 pep_position; UWORD8 i = 0; // Actual Frame Number modulo Paging Period fn_mod = l1s.actual_time.fn % (64*52); //---------------------------------------- // Step1: //---------------------------------------- // Find next potential PCCCH block index // according to current FN. //---------------------------------------- // Translate actual time Frame Number in an element of the "paging Block // available" set. mf52_index = fn_mod / 52; // Look for next PCCCH block "potentially" containing PNP. // Result in "i". while(((l1s.actual_time.fn_mod52 - PACKET_PG_POSITION[(i + (BS_PAG_BLKS+BS_PBCCH_BLKS)*11)]) >= 0) && (i < l1pa_l1ps_com.pccch.nb_ppch_per_mf52)) { i++; } // Compute "potential" PNP block index in the MF64x52. // block_index_mf64x52 has the same dimension as PAGING_GROUP!!! block_index_in_mf64x52 = mf52_index * l1pa_l1ps_com.pccch.nb_ppch_per_mf52 + i; //---------------------------------------- // Step2: //---------------------------------------- // Reverse ETSI equation to compute "m" // index corresponding to the next coming // PNP block. //---------------------------------------- // Compute intermediate value to avoid % usage. m_index_dvd_intermediate = block_index_in_mf64x52 - l1pa_l1ps_com.pccch.first_pg_grp + l1pa_l1ps_com.pccch.pg_blks_avail; if(m_index_dvd_intermediate >= l1pa_l1ps_com.pccch.pg_blks_avail) m_index_dvd_intermediate -= l1pa_l1ps_com.pccch.pg_blks_avail; // Compute the reverse of ETSI equation // m_index = ((block_index_in_mf64x52 - ALPHA - BETA)*SPLIT)DIV M // with: // ALPHA = (IMSImod10000)div(KC*N) // BETA = IMSImod1000 m_index_dvd = (UWORD32)m_index_dvd_intermediate * (UWORD32)l1pa_l1ps_com.pccch.split_pg_value; m_index = (UWORD16)(m_index_dvd / (UWORD32)(l1pa_l1ps_com.pccch.pg_blks_avail)); m_index_rest = m_index_dvd - (UWORD32)(m_index)*(UWORD32)l1pa_l1ps_com.pccch.pg_blks_avail; // Cope with rounding effect... // Choose next PAGING_GROUP index. // Note: if rest of the division "m_index_dvd/pg_blks_avail !=0" // then PAGING GROUP index must be incremented. if(m_index_rest != 0) { m_for_pep = m_index; m_index += 1; } else { m_for_pep = m_index - 1;; if(m_for_pep < 0) m_for_pep += l1pa_l1ps_com.pccch.split_pg_value; } //---------------------------------------- // Step3: //---------------------------------------- // Find PAGING GROUP associated with the // "m" index found in step 2. // Then compute MF52 containing this block // and associated block index in the MF52. //---------------------------------------- // PAGING GROUP computation: paging_group = (l1pa_l1ps_com.pccch.pg_offset + (((UWORD32)m_index * (UWORD32)l1pa_l1ps_com.pccch.pg_blks_avail) / (UWORD32)l1pa_l1ps_com.pccch.split_pg_value)) % l1pa_l1ps_com.pccch.pg_blks_avail ; // Computation of the MF52 for MS Packet Paging mf52_for_ms_pg = paging_group / l1pa_l1ps_com.pccch.nb_ppch_per_mf52; // Paging Block Index computation pg_block_index = paging_group % l1pa_l1ps_com.pccch.nb_ppch_per_mf52; // Normal and Extended paging position pnp_blk_position = PACKET_PG_POSITION[(pg_block_index + (l1pa_l1ps_com.pccch.bs_pag_blks_res + l1pa_l1ps_com.pccch.bs_pbcch_blks)*MAX_NBR_PG_BLKS)]; // Computation of the PPCH block position in the MF52 pnp_position = (pnp_blk_position - 1) + mf52_for_ms_pg * 52; // Time between actual fn and next PPCH block // Apply modulo 64*52. time_to_pnp = pnp_position - fn_mod + (64*52); if(time_to_pnp >= (64*52)) time_to_pnp -= (64*52); // Save Time to next PPCH block position in a global structure. // "time_to_pnp" is used in Cell reselection measurement scheduling. l1pa_l1ps_com.pccch.time_to_pnp = time_to_pnp; // Semaphore is Set, reset it when PNP inactive. if(l1a_l1s_com.task_param[PNP] == SEMAPHORE_SET) { if(l1s.task_status[PNP].current_status == INACTIVE) l1a_l1s_com.task_param[PNP] = SEMAPHORE_RESET; } if(l1a_l1s_com.task_param[PNP] == SEMAPHORE_RESET) { // Save scheduling result. l1s.task_status[PNP].time_to_exec = time_to_pnp; if(time_to_pnp == 0) { // Force PEP scheduling computation l1pa_l1ps_com.pccch.epg_computation = PPCH_POS_NOT_COMP; } } if(l1a_l1s_com.l1s_en_task[PEP] == TASK_ENABLED) { if(l1pa_l1ps_com.pccch.epg_computation == PPCH_POS_NOT_COMP) { // PAGING GROUP computation: paging_group = (l1pa_l1ps_com.pccch.pg_offset + (((UWORD32)(m_index) * (UWORD32)l1pa_l1ps_com.pccch.pg_blks_avail) / (UWORD32)l1pa_l1ps_com.pccch.split_pg_value)) % l1pa_l1ps_com.pccch.pg_blks_avail; // Computation of the MF52 for MS Packet Extented Paging mf52_for_ms_epg = ((paging_group + 3) / l1pa_l1ps_com.pccch.nb_ppch_per_mf52) % 64; // Paging Block Index computation pg_block_index = paging_group % l1pa_l1ps_com.pccch.nb_ppch_per_mf52; // Normal and Extended paging position pep_blk_position = PACKET_PG_POSITION[(((pg_block_index + 3) % l1pa_l1ps_com.pccch.nb_ppch_per_mf52) + (l1pa_l1ps_com.pccch.bs_pag_blks_res + l1pa_l1ps_com.pccch.bs_pbcch_blks)*11)]; // Computation of the PEPCH block position in the MF52 pep_position = (pep_blk_position - 1) + mf52_for_ms_epg * 52; // PEP is scheduled for the 1st time. If first PPCH block is a PEP and not PNP // then PEP scheduling has to be computed with "m_for_pep = m_index - 1" if(l1a_l1s_com.task_param[PEP] == SEMAPHORE_SET) { // PAGING GROUP computation: paging_group = (l1pa_l1ps_com.pccch.pg_offset + (((UWORD32)(m_for_pep) * (UWORD32)l1pa_l1ps_com.pccch.pg_blks_avail) / (UWORD32)l1pa_l1ps_com.pccch.split_pg_value)) % l1pa_l1ps_com.pccch.pg_blks_avail; // Computation of the MF52 for MS Packet Extented Paging mf52_for_ms_epg = ((paging_group + 3) / l1pa_l1ps_com.pccch.nb_ppch_per_mf52) % 64; // Paging Block Index computation pg_block_index = paging_group % l1pa_l1ps_com.pccch.nb_ppch_per_mf52; // Normal and Extended paging position pep_blk_position = PACKET_PG_POSITION[(((pg_block_index + 3) % l1pa_l1ps_com.pccch.nb_ppch_per_mf52) + (l1pa_l1ps_com.pccch.bs_pag_blks_res + l1pa_l1ps_com.pccch.bs_pbcch_blks)*11)]; // Computation of the PEPCH block position in the MF52 pep_position_2 = (pep_blk_position - 1) + mf52_for_ms_epg * 52; } //Step in PPCH reading block state machine l1pa_l1ps_com.pccch.epg_computation = PPCH_POS_COMP; } // Time between actual fn and next PEPCH block time_to_pep = (pep_position - fn_mod + (64*52)) % (64*52); if(l1a_l1s_com.task_param[PEP] == SEMAPHORE_SET) { // Time between actual fn and next PEPCH block time_to_pep_2 = (pep_position_2 - fn_mod + (64*52)) % (64*52); // Compute Position of First PEP block and update pep_position if(time_to_pep_2 < time_to_pep) { time_to_pep = time_to_pep_2; pep_position = pep_position_2; } // Semaphore is Set, reset it when PEP inactive. if(l1s.task_status[PEP].current_status == INACTIVE) l1a_l1s_com.task_param[PEP] = SEMAPHORE_RESET; } if(l1a_l1s_com.task_param[PEP] == SEMAPHORE_RESET) { // Save scheduling result. l1s.task_status[PEP].time_to_exec = time_to_pep; } }// End of if(l1a_l1s_com.l1s_en_task[PEP] == TASK_ENABLED) } // End of if PNP_TASK || PEP_TASK if(l1a_l1s_com.l1s_en_task[PALLC] == TASK_ENABLED) //--------------------------------- // ALL PCCCH reading is ENABLED. //--------------------------------- { // Semaphore is Set, reset it when PALLC inactive. if(l1a_l1s_com.task_param[PALLC] == SEMAPHORE_SET) { if(l1s.task_status[PALLC].current_status == INACTIVE) l1a_l1s_com.task_param[PALLC] = SEMAPHORE_RESET; } if(l1a_l1s_com.task_param[PALLC] == SEMAPHORE_RESET) { #define PCCCH0_START_TIME 13 - 1 // PCCCH block 0. #define PCCCH1_START_TIME 4 - 1 // PCCCH block 1. #define PCCCH2_START_TIME 8 - 1 // PCCCH block 2. UWORD32 min_time_to_pallc; if(l1s.actual_time.fn_mod13 <= PCCCH1_START_TIME) min_time_to_pallc = PCCCH1_START_TIME - l1s.actual_time.fn_mod13; else if(l1s.actual_time.fn_mod13 <= PCCCH2_START_TIME) min_time_to_pallc = PCCCH2_START_TIME - l1s.actual_time.fn_mod13; else min_time_to_pallc = PCCCH0_START_TIME - l1s.actual_time.fn_mod13; // Save scheduling result. l1s.task_status[PALLC].time_to_exec = min_time_to_pallc; } } // End of if(l1a_l1s_com.l1s_en_task[PALLC] == TASK_ENABLED) if(l1a_l1s_com.l1s_en_task[PBCCHS] == TASK_ENABLED) //-------------------------------------------- // Serving Cell PCCCH reading task is ENABLED. //-------------------------------------------- { if(l1s.task_status[PBCCHS].current_status == INACTIVE) { #define PbcchS l1pa_l1ps_com.pbcchs UWORD32 fn; UWORD32 min_time_to_pbcchs = MAX_FN; UWORD8 psi_index = 0; UWORD8 fn_sub_period = 0; if(PbcchS.control_offset) // 1) PBCCHS timeslot is lower than current PCCCH timeslot, this means that the scheduling // must be anticipated by 1 frame // 2) PBCCHS task must contain a synchro change (sync on "current TS" + 4) // and a synchro back to current TS. // => "offset" array contains the frame to which "next_time.fn" must comply. { fn = l1s.next_time.fn; } else { fn = l1s.actual_time.fn; } // Scheduling... { UWORD16 psi_period = PbcchS.pbcch_period; UWORD16 fn_mod_ps1_period = fn % PbcchS.pbcch_period; UWORD8 i; if(PbcchS.read_all_psi) { psi_period = 52; fn_sub_period = fn_mod_ps1_period / psi_period; fn_mod_ps1_period = fn % psi_period; } // Look for the closest PBCCH block (loop on 20 max) for(i=0;i<PbcchS.nbr_psi;i++) { WORD16 time_to_pbcchs; // Get time diff between current frame and this PBCCHS block. time_to_pbcchs = PbcchS.offset_array[i] - fn_mod_ps1_period; if(time_to_pbcchs < 0) time_to_pbcchs += psi_period; // Save Min time to next PBCCHS block. if(time_to_pbcchs < min_time_to_pbcchs) { min_time_to_pbcchs = time_to_pbcchs; psi_index = i; } } } // Save scheduling result. l1s.task_status[PBCCHS].time_to_exec = min_time_to_pbcchs; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[PBCCHS] = SEMAPHORE_RESET; // If block to decode is B0 (decoding is made in next MF52) then increment fn_sub_period // This is only applicable to the specific case: All PSI to read if(PbcchS.read_all_psi) { if(psi_index == 0) { fn_sub_period +=1; if(fn_sub_period >= PbcchS.psi1_repeat_period) fn_sub_period -= PbcchS.psi1_repeat_period; } } // Save Relative Position of the PBCCH block read to L3 l1pa_l1ps_com.pbcchs.rel_pos_to_report = PbcchS.relative_position_array[psi_index] + (fn_sub_period * (PbcchS.bs_pbcch_blks + 1)); } } if((l1a_l1s_com.l1s_en_task[PBCCHN_TRAN] == TASK_ENABLED) || (l1a_l1s_com.l1s_en_task[PBCCHN_IDLE] == TASK_ENABLED)) //-------------------------------------------- // Neighbor Cell PCCCH reading task is ENABLED. //-------------------------------------------- { #define PbcchN l1pa_l1ps_com.pbcchn WORD32 min_time_to_pbcchn; UWORD32 neighbor_fn; UWORD16 neighbor_fn_mod_ps1_period; WORD16 task; // in case of packet transfer mode there are no measurement windows if (l1a_l1s_com.l1s_en_task[PBCCHN_IDLE] == TASK_ENABLED) task=PBCCHN_IDLE; else task=PBCCHN_TRAN; // ================================ // compute the current neighbor FN // ================================ neighbor_fn = l1s.actual_time.fn + PbcchN.fn_offset ; neighbor_fn_mod_ps1_period = neighbor_fn % PbcchN.pbcch_period; // Get time diff between current neighbor frame and this PBCCHN block. min_time_to_pbcchn = PbcchN.offset- neighbor_fn_mod_ps1_period; if (min_time_to_pbcchn < 0) min_time_to_pbcchn += PbcchN.pbcch_period; if(l1s.task_status[task].current_status == INACTIVE) { // Clear param. synchro. semaphore. l1a_l1s_com.task_param[task] = SEMAPHORE_RESET; } // Save scheduling result. l1s.task_status[task].time_to_exec = min_time_to_pbcchn; } #endif // if L1_GPRS if ((l1a_l1s_com.l1s_en_task[NSYNC] == TASK_ENABLED) && (l1a_l1s_com.l1s_en_task[ALLC] == TASK_DISABLED)) // Do not allow NSYNC task to enter MFTAB in reorg paging mode //------------------------------------ // Neigbour Cell Synchro task enabled //------------------------------------ { if((l1s.task_status[FBNEW].current_status == INACTIVE) && (l1s.task_status[SB2].current_status == INACTIVE) && (l1s.task_status[SBCONF].current_status == INACTIVE)) { //Remarks: //-------- // We do not allow entrance of a neigh FB or SB task if there // is already some neigh task (FB/SB or BCCH) running. This is // to avoid to cope with many abort cases (we cannot list them // easily). #if (L1_12NEIGH == 1) // This machine does not work for DEDICATED MODE. #if (L1_GPRS) if ((l1a_l1s_com.mode != DEDIC_MODE) && (l1a_l1s_com.mode != PACKET_TRANSFER_MODE)) // Due to transition modes sometimes mode is PACKET_TRANSFER and // PDTCH is DISABLED. So we must test also PACKET_TRANSFER mode. #else if (l1a_l1s_com.mode != DEDIC_MODE) #endif { #endif UWORD8 i; UWORD8 j; UWORD8 first_in_list=l1a_l1s_com.nsync.first_in_list ; WORD32 best_time_to_fb = MAX_FN; WORD32 best_time_to_sbconf = MAX_FN; WORD32 best_time_to_sb2 = MAX_FN; UWORD8 best_neigh_fb = 255; UWORD8 best_neigh_sbconf = 255; UWORD8 best_neigh_sb2 = 255; #if (L1_12NEIGH ==1) #if (L1_EOTD == 1) // Up to NBR_NEIGHBOURS + 1 (Serving Cell pending) for(j=first_in_list;j<(NBR_NEIGHBOURS+1+first_in_list);j++) { if (j>=NBR_NEIGHBOURS+1) i=j-NBR_NEIGHBOURS-1; else i=j; #else // Up to NBR_NEIGHBOURS for(j=first_in_list;j<(NBR_NEIGHBOURS+first_in_list);j++) { if (j>=NBR_NEIGHBOURS) i=j-NBR_NEIGHBOURS; else i=j; #endif // L1_EOTD #else // L1_12NEIGH for(j=first_in_list;j<(6+first_in_list);j++) { if (j>=6) i=j-6; else i=j; #endif // L1_12NEIGH // Consider only the "in use" locations from the "N neigh. list". if(l1a_l1s_com.nsync.list[i].status == NSYNC_PENDING) { UWORD32 neigh_fn_mod51; switch(l1a_l1s_com.nsync.list[i].timing_validity) { case 0: // No valid info is supplied: search FB with no a priori info. { // Consider the Neighbour in respecting their order in the list. if(best_time_to_fb != 0) { best_time_to_fb = 0; best_neigh_fb = i; } } break; case 1: // Approximate timing is supplied: search FB with a priori info.. { UWORD32 min_time_to_fb = MAX_FN; // Get neighbour cell FN % 51. neigh_fn_mod51 = (l1s.actual_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51; // Attempt to read 2nd FB. // Frame 7 is the position to read 2nd FB within MF51 (due to C/W/R and AGC) if(neigh_fn_mod51 <= 7) { min_time_to_fb = 7 - neigh_fn_mod51; } // Attempt to read 3rd FB. // Frame 17 is the position to read 3rd FB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 17) { min_time_to_fb = 17 - neigh_fn_mod51; } // Attempt to read 4th FB. // Frame 27 is the position to read 4th FB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 27) { min_time_to_fb = 27 - neigh_fn_mod51; } // Attempt to read 5th FB. // Frame 37 is the position to read 5th FB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 37) { min_time_to_fb = 37 - neigh_fn_mod51; } // Attempt to read 1st FB. // Frame 48 is the position to read 1st FB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 48) { min_time_to_fb = 48 - neigh_fn_mod51; } // Attempt to read 2nd FB // Special case: frame 49 and frame 50 else { min_time_to_fb = 50 - neigh_fn_mod51 + 8; } if(min_time_to_fb <(UWORD32 ) best_time_to_fb) { best_time_to_fb = min_time_to_fb; best_neigh_fb = i; } } break; case 2: // Accurate timing is supplied: confirm SB. { UWORD32 min_time_to_sb = MAX_FN; // Get neighbour cell FN % 51. neigh_fn_mod51 = (l1s.actual_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51; // Attempt to read 2nd SB. // Frame 8 is the position to read 2nd SB within MF51 (due to C/W/R and AGC) if(neigh_fn_mod51 <= 8) { min_time_to_sb = 8 - neigh_fn_mod51; } // Attempt to read 3rd SB. // Frame 18 is the position to read 3rd SB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 18) { min_time_to_sb = 18 - neigh_fn_mod51; } // Attempt to read 4th SB. // Frame 28 is the position to read 4th SB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 28) { min_time_to_sb = 28 - neigh_fn_mod51; } // Attempt to read 5th SB. // Frame 38 is the position to read 5th SB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 38) { min_time_to_sb = 38 - neigh_fn_mod51; } // Attempt to read 1st SB. // Frame 49 is the position to read 1st SB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 49) { min_time_to_sb = 49 - neigh_fn_mod51; } // Attempt to read 2nd SB // Special case: Frame=50 (idle frame) else { min_time_to_sb = 9; } if(min_time_to_sb <(UWORD32 ) best_time_to_sbconf) { best_time_to_sbconf = min_time_to_sb; best_neigh_sbconf = i; } } break; #if ((REL99 == 1) && ((FF_BHO == 1) || (FF_RTD == 1))) case SB_ACQUISITION_PHASE: // SB search following a FB search. #else case 3: // SB search following a FB search. #endif { UWORD8 spent_fn; UWORD32 min_time_to_sb = MAX_FN; // "fn_offset" contains the FN%51 corresponding to the FB detected spent_fn = (l1s.actual_time.t3 - l1a_l1s_com.nsync.list[i].fn_offset + 51) % 51; // Attempt to read 1st SB. // Frame 8 is the position to read 1st SB within MF51 (due to C/W/R and AGC) if(spent_fn <= 8) { min_time_to_sb = 8 - spent_fn; } // Attempt to read 2nd SB. // Frame 18 is the position to read 2nd SB within MF51 (due to C/W/R and AGC) else if(spent_fn <= 18) { min_time_to_sb = 18 - spent_fn; } // Attempt to read 3rd SB. // Frame 28 is the position to read 3rd SB within MF51 (due to C/W/R and AGC) else if(spent_fn <= 28) { min_time_to_sb = 28 - spent_fn; } // Attempt to read 4th SB. // Frame 38 is the position to read 4th SB within MF51 (due to C/W/R and AGC) else if(spent_fn <= 38) { min_time_to_sb = 38 - spent_fn; } // Attempt to read 5tht SB. // Frame 49 is the position to read 5tht SB within MF51 (due to C/W/R and AGC) else if(spent_fn <= 49) { min_time_to_sb = 49 - spent_fn; } // Attempt to read 2nd SB // Special case: Frame=50 (idle frame) else { min_time_to_sb = 9; } if(min_time_to_sb <= ( UWORD32 )best_time_to_sb2) { best_time_to_sb2 = min_time_to_sb; best_neigh_sb2 = i; } } break; } // End of "switch" } // End of "if" } // End of "for" if(best_neigh_fb != 255) { // Save active neighbour id. l1a_l1s_com.nsync.active_fb_id = best_neigh_fb; // Save scheduling result. l1s.task_status[FBNEW].time_to_exec = best_time_to_fb; // Enable FBNEW task l1a_l1s_com.l1s_en_task[FBNEW] = TASK_ENABLED; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[FBNEW] = SEMAPHORE_RESET; } if(best_neigh_sbconf != 255) { // Save active neighbour id. l1a_l1s_com.nsync.active_sbconf_id = best_neigh_sbconf; // Save scheduling result. l1s.task_status[SBCONF].time_to_exec = best_time_to_sbconf; l1a_l1s_com.l1s_en_task[SBCONF] = TASK_ENABLED; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SBCONF] = SEMAPHORE_RESET; } if(best_neigh_sb2 != 255) { // Save active neighbour id. l1a_l1s_com.nsync.active_sb_id = best_neigh_sb2; // Save scheduling result. l1s.task_status[SB2].time_to_exec = best_time_to_sb2; // Enable SB2 task l1a_l1s_com.l1s_en_task[SB2] = TASK_ENABLED; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SB2] = SEMAPHORE_RESET; } #if (L1_12NEIGH == 1) } // End of "if / DEDIC = IDLE-MODE #endif } // End of "if / current_status" } // End of "if / NSYNC" if(l1a_l1s_com.l1s_en_task[HWTEST] == TASK_ENABLED) //------------------------- // HW_TEST task is ENABLED. //------------------------- { if(l1s.task_status[HWTEST].current_status == INACTIVE) // HW_TEST task is INACTIVE. // Rem: HW_TEST task has no occurence time. Therefore whenever HW_TEST // is ENABLED and INACTIVE it must be executed. { // Save scheduling result. l1s.task_status[HWTEST].time_to_exec = 0; } } //================================================================ //== DEDICATED MODE TASKS == //== -------------------- == //================================================================ #if (L1_12NEIGH == 0) if(l1a_l1s_com.l1s_en_task[FB26] == TASK_ENABLED) //------------------------- // FB26 task is ENABLED. //------------------------- { UWORD32 time_to_fb26 = MAX_FN; if(l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) //--------------------------------------------- // Dedicated mode tasks are enabled. //--------------------------------------------- { T_CHANNEL_DESCRIPTION *desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; // Rem: this task is used in dedicated/TCH_H/F if(desc_ptr->channel_type == TCH_H) { UWORD8 normalised_fn_mod26 = (l1s.actual_time.fn_in_report - desc_ptr->subchannel ) % 26; if(normalised_fn_mod26 <= 22) time_to_fb26 = 22 - normalised_fn_mod26; else time_to_fb26 = 26+ 22 - normalised_fn_mod26; } else if(desc_ptr->channel_type == TCH_F) { UWORD8 normalised_fn_mod26 = l1s.actual_time.fn_in_report % 26; if(normalised_fn_mod26 <= 23) time_to_fb26 = 23 - normalised_fn_mod26; else time_to_fb26 = 26 + 23 - normalised_fn_mod26; } } #if L1_GPRS else if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) //--------------------------------------------- // Packet Transfer mode task is enabled. //--------------------------------------------- { if(l1s.actual_time.t2 <= 23) time_to_fb26 = 23 - l1s.actual_time.t2; else time_to_fb26 = 26 + 23 - l1s.actual_time.t2; } #endif // No scheduling result for FB26 task to avoid selection of this task. // -> l1s.task_status[FB26].time_to_exec stays equal to MAX_FN // Set FB26 as PENDING to trigger the l1s_merge_manager() to install it // in MFTAB. if(time_to_fb26 == 0) l1s.task_status[FB26].new_status = PENDING; // Set active neighbor identifier. l1a_l1s_com.nsync.active_fb_id = 0; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[FB26] = SEMAPHORE_RESET; } // End if(...[FB26] == TASK_ENABLED) if(l1a_l1s_com.l1s_en_task[SB26] == TASK_ENABLED) //------------------------- // SB26 task is ENABLED. //------------------------- { WORD32 time_to_sb26 = MAX_FN; if(l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) //--------------------------------------------- // Dedicated mode tasks are enabled. //--------------------------------------------- { T_CHANNEL_DESCRIPTION *desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; // Rem: this task is used in dedicated/TCH_H/F if((desc_ptr->channel_type == TCH_F) || (desc_ptr->channel_type == TCH_H)) { // Monitoring area starting frame is reached... if(l1s.actual_time.fn <= l1a_l1s_com.nsync.list[0].fn_offset) time_to_sb26 = l1a_l1s_com.nsync.list[0].fn_offset - l1s.actual_time.fn; else time_to_sb26 = MAX_FN + l1a_l1s_com.nsync.list[0].fn_offset - l1s.actual_time.fn; } } #if L1_GPRS else if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) //--------------------------------------------- // Packet Transfer mode task is enabled. //--------------------------------------------- { UWORD8 SB26_attempt = l1a_l1s_com.nsync.list[0].sb26_attempt; // schedule SB26 at all possible positions // attempt=0 => first SB after FB found is at FB position + 52 // attempt=1 => next SB is at position: FN_offset + 9*26 // attempt=2 => or next SB is at position: FN_offset + 9*26 + 52 (due to Idle frame) // REM: an higher priority task could have canceled the SB scheduled, that's why // we must plan the following SB with its 2 possible positions. // Monitoring area starting frame is reached... time_to_sb26 = l1a_l1s_com.nsync.list[0].fn_offset - l1s.actual_time.fn; if(time_to_sb26 < 0) // in this case a SB was missed by a higher priority task { if (SB26_attempt == 1) // next SB is 9*26 frame later time_to_sb26 += 26*9; else if (SB26_attempt == 2) // or next FB is 9*26 + 52 frames later time_to_sb26 += 26*9 + 52; else // should never happen time_to_sb26 += MAX_FN; } if(time_to_sb26 == 0) { l1a_l1s_com.nsync.list[0].sb26_attempt++; if (SB26_attempt>2) l1a_l1s_com.nsync.list[0].sb26_attempt=1; } } #endif // No scheduling result for SB26 task to avoid selection of this task. // -> l1s.task_status[SB26].time_to_exec stays equal to MAX_FN // Set SB26 as PENDING to trigger the l1s_merge_manager() to install it // in MFTAB. if(time_to_sb26 == 0) l1s.task_status[SB26].new_status = PENDING; // Set active neighbor identifier. l1a_l1s_com.nsync.active_sb_id = 0; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SB26] = SEMAPHORE_RESET; } // End if(...[SB26] == TASK_ENABLED) if(l1a_l1s_com.l1s_en_task[SBCNF26] == TASK_ENABLED) //------------------------- // SBCNF26 task is ENABLED. //------------------------- { BOOL check_sbcnf26 = 0; if(l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) //--------------------------------------------- // Dedicated mode tasks are enabled. //--------------------------------------------- { T_CHANNEL_DESCRIPTION *desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; UWORD8 normalised_fn_mod26; normalised_fn_mod26 = (l1s.actual_time.fn_in_report - desc_ptr->subchannel ) % 26; if(((normalised_fn_mod26 == 22) && (desc_ptr->channel_type == TCH_H)) || (((l1s.actual_time.fn_in_report % 26) == 23) && (desc_ptr->channel_type == TCH_F))) // Monitoring area control frame is reached... { check_sbcnf26 = 1; } } #if L1_GPRS else if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) //--------------------------------------------- // Packet Transfer mode task is enabled. //--------------------------------------------- { if(l1s.actual_time.t2 == 23) // Monitoring area control frame is reached... { check_sbcnf26 = 1; } } #endif if(check_sbcnf26) // SBCNF26 must be checked. { UWORD32 next_neigh_fn_mod51; // Get neighbor domain frame number %51 for frame 24. next_neigh_fn_mod51 = (l1s.next_time.fn + l1a_l1s_com.nsync.list[0].fn_offset) % 51; // No scheduling result for SBCNF26 task to avoid selection of this task. // -> l1s.task_status[SBCNF26].time_to_exec stays equal to MAX_FN if((next_neigh_fn_mod51 % 10) == 1) // SB26 rx window starts in the frame 24... { if(l1a_l1s_com.nsync.list[0].time_alignmt >= l1_config.params.fb26_anchoring_time) // SB feet in the search slot... // Set SBCNF26 as PENDING to trigger the l1s_merge_manager() to install it // in MFTAB. { l1s.task_status[SBCNF26].new_status = PENDING; l1a_l1s_com.nsync.list[0].sb26_offset = 0; // Set active neighbor identifier. l1a_l1s_com.nsync.active_sbconf_id = 0; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SBCNF26] = SEMAPHORE_RESET; } } else if((next_neigh_fn_mod51 == 0) || (next_neigh_fn_mod51 == 10) || (next_neigh_fn_mod51 == 20) || (next_neigh_fn_mod51 == 30) || (next_neigh_fn_mod51 == 40)) // SB26 rx window starts in the frame 25... { if(l1a_l1s_com.nsync.list[0].time_alignmt < ((l1_config.params.fb26_anchoring_time +FB26_ACQUIS_DURATION -SB_ACQUIS_DURATION +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE)) // SB feet in the search slot... // Set SBCNF26 as PENDING to trigger the l1s_merge_manager() to install it // in MFTAB. { l1s.task_status[SBCNF26].new_status = PENDING; l1a_l1s_com.nsync.list[0].sb26_offset = 1; // Set active neighbor identifier. l1a_l1s_com.nsync.active_sbconf_id = 0; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SBCNF26] = SEMAPHORE_RESET; } } } } if(l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) //--------------------------------------------- // Dedicated mode tasks are enabled. //--------------------------------------------- { T_CHANNEL_DESCRIPTION *desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; T_SDCCH_DESC *sdcch_desc = NULL;//OMAPS00090550 // No scheduling result for DEDIC task to avoid selection of this task. // -> l1s.task_status[DEDIC].time_to_exec stays equal to MAX_FN // DEDIC task requires to run L1S scheduler every frame. l1a_l1s_com.time_to_next_l1s_task = 0; //================================= // MF51 tasks... //================================= if((desc_ptr->channel_type == SDCCH_4) || (desc_ptr->channel_type == SDCCH_8)) // SDCCH channel -> MF51 structure. { UWORD8 start_time =0; //omaps00090550 UWORD8 fn_in_report_mod51 = l1s.next_time.fn_in_report % 51; // Save position of the monitoring area for SDCCH. if(desc_ptr->channel_type == SDCCH_8) { start_time = SDCCH_DESC_NCOMB[desc_ptr->subchannel].mon_area_position; sdcch_desc = &(SDCCH_DESC_NCOMB[desc_ptr->subchannel]); } else { start_time = SDCCH_DESC_COMB[desc_ptr->subchannel].mon_area_position; sdcch_desc = &(SDCCH_DESC_COMB[desc_ptr->subchannel]); } if(l1a_l1s_com.l1s_en_task[FB51] == TASK_ENABLED) //------------------------- // FB51 task is ENABLED. //------------------------- { UWORD32 time_to_fb51; if(l1s.actual_time.fn_in_report <= start_time) time_to_fb51 = start_time - l1s.actual_time.fn_in_report; else time_to_fb51 = MAX_FN + start_time - l1s.actual_time.fn_in_report; // Save scheduling result. l1s.task_status[FB51].time_to_exec = time_to_fb51; // Set active neighbor identifier. l1a_l1s_com.nsync.active_fb_id = 0; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[FB51] = SEMAPHORE_RESET; } if(l1a_l1s_com.l1s_en_task[SB51] == TASK_ENABLED) //------------------------- // SB51 task is ENABLED. //------------------------- { // Rem: this task is used in dedicated/SDCCH. // SB reading task is 102 frames after the FB. UWORD32 time_to_sb51; UWORD32 fn_sb51 = (l1a_l1s_com.nsync.list[0].fn_offset + 102)%MAX_FN; fn_sb51 = l1a_l1s_com.nsync.list[0].fn_offset + 102; if(fn_sb51 >= MAX_FN) fn_sb51 -= MAX_FN; if(l1s.actual_time.fn <= fn_sb51) time_to_sb51 = fn_sb51 - l1s.actual_time.fn; else time_to_sb51 = MAX_FN + fn_sb51 - l1s.actual_time.fn; // Save scheduling result. l1s.task_status[SB51].time_to_exec = time_to_sb51; // Set active neighbor identifier. l1a_l1s_com.nsync.active_sb_id = 0; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SB51] = SEMAPHORE_RESET; } if(l1a_l1s_com.l1s_en_task[SBCNF51] == TASK_ENABLED) //------------------------- // SBCNF51 task is ENABLED. //------------------------- { // Rem: this task is used in dedicated/SDCCH. if((l1s.actual_time.fn_in_report >= start_time) && (l1s.actual_time.fn_in_report < start_time + 11)) { UWORD32 neigh_fn_mod51; // Get neighbour cell FN % 51 and then % 10. neigh_fn_mod51 = (l1s.actual_time.fn + l1a_l1s_com.nsync.list[0].fn_offset) % 51; // SBCNF51 task is a special case: it is not using a predictive scheduling. // Thi scheduling would be too complex. if((neigh_fn_mod51 == 0) || (neigh_fn_mod51 == 10) || (neigh_fn_mod51 == 20) || (neigh_fn_mod51 == 30) || (neigh_fn_mod51 == 40)) // It is time to start SBCNF51 task. { // SBCNF51 must be started immediately. l1s.task_status[SBCNF51].time_to_exec = 0; // Set active neighbor identifier. l1a_l1s_com.nsync.active_sbconf_id = 0; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SBCNF51] = SEMAPHORE_RESET; } else { // SBCNF51 is not started. l1s.task_status[SBCNF51].time_to_exec = MAX_FN; } } } if((l1a_l1s_com.l1s_en_task[DDL] == TASK_ENABLED) && (sdcch_desc != NULL))//OMAPS00090550 //------------------------- // SDCCH DL task is ENABLED. //------------------------- { UWORD32 time_to_ddl; if(fn_in_report_mod51 <= sdcch_desc->dl_sdcch_position) time_to_ddl = sdcch_desc->dl_sdcch_position - fn_in_report_mod51; else time_to_ddl = 51 + sdcch_desc->dl_sdcch_position - fn_in_report_mod51; // Save scheduling result. l1s.task_status[DDL].time_to_exec = time_to_ddl; } if((l1a_l1s_com.l1s_en_task[DUL] == TASK_ENABLED) && (sdcch_desc != NULL))//OMAPS00090550 //------------------------- // SDCCH DUL task is ENABLED. //------------------------- { UWORD32 time_to_dul; if(fn_in_report_mod51 <= sdcch_desc->ul_sdcch_position) time_to_dul = sdcch_desc->ul_sdcch_position - fn_in_report_mod51; else time_to_dul = 51 + sdcch_desc->ul_sdcch_position - fn_in_report_mod51; // Save scheduling result. l1s.task_status[DUL].time_to_exec = time_to_dul; } if((l1a_l1s_com.l1s_en_task[ADL] == TASK_ENABLED) && (sdcch_desc != NULL))//OMAPS00090550 //---------------------------------- // SACCH DL (SDCCH) task is ENABLED. //---------------------------------- { UWORD32 time_to_adl; if(l1s.next_time.fn_in_report <= sdcch_desc->dl_sacch_position) time_to_adl = sdcch_desc->dl_sacch_position - l1s.next_time.fn_in_report; else time_to_adl = 102 + sdcch_desc->dl_sacch_position - l1s.next_time.fn_in_report; // Save scheduling result. l1s.task_status[ADL].time_to_exec = time_to_adl; } if((l1a_l1s_com.l1s_en_task[AUL] == TASK_ENABLED) && (sdcch_desc != NULL))//OMAPS00090550 //---------------------------------- // SACCH UL (SDCCH) task is ENABLED. //---------------------------------- { UWORD32 time_to_aul; if(l1s.next_time.fn_in_report <= sdcch_desc->ul_sacch_position) time_to_aul = sdcch_desc->ul_sacch_position - l1s.next_time.fn_in_report; else time_to_aul = MAX_FN + sdcch_desc->ul_sacch_position - l1s.next_time.fn_in_report; // Save scheduling result. l1s.task_status[AUL].time_to_exec = time_to_aul; } } // channel_type == SDCCH_4 or SDCCH_8 #endif //================================================================ //== DEDICATED MODE TASKS == //== -------------------- == //== NEW NCELL MONITORING SCHEDULER for 12 Neighbors == //================================================================ #if (L1_12NEIGH == 1) #if (L1_GPRS) // This machine works only for DEDICATED MODE and PACKET TRANSFER MODE // (Remark: PACKET TRANSFER MODE activated == PDTCH task activated) if((l1a_l1s_com.mode == DEDIC_MODE) || (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED)) #else // This machine works only for DEDICATED MODE. if (l1a_l1s_com.mode == DEDIC_MODE) #endif { #define MF51 1 #define MF26 2 UWORD8 channel = 255; UWORD8 start_time; UWORD8 fn_in_report_mod51 = l1s.next_time.fn_in_report % 51; T_CHANNEL_DESCRIPTION *desc_ptr; T_SDCCH_DESC *sdcch_desc; if(l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) //--------------------------------------------- // Dedicated mode tasks are enabled. //--------------------------------------------- { // init desc_ptr desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; // No scheduling result for DEDIC task to avoid selection of this task. // -> l1s.task_status[DEDIC].time_to_exec stays equal to MAX_FN // DEDIC task requires to run L1S scheduler every frame l1a_l1s_com.time_to_next_l1s_task = 0; // Rem: this task is used in dedicated/TCH_H/F // MF51 tasks... //============== if((desc_ptr->channel_type == SDCCH_4) || (desc_ptr->channel_type == SDCCH_8)) // SDCCH channel -> MF51 structure. { // init channel to MF51 channel = MF51; // Save position of the monitoring area for SDCCH. if(desc_ptr->channel_type == SDCCH_8) { start_time = SDCCH_DESC_NCOMB[desc_ptr->subchannel].mon_area_position; sdcch_desc = &(SDCCH_DESC_NCOMB[desc_ptr->subchannel]); } else { start_time = SDCCH_DESC_COMB[desc_ptr->subchannel].mon_area_position; sdcch_desc = &(SDCCH_DESC_COMB[desc_ptr->subchannel]); } } // MF26 tasks... //============== else channel = MF26; } // End of "if DEDIC task" #if (L1_GPRS) else if (l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) channel = MF26; #endif //============================================================ // DEDIC MODE - MF51 - NEIGHBOUR MONITORING tasks SCHEDULING //============================================================ if (channel == MF51) { if (l1a_l1s_com.l1s_en_task[NSYNC] == TASK_ENABLED) //-------------------------------------------- // Neigbour Cell Synchro task enabled for MF51 //-------------------------------------------- { if((l1s.task_status[FB51].current_status == INACTIVE) && (l1s.task_status[SB51].current_status == INACTIVE) && (l1s.task_status[SBCNF51].current_status == INACTIVE)) { //Remarks: //-------- // We do not allow entrance of a neigh FB or SB task if there // is already some neigh task (FB/SB or BCCH) running. This is // to avoid to cope with many abort cases (we cannot list them // easily). UWORD8 i; UWORD8 j; UWORD8 first_in_list=l1a_l1s_com.nsync.first_in_list ; WORD32 best_time_to_fb = MAX_FN; WORD32 best_time_to_sb = MAX_FN; WORD32 best_time_to_sbconf = MAX_FN; UWORD8 best_neigh_fb = 255; UWORD8 best_neigh_sbconf = 255; UWORD8 best_neigh_sb = 255; #if (L1_EOTD == 1) // Up to NBR_NEIGHBOURS + 1 (Serving Cell pending) for(j=first_in_list;j<(NBR_NEIGHBOURS+1+first_in_list);j++) { if (j>=NBR_NEIGHBOURS+1) i=j-NBR_NEIGHBOURS-1; else i=j; #else // Up to NBR_NEIGHBOURS for(j=first_in_list;j<(NBR_NEIGHBOURS+first_in_list);j++) { if (j>=NBR_NEIGHBOURS) i=j-NBR_NEIGHBOURS; else i=j; #endif // L1_EOTD // Consider only the "in use" locations from the "12 neigh. list". if(l1a_l1s_com.nsync.list[i].status == NSYNC_PENDING) { switch(l1a_l1s_com.nsync.list[i].timing_validity) { case 0: // No valid info is supplied: search FB with no a priori info. #if ((REL99 == 1) && (FF_RTD == 1)) case 3: // approximate timing based on RTD is supplied #endif { UWORD32 min_time_to_fb = MAX_FN; if(l1s.actual_time.fn_in_report <= start_time) min_time_to_fb = start_time - l1s.actual_time.fn_in_report; else min_time_to_fb = MAX_FN + start_time - l1s.actual_time.fn_in_report; if(min_time_to_fb < (UWORD32)best_time_to_fb) { best_time_to_fb = min_time_to_fb; best_neigh_fb = i; } } break; case 1: // Approximate timing is supplied: search FB with a priori info.. { UWORD32 min_time_to_fb = MAX_FN; UWORD32 neigh_fn_mod51; if((l1s.actual_time.fn_in_report >= start_time) && (l1s.actual_time.fn_in_report < start_time + 11)) { UWORD32 neigh_fn_mod51; // Get neighbour cell FN % 51 and then % 10. neigh_fn_mod51 = (l1s.actual_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51; // Attempt to read 2nd FB. // Frame 7 is the position to read 2nd FB within MF51 (due to C/W/R and AGC) if(neigh_fn_mod51 <= 7) { min_time_to_fb = 7 - neigh_fn_mod51; } // Attempt to read 3rd FB. // Frame 17 is the position to read 3rd FB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 17) { min_time_to_fb = 17 - neigh_fn_mod51; } // Attempt to read 4th FB. // Frame 27 is the position to read 4th FB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 27) { min_time_to_fb = 27 - neigh_fn_mod51; } // Attempt to read 5th FB. // Frame 37 is the position to read 5th FB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 37) { min_time_to_fb = 37 - neigh_fn_mod51; } // Attempt to read 1st FB. // Frame 48 is the position to read 1st FB within MF51 (due to C/W/R and AGC) else if(neigh_fn_mod51 <= 48) { min_time_to_fb = 48 - neigh_fn_mod51; } // Attempt to read 2nd FB // Special case: frame 49 and frame 50 else { min_time_to_fb = 50 - neigh_fn_mod51 + 8; } if(min_time_to_fb <(UWORD32) best_time_to_fb) { best_time_to_fb = min_time_to_fb; best_neigh_fb = i; } } } break; case 2: // Accurate timing is supplied SBCONF: confirm SB. { UWORD32 min_time_to_sbconf = MAX_FN; if((l1s.actual_time.fn_in_report >= start_time) && (l1s.actual_time.fn_in_report < start_time + 11)) { UWORD32 neigh_fn_mod51; // Get neighbour cell FN % 51 and then % 10. neigh_fn_mod51 = (l1s.actual_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51; // SBCNF51 task is a special case: it is not using a predictive scheduling. // Thi scheduling would be too complex. if((neigh_fn_mod51 == 0) || (neigh_fn_mod51 == 10) || (neigh_fn_mod51 == 20) || (neigh_fn_mod51 == 30) || (neigh_fn_mod51 == 40)) // It is time to start SBCNF51 task. { min_time_to_sbconf = 0; } } if(min_time_to_sbconf <(UWORD32) best_time_to_sbconf) { best_time_to_sbconf = min_time_to_sbconf; best_neigh_sbconf = i; } } break; #if ((REL99 == 1) && ((FF_BHO == 1) || (FF_RTD == 1))) case SB_ACQUISITION_PHASE: // SB search following a FB search. #else case 3: // SB search following a FB search. #endif { UWORD32 min_time_to_sb = MAX_FN; UWORD32 fn_sb51 = (l1a_l1s_com.nsync.list[i].fn_offset + 102)%MAX_FN; fn_sb51 = l1a_l1s_com.nsync.list[i].fn_offset + 102; if(fn_sb51 >= MAX_FN) fn_sb51 -= MAX_FN; if(l1s.actual_time.fn <= fn_sb51) min_time_to_sb = fn_sb51 - l1s.actual_time.fn; else min_time_to_sb = MAX_FN + fn_sb51 - l1s.actual_time.fn; if(min_time_to_sb <(UWORD32) best_time_to_sb) { best_time_to_sb = min_time_to_sb; best_neigh_sb = i; } } break; } // End of "switch" } // End of "if PENDING" } // End of "for" if(best_neigh_fb != 255) // for FB ACQUISITION or CONFIRMATION { // Save active neighbour id. l1a_l1s_com.nsync.active_fb_id = best_neigh_fb; // Save scheduling result. l1s.task_status[FB51].time_to_exec = best_time_to_fb; // Enable FB51 task l1a_l1s_com.l1s_en_task[FB51] = TASK_ENABLED; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[FB51] = SEMAPHORE_RESET; } if(best_neigh_sbconf != 255) // for SB CONFIRMATION { // Save active neighbour id. l1a_l1s_com.nsync.active_sbconf_id = best_neigh_sbconf; // Save scheduling result. l1s.task_status[SBCNF51].time_to_exec = 0; // Enable SBCNF51 task l1a_l1s_com.l1s_en_task[SBCNF51] = TASK_ENABLED; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SBCNF51] = SEMAPHORE_RESET; } if(best_neigh_sb != 255) // for SB ACQUISITION { // Save active neighbour id. l1a_l1s_com.nsync.active_sb_id = best_neigh_sb; // Save scheduling result. l1s.task_status[SB51].time_to_exec = best_time_to_sb; // Enable SB2 task l1a_l1s_com.l1s_en_task[SB51] = TASK_ENABLED; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SB51] = SEMAPHORE_RESET; } } // End of "if / current_status" } // End of "if / NSYNC" if (l1a_l1s_com.l1s_en_task[DDL] == TASK_ENABLED) //------------------------- // SDCCH DL task is ENABLED. //------------------------- { UWORD32 time_to_ddl; if(fn_in_report_mod51 <= ( UWORD8)sdcch_desc->dl_sdcch_position) time_to_ddl = sdcch_desc->dl_sdcch_position - fn_in_report_mod51; else time_to_ddl = 51 + sdcch_desc->dl_sdcch_position - fn_in_report_mod51; // Save scheduling result. l1s.task_status[DDL].time_to_exec = time_to_ddl; } if (l1a_l1s_com.l1s_en_task[DUL] == TASK_ENABLED) //------------------------- // SDCCH DUL task is ENABLED. //------------------------- { UWORD32 time_to_dul; if(fn_in_report_mod51 <= sdcch_desc->ul_sdcch_position) time_to_dul = sdcch_desc->ul_sdcch_position - fn_in_report_mod51; else time_to_dul = 51 + sdcch_desc->ul_sdcch_position - fn_in_report_mod51; // Save scheduling result. l1s.task_status[DUL].time_to_exec = time_to_dul; } if (l1a_l1s_com.l1s_en_task[ADL] == TASK_ENABLED) //---------------------------------- // SACCH DL (SDCCH) task is ENABLED. //---------------------------------- { UWORD32 time_to_adl; if(l1s.next_time.fn_in_report <= sdcch_desc->dl_sacch_position) time_to_adl = sdcch_desc->dl_sacch_position - l1s.next_time.fn_in_report; else time_to_adl = 102 + sdcch_desc->dl_sacch_position - l1s.next_time.fn_in_report; // Save scheduling result. l1s.task_status[ADL].time_to_exec = time_to_adl; } if (l1a_l1s_com.l1s_en_task[AUL] == TASK_ENABLED) //---------------------------------- // SACCH UL (SDCCH) task is ENABLED. //---------------------------------- { UWORD32 time_to_aul; if(l1s.next_time.fn_in_report <= sdcch_desc->ul_sacch_position) time_to_aul = sdcch_desc->ul_sacch_position - l1s.next_time.fn_in_report; else time_to_aul = MAX_FN + sdcch_desc->ul_sacch_position - l1s.next_time.fn_in_report; // Save scheduling result. l1s.task_status[AUL].time_to_exec = time_to_aul; } } // End of "if MF51" //================================================================== // DEDIC/PACKET MODE - MF26 - NEIGHBOUR MONITORING tasks SCHEDULING //================================================================== if (channel == MF26) { #if L1_EDA UWORD8 enter_nsync_task = TRUE; //Initialize FB/SB activity detection flag if((l1s.actual_time.t2 < 20) || (l1s.actual_time.t2 == 25)) { l1ps_macs_com.fb_sb_task_enabled = FALSE; } #endif if (l1a_l1s_com.l1s_en_task[NSYNC] == TASK_ENABLED) //----------------------------------------------------------- // Neigbour Cell Synchro task enabled for DEDIC TCH or PACKET //----------------------------------------------------------- { T_CHANNEL_DESCRIPTION *desc_ptr; if (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) { desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; } if((l1s.task_status[FB26].current_status == INACTIVE) && (l1s.task_status[SB26].current_status == INACTIVE) && (l1s.task_status[SBCNF26].current_status == INACTIVE)) { //Remarks: //-------- // We do not allow entrance of a neigh FB or SB task if there // is already some neigh task (FB/SB or BCCH) running. This is // to avoid to cope with many abort cases (we cannot list them // easily). UWORD8 i; UWORD8 j; UWORD8 first_in_list=l1a_l1s_com.nsync.first_in_list ; WORD32 best_time_to_fb = MAX_FN; WORD32 best_time_to_sbconf = MAX_FN; WORD32 best_time_to_fbconf = MAX_FN; WORD32 best_time_to_sb = MAX_FN; UWORD8 best_neigh_fb = 255; UWORD8 best_neigh_sbconf = 255; UWORD8 best_neigh_fbconf = 255; UWORD8 best_neigh_sb = 255; #if ((REL99 == 1) && (FF_BHO == 1)) UWORD8 fb26_position ; #endif #if (L1_EOTD == 1) // Up to NBR_NEIGHBOURS + 1 (Serving Cell pending) for(j=first_in_list;j<(NBR_NEIGHBOURS+1+first_in_list);j++) { if (j>=NBR_NEIGHBOURS+1) i=j-NBR_NEIGHBOURS-1; else i=j; #else // Up to NBR_NEIGHBOURS for(j=first_in_list;j<(NBR_NEIGHBOURS+first_in_list);j++) { if (j>=NBR_NEIGHBOURS) i=j-NBR_NEIGHBOURS; else i=j; #endif // L1_EOTD // Consider only the "in use" locations from the "NBR_NEIGHBOURS neigh. list". if(l1a_l1s_com.nsync.list[i].status == NSYNC_PENDING) { switch(l1a_l1s_com.nsync.list[i].timing_validity) { case 0: // No valid info is supplied: search FB with no a priori info. { UWORD32 min_time_to_fb = MAX_FN; if (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) //--------------------------------------------- // Dedicated mode tasks are enabled. //--------------------------------------------- { // Rem: this task is used in dedicated/TCH_H/F // No Scheduling result for FB26 task to avoid selection of this task. if(desc_ptr->channel_type == TCH_H) { UWORD8 normalised_fn_mod26 = ((l1s.actual_time.fn_in_report) - desc_ptr->subchannel ) % 26; if(normalised_fn_mod26 <= 22) min_time_to_fb = 22 - normalised_fn_mod26; else min_time_to_fb = 26+ 22 - normalised_fn_mod26; } else if(desc_ptr->channel_type == TCH_F) { UWORD8 normalised_fn_mod26 = l1s.actual_time.fn_in_report % 26; if(normalised_fn_mod26 <= 23) min_time_to_fb = 23 - normalised_fn_mod26; else min_time_to_fb = 26 + 23 - normalised_fn_mod26; } } // end DEDIC task #if L1_GPRS else if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) //--------------------------------------------- // Packet Transfer mode task is enabled. //--------------------------------------------- { if(l1s.actual_time.t2 <= 23) min_time_to_fb = 23 - l1s.actual_time.t2; else min_time_to_fb = 26 + 23 - l1s.actual_time.t2; } #endif if(min_time_to_fb < ( UWORD32)best_time_to_fb) { best_time_to_fb = min_time_to_fb; best_neigh_fb = i; } } break; case 1: // Approximate timing is supplied: search FB with a priori info.. #if ((REL99 == 1) && (FF_RTD == 1)) case 3: // approximate timing based on RTD is supplied #endif { BOOL check_fbcnf26 = 0; UWORD32 min_time_to_fbconf = MAX_FN; if (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) //--------------------------------------------- // Dedicated mode tasks are enabled. //--------------------------------------------- { UWORD8 normalised_fn_mod26; normalised_fn_mod26 = (l1s.actual_time.fn_in_report - desc_ptr->subchannel ) % 26; if(((normalised_fn_mod26 == 22) && (desc_ptr->channel_type == TCH_H)) || (((l1s.actual_time.fn_in_report % 26) == 23) && (desc_ptr->channel_type == TCH_F))) // Monitoring area control frame is reached... { check_fbcnf26 = 1; } } // end DEDIC task #if L1_GPRS else if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) //--------------------------------------------- // Packet Transfer mode task is enabled. //--------------------------------------------- { if(l1s.actual_time.t2 == 23) // Monitoring area control frame is reached... { check_fbcnf26 = 1; } } #endif if(check_fbcnf26) // FBCNF26 must be checked. { UWORD32 next_neigh_fn_mod51; #if ((REL99 == 1) && (FF_RTD == 1)) UWORD32 next_neigh_time_alignmt; #endif // Get neighbor domain frame number %51 for frame 24. next_neigh_fn_mod51 = (l1s.next_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51; if( ((next_neigh_fn_mod51 % 10) == 0)&&(next_neigh_fn_mod51 != 50) ) // FB26 rx window starts in the frame 24... { // time_alignt has been advanced from 23 bits UWORD32 u32Temp; // and FB algo. needs 24 bits ==> miss 1 bit = 4 qbits u32Temp = l1_config.params.fb26_anchoring_time ; if(l1a_l1s_com.nsync.list[i].time_alignmt >= u32Temp +4 ) // FB feet in the search slot... { min_time_to_fbconf = 0; l1a_l1s_com.nsync.list[i].sb26_offset = 0; } } else if((next_neigh_fn_mod51 == 50)|| (next_neigh_fn_mod51 == 9) || (next_neigh_fn_mod51 == 19) || (next_neigh_fn_mod51 == 29) || (next_neigh_fn_mod51 == 39)) // FB26 rx window starts in the frame 25... { UWORD16 fb26, sb26; UWORD32 time; UWORD32 u32temp ; time = ((l1_config.params.fb26_anchoring_time +FB26_ACQUIS_DURATION -SB_ACQUIS_DURATION +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE); fb26 = FB26_ACQUIS_DURATION; sb26 = SB_ACQUIS_DURATION; u32temp = ((l1_config.params.fb26_anchoring_time +FB26_ACQUIS_DURATION -SB_ACQUIS_DURATION +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE); if(l1a_l1s_com.nsync.list[i].time_alignmt < (UWORD32) u32temp ) /* if(l1a_l1s_com.nsync.list[i].time_alignmt < (UWORD32)((l1_config.params.fb26_anchoring_time +FB26_ACQUIS_DURATION -SB_ACQUIS_DURATION +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE)) */ // FB feet in the search slot... // Set FBCNF26 as PENDING to trigger the l1s_merge_manager() to install it // in MFTAB. { min_time_to_fbconf = 0; l1a_l1s_com.nsync.list[i].sb26_offset = 1; } } #if ((REL99 == 1) && (FF_RTD == 1)) // RTD feature if ((l1a_l1s_com.nsync.list[i].timing_validity == 3) && (min_time_to_fbconf == 0)) { #if !L1_EGPRS next_neigh_time_alignmt = l1a_l1s_com.nsync.list[i].time_alignmt; #endif if (((next_neigh_fn_mod51 % 10) == 0) && (next_neigh_fn_mod51 != 50)) { // for frame 0, 10, 20, 30, 40 if (l1a_l1s_com.nsync.list[i].fb26_position == 255) // is it the first attempt? { if ((next_neigh_time_alignmt - RTD_LEFT_MARGIN) < l1_config.params.fb26_anchoring_time + 4) fb26_position = 0 ; // it means first try in the multiframe 51 at position = 0,10,20,30,40 else fb26_position = 255 ; } else { // the previous one must be at the other side position if (l1a_l1s_com.nsync.list[i].fb26_position == 1) { fb26_position = l1a_l1s_com.nsync.list[i].fb26_position ; } else { min_time_to_fbconf = MAX_FN; // discard this position which has been already tried } } } else { // for frame 9, 19, 29, 39, 50 if (l1a_l1s_com.nsync.list[i].fb26_position == 255) // is it the first attempt? { if ((next_neigh_time_alignmt + RTD_RIGHT_MARGIN) > ((l1_config.params.fb26_anchoring_time + FB26_ACQUIS_DURATION - SB_ACQUIS_DURATION + TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE)) fb26_position = 1 ; // it means first try in the multiframe 51 at position = 9,19,29,39,50 else fb26_position = 255 ; } else { // the previous one must be at the other side position if (l1a_l1s_com.nsync.list[i].fb26_position == 0) { fb26_position = l1a_l1s_com.nsync.list[i].fb26_position ; } else { min_time_to_fbconf = MAX_FN; // discard this position which has been already tried } } } } #endif // L1_R99 RTD feature if(min_time_to_fbconf == 0) { // Fixed BUG2963 best_time_to_fbconf = 0; best_neigh_fbconf = i; } } } break; case 2: // Accurate timing is supplied SBCONF: confirm SB. { BOOL check_sbcnf26 = 0; UWORD32 min_time_to_sbconf = MAX_FN; if (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) //--------------------------------------------- // Dedicated mode tasks are enabled. //--------------------------------------------- { UWORD8 normalised_fn_mod26; normalised_fn_mod26 = (l1s.actual_time.fn_in_report - desc_ptr->subchannel ) % 26; if(((normalised_fn_mod26 == 22) && (desc_ptr->channel_type == TCH_H)) || (((l1s.actual_time.fn_in_report % 26) == 23) && (desc_ptr->channel_type == TCH_F))) // Monitoring area control frame is reached... { check_sbcnf26 = 1; } } // end DEDIC task #if L1_GPRS else if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) //--------------------------------------------- // Packet Transfer mode task is enabled. //--------------------------------------------- { if(l1s.actual_time.t2 == 23) // Monitoring area control frame is reached... { check_sbcnf26 = 1; } } #endif if(check_sbcnf26) // SBCNF26 must be checked. { UWORD32 next_neigh_fn_mod51; UWORD32 u32Temp; UWORD32 u32Temp1; // Get neighbor domain frame number %51 for frame 24. next_neigh_fn_mod51 = (l1s.next_time.fn + l1a_l1s_com.nsync.list[i].fn_offset) % 51; // Cq19539: the RF SB26 acquisition window shall be scheduled within the RF FB26 acquisition window range // So the time alignment of the neighbour (+ TPU_CLOCK_RANGE if needed) shall be within the range of // [ fb26_anchoring_time , fb26_anchoring_time+FB26_ACQUIS_DURATION-SB_ACQUIS_DURATION+TPU_CLOCK_RANGE [ // (During an SB acquisition after a FB aquisition, it can't be outside of this range // because of the clipping to MAX_TOA_FOR_SB into l1s_read_fb). // If a SB26 burst acquisition window is started outside of this range, the RX of the NB // in the next frame will be delayed by one frame due to the delay needed by the TPU // to execute offset, leave TPU sleep mode, switch the TPU page, and restore the synchro. // Such a delay is taken into account within the computation of fb26_anchoring_time. // Therefore, a time alignement outside this range must be clipped to fb26_anchoring_time // and SB will be scheduled at the end of the frame 24. u32Temp1 = l1_config.params.fb26_anchoring_time ; u32Temp= ((l1_config.params.fb26_anchoring_time +FB26_ACQUIS_DURATION -SB_ACQUIS_DURATION +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE ); if (( l1a_l1s_com.nsync.list[i].time_alignmt >= u32Temp) && ( l1a_l1s_com.nsync.list[i].time_alignmt <u32Temp1 )) /* if (( l1a_l1s_com.nsync.list[i].time_alignmt >= (UWORD32)(l1_config.params.fb26_anchoring_time +FB26_ACQUIS_DURATION -SB_ACQUIS_DURATION +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE ) && ( l1a_l1s_com.nsync.list[i].time_alignmt < (UWORD32)l1_config.params.fb26_anchoring_time ))*/ { // clip time alignment because it's outside of allowed range l1a_l1s_com.nsync.list[i].time_alignmt = l1_config.params.fb26_anchoring_time; } if((next_neigh_fn_mod51 == 0) || (next_neigh_fn_mod51 == 10) || (next_neigh_fn_mod51 == 20) || (next_neigh_fn_mod51 == 30) || (next_neigh_fn_mod51 == 40)) // check if SB26 rx window can be started in the frame 25... { u32Temp= ((l1_config.params.fb26_anchoring_time +FB26_ACQUIS_DURATION -SB_ACQUIS_DURATION +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE); if (l1a_l1s_com.nsync.list[i].time_alignmt < u32Temp) /* if(l1a_l1s_com.nsync.list[i].time_alignmt < (UWORD32)(l1_config.params.fb26_anchoring_time +FB26_ACQUIS_DURATION -SB_ACQUIS_DURATION +TPU_CLOCK_RANGE) % TPU_CLOCK_RANGE)*/ // SB feet in the search slot... // Set sb26_offset to 1 to add a NOP in TPU scenario in order to reach frame 25 { min_time_to_sbconf = 0; l1a_l1s_com.nsync.list[i].sb26_offset = 1; } } else if((next_neigh_fn_mod51 % 10) == 1) // ... otherwise SB26 rx window starts at the end of the frame 24. { UWORD32 u32Temp; u32Temp = l1_config.params.fb26_anchoring_time; if(l1a_l1s_com.nsync.list[i].time_alignmt >= u32Temp ) /*if(l1a_l1s_com.nsync.list[i].time_alignmt >= (UWORD32)l1_config.params.fb26_anchoring_time)*/ // SB feet in the search slot... { min_time_to_sbconf = 0; l1a_l1s_com.nsync.list[i].sb26_offset = 0; } } if(min_time_to_sbconf == 0) { best_time_to_sbconf = 0; best_neigh_sbconf = i; } } } break; #if ((REL99 == 1) && ((FF_BHO == 1) || (FF_RTD == 1))) case SB_ACQUISITION_PHASE: // SB search following a FB search. #else case 3: // SB search following a FB search. #endif { UWORD32 min_time_to_sb = MAX_FN; UWORD8 sb26_attempt = l1a_l1s_com.nsync.list[i].sb26_attempt; UWORD32 u32Temp; // Monitoring area starting frame is reached... min_time_to_sb = l1a_l1s_com.nsync.list[i].fn_offset - l1s.actual_time.fn; if ((WORD32)min_time_to_sb < 0) //the SB following the FB was missed because of an higher priority task //next SB is 26*9 frames later or it is 26*9+52 frames later //Fix for BUG2864 and BUG2842 { if (sb26_attempt == 1) min_time_to_sb += 26*9; else if (sb26_attempt == 2) min_time_to_sb += 26*9+52; else min_time_to_sb += MAX_FN; //shall never happen } if (min_time_to_sb == 0) { l1a_l1s_com.nsync.list[i].sb26_attempt++; } u32Temp = best_time_to_sb; if((min_time_to_sb < 26) && (min_time_to_sb < u32Temp )) { best_time_to_sb = min_time_to_sb; best_neigh_sb = i; } } break; } // End of "switch" } // End of "if PENDING" } // End of "for" #if L1_EDA if((l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) && (l1ps_macs_com.fb_sb_task_detect)) { //Flag used to cope with worst case mixing FB/SB task and allocation for MS class 12 if(l1s.actual_time.t2 == 20) { l1ps_macs_com.fb_sb_task_enabled = TRUE; } else if (l1s.actual_time.t2 > 20) enter_nsync_task = l1ps_macs_com.fb_sb_task_enabled; } if (!(l1ps_macs_com.fb_sb_task_detect) || enter_nsync_task) { #endif // Remarks: //-------- // While FB26/SB26/SBCNF26 are set as PENDING to trigger the // l1s_merge_manager() to install it , we have to select the // highest priority task HERE. if(best_neigh_sb != 255) // SB26 is higher priority while it can not be delayed without // performing again an FB26 search ! { // Save active neighbour id. l1a_l1s_com.nsync.active_sb_id = best_neigh_sb; // set SB26 as pending to trigger the l1s_merge_manager() // to install it in MFTAB if (best_time_to_sb == 0) l1s.task_status[SB26].new_status = PENDING; // Enable SB2 task l1a_l1s_com.l1s_en_task[SB26] = TASK_ENABLED; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SB26] = SEMAPHORE_RESET; } else if(best_neigh_fbconf != 255) // FB CONFIRMATION is medium priority due to its short duration { // Save active neighbour id. l1a_l1s_com.nsync.active_fb_id = best_neigh_fbconf; // set FB as pending to trigger the l1s_merge_manager() // to install it in MFTAB if (best_time_to_fbconf == 0) l1s.task_status[FB26].new_status = PENDING; // Enable FB task l1a_l1s_com.l1s_en_task[FB26] = TASK_ENABLED; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[FB26] = SEMAPHORE_RESET; #if ((REL99 == 1) && (FF_RTD == 1)) // RTD feature if (l1a_l1s_com.nsync.list[best_neigh_fbconf].timing_validity == 3) { // check if we are not at the border of the window so FB must be detected inside the current window if (fb26_position == 255) l1a_l1s_com.nsync.list[best_neigh_fbconf].nb_fb_attempt = 1; else l1a_l1s_com.nsync.list[best_neigh_fbconf].fb26_position = fb26_position; } #endif // L1_R99 } else if(best_neigh_sbconf != 255) // SBCNF26 is medium priority due to its short duration { // Save active neighbour id. l1a_l1s_com.nsync.active_sbconf_id = best_neigh_sbconf; // set SBCNF26 as pending to trigger the l1s_merge_manager() // to install it in MFTAB if (best_time_to_sbconf == 0) l1s.task_status[SBCNF26].new_status = PENDING; // Enable SBCNF26 task l1a_l1s_com.l1s_en_task[SBCNF26] = TASK_ENABLED; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[SBCNF26] = SEMAPHORE_RESET; } else if(best_neigh_fb != 255) // FB26 is low priority due to its long duration { // Save active neighbour id. l1a_l1s_com.nsync.active_fb_id = best_neigh_fb; // set FB26 as pending to trigger the l1s_merge_manager() // to install it in MFTAB if (best_time_to_fb == 0) l1s.task_status[FB26].new_status = PENDING; // Enable FB26 task l1a_l1s_com.l1s_en_task[FB26] = TASK_ENABLED; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[FB26] = SEMAPHORE_RESET; } #if L1_EDA } #endif } // End of "if / current_status" } // End of " if NSYNC" } // End of "if channel is MF26" if (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) { #endif if(l1a_l1s_com.l1s_en_task[TCHA] == TASK_ENABLED) //---------------------------------- // SACCH (TCH) task is ENABLED. //---------------------------------- { UWORD32 time_to_tcha; if(l1s.next_time.fn_in_report <= 12) time_to_tcha = 12 - l1s.next_time.fn_in_report; else if(l1s.next_time.fn_in_report <= 38) time_to_tcha = 38 - l1s.next_time.fn_in_report; else if(l1s.next_time.fn_in_report <= 64) time_to_tcha = 64 - l1s.next_time.fn_in_report; else if(l1s.next_time.fn_in_report <= 90) time_to_tcha = 90 - l1s.next_time.fn_in_report; else time_to_tcha = 104 + 12 - l1s.next_time.fn_in_report; // Save scheduling result. l1s.task_status[TCHA].time_to_exec = time_to_tcha; } if(l1a_l1s_com.l1s_en_task[TCHTF] == TASK_ENABLED) //---------------------------------- // TCHTF task is ENABLED. //---------------------------------- { UWORD32 time_to_tchf; #if TESTMODE // if UL-only, ONLY schedule TCHA task, and schedule it every frame if (l1_config.TestMode && (l1_config.tmode.rf_params.down_up == TMODE_UPLINK)) { // Save scheduling result: force TCHA task over TCHTF l1s.task_status[TCHA].time_to_exec = 0; l1s.task_status[TCHTF].time_to_exec = 0xff; } else { if(l1s.next_time.fn_mod13 == 12) time_to_tchf = 1; else time_to_tchf = 0; // Save scheduling result. l1s.task_status[TCHTF].time_to_exec = time_to_tchf; } #else if(l1s.next_time.fn_mod13 == 12) time_to_tchf = 1; else time_to_tchf = 0; // Save scheduling result. l1s.task_status[TCHTF].time_to_exec = time_to_tchf; #endif } if(l1a_l1s_com.l1s_en_task[TCHTH] == TASK_ENABLED) //---------------------------------- // TCHTF task is ENABLED. //---------------------------------- { UWORD32 time_to_tchh; UWORD32 time_to_tchd; WORD32 normalised_fn_mod13; UWORD8 subchannel; subchannel = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->subchannel; normalised_fn_mod13 = l1s.next_time.fn_mod13 - subchannel; if(normalised_fn_mod13 < 0) normalised_fn_mod13 += 13; if((normalised_fn_mod13 == 0) || (normalised_fn_mod13 == 2) || (normalised_fn_mod13 == 4) || (normalised_fn_mod13 == 6) || (normalised_fn_mod13 == 8) || (normalised_fn_mod13 == 10)) { time_to_tchh = 0; time_to_tchd = 1; } else { time_to_tchd = 0; /*if (l1s.next_time.fn_mod13 == 12) { if (subchannel == 0) { time_to_tchd = 2; } else { time_to_tchd = 1; } }*/ if(normalised_fn_mod13 == 11) time_to_tchh = 2; else time_to_tchh = 1; } // Save scheduling result. l1s.task_status[TCHTH].time_to_exec = time_to_tchh; l1s.task_status[TCHD].time_to_exec = time_to_tchd; } #if (L1_12NEIGH == 1) } #endif } // End of if(DEDIC is ENABLED) #if L1_GPRS //========================================================== //== PACKET ACCESS == //========================================================== // Either fixed block allocation or USF method may be // used to determine possible PRACH slots. If fixed blocks // are allocated they take precedence over USF decoding // When PRACH slot is determined by fixed allocation this // is marked by fix_alloc_flag=TRUE, and USF method is not // executed afterwards. { if(l1a_l1s_com.l1s_en_task[PRACH] == TASK_ENABLED) // PRACH task enabled { BOOL fix_alloc_flag = FALSE; #if FF_L1_IT_DSP_USF // No USF uncertainty by default i.e. if fixed allocation mode is used // or dynamic on TDMA 1, 2 or 3 of a block. l1ps_macs_com.usf_status = USF_AVAILABLE; #endif // FF_L1_IT_DSP_USF if(l1pa_l1ps_com.pra_info.prach_alloc != DYN_PRACH_ALLOC) // FIXED BLOCK ALLOCATION { UWORD8 fn_mod_52; UWORD8 i, start_time =0;//omaps00090550 fn_mod_52 = l1s.next_time.fn_mod52; // start times for control phase for (i=0; i<l1pa_l1ps_com.pra_info.bs_prach_blks; i++) { // Block boundary for PRACH start_time = ORDERED_BLOCK_START_TIME[i]; if ((fn_mod_52 == start_time) || (fn_mod_52 == start_time + 1) || (fn_mod_52 == start_time + 2) || (fn_mod_52 == start_time + 3)) { fix_alloc_flag = TRUE; l1pa_l1ps_com.pra_info.rand --; if ( l1pa_l1ps_com.pra_info.rand == 0) { l1s.task_status[PRACH].new_status = PENDING; l1pa_l1ps_com.pra_info.prach_alloc = FIX_PRACH_ALLOC; } break; } } // end for } // either FIXED blocks or USF method if(!fix_alloc_flag) // DYNAMIC MODE WITH USF DECODING { API d_usf_updated; static API static_usf_state; // USF read on first frame of a block, valid for whole block UWORD8 actual_fn_mod13_mod4 = l1s.actual_time.fn_mod13_mod4; UWORD8 next_fn_mod13_mod4 = l1s.next_time.fn_mod13_mod4; // Flag used for correcting l1pa_l1ps_com.pra_info.rand in case it // has been decremented although USF was bad static BOOL static_usf_invalid_flag = FALSE; // Get USF from DSP => for PRACH only TS0 is needed // Read frame 3 of each block to anticipate USF state for first frame of next block // Do not read USF on frames that preceed idle frames if ((next_fn_mod13_mod4 == 0) && (l1s.next_time.fn_mod13 != 12)) { d_usf_updated = ((l1ps_dsp_com.pdsp_ndb_ptr->d_usf_updated_gprs >> ((7-0)*2)) & 0x0003); if (d_usf_updated == USF_INVALID) // USF decoding on block boundary // if USF invalid => decision to send PRACH is left to DSP { static_usf_invalid_flag = TRUE; l1pa_l1ps_com.pra_info.rand --; if ( l1pa_l1ps_com.pra_info.rand == 0) { l1s.task_status[PRACH].new_status = PENDING; #if FF_L1_IT_DSP_USF // Dynamic allocation in use, random number of opportunities // elapsed and USF status is not available. Therefore we have // to rely on DSP USF interrupt. l1ps_macs_com.usf_status = USF_AWAITED; #endif // FF_L1_IT_DSP_USF } } static_usf_state = d_usf_updated; } // Update USF state on the first frame of each block else if (actual_fn_mod13_mod4 == 0) { static_usf_state = ((l1ps_dsp_com.pdsp_ndb_ptr->d_usf_updated_gprs >> ((7-0)*2)) & 0x0003); if ((static_usf_state != USF_GOOD) && (static_usf_invalid_flag == TRUE)) // rand was decremented in previous frame but USF is bad => compensate { l1pa_l1ps_com.pra_info.rand ++; static_usf_invalid_flag = FALSE; } } if ((static_usf_state == USF_GOOD) && (l1s.next_time.fn_mod13 != 12)) { static_usf_invalid_flag = FALSE; l1pa_l1ps_com.pra_info.rand --; if ( l1pa_l1ps_com.pra_info.rand == 0) { l1s.task_status[PRACH].new_status = PENDING; } } } } } //===================================================== //== PACKET POLLING == //===================================================== { if(l1a_l1s_com.l1s_en_task[POLL] == TASK_ENABLED) // POLL task enabled (packet queuing notification { if(l1s.task_status[POLL].current_status == INACTIVE) { UWORD32 time_to_poll; time_to_poll = ( (l1pa_l1ps_com.poll_info.fn) - (l1s.next_time.fn % 42432) + 2*42432) % 42432; if((time_to_poll >= 32024) && (time_to_poll <= 42431)) { xSignalHeaderRec *msg; // Poll response occurence passed... // Task disabled to avoid a new transmission of L1P_POLL_DONE in following // TDMA if L1A isn't executed // This isn't a problem because the sending of two simultaneous POLL is forbidden l1a_l1s_com.l1s_en_task[POLL] = TASK_DISABLED; // send an error message to L1A msg = os_alloc_sig(sizeof(T_MPHP_POLLING_IND)); DEBUGMSG(status,NU_ALLOC_ERR) ((T_MPHP_POLLING_IND *)(msg->SigP))->fn = 0xFFFFFFFF; // Invalid (TO BE CONFIRMED) msg->SignalCode = L1P_POLL_DONE; os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } else if (time_to_poll == 0) { // Poll reponse occurs on next FN l1s.task_status[POLL].new_status = PENDING; l1s.task_status[POLL].time_to_exec = time_to_poll; } else { // Update scheduling result l1s.task_status[POLL].time_to_exec = time_to_poll; } } } } //================================================================ //== PACKET TASKS == //== ------------ == //================================================================ { if(l1a_l1s_com.l1s_en_task[PDTCH] == TASK_ENABLED) //------------------------- // PDTCH task is ENABLED. //------------------------- { UWORD8 time_to_pdtch; // PDTCH task begins on a block boundary (fn_mod13 = 0, 4, 8) if (l1s.next_time.fn_mod13 == 0) time_to_pdtch = 0; else if (l1s.next_time.fn_mod13 <= 4) time_to_pdtch = 4 - l1s.next_time.fn_mod13; else if (l1s.next_time.fn_mod13 <= 8) time_to_pdtch = 8 - l1s.next_time.fn_mod13; else time_to_pdtch = 13 - l1s.next_time.fn_mod13; // Save scheduling result. l1s.task_status[PDTCH].time_to_exec = time_to_pdtch; } if(l1a_l1s_com.l1s_en_task[PTCCH] == TASK_ENABLED) //------------------------- // PTCCH task is ENABLED. //------------------------- { #define TA_INDEX l1pa_l1ps_com.transfer.aset->packet_ta.ta_index typedef struct { UWORD16 start_ptcch_dl_block; // DL PTCCH block position (2 TDMA in advance). UWORD16 tai_to_fnmod416; // UL PTCCH position (2 TDMA in advance). } T_PTCCH_SCHEDULE_INFO; const T_PTCCH_SCHEDULE_INFO PTCCH_SCHEDULE[16] = { {116, 12},{116, 38},{116, 64},{116, 90}, {220,116},{220,142},{220,168},{220,194}, {324,220},{324,246},{324,272},{324,298}, { 12,324},{ 12,350},{ 12,376},{ 12,402} }; UWORD16 fn_mod416 = l1s.next_time.fn % 416; UWORD32 time_to_ptcch_dl = MAX_FN; UWORD32 time_to_ptcch_ul = MAX_FN; // PTCCH/DL scheduling... { if(l1pa_l1ps_com.transfer.ptcch.request_dl) // Request to start PTCCH/DL after PTCCH/UL execution. { if(fn_mod416 <= PTCCH_SCHEDULE[TA_INDEX].start_ptcch_dl_block) time_to_ptcch_dl = PTCCH_SCHEDULE[TA_INDEX].start_ptcch_dl_block - fn_mod416; else time_to_ptcch_dl = 416 + PTCCH_SCHEDULE[TA_INDEX].start_ptcch_dl_block - fn_mod416; if(time_to_ptcch_dl == 0) { // PTCCH must execute PTCCH/DL. l1pa_l1ps_com.transfer.ptcch.activity |= PTCCH_DL; // Reset DL request bit. l1pa_l1ps_com.transfer.ptcch.request_dl = FALSE; } } if(l1pa_l1ps_com.transfer.ptcch.activity & PTCCH_DL) // PTCCH/DL alrady active, continue reception at correct boundaries. { if(l1s.next_time.t2 <= 12) time_to_ptcch_dl = 12 - l1s.next_time.t2; else time_to_ptcch_dl = 26 + 12 - l1s.next_time.t2; } } // PTCCH/UL scheduling...always enabled according to TAI. { // Schedule PTCCH/UL according to TAI. if(fn_mod416 <= PTCCH_SCHEDULE[TA_INDEX].tai_to_fnmod416) time_to_ptcch_ul = PTCCH_SCHEDULE[TA_INDEX].tai_to_fnmod416 - fn_mod416; else time_to_ptcch_ul = 416 + PTCCH_SCHEDULE[TA_INDEX].tai_to_fnmod416 - fn_mod416; if(time_to_ptcch_ul == 0) { // PTCCH must execute PTCCH/UL. l1pa_l1ps_com.transfer.ptcch.activity |= PTCCH_UL; } } // Save scheduling result. if(time_to_ptcch_dl < time_to_ptcch_ul) l1s.task_status[PTCCH].time_to_exec = time_to_ptcch_dl; else l1s.task_status[PTCCH].time_to_exec = time_to_ptcch_ul; // Clear param. synchro. semaphore. l1a_l1s_com.task_param[PTCCH] = SEMAPHORE_RESET; } if(l1a_l1s_com.l1s_en_task[SINGLE] == TASK_ENABLED) //------------------------- // SINGLE task is ENABLED. //------------------------- { // SINGLE task can be re-entrant, we can't check for // current_status == INACTIVE. if((l1pa_l1ps_com.transfer.single_block.activity & SINGLE_DL) || (l1pa_l1ps_com.transfer.single_block.activity & SINGLE_UL)) // L1 is camped on SINGLE timeslot. // -> no need to make a temporary synchro change. // -> SINGLE task is scheduled 1 frame before the block position. { UWORD32 time_to_single; if (l1s.next_time.fn_mod13 == 0) time_to_single = 0; else if (l1s.next_time.fn_mod13 <= 4) time_to_single = 4 - l1s.next_time.fn_mod13; else if (l1s.next_time.fn_mod13 <= 8) time_to_single = 8 - l1s.next_time.fn_mod13; else time_to_single = 13 - l1s.next_time.fn_mod13; // SINGLE task requires to run L1S scheduler every frame. l1a_l1s_com.time_to_next_l1s_task = 0; // Save scheduling result. l1s.task_status[SINGLE].time_to_exec = time_to_single; } } // SINGLE task enabled if(l1a_l1s_com.l1s_en_task[ITMEAS] == TASK_ENABLED) //------------------------- // ITMEAS task is ENABLED. //------------------------- { UWORD8 time_to_itmeas; // time to ITMEAS processing // ITMEAS must be scheduled 2 frames in advance (C W W R scheme) // --> use of 'next_plus_time' switch(l1pa_l1ps_com.itmeas.position) { case ANY_IDLE_FRAME: // ITMEAS task must be scheduled on any idle frame --> fn_mod13 = 12 time_to_itmeas = 12 - l1s.next_plus_time.fn_mod13; break; case PTCCH_FRAME: { // ITMEAS must be scheduled on a PTCCH frame --> fn_mod26 = 12 if (l1s.next_plus_time.t2 <= 12) time_to_itmeas = 12 - l1s.next_plus_time.t2; else time_to_itmeas = 38 - l1s.next_plus_time.t2; } break; case SEARCH_FRAME: { // ITMEAS must be scheduled on a search frame --> fn_mod26 = 25 time_to_itmeas = 25 - l1s.next_plus_time.t2; } break; } // End of "switch" // Save scheduling result. l1s.task_status[ITMEAS].time_to_exec = time_to_itmeas; if(l1s.task_status[ITMEAS].current_status == INACTIVE) { // Clear param. synchro. semaphore. l1a_l1s_com.task_param[ITMEAS] = SEMAPHORE_RESET; } } // ITMEAS task enabled } // end of packet tasks #endif //-------------------------------------------- // TASK SELECTION... //-------------------------------------------- { WORD32 forward_task = NO_NEW_TASK; WORD32 forward_task_complete = MAX_FN; WORD32 forward_task_size = MAX_FN; WORD32 backward_task = NO_NEW_TASK; WORD8 task; // FORWARD procedure... // Look for best pending task... // Tasks are ordered: Low priority .. to high priority. for(task=0; task<NBR_DL_L1S_TASKS; task++) { if(l1a_l1s_com.l1s_en_task[task] == TASK_ENABLED) { if(l1s.task_status[task].time_to_exec < forward_task_complete) { forward_task = task; forward_task_complete = l1s.task_status[task].time_to_exec + TASK_ROM_MFTAB[task].size - 2; } } } if(forward_task != NO_NEW_TASK) { task = forward_task; // BACKWARD procedure... while((--task>=0) && (backward_task == NO_NEW_TASK)) { if(l1a_l1s_com.l1s_en_task[task] == TASK_ENABLED) { if((l1s.task_status[task].time_to_exec + TASK_ROM_MFTAB[task].size - 2) <= (l1s.task_status[forward_task].time_to_exec)) { backward_task = task; } } } if(backward_task != NO_NEW_TASK) { Select_min_time(l1s.task_status[backward_task].time_to_exec, l1a_l1s_com.time_to_next_l1s_task); // Pass back the best task. if(l1s.task_status[backward_task].time_to_exec == 0) *best_pending_task = backward_task; else *best_pending_task = NO_NEW_TASK; } else { Select_min_time(l1s.task_status[forward_task].time_to_exec, l1a_l1s_com.time_to_next_l1s_task); // Pass back the best task. if(l1s.task_status[forward_task].time_to_exec == 0) *best_pending_task = forward_task; else *best_pending_task = NO_NEW_TASK; } } else { // Pass back the best task. *best_pending_task = NO_NEW_TASK; } } } // End of procedure. //#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_merge_manager() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : */ /*-------------------------------------------------------*/ void l1s_merge_manager(WORD32 pending_task) { if(pending_task != NO_NEW_TASK) // There is a new pending task... { if(pending_task == SYNCHRO) // SYNCHRO task must be executed in any case. // It is used also to reset the MFTAB content. { WORD32 i; #if L1_GPRS // PDTCH task can't be aborted... SYNCHRO is delayed to next block boundary // This is needed when a synchronization change is needed to switch to a new // while a TBF is currently running: the end of the current TBF mustn't // be aborted so the first block of the new TBF will be used to switch to the // new synchronization. // SYNCHRO task has also to be delayed if a task needing a pseudo-synchro (with a synchro back // performed on the burst4, i.e. PBCCHS, PBCCHN_IDLE, SMSCB, PBCCHN_TRAN and Normal or Extended BCCH // ,(Packet)normal and (Packet)extended paging in Packet Transfer) is interrupted. This delay is requested in order to // to finish the current TPU scenario and to not disturb current L1 Timeslot Number Reference. // Cf. correction of BUG1004. if((l1s.task_status[PBCCHS].current_status == INACTIVE) && (l1s.task_status[PBCCHN_IDLE].current_status == INACTIVE) && (l1s.task_status[PBCCHN_TRAN].current_status == INACTIVE) && (l1s.task_status[PDTCH].current_status == INACTIVE) && (l1s.task_status[SMSCB].current_status == INACTIVE) && (((l1a_l1s_com.mode != PACKET_TRANSFER_MODE) || ((l1s.task_status[NBCCHS].current_status == INACTIVE) && (l1s.task_status[EBCCHS].current_status == INACTIVE) #if 0 /* FreeCalypso TCS211 reconstruction */ && (l1s.task_status[PNP].current_status == INACTIVE) && (l1s.task_status[PEP].current_status == INACTIVE) && (l1s.task_status[NP].current_status == INACTIVE) && (l1s.task_status[EP].current_status == INACTIVE) #endif )))) #else if (l1s.task_status[SMSCB].current_status == INACTIVE) #endif { // Clear the current content of the DL MFTAB. l1s_clear_mftab(l1s.mftab.frmlst); #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) trace_info.abort_task = pending_task; #endif // Load the ABORT function in the MFTAB. l1s_load_mftab( BLOC_ABORT, // Rom block address. BLOC_ABORT_SIZE, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. // Load the new task in the MFTAB. l1s_load_mftab( TASK_ROM_MFTAB[pending_task].address, // Rom block address. TASK_ROM_MFTAB[pending_task].size, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. // All task become INACTIVE except PENDING which becomes ACTIVE. for(i=0; i<NBR_DL_L1S_TASKS; i++) l1s.task_status[i].current_status = INACTIVE; l1s.task_status[pending_task].current_status = ACTIVE; // Load FRAME_COUNT with the new task Rom block size. l1s.frame_count = TASK_ROM_MFTAB[pending_task].size; // MFTAB is reset, no more task not compatible with Neigh. Measurement. // Clear "forbid_meas". l1s.forbid_meas = 0; // Check that ABORT task is not bigger than pending_task. if(BLOC_ABORT_SIZE > l1s.frame_count) l1s.frame_count = BLOC_ABORT_SIZE; return; } } //(pending_task == SYNCHRO) else if(l1s.frame_count <= 2) // The incoming pending task can be merged within the MFTAB. { BOOL specific_case = FALSE; if(pending_task == DUL) { // this DOOLEAN is mandatory because we can access to this channel description only in dedicated // otherwise we have memory access error during the execution. T_CHANNEL_DESCRIPTION *desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; if ((desc_ptr->channel_type == SDCCH_8) && ((desc_ptr->subchannel>=4 && (desc_ptr->subchannel<=7))) ) if ((l1s.actual_time.fn % 102) > 51) // only in the second multiframe D51 specific_case = TRUE; } if(specific_case == TRUE) { // DUL(subch6) and ADL(subch6) (same for subch 4,5,6,7). // Here the task DUL is already installed which means that // if we install the ADL task we will have the UL task // controled before the DL task. This is not compatible // with the tpu programming. // To correct the problem, we detect this case, flush the // MFTAB and install a mixed DL/UL task block containing // the full ADL task and the end of the DUL task. // (see mftab.h) // The MFTAB is cleared. // Load the SPECIAL ADL/DUL MIXED TASK in the MFTAB. l1s_load_mftab( BLOC_DUL_ADL_MIXED, // Rom block address. BLOC_DUL_ADL_MIXED_SIZED, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. l1s.task_status[DUL].current_status = ACTIVE; l1s.task_status[ADL].current_status = ACTIVE; // Load FRAME_COUNT with the new task Rom block size. l1s.frame_count = BLOC_DUL_ADL_MIXED_SIZED; } else { l1s_load_mftab( TASK_ROM_MFTAB[pending_task].address, // Rom block address. TASK_ROM_MFTAB[pending_task].size, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. // PENDING becomes ACTIVE except if it is already active, // in this case is is stated RE_ENTERED. if(l1s.task_status[pending_task].current_status == ACTIVE) l1s.task_status[pending_task].current_status = RE_ENTERED; else l1s.task_status[pending_task].current_status = ACTIVE; // Load FRAME_COUNT with the new task Rom block size. l1s.frame_count = TASK_ROM_MFTAB[pending_task].size; } } else // The incoming pending task CANNOT be merged within the MFTAB. { #if L1_GPRS // Interference measurements special merging case // Merge is not possible when FB26/SB26/SBCNF26 in packet transfer // are also pending. if((pending_task == ITMEAS) && (l1s.task_status[FB26].new_status == NOT_PENDING) && (l1s.task_status[SB26].new_status == NOT_PENDING) && (l1s.task_status[SBCNF26].new_status == NOT_PENDING)) { // If frame_count = 3: // - Serving task (aligned on MF52 or MF51): interference measurements can // be done during the last work phase (merge with the last Control // of the serving task) // // Frame count 6 5 4 3 2 1 // Serving task C W R // C W R // C W R // C W R // ITMEAS C W W R // // - Neighbor tasks: merge always forbidden by l1s.forbid_meas if((l1s.frame_count == 3) && (l1s.forbid_meas < 2)) { l1s_load_mftab( TASK_ROM_MFTAB[ITMEAS].address, // Rom block address. TASK_ROM_MFTAB[ITMEAS].size, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. // PENDING becomes ACTIVE. l1s.task_status[pending_task].current_status = ACTIVE; // Load FRAME_COUNT with the new task Rom block size. l1s.frame_count = TASK_ROM_MFTAB[pending_task].size; } } // End if "pending task is ITMEAS" else #endif if((l1s.task_status[FBNEW].current_status != INACTIVE) && (pending_task != FBNEW)) // FBNEW task is the only aborted task. // We check to avoid aborting FBNEW by itself. { WORD32 i; // Clear the current content of the DL MFTAB. l1s_clear_mftab(l1s.mftab.frmlst); #if ((TRACE_TYPE == 1) || (TRACE_TYPE == 4)) trace_info.abort_task = pending_task; #endif // Load the ABORT function in the MFTAB. l1s_load_mftab( BLOC_ABORT, // Rom block address. BLOC_ABORT_SIZE, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. // Load the new task in the MFTAB. l1s_load_mftab( TASK_ROM_MFTAB[pending_task].address, // Rom block address. TASK_ROM_MFTAB[pending_task].size, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. // All task become INACTIVE except PENDING which becomes ACTIVE. for(i=0; i<NBR_DL_L1S_TASKS; i++) l1s.task_status[i].current_status = INACTIVE; l1s.task_status[pending_task].current_status = ACTIVE; // Load FRAME_COUNT with the new task Rom block size. l1s.frame_count = TASK_ROM_MFTAB[pending_task].size; // MFTAB is reset, no more task not compatible with Neigh. Measurement. // Clear "forbid_meas". l1s.forbid_meas = 0; // Check that ABORT task is not bigger than pending_task. if(BLOC_ABORT_SIZE > l1s.frame_count) l1s.frame_count = BLOC_ABORT_SIZE; } else // NO abort. {} } } //--------------------------------------------------------- // Additional tasks................ //--------------------------------------------------------- // -> These tasks are generaly supperposed to // another main task. // RAACC with ALLC / NP / EP / NBCCHS / EBCCHS // FB26 / SB26 / SBCNF26 with TCHTF // ... //--------------------------------------------------------- if(l1s.task_status[RAACC].new_status == PENDING) // CHANNEL ACCESS task is pending and MUST be set in the MFTAB. // Merge is always possible since only the serving tasks can be running. // ->install RAACC whitout any other change. { l1s_load_mftab( TASK_ROM_MFTAB[RAACC].address, // Rom block address. TASK_ROM_MFTAB[RAACC].size, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. l1s.task_status[RAACC].current_status = ACTIVE; // Load FRAME_COUNT with the RAAC Rom block size. if(l1s.frame_count < TASK_ROM_MFTAB[RAACC].size) l1s.frame_count = TASK_ROM_MFTAB[RAACC].size; } #if L1_GPRS if((l1s.task_status[TCHTF].current_status != INACTIVE) || (l1s.task_status[TCHTH].current_status != INACTIVE) || (l1s.task_status[PDTCH].current_status != INACTIVE)) #endif { // Dedicated/Transfer mode monitoring tasks... if(l1s.task_status[FB26].new_status == PENDING) { UWORD8 time_to_task_complete = TASK_ROM_MFTAB[FB26].size - 2; #if L1_GPRS if((l1s.task_status[PBCCHS ].time_to_exec >= time_to_task_complete) && (l1s.task_status[NBCCHS ].time_to_exec >= time_to_task_complete) && (l1s.task_status[EBCCHS ].time_to_exec >= time_to_task_complete) && (l1s.task_status[PBCCHN_TRAN].time_to_exec >= time_to_task_complete) && (l1s.task_status[NP ].time_to_exec >= time_to_task_complete) && (l1s.task_status[EP ].time_to_exec >= time_to_task_complete) && (l1s.task_status[BCCHN_TRAN ].time_to_exec >= time_to_task_complete)) #endif { l1s_load_mftab( TASK_ROM_MFTAB[FB26].address, // Rom block address. TASK_ROM_MFTAB[FB26].size, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. l1s.task_status[FB26].current_status = ACTIVE; } } else if(l1s.task_status[SB26].new_status == PENDING) { UWORD8 time_to_task_complete = TASK_ROM_MFTAB[SB26].size - 2; #if L1_GPRS if((l1s.task_status[PBCCHS ].time_to_exec >= time_to_task_complete) && (l1s.task_status[NBCCHS ].time_to_exec >= time_to_task_complete) && (l1s.task_status[EBCCHS ].time_to_exec >= time_to_task_complete) && (l1s.task_status[PBCCHN_TRAN].time_to_exec >= time_to_task_complete) && (l1s.task_status[NP ].time_to_exec >= time_to_task_complete) && (l1s.task_status[EP ].time_to_exec >= time_to_task_complete) && (l1s.task_status[BCCHN_TRAN ].time_to_exec >= time_to_task_complete)) #endif { l1s_load_mftab( TASK_ROM_MFTAB[SB26].address, // Rom block address. TASK_ROM_MFTAB[SB26].size, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. l1s.task_status[SB26].current_status = ACTIVE; } } else if(l1s.task_status[SBCNF26].new_status == PENDING) { UWORD8 time_to_task_complete = TASK_ROM_MFTAB[SBCNF26].size - 2; #if L1_GPRS if((l1s.task_status[PBCCHS ].time_to_exec >= time_to_task_complete) && (l1s.task_status[NBCCHS ].time_to_exec >= time_to_task_complete) && (l1s.task_status[EBCCHS ].time_to_exec >= time_to_task_complete) && (l1s.task_status[PBCCHN_TRAN].time_to_exec >= time_to_task_complete) && (l1s.task_status[NP ].time_to_exec >= time_to_task_complete) && (l1s.task_status[EP ].time_to_exec >= time_to_task_complete) && (l1s.task_status[BCCHN_TRAN ].time_to_exec >= time_to_task_complete)) #endif { l1s_load_mftab( TASK_ROM_MFTAB[SBCNF26].address, // Rom block address. TASK_ROM_MFTAB[SBCNF26].size, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. l1s.task_status[SBCNF26].current_status = ACTIVE; } } } #if L1_GPRS if(l1s.task_status[PRACH].new_status == PENDING) // PACKET CHANNEL ACCESS task is pending and MUST be set in the MFTAB. // Merge is always possible since only the serving tasks can be running. // ->install PRACH without any other change. { l1s_load_mftab( TASK_ROM_MFTAB[PRACH].address, // Rom block address. TASK_ROM_MFTAB[PRACH].size, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. l1s.task_status[PRACH].current_status = ACTIVE; // Load FRAME_COUNT with the RAAC Rom block size. if(l1s.frame_count < TASK_ROM_MFTAB[PRACH].size) l1s.frame_count = TASK_ROM_MFTAB[PRACH].size; } else if((l1s.task_status[POLL].new_status == PENDING) && (l1s.task_status[POLL].current_status != ACTIVE)) // POLL RESPONSE task is pending. // Merge is not always possible since POLL can conflict with a Neighbour process // (SB2, SBCONF, BCCHN, BCCHN_TOP, PBCCHN_IDLE) or PBCCHS and CCCH operation mode II/III tasks. // From the fact that POLL can be load in MFTAB here below (when there is no pending_task // except POLL), merging can be done only if current_status is != ACTIVE. { UWORD8 time_to_task_complete = BLOC_POLL_NO_HOPP_SIZE - 2; if((l1s.task_status[PBCCHS ].time_to_exec >= time_to_task_complete) && (l1s.task_status[PBCCHN_IDLE].time_to_exec >= time_to_task_complete) && (l1s.task_status[BCCHN ].time_to_exec >= time_to_task_complete) && (l1s.task_status[BCCHN_TOP ].time_to_exec >= time_to_task_complete) && (l1s.task_status[SMSCB ].time_to_exec >= time_to_task_complete) && (l1s.task_status[NP ].time_to_exec >= time_to_task_complete) && (l1s.task_status[EP ].time_to_exec >= time_to_task_complete) && (l1s.task_status[SB2 ].time_to_exec >= time_to_task_complete) && (l1s.task_status[SBCONF ].time_to_exec >= time_to_task_complete)) { if((l1s.task_status[PBCCHS ].current_status != ACTIVE) && (l1s.task_status[PBCCHN_IDLE].current_status != ACTIVE) && (l1s.task_status[BCCHN ].current_status != ACTIVE) && (l1s.task_status[BCCHN_TOP ].current_status != ACTIVE) && (l1s.task_status[SMSCB ].current_status != ACTIVE) && (l1s.task_status[NP ].current_status != ACTIVE) && (l1s.task_status[EP ].current_status != ACTIVE) && (l1s.task_status[SB2 ].current_status != ACTIVE) && (l1s.task_status[SBCONF ].current_status != ACTIVE)) { l1s_load_mftab( BLOC_POLL_NO_HOPP, // Rom block address. BLOC_POLL_NO_HOPP_SIZE, // Rom block size. l1s.afrm, // Start with current frame. l1s.mftab.frmlst); // Proceed on MFTAB. l1s.task_status[POLL].current_status = ACTIVE; // Load FRAME_COUNT with the POLL Rom block size. if(l1s.frame_count < BLOC_POLL_NO_HOPP_SIZE) l1s.frame_count = BLOC_POLL_NO_HOPP_SIZE; } } } #endif } //#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_execute_frame() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : */ /*-------------------------------------------------------*/ void l1s_execute_frame() { // Execute functions from MFTAB. l1s_exec_mftab(); // Force time_to_next_l1s_task to 0. // This statement has been introduced to force L1S to // reschedule the next activity when the current activity // is completed. if(l1s.frame_count == 1) l1a_l1s_com.time_to_next_l1s_task = 0; // Decrement the actual FRAME_COUNT. if(l1s.frame_count > 0) l1s.frame_count--; // Decrement the actual meas_forbidden counter. if(l1s.forbid_meas > 0) l1s.forbid_meas--; } //#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_meas_manager() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is the measurement tasks manager. */ /* The followings tasks are handled: */ /* */ /* FSMS_MEAS: */ /* 1) Full list measurement in Cell Selection */ /* The machine performs 1 valid measurement per carrier */ /* from the full list of GSM carriers. To achieve 1 */ /* valid measurement, 2 attempt with 2 different AGC */ /* are performed worst case. When all carriers are */ /* a reporting message L1C_VALID_MEAS_INFO is built and */ /* sent to L1A. */ /* */ /* 2) Full list measurement in Idle mode. */ /* The machine performs 1 valid measurement per carrier */ /* from the full list of GSM carriers. To achieve 1 */ /* valid measurement, 2 attempt with 2 different AGC */ /* are performed worst case. When all carriers are */ /* a reporting message L1C_VALID_MEAS_INFO is built and */ /* sent to L1A. */ /* */ /* I_BAMS_MEAS: BA list measurement in Idle mode. */ /* The machine performs 8 measurements per PCH reading */ /* (4*2) looping on the BA list. When 8 measurements are */ /* completed (end of PCH) a reporting message */ /* L1C_RXLEV_PERIODIC_DONE is built and sent to L1A. */ /* */ /*-------------------------------------------------------*/ void l1s_meas_manager(void) { /* static static_s_rxlev_cntr = 0; */ UWORD32 i; UWORD8 IL_for_rxlev; UWORD8 adc_active = INACTIVE; static xSignalHeaderRec *pch_msg = NULL; static UWORD8 static_read_index = 0; static UWORD8 static_ctrl_index = 0; #if((RF_FAM == 61) && (CODE_VERSION != SIMULATION)) UWORD16 dco_algo_ctl_pw = 0; UWORD16 dco_algo_ctl_pw_temp = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = 180; #endif #if(CODE_VERSION == SIMULATION)// This is a temp fix- pl Verify the RF family for L1 simulator and change UWORD16 dco_algo_ctl_pw = 0; UWORD16 dco_algo_ctl_pw_temp = 0; UWORD8 if_ctl = 0; UWORD8 if_threshold = 180; #endif #if FF_L1_IT_DSP_USF // Bypass Circuit switched measurment during Packet Access phase: // 1) FSMS_MEAS not active because full list measurement not allowed in // this state (see S921 Annex C "Transisition rules"). // 2) I_BAMS_MEAS inactive because PCCCH idle therefore P_CRMS_MEAS is // used for neighbour monitoring. // 3) D_BAMS_MEAS is inactive because dedicated mode not compatible with // this state. // Running it induces side effects with Fast USF during PA because it // clears l1pa_l1ps_com.cr_freq_list.pnp_ctrl... // PA state detection with fast USF interrupt in use... if ((l1a_l1s_com.l1s_en_task[PALLC] == TASK_ENABLED) && (l1ps_macs_com.usf_status == USF_AWAITED)) return; #endif #if (FF_L1_FAST_DECODING == 1) if (l1a_apihisr_com.fast_decoding.deferred_control_req == TRUE) { /* Do not execute l1s_meas_manager if a fast decoding IT is scheduled */ return; } #endif /*#if (FF_L1_FAST_DECODING == 1)*/ //==================================================== // RESET MEASUREMENT MACHINES WHEN SYNCHRO EXECUTED. //==================================================== if(l1s.tpu_ctrl_reg & CTRL_SYNC) // SYNCHRO task has been controled, anything else is forbidden!!! // -> Reset FULL SET and BA LIST measurement machines. // -> return. { // Rem: // SYNCHRO task affects Idle FSMS_MEAS task since 1 frame is skipped. // Idle FSMS_MEAS session is restarted from scratch. // Reset Idle mode FULL LIST measurement machine. { // Init power measurement multi_session process l1a_l1s_com.full_list.meas_1st_pass_ctrl = 1; // Set 1st pass flag for power measurement session in ctrl. l1a_l1s_com.full_list.meas_1st_pass_read = 1; // Set 1st pass flag for power measurement session in read. l1a_l1s_com.full_list.nbr_sat_carrier_ctrl = 0; // Clear number of saturated carrier in ctrl. l1a_l1s_com.full_list.nbr_sat_carrier_read = 0; // Clear number of saturated carrier in read. l1a_l1s_com.full_list.ms_ctrl = 0; //nbr of meas.controled. l1a_l1s_com.full_list.ms_ctrl_d = 0; // ... 1 frame delay. l1a_l1s_com.full_list.ms_ctrl_dd = 0; // ... 2 frames delay. // Set global parameters for full list measurement. l1a_l1s_com.full_list.next_to_ctrl = 0; l1a_l1s_com.full_list.next_to_read = 0; } // Reset BA LIST measurement machine. { // Rewind "next_to_ctrl" counter to come back to the next carrier to // measure. l1a_l1s_com.ba_list.next_to_ctrl = l1a_l1s_com.ba_list.next_to_read; // Reset flags. l1a_l1s_com.ba_list.ms_ctrl = 0; l1a_l1s_com.ba_list.ms_ctrl_d = 0; l1a_l1s_com.ba_list.ms_ctrl_dd = 0; // Reset serving cell dedicated mode measurement session. l1s_reset_dedic_serving_meas(); } return; } if(l1s.dsp_ctrl_reg & CTRL_ABORT) // A task conflict has happened, ABORT has been controled reseting // the MCU/DSP communication. We must rewind any measurement activity. { // FULL LIST measurement machine. { // Init power measurement multi_session process l1a_l1s_com.full_list.meas_1st_pass_ctrl = l1a_l1s_com.full_list.meas_1st_pass_read; l1a_l1s_com.full_list.nbr_sat_carrier_ctrl = l1a_l1s_com.full_list.nbr_sat_carrier_read; // Clear number of saturated carrier in ctrl. l1a_l1s_com.full_list.ms_ctrl = 0; //nbr of meas.controled. l1a_l1s_com.full_list.ms_ctrl_d = 0; // ... 1 frame delay. l1a_l1s_com.full_list.ms_ctrl_dd = 0; // ... 2 frames delay. // Set global parameters for full list measurement. l1a_l1s_com.full_list.next_to_ctrl = l1a_l1s_com.full_list.next_to_read; } return; } //==================================================== // FULL LIST... // -> Cell Selection or, // -> Idle mode. //==================================================== // Clear semaphore when all running meas. are completed... if(!l1a_l1s_com.full_list.ms_ctrl_d && !l1a_l1s_com.full_list.ms_ctrl_dd) { l1a_l1s_com.meas_param &= FSMS_MEAS_MASK; } // When a READ is performed we set dsp_r_page_used flag to switch the read page... //if(l1a_l1s_com.full_list.ms_ctrl_dd) l1s_dsp_com.dsp_r_page_used = TRUE; // Call Cell Selection measurement management function or Idle PLMN permitted function // if meas. task still enabled. if((l1a_l1s_com.l1s_en_meas & FSMS_MEAS) && !(l1a_l1s_com.meas_param & FSMS_MEAS)) { #if L1_GPRS UWORD8 pm_read[NB_MEAS_MAX_GPRS]; #else UWORD8 pm_read[NB_MEAS_MAX]; #endif UWORD8 nbmeas, max_nbmeas; // When FULL LIST measurement task is enabled L1S is executed every frame. l1a_l1s_com.time_to_next_l1s_task = 0; // the first PW window if ((l1a_l1s_com.full_list.next_to_ctrl ==0 ) &&(l1a_l1s_com.full_list.next_to_read ==0)) { // ADC measurement // *************** if ((l1a_l1s_com.mode == CS_MODE) || (l1a_l1s_com.mode == CS_MODE0)) // only in cell selection and inside the first window { // ADC performed only with the 1st PW window if (l1a_l1s_com.adc_mode & ADC_NEXT_MEAS_SESSION) // perform ADC only one time { adc_active = ACTIVE; l1a_l1s_com.adc_mode &= ADC_MASK_RESET_IDLE; // reset in order to have only one ADC measurement in Idle } else if (l1a_l1s_com.adc_mode & ADC_EACH_MEAS_SESSION) // perform ADC on each bloc adc_active = ACTIVE; } } // ********************** // READ task if needed!!! // ********************** if(l1a_l1s_com.full_list.ms_ctrl_dd) l1_check_com_mismatch(FULL_LIST_MEAS_ID); //A measure was control two TDMA earlier. Read ms_ctrl_dd number of measures. #if L1_GPRS // !!! WARNING: word32 type is for compatibility with chipset == 0. // Can be word16 if only chipset == 2 is used. Extraction of pm using // AND operator can be removed. // Read power measurement result from DSP. switch(l1a_l1s_com.dsp_scheduler_mode) { // MCU/DSP interface is GSM one case GSM_SCHEDULER: // Read power measurement result from DSP. l1ddsp_meas_read(l1a_l1s_com.full_list.ms_ctrl_dd,pm_read); break; // MCU/DSP interface is GPRS one case GPRS_SCHEDULER: // Read power measurement result from DSP. l1pddsp_meas_read(l1a_l1s_com.full_list.ms_ctrl_dd,pm_read); break; } #else // Read power measurement result from DSP. l1ddsp_meas_read(l1a_l1s_com.full_list.ms_ctrl_dd,pm_read); #endif // When a READ is performed we set dsp_r_page_used flag to switch the read page... if(l1a_l1s_com.full_list.ms_ctrl_dd) l1s_dsp_com.dsp_r_page_used = TRUE; for(i=0; i < l1a_l1s_com.full_list.ms_ctrl_dd; i++) // Background measurements.... // A measurement controle was performed 2 tdma earlier, read result now!! { #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_READ_FULL_LIST_MEAS, (UWORD32)(-1));//OMAPS00090550 #endif l1_check_pm_error(pm_read[i], FULL_LIST_MEAS_ID); #if (TRACE_TYPE==3) stats_samples_pm(pm_read[i]); #endif // If we are running 2nd pass (because of saturated carrier during 1st pass), // we read radio_freq until we found the next one which is flagged saturated. if((!l1a_l1s_com.full_list.meas_1st_pass_read) && ( l1a_l1s_com.full_list.nbr_sat_carrier_read!=0)) { while(l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_read]==0) l1a_l1s_com.full_list.next_to_read++; // increase carrier index until a saturated one // is found. l1a_l1s_com.full_list.nbr_sat_carrier_read--; } // Test meas value and validate or not the measurement. // Fill accordingly input_level and sat_flag fields. // L1_FF_MULTIBAND TBD IL_for_rxlev = l1ctl_csgc((UWORD8)(pm_read[i]),l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_read].radio_freq); #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_FULL_LIST_MEAS(pm_read[i], IL_for_rxlev, FULL_LIST_MEAS_ID, l1a_l1s_com.full_list.next_to_read) #endif // Accumulate only valid results (no saturated carriers) if (l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_read]==0) { // Fill result "message" (array passed by L3 is directly filled by L1S). #if TESTMODE if (l1_config.TestMode) { // L1_FF_MULTIBAND TBD l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_read].accum_power_result = IL_for_rxlev; } else { // L1_FF_MULTIBAND TBD l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_read].accum_power_result += l1s_encode_rxlev(IL_for_rxlev); } #else // L1_FF_MULTIBAND TBD l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_read].accum_power_result += l1s_encode_rxlev(IL_for_rxlev); #endif } #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_POWER) buffer_trace( 4, l1a_l1s_com.full_list.next_to_read+l1_config.std.radio_freq_index_offset, pm_read[i], l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_read], 0); #endif #endif // Increment "next_to_read" field for next measurement... if(++l1a_l1s_com.full_list.next_to_read >= l1a_l1s_com.full_list_ptr->power_array_size) { l1a_l1s_com.full_list.next_to_read = 0; l1a_l1s_com.full_list.meas_1st_pass_read = 0; } }// end of for (READ) // ********************** // CTRL task if needed!!! // ********************** // We can make a measurement on any frame excepted the frame // used to execute tasks not compatible with full list measurement. // (FBNEW,SB2,... #if L1_GPRS if(((l1pa_l1ps_com.cr_freq_list.ms_ctrl_d == 0) && (l1a_l1s_com.ba_list.np_ctrl == 0)) && (l1s.forbid_meas < 2)) #else if((l1a_l1s_com.ba_list.np_ctrl == 0) && (l1s.forbid_meas < 2)) #endif { if(!l1a_l1s_com.full_list.meas_1st_pass_ctrl) // 2nd pass { if(l1a_l1s_com.full_list.nbr_sat_carrier_ctrl!=0) // there are still saturated carriers { WORD16 tpu_win_rest; UWORD16 power_meas_split; // Compute how many BP_SPLIT remains for full list meas. // Rem: we take into account the SYNTH load for 1st RX in next frame. tpu_win_rest = FRAME_SPLIT - l1s.tpu_win; power_meas_split = (l1_config.params.rx_synth_load_split + PWR_LOAD); max_nbmeas = 0; while(tpu_win_rest >= power_meas_split) { max_nbmeas ++; tpu_win_rest -= power_meas_split; } if(l1a_l1s_com.full_list.nbr_sat_carrier_ctrl >= max_nbmeas ) nbmeas = max_nbmeas; else nbmeas = l1a_l1s_com.full_list.nbr_sat_carrier_ctrl; #if L1_GPRS switch(l1a_l1s_com.dsp_scheduler_mode) { // MCU/DSP interface is GSM one case GSM_SCHEDULER: { // GSM scheduler can perform 8/4 meas. per TDMA depending on DSP code if(nbmeas > NB_MEAS_MAX) nbmeas = NB_MEAS_MAX; // Program DSP to make nbmeas neighbor measurments. // DSP code 33 is the only one to support more than 4PM (up to 8PM) #if (DSP != 33) && (DSP != 34) && (DSP != 35) && (DSP != 36) && (DSP != 37) && (DSP != 38) && (DSP != 39) if(l1s.tpu_win) // check whether NB scheduled in same frame { if (nbmeas > NB_MEAS_MAX-1) // MCU-DSP I/F only supports 1NB + 3PM or 4PM nbmeas = NB_MEAS_MAX-1; // TPU RAM needs to be checked, too !!! } l1ddsp_load_monit_task(nbmeas,0); #else // For activation of more than 4PM, DSP checks the bit field 0x200 (1PM correspond to 0x201) l1ddsp_load_monit_task(nbmeas+0x200, 0); #endif } break; // MCU/DSP interface is GPRS one case GPRS_SCHEDULER: { // GPRS scheduler can perform 8 meas. per TDMA max. if (nbmeas > NB_MEAS_MAX_GPRS) nbmeas = NB_MEAS_MAX_GPRS; // Program DSP to make nbmeas neighbor measurments. // Note: At this level, l1s.tpu_win is considered to be // equal to 1 or 2. if(l1s.tpu_win) l1pddsp_meas_ctrl(nbmeas, 1); else l1pddsp_meas_ctrl(nbmeas, 0); } break; } #else // GSM scheduler can perform 8/4 meas. per TDMA depending on DSP code if(nbmeas > NB_MEAS_MAX) nbmeas = NB_MEAS_MAX; // Program DSP to make nbmeas neighbor measurments. // DSP code 33 is the only one to support more than 4PM (up to 8PM) #if (DSP != 33) && (DSP != 34) && (DSP != 35) && (DSP != 36) && (DSP != 37) && (DSP != 38) && (DSP != 39) if(l1s.tpu_win) // check whether NB scheduled in same frame { if (nbmeas > NB_MEAS_MAX-1) // MCU-DSP I/F only supports 1NB + 3PM or 4PM nbmeas = NB_MEAS_MAX-1; // TPU RAM needs to be checked, too !!! } l1ddsp_load_monit_task(nbmeas,0); #else // For activation of more than 4PM, DSP checks the bit field 0x200 (1PM correspond to 0x201) l1ddsp_load_monit_task(nbmeas+0x200, 0); #endif #endif // for each meas. do TPU control. for ( i = 0; i<nbmeas; i++) { while(l1a_l1s_com.full_list.sat_flag[l1a_l1s_com.full_list.next_to_ctrl]==0) l1a_l1s_com.full_list.next_to_ctrl++; // increase carrier index until a saturated one // is found. // Decrement the number of sat carriers. l1a_l1s_com.full_list.nbr_sat_carrier_ctrl--; #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_CTRL_FULL_LIST_MEAS, (UWORD32)(-1));//OMAPS00090550 #endif #if(RF_FAM == 61) // Locosto DCO #if (PWMEAS_IF_MODE_FORCE == 0) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_INVALID , 0, ( l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_ctrl].radio_freq),if_threshold); #else if_ctl = IF_120KHZ_DSP; dco_algo_ctl_pw_temp = DCO_IF_0KHZ; #endif dco_algo_ctl_pw |= ((dco_algo_ctl_pw_temp & 0x03)<< (i*2)); #endif // tpu pgm: 1 measurement only. // L1_FF_MULTIBAND TBD l1dtpu_meas(l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_ctrl].radio_freq, l1_config.params.low_agc, 0, l1s.tpu_win, l1s.tpu_offset, adc_active #if(RF_FAM == 61) ,L1_AFC_SCRIPT_MODE ,if_ctl #endif ); // only one ADC: with the first window adc_active = INACTIVE; // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD); // increment carrier counter for next measurement... if(++l1a_l1s_com.full_list.next_to_ctrl >= l1a_l1s_com.full_list_ptr->power_array_size) l1a_l1s_com.full_list.next_to_ctrl = 0; } #if(RF_FAM == 61) l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Flag measurement control. // ************************** // Set nbr of meas. programmed "ms_ctrl" to nbmeas. // It will be used as 2 tdma delayed to // trigger the reading. l1a_l1s_com.full_list.ms_ctrl = nbmeas; // 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; } } else // 1st pass { WORD16 tpu_win_rest; UWORD16 power_meas_split; // Compute how many BP_SPLIT remains for full list meas. // Rem: we take into account the SYNTH load for 1st RX in next frame. tpu_win_rest = FRAME_SPLIT - l1s.tpu_win; power_meas_split = (l1_config.params.rx_synth_load_split + PWR_LOAD); max_nbmeas = 0; while(tpu_win_rest >= power_meas_split) { max_nbmeas ++; tpu_win_rest -= power_meas_split; } i = l1a_l1s_com.full_list_ptr->power_array_size - l1a_l1s_com.full_list.next_to_ctrl; if( i >= max_nbmeas ) nbmeas = max_nbmeas; else nbmeas = i; #if L1_GPRS switch(l1a_l1s_com.dsp_scheduler_mode) { // MCU/DSP interface is GSM one case GSM_SCHEDULER: { // GSM scheduler can perform 8/4 meas. per TDMA depending on DSP code if(nbmeas > NB_MEAS_MAX) nbmeas = NB_MEAS_MAX; // Program DSP to make nbmeas neighbor measurments. // DSP code 33 is the only one to support more than 4PM (up to 8PM) #if (DSP != 33) && (DSP != 34) && (DSP != 35) && (DSP != 36) && (DSP != 37) && (DSP != 38) && (DSP != 39) if(l1s.tpu_win) // check whether NB scheduled in same frame { if (nbmeas > NB_MEAS_MAX-1) // MCU-DSP I/F only supports 1NB + 3PM or 4PM nbmeas = NB_MEAS_MAX-1; // TPU RAM needs to be checked, too !!! } l1ddsp_load_monit_task(nbmeas,0); #else // For activation of more than 4PM, DSP checks the bit field 0x200 (1PM correspond to 0x201) l1ddsp_load_monit_task(nbmeas+0x200, 0); #endif } break; // MCU/DSP interface is GPRS one case GPRS_SCHEDULER: { // GPRS scheduler can perform 8 meas. per TDMA max. if (nbmeas > NB_MEAS_MAX_GPRS) nbmeas = NB_MEAS_MAX_GPRS; // Program DSP to make nbmeas neighbor measurments. // Note: At this level, l1s.tpu_win is considered to be // equal to 1 or 2. if(l1s.tpu_win) l1pddsp_meas_ctrl(nbmeas, 1); else l1pddsp_meas_ctrl(nbmeas, 0); } break; } #else // GSM scheduler can perform 8/4 meas. per TDMA depending on DSP code if(nbmeas > NB_MEAS_MAX) nbmeas = NB_MEAS_MAX; // Program DSP to make nbmeas neighbor measurments. // DSP code 33 is the only one to support more than 4PM (up to 8PM) #if (DSP != 33) && (DSP != 34) && (DSP != 35) && (DSP != 36) && (DSP != 37) && (DSP != 38) && (DSP !=39) if(l1s.tpu_win) // check whether NB scheduled in same frame { if (nbmeas > NB_MEAS_MAX-1) // MCU-DSP I/F only supports 1NB + 3PM or 4PM nbmeas = NB_MEAS_MAX-1; // TPU RAM needs to be checked, too !!! } l1ddsp_load_monit_task(nbmeas,0); #else // For activation of more than 4PM, DSP checks the bit field 0x200 (1PM correspond to 0x201) l1ddsp_load_monit_task(nbmeas+0x200, 0); #endif #endif // for each meas. do TPU control. for (i=0; i<nbmeas; i++) { #if(RF_FAM == 61) // Locosto DCO #if (PWMEAS_IF_MODE_FORCE == 0) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_INVALID , 0, l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_ctrl].radio_freq,if_threshold); #else if_ctl = IF_120KHZ_DSP; dco_algo_ctl_pw_temp = DCO_IF_0KHZ; #endif dco_algo_ctl_pw |= ((dco_algo_ctl_pw_temp & 0x03)<< (i*2)) ; #endif // tpu pgm: 1 measurement only. // L1_FF_MULTIBAND TBD l1dtpu_meas(l1a_l1s_com.full_list_ptr->power_array[l1a_l1s_com.full_list.next_to_ctrl].radio_freq, l1_config.params.high_agc, 0, l1s.tpu_win, l1s.tpu_offset,adc_active #if(RF_FAM == 61) ,L1_AFC_SCRIPT_MODE ,if_ctl #endif ); // only one ADC: with the first window adc_active = INACTIVE; // increment carrier counter for next measurement... if(++l1a_l1s_com.full_list.next_to_ctrl >= l1a_l1s_com.full_list_ptr->power_array_size) { l1a_l1s_com.full_list.next_to_ctrl = 0; // Go back to the top of the list. l1a_l1s_com.full_list.meas_1st_pass_ctrl = 0; // End of 1st pass. } // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD); } #if(RF_FAM == 61) l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw); #endif l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Flag measurement control. // ************************** // Set nbr of meas. programmed "ms_ctrl" to nbmeas. // It will be used as 2 tdma delayed to // trigger the reading. l1a_l1s_com.full_list.ms_ctrl = nbmeas; // 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; } } //Time to make reporting....... if((!l1a_l1s_com.full_list.meas_1st_pass_read) && ( l1a_l1s_com.full_list.nbr_sat_carrier_read == 0)) { xSignalHeaderRec *fl_msg; /*-----------------------------------------------*/ /* Time to report (1 valid measurement has */ /* been performed on each carrier) if: */ /* Cell Selection or PLMN selection, and */ /* The 1st pass has been completed, and */ /* No more carrier saturated to control, and */ /* No measurement in the pipeline. */ /*-----------------------------------------------*/ // Reset the FSMS_MEAS process to avoid to keep sending // report message to L1A. l1a_l1s_com.l1s_en_meas &= FSMS_MEAS_MASK; // Clear Cell Selection/Idle Full List Measurement enable flag. // alloc L1C_VALID_MEAS_INFO message... fl_msg = os_alloc_sig(sizeof(int)); DEBUGMSG(status,NU_ALLOC_ERR) fl_msg->SignalCode = L1C_VALID_MEAS_INFO; // L1_FF_MULTIBAND TBD fl_msg->SigP= (void *) l1a_l1s_com.full_list_ptr; // send L1C_VALID_MEAS_INFO message... os_send_sig(fl_msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) }//end of reporting }// end of FSMS_MEAS //==================================================== // BA LIST... // -> Idle mode. //==================================================== // When a READ is performed we usueally set "dsp_r_page_used" flag to switch the // read page but since I_BAMS is executed in the same frame as Normal Paging (NP), // the setting of "dsp_r_page_used" is already done in READ(NP). if((l1a_l1s_com.l1s_en_meas & I_BAMS_MEAS) && (l1a_l1s_com.meas_param & I_BAMS_MEAS)) // Some changes occured on the BA list or the PAGING PARAMETERS have // changed. { // Reset BA semaphore. l1a_l1s_com.meas_param &= I_BAMS_MEAS_MASK; /* pch_msg != NULL added below due to the fast pagin feature + power reduction feature * as the measurement can end in potentially 2 TDMA frames itself and an IBA_R message * when comes in certail TDMA frames of paging task, both static ctrl index and static * read index will be zero */ /* FreeCalypso TCS211 reconstruction: above change reverted */ if((static_ctrl_index != 0) || (static_read_index != 0)) { // Paging process has been interrupted by a L3 message // Deallocate memory for the received message if msg not forwarded to L3. // ---------------------------------------------------------------------- #if (GSM_IDLE_RAM != 1) os_free_sig(pch_msg); DEBUGMSG(status,NU_DEALLOC_ERR) #endif pch_msg = NULL; static_ctrl_index = 0; static_read_index = 0; // Rewind ba counters to come back to the first carrier of this // aborted session. l1a_l1s_com.ba_list.next_to_read = l1a_l1s_com.ba_list.first_index; l1a_l1s_com.ba_list.next_to_ctrl = l1a_l1s_com.ba_list.first_index; // Reset flags. l1a_l1s_com.ba_list.ms_ctrl = FALSE; l1a_l1s_com.ba_list.ms_ctrl_d = FALSE; l1a_l1s_com.ba_list.ms_ctrl_dd = FALSE; } } else if ((l1a_l1s_com.l1s_en_meas & I_BAMS_MEAS) && !(l1a_l1s_com.meas_param & I_BAMS_MEAS)) // Idle Neighbor Cells Power Measurements fonction if meas. task still enabled. { UWORD8 nbr_carrier = l1a_l1s_com.ba_list.nbr_carrier; // variables introduced to cope with RACH sent on one frame of the paging block static UWORD8 static_nbmeas_to_report = 8; static UWORD8 static_nbmeas_ctrl_d = 0; static UWORD8 static_nbmeas_ctrl_dd = 0; #if 0 /* FreeCalypso TCS211 reconstruction */ static UWORD8 num_pm[4]={0,0,0,0}; #if (FF_L1_FAST_DECODING == 1) static UWORD8 num_pm_fp[2]={0,0}; #endif static UWORD8 num_pm_frames = 0; /* number of frames over which measurement is scheduled */ #endif UWORD8 nbmeas_ctrl = 0; #if (FF_L1_FAST_DECODING == 1) BOOL schedule_measures = FALSE; BOOL fast_decoding = l1s_check_fast_decoding_authorized(NP); #endif /* FF_L1_FAST_DECODING */ // ******************** // READ task if needed // ******************** if(l1a_l1s_com.ba_list.ms_ctrl_dd == TRUE) // Background measurements.... // A measurement controle (set in "l1s_ctrl_ms()" function) was performed // 2 tdma earlier, read result now!! { UWORD16 radio_freq_read; UWORD8 ba_index_read; l1_check_com_mismatch(I_BA_MEAS_ID); for(i=0; i<static_nbmeas_ctrl_dd; i++) { UWORD32 pm; #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_READ_I_BA_MEAS, (UWORD32)(-1));//OMAPS00090550 #endif // Read power measurement result from DSP. pm = (l1s_dsp_com.dsp_db_r_ptr->a_pm[i] & 0xffff) >> 5; l1_check_pm_error(pm, I_BA_MEAS_ID); #if (TRACE_TYPE==3) stats_samples_pm(pm); #endif ba_index_read = l1a_l1s_com.ba_list.next_to_read; radio_freq_read = l1a_l1s_com.ba_list.A[ba_index_read].radio_freq; // Get Input level corresponding to the used IL and pm result. IL_for_rxlev = l1ctl_pgc((UWORD8)pm, l1a_l1s_com.ba_list.used_il_dd[i], l1a_l1s_com.ba_list.used_lna_dd[i], radio_freq_read); #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_MON_MEAS(pm, IL_for_rxlev, I_BA_MEAS_ID, radio_freq_read) #endif #if 0 /* FreeCalypso TCS211 reconstruction */ //Check if the message is not empty, else allocate memory if (pch_msg == NULL) { pch_msg = os_alloc_sig(sizeof(T_L1C_RXLEV_PERIODIC_DONE)); DEBUGMSG(status,NU_ALLOC_ERR) pch_msg->SignalCode = L1C_RXLEV_PERIODIC_DONE; } #endif // Fill reporting message. ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))-> A[static_read_index].radio_freq_no = radio_freq_read; ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))-> A[static_read_index].rxlev = l1s_encode_rxlev(IL_for_rxlev); // Increment the number of neighbor meas read. static_read_index ++; // Increment "l1s.next_to_read" field for next measurement... if(++l1a_l1s_com.ba_list.next_to_read >= nbr_carrier) l1a_l1s_com.ba_list.next_to_read = 0; }//end for // Serving cell measurements... // Accumulate the new measurement with the partial result. // Compensate AGC for current measurement value. l1a_l1s_com.Scell_info.meas.acc += l1a_l1s_com.Scell_IL_for_rxlev; /* static_s_rxlev_cntr++; */ // ********** // Reporting // ********** if (static_read_index==static_nbmeas_to_report) { #if (GSM_IDLE_RAM == 1) if (!READ_TRAFFIC_CONT_STATE) { CSMI_TrafficControllerOn(); } // 1st paging block, so it's time to allocate L1C_RXLEV_PERIODIC_IND msg if (pch_msg == NULL) { pch_msg = os_alloc_sig(sizeof(T_L1C_RXLEV_PERIODIC_DONE)); DEBUGMSG(status,NU_ALLOC_ERR) pch_msg->SignalCode = L1C_RXLEV_PERIODIC_DONE; } for(i=0; i<static_nbmeas_to_report; i++) { ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->A[i].radio_freq_no = l1s.A[i].radio_freq_no; ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->A[i].rxlev = l1s.A[i].rxlev; // Fill reporting message. } #endif static_read_index = 0; // Fill serving cell RXLEV field. //#if (FF_L1_FAST_DECODING == 1) /* Reporting done after the 2nd NP burst, bursts 3 and 4 are unknown */ //if (fast_decoding == TRUE) // ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->s_rxlev = l1s_encode_rxlev(l1a_l1s_com.Scell_info.meas.acc/2); //else // ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->s_rxlev = l1s_encode_rxlev(l1a_l1s_com.Scell_info.meas.acc/4); //#else /* #if (FF_L1_FAST_DECODING == 1) */ // ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->s_rxlev = l1s_encode_rxlev(l1a_l1s_com.Scell_info.meas.acc/4); //#endif /* #if (FF_L1_FAST_DECODING == 1) #else */ ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->s_rxlev = l1s_encode_rxlev(l1a_l1s_com.Scell_info.meas.acc/4); // Fill "nbr_of_carriers" field, it is 7 when a RACH coincides with paging block, 8 otherwise. ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->nbr_of_carriers = static_nbmeas_to_report; // Fill BA identifier field. ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->ba_id = l1a_l1s_com.ba_list.ba_id; // Enhanced RSSI #if 0 /* FreeCalypso TCS211 reconstruction */ ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->qual_acc_idle =qual_acc_idle1[0] ; ((T_L1C_RXLEV_PERIODIC_DONE*)(pch_msg->SigP))->qual_nbr_meas_idle =qual_acc_idle1[1]* TOTAL_NO_OF_BITS_IDLE_MEAS; #endif // send L1C_RXLEV_PERIODIC_IND message... os_send_sig(pch_msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) #if 0 /* FreeCalypso TCS211 reconstruction */ // Reseting the value qual_acc_idle1[0]= 0; qual_acc_idle1[1] =0; #endif // Reset pointer for debugg. pch_msg = NULL; /* static_s_rxlev_cntr = 0; */ } }// end of READ // ********** // CTRL task // ********** if (l1a_l1s_com.ba_list.np_ctrl == 1) { #if (GSM_IDLE_RAM != 1) // 1st paging block, so it's time to allocate L1C_RXLEV_PERIODIC_IND msg if (pch_msg == NULL) { pch_msg = os_alloc_sig(sizeof(T_L1C_RXLEV_PERIODIC_DONE)); DEBUGMSG(status,NU_ALLOC_ERR) pch_msg->SignalCode = L1C_RXLEV_PERIODIC_DONE; /* static_s_rxlev_cntr = 0; */ } #endif // Reset accumalator for serving measurements. l1a_l1s_com.Scell_info.meas.acc = 0; // Clear read period counter static_read_index = 0; // Save first BA index to be measured in this new session. l1a_l1s_com.ba_list.first_index = l1a_l1s_com.ba_list.next_to_ctrl; // Reset static variables for control of nbmeas per frame static_nbmeas_to_report = 8; static_nbmeas_ctrl_d = 0; static_nbmeas_ctrl_dd = 0; } // A PCH burst has been controled, we must make the control of 1 or 2 new measurements. if ((static_ctrl_index == (l1a_l1s_com.ba_list.np_ctrl-1)*2) || (static_ctrl_index == (l1a_l1s_com.ba_list.np_ctrl-1)*2 - 1)) { UWORD16 radio_freq_ctrl; UWORD8 ba_index_ctrl; // check whether RACH has been controlled in the same frame // if YES only one PW measurement will be controlled and the number of meas to report is decremented by 1 if (l1s.tpu_win >= (3 * BP_SPLIT + l1_config.params.tx_ra_load_split + l1_config.params.rx_synth_load_split)) { static_nbmeas_to_report--; nbmeas_ctrl = 1; } else { nbmeas_ctrl = 2; } /* end else no RACH */ for(i=0; i<nbmeas_ctrl; i++) { UWORD8 lna_off; WORD32 agc; #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif ba_index_ctrl = l1a_l1s_com.ba_list.next_to_ctrl; radio_freq_ctrl = l1a_l1s_com.ba_list.A[ba_index_ctrl].radio_freq; #if (L1_FF_MULTIBAND == 0) // Get AGC according to the last known IL. agc = Cust_get_agc_from_IL(radio_freq_ctrl, l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level >> 1, PWR_ID); lna_off = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].lna_off; // Memorize the IL used for AGC setting. l1a_l1s_com.ba_list.used_il[i] = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level; l1a_l1s_com.ba_list.used_lna[i] = l1a_l1s_com.last_input_level[radio_freq_ctrl - 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_ctrl); lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; // Get AGC according to the last known IL. agc = Cust_get_agc_from_IL(radio_freq_ctrl, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, PWR_ID); // Memorize the IL used for AGC setting. l1a_l1s_com.ba_list.used_il[i] = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; l1a_l1s_com.ba_list.used_lna[i] = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; #endif // #if (L1_FF_MULTIBAND == 0) else #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_CTRL_I_BA_MEAS,(UWORD32)(-1));//OMAPS00090550 #endif #if(RF_FAM == 61) // Locosto DCO #if (PWMEAS_IF_MODE_FORCE == 0) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw_temp, &if_ctl, (UWORD8) L1_IL_VALID , l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level, radio_freq_ctrl,if_threshold); #else if_ctl = IF_120KHZ_DSP; dco_algo_ctl_pw_temp = DCO_IF_0KHZ; #endif dco_algo_ctl_pw |= ((dco_algo_ctl_pw_temp & 0x03)<< (i*2)) ; #endif // tpu pgm: 1 measurement only. l1dtpu_meas(radio_freq_ctrl, agc, lna_off, l1s.tpu_win, l1s.tpu_offset, INACTIVE #if(RF_FAM == 61) ,L1_AFC_SCRIPT_MODE ,if_ctl #endif ); // increment carrier counter for next measurement... if(++l1a_l1s_com.ba_list.next_to_ctrl >= nbr_carrier) l1a_l1s_com.ba_list.next_to_ctrl = 0; #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH) buffer_trace(4, l1s.actual_time.fn, radio_freq, l1s.tpu_win, 0); #endif #endif // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD); // Increment the number of neighbor meas controled. static_ctrl_index ++; // static_ctrl_index %=8; if (static_ctrl_index >= static_nbmeas_to_report) static_ctrl_index = 0; } #if(RF_FAM == 61) l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw); #endif l1ddsp_load_monit_task(nbmeas_ctrl, 0); l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Flag measurement control. // ************************** // Set flag "ms_ctrl" to 1. It will be used as 2 tdma delayed for // background measurement reading. l1a_l1s_com.ba_list.ms_ctrl = TRUE; // Flag DSP and TPU programmation. // ******************************** // Set "CTRL_MS" flag in the control flag register. l1s.tpu_ctrl_reg |= CTRL_MS; l1s.dsp_ctrl_reg |= CTRL_MS; }//end ctrl // Pipeline for tracking of the number of measurements controlled static_nbmeas_ctrl_dd = static_nbmeas_ctrl_d; static_nbmeas_ctrl_d = nbmeas_ctrl; }//end I_BAMS_MEAS //==================================================== // BA LIST... // -> Dedicated mode. //==================================================== // When a READ is performed we set dsp_r_page_used flag to switch the read page... if(l1a_l1s_com.ba_list.ms_ctrl_dd==TRUE) l1s_dsp_com.dsp_r_page_used = TRUE; if((l1a_l1s_com.l1s_en_meas & D_BAMS_MEAS) && (l1a_l1s_com.meas_param & D_BAMS_MEAS)) // Some changes occured on the BA list or the Dedicated channel have // changed. { #if FF_L1_IT_DSP_DTX // Postpone rewind from DTX HISR to L1S to keep same behaviour if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) { #endif if(l1a_l1s_com.ba_list.ms_ctrl_d == FALSE) // Reset BA semaphore. // Rem: BA semaphore is reset only if the pipeline ctrl // is empty. { l1a_l1s_com.meas_param &= D_BAMS_MEAS_MASK; } // Rewind "next_to_ctrl" counter to come back to the next carrier to // measure. l1a_l1s_com.ba_list.next_to_ctrl = l1a_l1s_com.ba_list.next_to_read; // Reset of "ms_ctrl, ms_ctrl_d, msctrl_dd" is done at L1 startup // and when SYNCHRO task is executed. #if FF_L1_IT_DSP_DTX } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) #endif } else if ( (l1a_l1s_com.l1s_en_meas & D_BAMS_MEAS) && !(l1a_l1s_com.meas_param & D_BAMS_MEAS) && (l1a_l1s_com.l1s_en_task[DEDIC] == TASK_ENABLED) ) // Call Dedicated Neighbor Cells Power Measurements fonction // if meas. task still enabled and global dedicated mode task enabled. { UWORD8 nbr_carrier = l1a_l1s_com.ba_list.nbr_carrier; T_CHANNEL_DESCRIPTION *desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; UWORD32 pm; UWORD8 lna_off; WORD32 agc; #if FF_L1_IT_DSP_DTX // Read operation to be done from L1S only if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) { #endif // ******************** // READ task if needed // ******************** if(l1a_l1s_com.ba_list.ms_ctrl_dd == TRUE) // Background measurements.... // A measurement controle (set in "l1s_ctrl_ms()" function) was performed // 2 tdma earlier, read result now!! { UWORD16 radio_freq_read; UWORD8 ba_index_read; l1_check_com_mismatch(D_BA_MEAS_ID); #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_READ_D_BA_MEAS, (UWORD32)(-1));//OMAPS00090550 #endif // Read power measurement result from DSP. pm = (l1s_dsp_com.dsp_db_r_ptr->a_pm[0] & 0xffff) >> 5; l1_check_pm_error(pm, D_BA_MEAS_ID); #if (TRACE_TYPE==3) stats_samples_pm(pm); #endif ba_index_read = l1a_l1s_com.ba_list.next_to_read; radio_freq_read = l1a_l1s_com.ba_list.A[ba_index_read].radio_freq; // Get Input level corresponding to the used IL and pm result. IL_for_rxlev = l1ctl_pgc((UWORD8)pm,l1a_l1s_com.ba_list.used_il_dd[0],l1a_l1s_com.ba_list.used_lna_dd[0], radio_freq_read); #if (TRACE_TYPE == 1) || (TRACE_TYPE == 4) RTTL1_FILL_MON_MEAS(pm, IL_for_rxlev, D_BA_MEAS_ID, radio_freq_read) #endif // Accumulate new RXLEV level in the BA list. l1a_l1s_com.ba_list.A[ba_index_read].acc += l1s_encode_rxlev(IL_for_rxlev); l1a_l1s_com.ba_list.A[ba_index_read].nbr_meas++; // Increment "l1s.next_to_read" field for next measurement... if(++l1a_l1s_com.ba_list.next_to_read >= nbr_carrier) l1a_l1s_com.ba_list.next_to_read = 0; }// end of READ #if FF_L1_IT_DSP_DTX } // if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) #endif // ********** // CTRL task // ********** if((desc_ptr->channel_type == SDCCH_4) || (desc_ptr->channel_type == SDCCH_8)) // case SDCCH... { UWORD8 ba_index_ctrl; UWORD16 radio_freq_ctrl; #if (L1_FF_MULTIBAND == 1) UWORD8 operative_radio_freq; #endif if(l1s.forbid_meas < 2) // We must perform a measurement on every frame except when // FB51/SB51/SBCNF51 tasks are running, those tasks are not compatible // with neigh. measurement. { ba_index_ctrl = l1a_l1s_com.ba_list.next_to_ctrl; radio_freq_ctrl = l1a_l1s_com.ba_list.A[ba_index_ctrl].radio_freq; #if (L1_FF_MULTIBAND == 0) agc = Cust_get_agc_from_IL(radio_freq_ctrl, l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level >> 1, PWR_ID); lna_off = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].lna_off; // Store IL used for current CTRL in order to be able to build IL from pm // in READ phase. l1a_l1s_com.ba_list.used_il[0] = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level; l1a_l1s_com.ba_list.used_lna[0] = l1a_l1s_com.last_input_level[radio_freq_ctrl - 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_ctrl); lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; agc = Cust_get_agc_from_IL(radio_freq_ctrl, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, PWR_ID); // Store IL used for current CTRL in order to be able to build IL from pm // in READ phase. l1a_l1s_com.ba_list.used_il[0] = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; l1a_l1s_com.ba_list.used_lna[0] = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; #endif // #if (L1_FF_MULTIBAND == 0) else #if (TRACE_TYPE!=0) && (TRACE_TYPE!=5) trace_fct(CST_CTRL_D_BA_MEAS,(UWORD32)( -1));//OMAPS00090550 #endif #if(RF_FAM == 61) // Locosto DCO #if (PWMEAS_IF_MODE_FORCE == 0) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw, &if_ctl, (UWORD8) L1_IL_VALID , l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level, radio_freq_ctrl,if_threshold); #else if_ctl = IF_120KHZ_DSP; dco_algo_ctl_pw = DCO_IF_0KHZ; #endif l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw); #endif // TPU pgm: 1 measurement only. l1dtpu_meas(radio_freq_ctrl, agc, lna_off, l1s.tpu_win, l1s.tpu_offset, INACTIVE #if(RF_FAM == 61) ,L1_AFC_SCRIPT_MODE ,if_ctl #endif ); // increment carrier counter for next measurement... if(++l1a_l1s_com.ba_list.next_to_ctrl >= nbr_carrier) l1a_l1s_com.ba_list.next_to_ctrl = 0; #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH) buffer_trace(4, l1s.actual_time.fn, radio_freq, l1s.tpu_win, 0); #endif #endif // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD); // DSP pgm: 1 measurement only. l1ddsp_load_monit_task(1, 0); l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Flag measurement control. // ************************** // Set flag "ms_ctrl" to 1. It will be used as 2 tdma delayed for // background measurement reading. l1a_l1s_com.ba_list.ms_ctrl = TRUE; // 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; } } else // case TCH... { UWORD8 ba_index_ctrl; UWORD16 radio_freq_ctrl; #if (L1_FF_MULTIBAND == 1) UWORD16 operative_radio_freq; #endif //T_CHANNEL_DESCRIPTION *desc_ptr = l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr; -OMAPS-90550-new if(l1s.forbid_meas == 0) // We must perform a measurement on every frame except frames 23, 24 (TCH_HS SC0) // 24, 25 (TCH_HS SC1 anf TCH_FS) // when FB26/SB26/SBCNF26 tasks are running, those task are not compatible // with neigh. measurement. { #if FF_L1_IT_DSP_DTX if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED) { #endif ba_index_ctrl = l1a_l1s_com.ba_list.next_to_ctrl; radio_freq_ctrl = l1a_l1s_com.ba_list.A[ba_index_ctrl].radio_freq; #if (L1_FF_MULTIBAND == 0) agc = Cust_get_agc_from_IL(radio_freq_ctrl, l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level >> 1, PWR_ID); lna_off = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].lna_off; // Store IL used for current CTRL in order to be able to build IL from pm // in READ phase. l1a_l1s_com.ba_list.used_il[0] = l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level; l1a_l1s_com.ba_list.used_lna[0] = l1a_l1s_com.last_input_level[radio_freq_ctrl - 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_ctrl); lna_off = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; agc = Cust_get_agc_from_IL(radio_freq_ctrl, l1a_l1s_com.last_input_level[operative_radio_freq].input_level >> 1, PWR_ID); // Store IL used for current CTRL in order to be able to build IL from pm // in READ phase. l1a_l1s_com.ba_list.used_il[0] = l1a_l1s_com.last_input_level[operative_radio_freq].input_level; l1a_l1s_com.ba_list.used_lna[0] = l1a_l1s_com.last_input_level[operative_radio_freq].lna_off; #endif // #if (L1_FF_MULTIBAND == 0) #if(RF_FAM == 61) // Locosto DCO #if (PWMEAS_IF_MODE_FORCE == 0) cust_get_if_dco_ctl_algo(&dco_algo_ctl_pw, &if_ctl, (UWORD8) L1_IL_VALID , l1a_l1s_com.last_input_level[radio_freq_ctrl - l1_config.std.radio_freq_index_offset].input_level, radio_freq_ctrl,if_threshold); #else if_ctl = IF_120KHZ_DSP; dco_algo_ctl_pw = DCO_IF_0KHZ; #endif l1ddsp_load_dco_ctl_algo_pw(dco_algo_ctl_pw); #endif // TPU pgm: 1 measurement only. l1dtpu_meas(radio_freq_ctrl, agc, lna_off, l1s.tpu_win, l1s.tpu_offset, INACTIVE #if(RF_FAM == 61) ,L1_AFC_SCRIPT_MODE ,if_ctl #endif ); // increment carrier counter for next measurement... if(++l1a_l1s_com.ba_list.next_to_ctrl >= nbr_carrier) l1a_l1s_com.ba_list.next_to_ctrl = 0; #if L2_L3_SIMUL #if (DEBUG_TRACE == BUFFER_TRACE_OFFSET_NEIGH) buffer_trace(4, l1s.actual_time.fn, radio_freq, l1s.tpu_win, 0); #endif #endif // Increment tpu window identifier. l1s.tpu_win += (l1_config.params.rx_synth_load_split + PWR_LOAD); // DSP pgm: 1 measurement only. l1ddsp_load_monit_task(1, 0); l1s_dsp_com.dsp_db_w_ptr->d_debug = (l1s.debug_time + 2) ; // Flag measurement control. // ************************** // Set flag "ms_ctrl" to 1. It will be used as 2 tdma delayed for // background measurement reading. l1a_l1s_com.ba_list.ms_ctrl = TRUE; // 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; #if FF_L1_IT_DSP_DTX } // if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED) #endif } } #if FF_L1_IT_DSP_DTX if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) { #endif // Time to make reporting... //-------------------------- if(l1s.next_time.fn_in_report == 0) { l1s_dedic_reporting(); // Check if any NEW BA available, if so download it... if(l1a_l1s_com.ba_list.new_list_present == TRUE) { WORD32 i; // Set parameter synchro semaphore for D_BAMS task. // This is used to reject any measurement which could // be in the C/W/R pipeline. l1a_l1s_com.meas_param |= D_BAMS_MEAS; // Download new list. for(i=0;i<l1a_l1s_com.ba_list.new_list.num_of_chans;i++) { l1a_l1s_com.ba_list.A[i].radio_freq = l1a_l1s_com.ba_list.new_list.chan_list.A[i]; } l1a_l1s_com.ba_list.ba_id = l1a_l1s_com.ba_list.new_list.ba_id; l1a_l1s_com.ba_list.nbr_carrier = l1a_l1s_com.ba_list.new_list.num_of_chans; l1a_l1s_com.dedic_set.pwrc = l1a_l1s_com.ba_list.new_list.pwrc; l1a_l1s_com.dedic_set.aset->dtx_allowed = l1a_l1s_com.ba_list.new_list.dtx_allowed; // Set the TCH mode (DAI mode and DTX) in MCU-DSP com. l1ddsp_load_tch_mode(l1a_l1s_com.dedic_set.aset->dai_mode, l1a_l1s_com.dedic_set.aset->dtx_allowed); // clear NEW BA present flag. l1a_l1s_com.ba_list.new_list_present = 0; #if FF_L1_IT_DSP_DTX // Initialize timer for fast DTX availabilty l1a_apihisr_com.dtx.fast_dtx_ready_timer = FAST_DTX_LATENCY; #endif } } #if FF_L1_IT_DSP_DTX } //if (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) #endif }//end D_BAMS_MEAS #if FF_L1_IT_DSP_DTX // Pipelining of control operations to be delayed in DTX interrupt when used. if (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED) { #endif // Clear np flag. //--------------- l1a_l1s_com.ba_list.np_ctrl = 0; #if L1_GPRS // Clear controlled flag pnp_ctrl. //------------------------------- l1pa_l1ps_com.cr_freq_list.pnp_ctrl = 0; #endif // C W R pipeline management. //--------------------------- l1a_l1s_com.full_list.ms_ctrl_dd = l1a_l1s_com.full_list.ms_ctrl_d; l1a_l1s_com.full_list.ms_ctrl_d = l1a_l1s_com.full_list.ms_ctrl; l1a_l1s_com.full_list.ms_ctrl = 0; l1a_l1s_com.ba_list.ms_ctrl_dd = l1a_l1s_com.ba_list.ms_ctrl_d; l1a_l1s_com.ba_list.ms_ctrl_d = l1a_l1s_com.ba_list.ms_ctrl; l1a_l1s_com.ba_list.ms_ctrl = FALSE; for(i=0; i<C_BA_PM_MEAS; i++) { l1a_l1s_com.ba_list.used_il_dd[i] = l1a_l1s_com.ba_list.used_il_d[i]; l1a_l1s_com.ba_list.used_il_d [i] = l1a_l1s_com.ba_list.used_il [i]; l1a_l1s_com.ba_list.used_lna_dd[i] = l1a_l1s_com.ba_list.used_lna_d[i]; l1a_l1s_com.ba_list.used_lna_d [i] = l1a_l1s_com.ba_list.used_lna [i]; } #if FF_L1_IT_DSP_DTX } #endif } //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #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_end_manager() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : */ /*-------------------------------------------------------*/ #if (L1_DYN_DSP_DWNLD == 1) void l1s_end_manager() { BOOL misc_task_ctrl_dyn_dwnld = FALSE; #if L1_GPRS #if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX) || (FF_L1_FAST_DECODING == 1) // In case of Fast USF, PDTCH Read operations are not affected by // USF validity. if ((l1ps_macs_com.rlc_downlink_call == TRUE) #if FF_L1_IT_DSP_USF && (l1ps_macs_com.usf_status != USF_IT_DSP) #endif #if FF_L1_IT_DSP_DTX && (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) #endif #if (FF_L1_FAST_DECODING == 1) && (l1a_apihisr_com.fast_decoding.status != C_FAST_DECODING_PROCESSING) #endif ) l1ps_macs_rlc_downlink_call(); #else if (l1ps_macs_com.rlc_downlink_call == TRUE) l1ps_macs_rlc_downlink_call(); #endif #endif // L1_GPRS #if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX) || (FF_L1_FAST_DECODING == 1) // TPU and DSP pages can be switched only if relevant scenario are complete // which may be postponed late in the TDMA when Fast USF is used. if (TRUE #if FF_L1_IT_DSP_USF && (l1ps_macs_com.usf_status != USF_AWAITED) #endif #if FF_L1_IT_DSP_DTX && (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED) #endif #if (FF_L1_FAST_DECODING == 1) && (l1a_apihisr_com.fast_decoding.deferred_control_req == FALSE) #endif /*#if (FF_L1_FAST_DECODING == 1)*/ ) { #endif // call the gauging algorithm only with paging or Packet paging in Idle mode // avoid call with NP during packet Tranfer Mode (NMOII) if (l1a_l1s_com.mode == I_MODE) l1s_gauging_task(); if(l1s_dsp_com.dsp_r_page_used == TRUE) /*************************************************************/ /* The "read" page for comm. with DSP has been used in the */ /* current TDMA. */ /* --> clear it!!! */ /* --> switch it!!! */ /*************************************************************/ { // clear page. l1s_reset_db_dsp_to_mcu(l1s_dsp_com.dsp_db_r_ptr); // switch page. l1s_dsp_com.dsp_r_page ^= 1; } if(l1s.dyn_dwnld_state > 0) misc_task_ctrl_dyn_dwnld = TRUE; #if (AUDIO_TASK == 1) if(l1s.dsp_ctrl_reg != NO_CTRL) /*************************************************************/ /* Some controle (RX/TX/MS) have been performed in the */ /* current frame. We must close the MCU/DSP comm. page now. */ /*************************************************************/ { // Omega power down for TCH/F and TCH/H at release. if(l1a_l1s_com.dedic_set.stop_tch == TRUE) { l1ddsp_stop_tch(); l1a_l1s_com.dedic_set.stop_tch = FALSE; } // A misc task is working with a GSM tasks or the DSP requests an IT com. // Or the gauging is active or dynamic download activity is active #if (CHIPSET==7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12) || (CHIPSET == 15) // with Calypso the DSP can be in Idle3 during the Gauging if ( (l1s.l1_audio_it_com) || (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) || (misc_task_ctrl_dyn_dwnld == TRUE)) #else if ( (l1s.l1_audio_it_com) || (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) || (l1s.pw_mgr.gauging_task == ACTIVE) || (misc_task_ctrl_dyn_dwnld == TRUE)) #endif { // When a MISC task is enabled L1S must be ran every frame // to be able to enable the frame interrupt for DSP l1a_l1s_com.time_to_next_l1s_task = 0; l1ddsp_end_scenario(GSM_MISC_CTL); } else { l1ddsp_end_scenario(GSM_CTL); } } else // No GSM task { // A misc task is working without a GSM tasks or the DSP request an IT com. // Or the gauging is active or dynamic download activity is active #if (CHIPSET==7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12) || (CHIPSET == 15) // with Calypso the DSP can be in Idle3 during the Gauging if ( (l1s.l1_audio_it_com) || (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) || (misc_task_ctrl_dyn_dwnld == TRUE)) #else if ( (l1s.l1_audio_it_com) || (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) || (l1s.pw_mgr.gauging_task == ACTIVE) || (misc_task_ctrl_dyn_dwnld == TRUE)) #endif { // When a MISC task is enabled L1S must be ran every frame // to be able to enable the frame interrupt for DSP l1a_l1s_com.time_to_next_l1s_task = 0; l1ddsp_end_scenario(MISC_CTL); } } #else if(l1s.dsp_ctrl_reg != NO_CTRL) /*************************************************************/ /* Some controle (RX/TX/MS) have been performed in the */ /* current frame. We must close the MCU/DSP comm. page now. */ /*************************************************************/ { // Omega power down for TCH/F and TCH/H at release. if(l1a_l1s_com.dedic_set.stop_tch == TRUE) { l1ddsp_stop_tch(); l1a_l1s_com.dedic_set.stop_tch = FALSE; } l1ddsp_end_scenario(GSM_CTL); } #endif // AUDIO_TASK == 1 if(l1s.tpu_ctrl_reg != NO_CTRL) /*************************************************************/ /* Some controle (RX/TX/MS/SYNC) have been performed in the */ /* current frame. We must close the MCU/TPU comm. page now. */ /*************************************************************/ { l1dtpu_end_scenario(); } // Propagate input level and lna state for Serving (Idle/dedic) tasks //------------------------------------------------------------------- l1a_l1s_com.Scell_used_IL_dd.input_level = l1a_l1s_com.Scell_used_IL_d.input_level; l1a_l1s_com.Scell_used_IL_d.input_level = l1a_l1s_com.Scell_used_IL.input_level; l1a_l1s_com.Scell_used_IL.input_level = l1_config.params.il_min; l1a_l1s_com.Scell_used_IL_dd.lna_off = l1a_l1s_com.Scell_used_IL_d.lna_off; l1a_l1s_com.Scell_used_IL_d.lna_off = l1a_l1s_com.Scell_used_IL.lna_off; l1a_l1s_com.Scell_used_IL.lna_off = FALSE; // Propagate radio_freq for dedic. mode use (hopping). //----------------------------------------------- l1a_l1s_com.dedic_set.radio_freq_dd = l1a_l1s_com.dedic_set.radio_freq_d; l1a_l1s_com.dedic_set.radio_freq_d = l1a_l1s_com.dedic_set.radio_freq; #if L1_GPRS // Propagate radio_freq for packet idle mode use (hopping). //----------------------------------------------- l1pa_l1ps_com.p_idle_param.radio_freq_dd = l1pa_l1ps_com.p_idle_param.radio_freq_d; l1pa_l1ps_com.p_idle_param.radio_freq_d = l1pa_l1ps_com.p_idle_param.radio_freq; #endif #if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX) || (FF_L1_FAST_DECODING == 1) } #endif } #else void l1s_end_manager() { #if L1_GPRS #if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX) // In case of Fast USF, PDTCH Read operations are not affected by // USF validity. if ((l1ps_macs_com.rlc_downlink_call == TRUE) #if FF_L1_IT_DSP_USF && (l1ps_macs_com.usf_status != USF_IT_DSP) #endif #if FF_L1_IT_DSP_DTX && (l1a_apihisr_com.dtx.dtx_status != DTX_IT_DSP) #endif ) l1ps_macs_rlc_downlink_call(); #else if (l1ps_macs_com.rlc_downlink_call == TRUE) l1ps_macs_rlc_downlink_call(); #endif #endif // L1_GPRS #if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX) // TPU and DSP pages can be switched only if relevant scenario are complete // which may be postponed late in the TDMA when Fast USF is used. if (TRUE #if FF_L1_IT_DSP_USF && (l1ps_macs_com.usf_status != USF_AWAITED) #endif #if FF_L1_IT_DSP_DTX && (l1a_apihisr_com.dtx.dtx_status != DTX_AWAITED) #endif ) { #endif // call the gauging algorithm only with paging or Packet paging in Idle mode // avoid call with NP during packet Tranfer Mode (NMOII) if (l1a_l1s_com.mode == I_MODE) l1s_gauging_task(); if(l1s_dsp_com.dsp_r_page_used == TRUE) /*************************************************************/ /* The "read" page for comm. with DSP has been used in the */ /* current TDMA. */ /* --> clear it!!! */ /* --> switch it!!! */ /*************************************************************/ { // clear page. l1s_reset_db_dsp_to_mcu(l1s_dsp_com.dsp_db_r_ptr); // switch page. l1s_dsp_com.dsp_r_page ^= 1; } #if (AUDIO_TASK == 1) if(l1s.dsp_ctrl_reg != NO_CTRL) /*************************************************************/ /* Some controle (RX/TX/MS) have been performed in the */ /* current frame. We must close the MCU/DSP comm. page now. */ /*************************************************************/ { // Omega power down for TCH/F and TCH/H at release. if(l1a_l1s_com.dedic_set.stop_tch == TRUE) { l1ddsp_stop_tch(); l1a_l1s_com.dedic_set.stop_tch = FALSE; } // A misc task is working with a GSM tasks or the DSP requests an IT com. // Or the gauging is active #if (CHIPSET==7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12) || (CHIPSET == 15) // with Calypso the DSP can be in Idle3 during the Gauging if ( (l1s.l1_audio_it_com) || (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ)) #else if ( (l1s.l1_audio_it_com) || (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) || (l1s.pw_mgr.gauging_task == ACTIVE) ) #endif { // When a MISC task is enabled L1S must be ran every frame // to be able to enable the frame interrupt for DSP l1a_l1s_com.time_to_next_l1s_task = 0; l1ddsp_end_scenario(GSM_MISC_CTL); } else { l1ddsp_end_scenario(GSM_CTL); } } else // No GSM task { // A misc task is working without a GSM tasks or the DSP request an IT com. // Or the gauging is active #if (CHIPSET==7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12) || (CHIPSET == 15) // with Calypso the DSP can be in Idle3 during the Gauging if ( (l1s.l1_audio_it_com) || (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ)) #else if ( (l1s.l1_audio_it_com) || (l1s_dsp_com.dsp_ndb_ptr->d_toneskb_status & B_IT_COM_REQ) || (l1s.pw_mgr.gauging_task == ACTIVE) ) #endif { // When a MISC task is enabled L1S must be ran every frame // to be able to enable the frame interrupt for DSP l1a_l1s_com.time_to_next_l1s_task = 0; l1ddsp_end_scenario(MISC_CTL); } } #else if(l1s.dsp_ctrl_reg != NO_CTRL) /*************************************************************/ /* Some controle (RX/TX/MS) have been performed in the */ /* current frame. We must close the MCU/DSP comm. page now. */ /*************************************************************/ { // Omega power down for TCH/F and TCH/H at release. if(l1a_l1s_com.dedic_set.stop_tch == TRUE) { l1ddsp_stop_tch(); l1a_l1s_com.dedic_set.stop_tch = FALSE; } l1ddsp_end_scenario(GSM_CTL); } #endif // AUDIO_TASK == 1 if(l1s.tpu_ctrl_reg != NO_CTRL) /*************************************************************/ /* Some controle (RX/TX/MS/SYNC) have been performed in the */ /* current frame. We must close the MCU/TPU comm. page now. */ /*************************************************************/ { l1dtpu_end_scenario(); } // Propagate input level and lna state for Serving (Idle/dedic) tasks //------------------------------------------------------------------- l1a_l1s_com.Scell_used_IL_dd.input_level = l1a_l1s_com.Scell_used_IL_d.input_level; l1a_l1s_com.Scell_used_IL_d.input_level = l1a_l1s_com.Scell_used_IL.input_level; l1a_l1s_com.Scell_used_IL.input_level = l1_config.params.il_min; l1a_l1s_com.Scell_used_IL_dd.lna_off = l1a_l1s_com.Scell_used_IL_d.lna_off; l1a_l1s_com.Scell_used_IL_d.lna_off = l1a_l1s_com.Scell_used_IL.lna_off; l1a_l1s_com.Scell_used_IL.lna_off = FALSE; // Propagate radio_freq for dedic. mode use (hopping). //----------------------------------------------- l1a_l1s_com.dedic_set.radio_freq_dd = l1a_l1s_com.dedic_set.radio_freq_d; l1a_l1s_com.dedic_set.radio_freq_d = l1a_l1s_com.dedic_set.radio_freq; #if L1_GPRS // Propagate radio_freq for packet idle mode use (hopping). //----------------------------------------------- l1pa_l1ps_com.p_idle_param.radio_freq_dd = l1pa_l1ps_com.p_idle_param.radio_freq_d; l1pa_l1ps_com.p_idle_param.radio_freq_d = l1pa_l1ps_com.p_idle_param.radio_freq; #endif #if (FF_L1_IT_DSP_USF) || (FF_L1_IT_DSP_DTX) } #endif } #endif // L1_DSP_DYN_DWNLD //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM //------------------------------------------------------------------------------------------------ /*-------------------------------------------------------*/ /* l1s_dedicated_mode_manager() */ /*-------------------------------------------------------*/ /* Parameters : */ /* Return : */ /* Functionality : */ /*-------------------------------------------------------*/ void l1s_dedicated_mode_manager() { T_CHANNEL_DESCRIPTION *chan1_desc_ptr; T_CHANNEL_DESCRIPTION *chan2_desc_ptr; T_MOBILE_ALLOCATION *alist_ptr; xSignalHeaderRec *msg; BOOL process_assign_now = TRUE; #if (FF_L1_TCH_VOCODER_CONTROL == 1) // Start vocoder #if (L1_VOCODER_IF_CHANGE == 1) if (l1a_l1s_com.dedic_set.start_vocoder == TCH_VOCODER_ENABLE_COMMAND) { l1a_l1s_com.dedic_set.sync_tch = TRUE; l1a_l1s_com.dedic_set.vocoder_on = TRUE; l1a_l1s_com.dedic_set.start_vocoder = TCH_VOCODER_RESET_COMMAND; // Triton Audio ON/OFF Changes #if (L1_AUDIO_MCU_ONOFF == 1) l1s.audio_on_off_ctl.l1_audio_switch_on_ul_request++; l1s.audio_on_off_ctl.l1_audio_switch_on_dl_request++; #endif // L1_AUDIO_MCU_ONOFF msg = os_alloc_sig(0); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = L1_VOCODER_CFG_ENABLE_CON; os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } else if(l1a_l1s_com.dedic_set.start_vocoder == TCH_VOCODER_DISABLE_COMMAND) { l1a_l1s_com.dedic_set.vocoder_on = FALSE; l1a_l1s_com.dedic_set.start_vocoder = TCH_VOCODER_RESET_COMMAND; // Triton Audio ON/OFF Changes #if (L1_AUDIO_MCU_ONOFF == 1) l1s.audio_on_off_ctl.l1_audio_switch_on_ul_request--; l1s.audio_on_off_ctl.l1_audio_switch_on_dl_request--; #endif // L1_AUDIO_MCU_ONOFF msg = os_alloc_sig(0); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = L1_VOCODER_CFG_DISABLE_CON; os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } #else #if (W_A_DSP_PR20037 == 1) if (l1a_l1s_com.dedic_set.start_vocoder == TCH_VOCODER_ENABLE_REQ) { l1a_l1s_com.dedic_set.sync_tch = TRUE; l1a_l1s_com.dedic_set.vocoder_on = TRUE; l1a_l1s_com.dedic_set.start_vocoder = TCH_VOCODER_ENABLED; } else if(l1a_l1s_com.dedic_set.start_vocoder == TCH_VOCODER_DISABLE_REQ) { l1a_l1s_com.dedic_set.vocoder_on = FALSE; l1a_l1s_com.dedic_set.start_vocoder = TCH_VOCODER_DISABLED; } #else // W_A_DSP_PR20037 == 0 if (l1a_l1s_com.dedic_set.start_vocoder == TRUE) { l1a_l1s_com.dedic_set.start_vocoder = FALSE; l1a_l1s_com.dedic_set.sync_tch = TRUE; l1a_l1s_com.dedic_set.vocoder_on = TRUE; } #endif // W_A_DSP_PR20037 #endif // L1_VOCODER_IF_CHANGE #endif // FF_L1_TCH_VOCODER_CONTROL == 1 //========================================= // Process the new dedicated parameter set. //========================================= #if ((REL99 == 1) && (FF_BHO == 1)) if(l1a_l1s_com.dedic_set.long_rem_handover_type != BLIND_HANDOVER) { #endif if( (l1a_l1s_com.dedic_set.SignalCode == MPHC_CHANNEL_ASSIGN_REQ) || (l1a_l1s_com.dedic_set.SignalCode == MPHC_SYNC_HO_REQ) || (l1a_l1s_com.dedic_set.SignalCode == MPHC_ASYNC_HO_REQ) ) { //Some pre-processing of the ASSIGNMENT/HANDOVER COMMANDS is required to reliably pass //GSM 11.10 17.1 where ASSIGNMENT from TCH/F -> TCH/F without //a start time must transmit on the new channel within 20ms //Also, should reduce muting/click on channel change if( (l1a_l1s_com.dedic_set.fset->neig_sti_fn == -1 ) && (l1a_l1s_com.dedic_set.fset->chan1.desc.channel_type == TCH_F) && (l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type == TCH_F) ) { //ASSIGNMENT from TCH/F -> TCH/F immediately. Must wait until //the current FACCH boundary is complete, before processing the assignment //as the 20ms timer is started at the end of the last valid speech/FACCH block. UWORD32 facch_position = (l1s.next_time.fn_in_report % 13) % 4; if(facch_position == 1) process_assign_now = TRUE; else process_assign_now = FALSE; } else { process_assign_now = TRUE; } } #if ((REL99 == 1) && (FF_BHO == 1)) } #endif // Now see if channel change commands are pending..... if( ( l1a_l1s_com.dedic_set.SignalCode == MPHC_IMMED_ASSIGN_REQ ) || ( (l1a_l1s_com.dedic_set.SignalCode == MPHC_CHANNEL_ASSIGN_REQ) && (process_assign_now == TRUE) ) || ( (l1a_l1s_com.dedic_set.SignalCode == MPHC_SYNC_HO_REQ) && (process_assign_now == TRUE) ) || ( (l1a_l1s_com.dedic_set.SignalCode == MPHC_ASYNC_HO_REQ) && (process_assign_now == TRUE) ) || ( l1a_l1s_com.dedic_set.SignalCode == MPHC_HANDOVER_FAIL_REQ) || ( l1a_l1s_com.dedic_set.SignalCode == MPHC_CHANGE_FREQUENCY) ) // A new channel is given in fset... { #if 0 /* FreeCalypso TCS211 reconstruction */ // Reset DTX AMR status #if (AMR == 1) l1s.dtx_amr_dl_on=FALSE; #endif #endif // When a Dedicated mode request is pending, L1S must be ran every frame // to be able to cope with STI. l1a_l1s_com.time_to_next_l1s_task = 0; // Set the default channel/description. //------------------------------------- chan1_desc_ptr = &l1a_l1s_com.dedic_set.fset->chan1.desc; chan2_desc_ptr = &l1a_l1s_com.dedic_set.fset->chan2.desc; alist_ptr = &l1a_l1s_com.dedic_set.fset->ma.freq_list; // Starting time management. //========================== if(l1a_l1s_com.dedic_set.fset->neig_sti_fn != -1) // Starting time present. { WORD32 time_diff; WORD32 frame_shift=0; WORD32 tn_diff; tn_diff = l1a_l1s_com.tn_difference; if(tn_diff < 0) { frame_shift -= 1; tn_diff += 8; } if((l1a_l1s_com.dedic_set.fset->cell_desc.time_alignmt + (tn_diff * BP_DURATION)) >= SWITCH_TIME) frame_shift += 1; time_diff = ( (l1a_l1s_com.dedic_set.fset->serv_sti_fn - 1) + frame_shift - (l1s.next_time.fn % 42432) + 2*42432) % 42432; if(((time_diff >= (32024)) && (time_diff <= (42431))) || (time_diff == 0)) // Starting time has been passed or the current frame corresponds to STARTING TIME... // -> Reset STI (neig. domain and serv. domain) (set to -1). // -> Channel description must be the one for After STI (default case). // -> Frequency redefinition must be confirmed if any. // Rem: numbers come from GSM04.08, $10.5.2.38. // Rem: starting time detected 1 frame in adavance, this frame is used by // SYNCHRO task. { l1a_l1s_com.dedic_set.fset->serv_sti_fn = -1; l1a_l1s_com.dedic_set.fset->neig_sti_fn = -1; #if (TRACE_TYPE!=0) // Trace "starting time" on log file and screen. trace_fct(CST_STI_PASSED, l1a_l1s_com.Scell_info.radio_freq); #endif if(l1a_l1s_com.dedic_set.fset->freq_redef_flag == TRUE) // FREQUENCY REDEFINITION must be confirmed. { xSignalHeaderRec *conf_msg; // Clear FREQUENY REDEFINITION flag. l1a_l1s_com.dedic_set.fset->freq_redef_flag = FALSE; // Alloc confirmation message... conf_msg = os_alloc_sig(sizeof(int)); DEBUGMSG(status,NU_ALLOC_ERR) conf_msg->SignalCode = L1C_REDEF_DONE; // Send confirmation message... os_send_sig(conf_msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } } else // -> Channel description must be the one for Before STI. { chan1_desc_ptr = &l1a_l1s_com.dedic_set.fset->chan1.desc_bef_sti; chan2_desc_ptr = &l1a_l1s_com.dedic_set.fset->chan2.desc_bef_sti; alist_ptr = &l1a_l1s_com.dedic_set.fset->ma.freq_list_bef_sti; } } // Switch active channel to the new given one. //-------------------------------------------- if(chan1_desc_ptr->channel_type != INVALID_CHANNEL) // The ongoing configuration for the new channel is valid. { UWORD8 current_channel_type = INVALID_CHANNEL; UWORD8 current_channel_mode = SIG_ONLY_MODE; UWORD8 new_channel_type = chan1_desc_ptr->channel_type; if(l1a_l1s_com.dedic_set.aset != NULL) { current_channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type; current_channel_mode = l1a_l1s_com.dedic_set.aset->chan1.mode; } #if W_A_DSP1 if(l1a_l1s_com.dedic_set.SignalCode != MPHC_CHANGE_FREQUENCY) { old_sacch_DSP_bug = TRUE; } #endif l1a_l1s_com.dedic_set.fset->chan1.desc_ptr = chan1_desc_ptr; l1a_l1s_com.dedic_set.fset->chan2.desc_ptr = chan2_desc_ptr; l1a_l1s_com.dedic_set.fset->ma.alist_ptr = alist_ptr; // Keep Timing Advance from current active channel. if(l1a_l1s_com.dedic_set.SignalCode == MPHC_CHANNEL_ASSIGN_REQ) { l1a_l1s_com.dedic_set.fset->new_timing_advance = l1a_l1s_com.dedic_set.aset->new_timing_advance; l1a_l1s_com.dedic_set.fset->timing_advance = l1a_l1s_com.dedic_set.aset->timing_advance; } // If current active channel is a TCH channel then we must inform the // DSP to stop any vocoder activity when leaving this channel. if(((current_channel_type == TCH_F) || (current_channel_type == TCH_H)) && (new_channel_type != TCH_F) && (new_channel_type != TCH_H)) { l1a_l1s_com.dedic_set.stop_tch = TRUE; /* * FreeCalypso TCS211 reconstruction: the following code * appears to be a LoCosto-ism, so let's take it out. */ #if 0 // If audio enabling was forced by L1S because of a HO failure, do not force it anymore. // Restore it in the state required by the MMI if the feature is compiled. if (l1a_l1s_com.audio_forced_by_l1s == TRUE) { #if (L1_EXTERNAL_AUDIO_VOICE_ONOFF == 1) if (l1a_l1s_com.audio_onoff_task.parameters.onoff_value == FALSE) { l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP; } #else // L1_EXTERNAL_AUDIO_VOICE_ONOFF l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP; #endif // L1_EXTERNAL_AUDIO_VOICE_ONOFF l1a_l1s_com.audio_forced_by_l1s = FALSE; } #endif } // The new channel becomes the ACTIVE one. l1a_l1s_com.dedic_set.aset = l1a_l1s_com.dedic_set.fset; // Active channel is CHAN1 by default. l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan1); // Store new ciphering setting in MCU-DSP com. l1ddsp_load_ciph_param(l1a_l1s_com.dedic_set.aset->a5mode, &(l1a_l1s_com.dedic_set.aset->ciph_key)); // Set the TCH mode (DAI mode and DTX) in MCU-DSP com. l1ddsp_load_tch_mode(l1a_l1s_com.dedic_set.aset->dai_mode, l1a_l1s_com.dedic_set.aset->dtx_allowed); // Dedicated set TXPWR command must be applied at once. l1s.applied_txpwr = l1a_l1s_com.dedic_set.aset->new_target_txpwr; l1s.reported_txpwr = l1s.applied_txpwr; // Switch from current mode to DEDICATED MODE. l1a_l1s_com.mode = DEDIC_MODE; // Enable globally all dedicated tasks. l1a_l1s_com.l1s_en_task[DEDIC] = TASK_ENABLED; // Set SYNCHRO task enable flag -> synchro to the new serving cell. // Set "sync_tch" flag if TCH/F or TCH/H channel whatever the channel mode. // Rem: no synchro required when just changing the freq list. if(l1a_l1s_com.dedic_set.SignalCode != MPHC_CHANGE_FREQUENCY) { UWORD8 channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type; // TF 12/8/98 - the following line was moved from above to solve bad meas reports // after frequency redefinition bug. // Given beacon becomes the serving cell, download cell description // in the serving cell structure. l1a_l1s_com.Scell_info = l1a_l1s_com.dedic_set.aset->cell_desc; #if (AMR == 1) // Reset DTX AMR status l1s.dtx_amr_dl_on=FALSE; #endif if((channel_type == TCH_F) || (channel_type == TCH_H)) { #if (FF_L1_TCH_VOCODER_CONTROL == 1) // With this feature, SACCH reset is controlled by L1, not sync_tch l1a_l1s_com.dedic_set.reset_sacch = TRUE; #endif l1a_l1s_com.dedic_set.sync_tch = TRUE; l1a_l1s_com.dedic_set.reset_facch = TRUE; // Reset DTX mode flags l1s.dtx_ul_on = FALSE; l1s.facch_bursts = -1; } // SYNCHRO task and its associated parameters (tn_difference, dl_tn and // dsp_scheduler_mode) are not Enabled/Updated if we are in the specific case: // L1A is touching SYNCHRO parameters and leave L1A to go in HISR (L1S) // in middle of the update (cf. BUG1339) if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET) { #if L1_GPRS // Select GSM DSP Scheduler. l1a_l1s_com.dsp_scheduler_mode = GSM_SCHEDULER; #endif // Enable SYNCHRO task to achive the new configuration. Since SYNCHRO // has the highest priority and the installation of this task in // the MFTAB is made after a CLEAR of the MFTAB, we insure that // any uncompleted task will be ABORTED. l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED; } #if IDS // Set b_itc (Information transfer capability) bits in d_ra_conf l1s_dsp_com.dsp_ndb_ptr->d_ra_conf = (UWORD16) l1a_l1s_com.dedic_set.aset->ids_mode; #endif #if (AMR == 1) // If the new channel mode to apply is an adaptative mode // then the AMR parameter must be transmitted to the DSP if ( (l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AHS_MODE) || (l1a_l1s_com.dedic_set.aset->achan_ptr->mode == TCH_AFS_MODE) ) { // Transmit the AMR ver 1.0 settings to the DSP l1ddsp_load_amr_param(l1a_l1s_com.dedic_set.aset->amr_configuration,l1a_l1s_com.dedic_set.aset->cmip); #if (L1_AMR_NSYNC == 1) // AMR NSYNC bit: set to 0 by load_amr_param, set to 1 if HO from AMR cell to AMR cell, reset by DSP if ( (current_channel_mode == TCH_AFS_MODE) || (current_channel_mode == TCH_AHS_MODE) ) { #if (FF_L1_TCH_VOCODER_CONTROL == 1) if(l1a_l1s_com.dedic_set.vocoder_on == TRUE) { l1s_dsp_com.dsp_ndb_ptr->a_amr_config[NSYNC_INDEX] |= (1 << NSYNC_SHIFT); } #else l1s_dsp_com.dsp_ndb_ptr->a_amr_config[NSYNC_INDEX] |= (1 << NSYNC_SHIFT); #endif } #endif // Set the flag to tell to DSP that a new AMR config is ready in the API memory l1a_l1s_com.dedic_set.sync_amr = TRUE; } #endif #if FF_L1_IT_DSP_DTX // Initialize timer for fast DTX availabilty l1a_apihisr_com.dtx.fast_dtx_ready_timer = FAST_DTX_LATENCY; #endif } // Set HO_ACCESS counter according to HO type. if(l1a_l1s_com.dedic_set.SignalCode == MPHC_ASYNC_HO_REQ) { UWORD8 channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type; l1a_l1s_com.dedic_set.aset->ho_acc_to_send = -1; // Send HO_ACCESS until... if((channel_type == TCH_F) || (channel_type == TCH_H)) l1a_l1s_com.dedic_set.aset->t3124 = 70; // Send HO_ACCESS for 320ms. else l1a_l1s_com.dedic_set.aset->t3124 = 147; // Send HO_ACCESS for 675ms. } else if(l1a_l1s_com.dedic_set.SignalCode == MPHC_SYNC_HO_REQ) l1a_l1s_com.dedic_set.aset->ho_acc_to_send = 4; // Send 4 HO_ACCESS. else l1a_l1s_com.dedic_set.aset->ho_acc_to_send = 0; // No HO_ACCESS to send. if(l1a_l1s_com.dedic_set.SignalCode != MPHC_CHANGE_FREQUENCY) // Rem: no confirmation msg required when just changing the freq list. { // alloc confirmation message... msg = os_alloc_sig(sizeof(int)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = L1C_DEDIC_DONE; // send confirmation message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) #if (TRACE_TYPE==5) trace_dedic(); #endif #if (FF_REPEATED_SACCH == 1) l1s.repeated_sacch.buffer_empty = TRUE; //sacch buffer l1s.repeated_sacch.sro = 0; //BTS repetition order l1s.repeated_sacch.srr = 0; //MS repetition request #endif /* (FF_REPEATED_SACCH == 1) */ #if ((FF_REPEATED_SACCH == 1) && (TRACE_TYPE == 1 || TRACE_TYPE == 4)) trace_info.repeat_sacch.dl_count = 0; trace_info.repeat_sacch.dl_combined_good_count = 0; trace_info.repeat_sacch.dl_error_count = 0; trace_info.repeat_sacch.srr= 0; trace_info.repeat_sacch.sro= 0; trace_info.repeat_sacch.dl_good_norep = 0; trace_info.repeat_sacch.dl_buffer_empty = TRUE; #endif /* ((FF_REPEATED_SACCH == 1) && (TRACE_TYPE == 1 || TRACE_TYPE == 4))*/ #if (TRACE_TYPE==1) || (TRACE_TYPE==4) 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 ) trace_info.facch_dl_combined_good_count = 0; /* reported and chase combined also(2nd attempt) <= facch_dl_good_block_reported */ trace_info.facch_dl_repetition_block_count = 0; /*represents duplicate not passed to PS */ trace_info.facch_dl_count_all = 0; /* ALL FACCHS received good or bad*/ trace_info.facch_dl_good_block_reported = 0; /* facch_dl_count */ #endif /* (FF_REPEATED_DL_FACCH == 1 ) */ trace_info.sacch_d_nerr = 0; #endif #if ( FF_REPEATED_DL_FACCH == 1) l1s.repeated_facch.pipeline[0].buffer_empty=l1s.repeated_facch.pipeline[1].buffer_empty=TRUE; if ( l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type == TCH_F) /* For TCH/F */ { l1s.repeated_facch.counter_candidate=0; l1s.repeated_facch.counter=1; } if ( l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type == TCH_H) /* For TCH/H */ { // l1s.repeated_facch.counter_candidate=l1s.repeated_facch.counter=0; /* l1s.repeated_facch.counter_candidate=0; l1s.repeated_facch.counter=1;*/ l1s.repeated_facch.counter_candidate=l1s.repeated_facch.counter=0; } #endif /* (FF_REPEATED_DL_FACCH == 1 ) */ } // Clear dedicated channel trigger message. l1a_l1s_com.dedic_set.SignalCode = NULL; // Clear the dedicated handover fail mode. l1a_l1s_com.dedic_set.handover_fail_mode = FALSE; } } else if(l1a_l1s_com.dedic_set.SignalCode == MPHC_CHANNEL_MODE_MODIFY_REQ) // We must change the current channel mode for the given subchannel. { UWORD8 channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type; UWORD8 channel_mode = l1a_l1s_com.dedic_set.aset->chan1.mode; if((channel_type == TCH_F) || (channel_type == TCH_H)) { #if (FF_L1_TCH_VOCODER_CONTROL == 1) // With this feature, SACCH reset is controlled by L1, not sync_tch l1a_l1s_com.dedic_set.reset_sacch = TRUE; #endif l1a_l1s_com.dedic_set.sync_tch = TRUE; } if(l1a_l1s_com.dedic_set.mode_modif.subchannel == l1a_l1s_com.dedic_set.aset->chan1.desc.subchannel) l1a_l1s_com.dedic_set.aset->chan1.mode = l1a_l1s_com.dedic_set.mode_modif.channel_mode; else l1a_l1s_com.dedic_set.aset->chan2.mode = l1a_l1s_com.dedic_set.mode_modif.channel_mode; #if (AMR == 1) // If the new channel mode to apply is an adaptative mode // then the AMR parameter must be transmitted to the DSP if ( (l1a_l1s_com.dedic_set.mode_modif.channel_mode == TCH_AHS_MODE) || (l1a_l1s_com.dedic_set.mode_modif.channel_mode == TCH_AFS_MODE) ) { // Transmit the AMR ver 1.0 settings to the DSP l1ddsp_load_amr_param(l1a_l1s_com.dedic_set.mode_modif.amr_configuration,C_AMR_CMIP_DEFAULT); #if (L1_AMR_NSYNC == 1) // AMR NSYNC bit: set to 0 by load_amr_param, set to 1 if HO from AMR cell to AMR cell, reset by DSP if ( (channel_mode == TCH_AFS_MODE) || (channel_mode == TCH_AHS_MODE) ) { #if (FF_L1_TCH_VOCODER_CONTROL == 1) if(l1a_l1s_com.dedic_set.vocoder_on == TRUE) { l1s_dsp_com.dsp_ndb_ptr->a_amr_config[NSYNC_INDEX] |= (1 << NSYNC_SHIFT); } #else l1s_dsp_com.dsp_ndb_ptr->a_amr_config[NSYNC_INDEX] |= (1 << NSYNC_SHIFT); #endif } #endif // Set the flag to tell to DSP that a new AMR config is ready in the API memory l1a_l1s_com.dedic_set.sync_amr = TRUE; } #endif // Reset input msg. l1a_l1s_com.dedic_set.SignalCode = NULL; #if FF_L1_IT_DSP_DTX // Initialize timer for fast DTX availabilty l1a_apihisr_com.dtx.fast_dtx_ready_timer = FAST_DTX_LATENCY; #endif } else if(l1a_l1s_com.dedic_set.SignalCode == MPHC_SET_CIPHERING_REQ) // Ciphering mode must change. { // Store new ciphering setting in MCU-DSP com. l1ddsp_load_ciph_param(l1a_l1s_com.dedic_set.aset->a5mode, &(l1a_l1s_com.dedic_set.aset->ciph_key)); // Reset input msg. l1a_l1s_com.dedic_set.SignalCode = NULL; } else if(l1a_l1s_com.dedic_set.SignalCode == MPHC_STOP_DEDICATED_REQ) // All channel must be aborted... { // Perform the functions below if there is active dedicated set. // This check is to take care of race condition which can happen // if MPHC_STOP_DEDICATED_REQ is receivedm before MPHC_HANDOVER_FAIL_REQ #if 0 /* FreeCalypso TCS211 reconstruction */ if (l1a_l1s_com.dedic_set.aset!=NULL) { #endif // Stop TCH/F and TCH/H (stop Omega) (used in SYNCHRO task). UWORD8 channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type; if((channel_type == TCH_F) || (channel_type == TCH_H)) { l1a_l1s_com.dedic_set.stop_tch = TRUE; /* FreeCalypso change: same situation as earlier in this function */ #if 0 // If audio enabling was forced by L1S because of a HO failure, do not force it anymore. // Restore it in the state required by the MMI if the feature is compiled. if (l1a_l1s_com.audio_forced_by_l1s == TRUE) { #if (L1_EXTERNAL_AUDIO_VOICE_ONOFF == 1) if (l1a_l1s_com.audio_onoff_task.parameters.onoff_value == FALSE) { l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP; } #else // L1_EXTERNAL_AUDIO_VOICE_ONOFF l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP; #endif // L1_EXTERNAL_AUDIO_VOICE_ONOFF l1a_l1s_com.audio_forced_by_l1s = FALSE; } #endif #if (AMR == 1) // Reset DTX AMR status l1s.dtx_amr_dl_on=FALSE; #endif } // Clear d_ra_conf => default value l1s_dsp_com.dsp_ndb_ptr->d_ra_conf = 0; // Clear ciphering setting in MCU-DSP com. l1ddsp_load_ciph_param(0, &(l1a_l1s_com.dedic_set.aset->ciph_key)); // Reset the global dedicated enable flag. l1a_l1s_com.l1s_en_task[DEDIC] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[DDL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[DUL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[ADL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[AUL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHTH] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHD] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHTF] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHA] = TASK_DISABLED; #if 0 /* FreeCalypso TCS211 reconstruction */ } else { /* FreeCalypso change: same AUDIO_TASK situation as earlier */ #if 0 if (l1a_l1s_com.audio_forced_by_l1s == TRUE) { #if (L1_EXTERNAL_AUDIO_VOICE_ONOFF == 1) if (l1a_l1s_com.audio_onoff_task.parameters.onoff_value == FALSE) { l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP; } #else // L1_EXTERNAL_AUDIO_VOICE_ONOFF l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_OFF_STOP; #endif // L1_EXTERNAL_AUDIO_VOICE_ONOFF l1a_l1s_com.audio_forced_by_l1s = FALSE; } #endif #if (AMR == 1) // Reset DTX AMR status l1s.dtx_amr_dl_on=FALSE; #endif // Clear d_ra_conf => default value l1s_dsp_com.dsp_ndb_ptr->d_ra_conf = 0; } #endif /* FreeCalypso TCS211 reconstruction */ // Reset input msg. l1a_l1s_com.dedic_set.SignalCode = NULL; #if ((REL99 == 1) && (FF_BHO == 1)) // this is required in BHO as you need to retain the previous channel info. //This is checked in HO_REQ to L1S.....In normal handover this does not happen if(l1a_l1s_com.dedic_set.handover_type == NORMAL_HANDOVER) { // Reset active dedicated set. l1a_l1s_com.dedic_set.aset = NULL; } #else // Reset active dedicated set. l1a_l1s_com.dedic_set.aset = NULL; #endif // SYNCHRO task and its associated parameters (tn_difference, dl_tn and // dsp_scheduler_mode) are not Enabled/Updated if we are in the specific case: // L1A is touching SYNCHRO parameters and leave L1A to go in HISR (L1S) // in middle of the update (cf. BUG1339) if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET) { // The code shall always goes here as the upper layers are not allowed to send new // requests that can change the layer1 timing reference before the MPHC_STOP_DEDICATED_REQ // has been confirmed by the MPHC_STOP_DEDICATED_CON. // Since SYNCHRO has the highest priority and the installation of // this task in the MFTAB is made after a CLEAR of the MFTAB, we // insure that any uncompleted task will be ABORTED. l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED; // The dedicated mode will be aborted within the current TDMA frame, // L1S confirm to L1A that the dedicated mode is stopped. // alloc confirmation message... msg = os_alloc_sig(sizeof(int)); DEBUGMSG(status,NU_ALLOC_ERR) msg->SignalCode = L1C_STOP_DEDICATED_DONE; // send confirmation message... os_send_sig(msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } #if ((REL99 == 1) && (FF_BHO == 1)) // Check whether above stop dedicated mode procedure is done due // to blind handover request. if(l1a_l1s_com.dedic_set.handover_type == BLIND_HANDOVER) { // MPHC_STOP_DEDICATED was due to blind handover. // Set semaphores for FBSB task // Store the info from request message. l1a_l1s_com.nsync_fbsb.radio_freq = l1a_l1s_com.dedic_set.bcch_carrier_of_nbr_cell; l1a_l1s_com.nsync_fbsb.fn_offset = 0; l1a_l1s_com.nsync_fbsb.time_alignmt = 0; l1a_l1s_com.nsync_fbsb.fb_found_attempt = 0; // Enable FBSB task l1a_l1s_com.l1s_en_task[FBSB] = TASK_ENABLED; } #endif // #if ((REL99 == 1) && (FF_BHO == 1)) } else if((l1a_l1s_com.dedic_set.SignalCode == OML1_START_DAI_TEST_REQ) || (l1a_l1s_com.dedic_set.SignalCode == OML1_STOP_DAI_TEST_REQ)) // New DAI mode given... // We must store the mode in NDB and resynchronize the speech. { // Set the TCH mode (DAI mode and DTX) in MCU-DSP com. l1ddsp_load_tch_mode(l1a_l1s_com.dedic_set.aset->dai_mode, l1a_l1s_com.dedic_set.aset->dtx_allowed); // Reset input msg. l1a_l1s_com.dedic_set.SignalCode = NULL; } //============================================= // Process the ongoing dedicated parameter set. //============================================= if((!(l1a_l1s_com.l1s_en_task[SYNCHRO] == TASK_ENABLED)) && (l1a_l1s_com.dedic_set.aset != NULL)) // No synchro performed this frame. // -> process current active dedicated parameter set. { // TCH/SDCCH statistics or Frame Error rate : // must wait for Dedicated mode setting .... #if (TRACE_TYPE==3) if (l1_stats.wait_time > 0 ) l1_stats.wait_time--; #endif //------------------- // TXPWR controle... //------------------- // Save last applied TXPWR to be reported. // Get TXPWR to be applied in the next 13 frames. if((l1s.next_time.fn_in_report % 13) == 0) { l1s.reported_txpwr = l1s.applied_txpwr; l1s.applied_txpwr = l1ctl_txpwr(l1a_l1s_com.dedic_set.aset->new_target_txpwr, l1s.applied_txpwr); } //---------------------------- // Timing Advance controle... //---------------------------- // Timing advance is updated for the 1st frame of the reporting period // with new value coming from SACCH(L1 header). if(l1s.next_time.fn_in_report == 0) { l1a_l1s_com.dedic_set.aset->timing_advance = l1a_l1s_com.dedic_set.aset->new_timing_advance; } //------------------------------------- // Set the default channel/description. //------------------------------------- chan1_desc_ptr = &l1a_l1s_com.dedic_set.aset->chan1.desc; chan2_desc_ptr = &l1a_l1s_com.dedic_set.aset->chan2.desc; alist_ptr = &l1a_l1s_com.dedic_set.aset->ma.freq_list; // Active channel is CHAN1 by default. //------------------------------------ l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan1); //----------------------------- // Starting time management... //----------------------------- if(l1a_l1s_com.dedic_set.aset->serv_sti_fn != -1) // Starting time present. //----------------------- { WORD32 time_diff; time_diff = (l1a_l1s_com.dedic_set.aset->neig_sti_fn - (l1s.next_time.fn % 42432) + 2*42432) % 42432; if(((time_diff >= (32024)) && (time_diff <= (42431))) || (time_diff == 0)) // Starting time has been passed or the current frame corresponds to STARTING TIME... //----------------------------------------------------------------------------------- // -> Reset STI (neig. domain and serv. domain) (set to -1). // -> Channel description must be the one for After STI (default case). // -> Frequency redefinition must be confirmed if any. // Rem: numbers come from GSM04.08, $10.5.2.38. { l1a_l1s_com.dedic_set.aset->serv_sti_fn = -1; l1a_l1s_com.dedic_set.aset->neig_sti_fn = -1; #if (TRACE_TYPE!=0) // Trace "starting time" on log file and screen. trace_fct(CST_STI_PASSED, l1a_l1s_com.Scell_info.radio_freq); #endif if(l1a_l1s_com.dedic_set.aset->freq_redef_flag == TRUE) // FREQUENCY REDEFINITION must be confirmed. { xSignalHeaderRec *conf_msg; // Clear FREQUENY REDEFINITION flag. l1a_l1s_com.dedic_set.aset->freq_redef_flag = FALSE; // Alloc confirmation message... conf_msg = os_alloc_sig(sizeof(int)); DEBUGMSG(status,NU_ALLOC_ERR) conf_msg->SignalCode = L1C_REDEF_DONE; // Send confirmation message... os_send_sig(conf_msg, L1C1_QUEUE); DEBUGMSG(status,NU_SEND_QUEUE_ERR) } #if FF_L1_IT_DSP_DTX // Initialize timer for fast DTX availabilty l1a_apihisr_com.dtx.fast_dtx_ready_timer = FAST_DTX_LATENCY; #endif } else // -> Channel description must be the one for Before STI. { chan1_desc_ptr = &l1a_l1s_com.dedic_set.aset->chan1.desc_bef_sti; chan2_desc_ptr = &l1a_l1s_com.dedic_set.aset->chan2.desc_bef_sti; alist_ptr = &l1a_l1s_com.dedic_set.aset->ma.freq_list_bef_sti; } } //--------------------------- // Set the active parameters. //--------------------------- l1a_l1s_com.dedic_set.aset->chan1.desc_ptr = chan1_desc_ptr; l1a_l1s_com.dedic_set.aset->chan2.desc_ptr = chan2_desc_ptr; l1a_l1s_com.dedic_set.aset->ma.alist_ptr = alist_ptr; //------------------------------------------------------- // Enable Dedicated mode tasks according to channel type. //------------------------------------------------------- switch(l1a_l1s_com.dedic_set.aset->achan_ptr->desc_ptr->channel_type) { case SDCCH_8: case SDCCH_4: { l1a_l1s_com.l1s_en_task[DDL] = TASK_ENABLED; l1a_l1s_com.l1s_en_task[DUL] = TASK_ENABLED; l1a_l1s_com.l1s_en_task[ADL] = TASK_ENABLED; l1a_l1s_com.l1s_en_task[AUL] = TASK_ENABLED; l1a_l1s_com.l1s_en_task[TCHTH] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHD] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHTF] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHA] = TASK_DISABLED; } break; case TCH_F: { l1a_l1s_com.l1s_en_task[DDL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[DUL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[ADL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[AUL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHTH] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHD] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHTF] = TASK_ENABLED; l1a_l1s_com.l1s_en_task[TCHA] = TASK_ENABLED; } break; case TCH_H: { l1a_l1s_com.l1s_en_task[DDL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[DUL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[ADL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[AUL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHTH] = TASK_ENABLED; l1a_l1s_com.l1s_en_task[TCHD] = TASK_ENABLED; l1a_l1s_com.l1s_en_task[TCHTF] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHA] = TASK_ENABLED; } break; } //---------------------------------------------- // Set the active subchannel (case of 2 TCH/H-). //---------------------------------------------- if(l1a_l1s_com.dedic_set.aset->chan2.desc.channel_type == TCH_H) // 2 TCHH channels are maintained... Swap from one to the other each frame. { UWORD8 fn_mod13; // Get FN % 13. fn_mod13 = l1s.actual_time.t2; if(fn_mod13 >= 13) fn_mod13 -= 13; if((fn_mod13) == (2*(fn_mod13/2))) // Current "FN %13" is EVEN, we must set the active channel pointer // to the channel maintaining the subchannel 1. { if(l1a_l1s_com.dedic_set.aset->chan1.desc.subchannel == 1) l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan1); else l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan2); } else // Current "FN %13" is ODD, we must set the active channel pointer // to the channel maintaining the subchannel 0. { if(l1a_l1s_com.dedic_set.aset->chan1.desc.subchannel == 0) l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan1); else l1a_l1s_com.dedic_set.aset->achan_ptr = &(l1a_l1s_com.dedic_set.aset->chan2); } } //----------------------------------------------------------------- // T3124 timer management (HO, physical information management)... //----------------------------------------------------------------- if(l1a_l1s_com.dedic_set.aset->t3124 != 0) // Waiting for "PHYSICAL INFORMATION" message from BTS. { // Decrement T3124 timer. l1a_l1s_com.dedic_set.aset->t3124--; if(l1a_l1s_com.dedic_set.aset->t3124 == 0) // TIMEOUT: send L1C_HANDOVER_FINISHED message with a TIMEOUT indication. { UWORD8 channel_type = l1a_l1s_com.dedic_set.aset->chan1.desc.channel_type; // Stop TCH/F and TCH/H (stop Omega) (used in SYNCHRO task) if((channel_type == TCH_F) || (channel_type == TCH_H)) { l1a_l1s_com.dedic_set.stop_tch = TRUE; /* * FreeCalypso change: same AUDIO_TASK conditional issue as earlier. */ #if 0 // CQ: Force the Audio ON to avoid having the DSP reseting the VDLON and producing a pop noise // on single ended outputs. l1s_dsp_com.dsp_ndb_ptr->d_toneskb_init |= (API) B_AUDIO_ON_START; l1s.l1_audio_it_com = TRUE; l1a_l1s_com.audio_forced_by_l1s = TRUE; #endif } /* * FreeCalypso: the following code has been reconstructed from the * TCS211 binary object; it appears neither in the LoCosto nor * in the TSM30 source. */ #if (AEC) if((l1s.aec.aec_control & 0x0002) || (l1s.aec.aec_control & 0x0004)) { l1s.aec.aec_control = l1a_l1s_com.aec_task.parameters.aec_control | 0x0001; l1s_dsp_com.dsp_ndb_ptr->d_aec_ctrl = l1s.aec.aec_control; } #endif // Clear ciphering setting in MCU-DSP com. l1ddsp_load_ciph_param(0, &(l1a_l1s_com.dedic_set.aset->ciph_key)); // Reset the global dedicated enable flag. l1a_l1s_com.l1s_en_task[DEDIC] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[DDL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[DUL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[ADL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[AUL] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHTH] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHD] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHTF] = TASK_DISABLED; l1a_l1s_com.l1s_en_task[TCHA] = TASK_DISABLED; // Reset active dedicated set. l1a_l1s_com.dedic_set.aset = NULL; // Enter to the handover fail mode. l1a_l1s_com.dedic_set.handover_fail_mode = TRUE; // SYNCHRO task and its associated parameters (tn_difference, dl_tn and // dsp_scheduler_mode) are not Enabled/Updated if we are in the specific case: // L1A is touching SYNCHRO parameters and leave L1A to go in HISR (L1S) // in middle of the update (cf. BUG1339) if(l1a_l1s_com.task_param[SYNCHRO] == SEMAPHORE_RESET) { // Since SYNCHRO has the highest priority and the installation of // this task in the MFTAB is made after a CLEAR of the MFTAB, we // insure that any uncompleted task will be ABORTED. l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED; } // Handover access procedure is completed. // -> send L1C_HANDOVER_FINISHED message with "cause = TIMEOUT" to L1A. l1s_send_ho_finished(HO_TIMEOUT); } } #if FF_L1_IT_DSP_DTX // ASET validity check (cleared upon handover timeout) if (l1a_l1s_com.dedic_set.aset != NULL) { // Handover in progress (equals -1 if asynchronous) if(l1a_l1s_com.dedic_set.aset->ho_acc_to_send != 0) // Initialize timer for fast DTX availabilty l1a_apihisr_com.dtx.fast_dtx_ready_timer = FAST_DTX_LATENCY; // Dedicated channel mode change. Fast DTX interrupt can be used after some time if (l1a_apihisr_com.dtx.fast_dtx_ready_timer == FAST_DTX_LATENCY) { // Clear DTX interrupt condition l1a_apihisr_com.dtx.pending = FALSE; // Enable TX activity l1a_apihisr_com.dtx.tx_active = TRUE; // No DTX status awaited l1a_apihisr_com.dtx.dtx_status = DTX_AVAILABLE; // Fast DTX shall not be used for a while l1a_apihisr_com.dtx.fast_dtx_ready = FALSE; } // Fast DTX latency timer handling (not on idle frame) if ((l1a_apihisr_com.dtx.fast_dtx_ready_timer > 0) && (l1s.next_time.fn_mod13 != 12)) l1a_apihisr_com.dtx.fast_dtx_ready_timer--; // Timeout processed on a DTX block status boundary else if (l1a_apihisr_com.dtx.fast_dtx_ready_timer == 0) { UWORD8 channel_type; UWORD8 subchannel; 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; // Wait for DTX status boundary to enable Fast DTX use if ((((channel_type == TCH_F) || ((channel_type == TCH_H) && (subchannel == 0))) && // TCH-AFS and TCH-AHS0 (l1s.actual_time.fn_mod13_mod4 == 3)) || // DTX status reported during TDMA3 (((channel_type == TCH_H) && (subchannel == 1)) && // TCH-AHS1 (l1s.next_time.fn_mod13_mod4 == 1)) // DTX status reported during TDMA0 ) { l1a_apihisr_com.dtx.fast_dtx_ready = TRUE; } } } #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 #if FF_L1_IT_DSP_USF /*-------------------------------------------------------*/ /* l1usf_apihisr() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is called from the HISR handling the */ /* processing of the DSP USF IT interrupt. It is */ /* triggered upon USF decoding completion, once the */ /* results have been reported in API. */ /* Operations executed: */ /* 1) MACS allocation update */ /* 2) DSP programming */ /* 3) ABB (APC, ramps) programming */ /* 4) TCR measurement handling */ /* 5) TPU scenario enabling and API DB pages switch */ /* */ /*-------------------------------------------------------*/ void l1usf_apihisr(void) { // Make sure the interrupt was expected if (l1ps_macs_com.usf_status == USF_AWAITED) { // Flags the USF HISR before MACS/L1S update l1ps_macs_com.usf_status = USF_IT_DSP; // Test if PDTCH task is running if (l1s.task_status[PDTCH].current_status != INACTIVE) { // MACS allocation update (allocation then TPU, DSP and ABB) l1ps_ctrl_pdtch(PDTCH, BURST_3); // Packet transfer meas. manager update (PM control pipelines) l1ps_transfer_meas_manager(); // End manager update (TPU enable and API DB switches) l1s_end_manager(); } // Test if PRACH task is running else if (l1s.task_status[PRACH].current_status == ACTIVE) { // PRACH control l1ps_ctrl_prach(PRACH, BURST_3); // Packet meas. manager update (PM control pipelines) l1ps_meas_manager(); // End manager update (TPU enable and API DB switches) l1s_end_manager(); } // USF validity is no more pending l1ps_macs_com.usf_status = USF_AVAILABLE; } // Clear USF pending condition l1a_apihisr_com.usf.pending = FALSE; } #endif // FF_L1_IT_DSP_USF #if FF_L1_IT_DSP_DTX /*-------------------------------------------------------*/ /* l1dtx_apihisr() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* This function is called from the HISR handling the */ /* processing of the DSP DTX IT interrupt. It is */ /* triggered once DTX status is available and reported */ /* in API. */ /* Operations executed: */ /* 1) TX/DSP part of TCH programming */ /* 2) Dedicated mode BA list measurements handling */ /* 3) TPU scenario enabling and API DB pages switch */ /* */ /*-------------------------------------------------------*/ void l1dtx_apihisr(void) { // Make sure the interrupt was expected if (l1a_apihisr_com.dtx.dtx_status == DTX_AWAITED) { // Flags the DTX HISR before L1S update l1a_apihisr_com.dtx.dtx_status = DTX_IT_DSP; // Latch TX activity status if (l1s_dsp_com.dsp_ndb_ptr->d_fast_dtx_enc_data) l1a_apihisr_com.dtx.tx_active = TRUE; else l1a_apihisr_com.dtx.tx_active = FALSE; // TCH/F is running, invoke its control function if (l1a_l1s_com.l1s_en_task[TCHTF] == TASK_ENABLED) l1s_ctrl_tchtf(TCHTF, NO_PAR); // TCH/H is running, invoke its control function else if (l1a_l1s_com.l1s_en_task[TCHTH] == TASK_ENABLED) l1s_ctrl_tchth(TCHTH, NO_PAR); // Dedicated mode measurement manager l1s_meas_manager(); // End manager update (TPU enable and API DB switches) l1s_end_manager(); // DTX status is no more pending l1a_apihisr_com.dtx.dtx_status = DTX_AVAILABLE; } // Clear DTX pending condition l1a_apihisr_com.dtx.pending = FALSE; } #endif // FF_L1_IT_DSP_DTX #if (FF_L1_FAST_DECODING == 1) void l1_fast_decoding_apihisr(void) { /* Tracks if a fast paging burst will be performed, an IT will happen */ BOOL new_IT_awaited = FALSE; /* Clear the pending condition */ l1a_apihisr_com.fast_decoding.pending = FALSE; /* In case semaphore of a task gets set in between force CRC error to be true */ if(l1a_l1s_com.task_param[l1a_apihisr_com.fast_decoding.task] == SEMAPHORE_SET) { l1a_apihisr_com.fast_decoding.crc_error = TRUE; } /* Make sure the interrupt was expected */ if (l1a_apihisr_com.fast_decoding.status == C_FAST_DECODING_AWAITED) { /* Update the status */ l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_PROCESSING; /* Check the NP/PNP burst number, if this is the 4th one nothing has */ /* to be done (usual scheduling) */ if (l1a_apihisr_com.fast_decoding.deferred_control_req) { l1a_apihisr_com.fast_decoding.deferred_control_req = FALSE; /* Retrieve decoding status from the DSP */ if (l1a_apihisr_com.fast_decoding.crc_error) { /* Block decoding failed, more bursts must be received */ switch(l1a_apihisr_com.fast_decoding.task) { case NP: { l1s_ctrl_snb_dl(NP, l1a_apihisr_com.fast_decoding.burst_id); new_IT_awaited = TRUE; break; } /* case NP: */ #if L1_GPRS case PNP: { l1ps_ctrl_snb_dl(PNP, l1a_apihisr_com.fast_decoding.burst_id); new_IT_awaited = TRUE; break; } /* case PNP: */ #endif /* L1_GPRS */ case NBCCHS: { l1s_ctrl_snb_dl(NBCCHS, l1a_apihisr_com.fast_decoding.burst_id); new_IT_awaited = TRUE; break; } /* case NBCCHS */ } /* switch(l1a_apihisr_com.fast_decoding.task) */ } /* end if CRC error */ else /* if (l1a_apihisr_com.fast_decoding.crc_error == TRUE) */ { #if L1_GPRS /* Decoding OK so no new control so no new IT to expect */ /* reading normal burst in packet idle mode on a different timeslot so need to restore synchro*/ if ( (l1a_apihisr_com.fast_decoding.task == NP) && (l1a_l1s_com.l1s_en_task[PNP] == TASK_ENABLED) && (l1s.algo_change_synchro_active) ) { /* Ensure that synchro back is executed in the NMO II or III */ l1s_restore_synchro(); l1s.ctrl_synch_before = FALSE; l1s.algo_change_synchro_active = FALSE; } #endif /* L1_GPRS */ } /* end else no CRC error */ /* In any case power measurements schedulers and end of frame processing */ /* must be executed now */ #if L1_GPRS /* Packet Measurement Manager */ l1ps_meas_manager(); #endif /* Measurement Manager */ l1s_meas_manager(); /* End Manager */ l1s_end_manager(); } else /* if (l1a_apihisr_com.fast_decoding.control_required) */ { /* No new control so no new IT to expect */ } } /* if (l1a_apihisr_com.fast_decoding.status == C_FAST_DECODING_AWAITED) */ else { /* Interrupt received but not expected, this shouldn't happen */ l1_trace_IT_DSP_error(IT_DSP_ERROR_FAST_DECODING_UNEXP); } /* Status update depending on CRC and the scheduling of another bursts */ if (new_IT_awaited) { /* New IT awaited */ l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_AWAITED; } else if (l1a_apihisr_com.fast_decoding.crc_error == FALSE) { /* No new IT awaited, the CRC is OK, fast decoding is complete */ l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_COMPLETE; } else { /* No new IT awaited and CRC is still fail, typically 4th burst received */ /* but decoding has failed. */ l1a_apihisr_com.fast_decoding.status = C_FAST_DECODING_NONE; } } /* end function l1_fast_decoding_apihisr */ #endif /* FF_L1_FAST_DECODING */ //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #endif // MOVE_IN_INTERNAL_RAM