FreeCalypso > hg > fc-magnetite
view src/cs/layer1/p_cfile/l1p_asyn.c @ 632:d968a3216ba0
new tangomdm build target
TCS211/Magnetite built for target leonardo runs just fine on the Tango-based
Caramel board, but a more proper tangomdm build target is preferable in order
to better market these Tango modems to prospective commercial customers. The
only differences are in GPIO and MCSI config:
* MCSI is enabled in the tangomdm build config.
* GPIO 1 is loudspeaker amplifier control on Leonardo, but on Tango platforms
it can be used for anything. On Caramel boards this GPIO should be
configured as an output driving high.
* GPIO 2 needs to be configured as Calypso input on Leonardo, but on Tango
platforms it can be used for anything. On Caramel boards this GPIO should be
configured as an output, either high or low is OK.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 04 Jan 2020 19:27:41 +0000 |
parents | 0740b5ff15f6 |
children |
line wrap: on
line source
/************* Revision Controle System Header ************* * GSM Layer 1 software * L1P_ASYN.C * * Filename l1p_asyn.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 L1P_ASYN_C //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END // KEEP IN EXTERNAL MEM otherwise #endif //#pragma DUPLICATE_FOR_INTERNAL_RAM_START #include "l1_macro.h" #include "l1_confg.h" #if L1_GPRS #if (CODE_VERSION == SIMULATION) #include <string.h> #include "l1_types.h" #include "sys_types.h" #include "l1_const.h" #if TESTMODE #include "l1tm_defty.h" #endif #if (AUDIO_TASK == 1) #include "l1audio_const.h" #include "l1audio_cust.h" #include "l1audio_defty.h" #endif #if (L1_GTT == 1) #include "l1gtt_const.h" #include "l1gtt_defty.h" #endif #if (L1_MP3 == 1) #include "l1mp3_defty.h" #endif #if (L1_MIDI == 1) #include "l1midi_defty.h" #endif #include "l1_defty.h" #include "cust_os.h" #include "l1_msgty.h" #include "l1_varex.h" #include "l1_signa.h" #include "l1_proto.h" #include "l1_time.h" #include "l1_ctl.h" #include "l1p_cons.h" #include "l1p_msgt.h" #include "l1p_deft.h" #include "l1p_vare.h" #include "l1p_tabs.h" #include "l1p_sign.h" #include "l1p_mfta.h" #include "l1p_macr.h" #include "macs_def.h" #include "macs_cst.h" #else #include <string.h> #include "l1_types.h" #include "sys_types.h" #include "l1_const.h" #if TESTMODE #include "l1tm_defty.h" #endif #if (AUDIO_TASK == 1) #include "l1audio_const.h" #include "l1audio_cust.h" #include "l1audio_defty.h" #endif #if (L1_GTT == 1) #include "l1gtt_const.h" #include "l1gtt_defty.h" #endif #if (L1_MP3 == 1) #include "l1mp3_defty.h" #endif #if (L1_MIDI == 1) #include "l1midi_defty.h" #endif #include "l1_defty.h" #include "cust_os.h" #include "l1_msgty.h" #include "l1_varex.h" #include "l1_signa.h" #include "l1_proto.h" #include "l1_time.h" #include "l1_ctl.h" #include "l1p_cons.h" #include "l1p_msgt.h" #include "l1p_deft.h" #include "l1p_vare.h" #include "l1p_tabs.h" #include "l1p_sign.h" #include "l1p_mfta.h" #include "l1p_macr.h" #include "macs_def.h" #include "macs_cst.h" #endif T_TRANSFER_SET *l1pa_get_free_transfer_set (UWORD8 new_tbf); void l1pa_transfer_process (xSignalHeaderRec *msg); void l1pa_access_process (xSignalHeaderRec *msg); void l1pa_idle_packet_polling_process (xSignalHeaderRec *msg); void l1pa_idle_paging_process (xSignalHeaderRec *msg); void l1pa_cr_meas_process (xSignalHeaderRec *msg); void l1pa_serving_cell_pbcch_read_process (xSignalHeaderRec *msg); void l1pa_neighbor_cell_pbcch_read_process (xSignalHeaderRec *msg); int l1pa_sort (const void *a, const void *b); void l1pa_reset_cr_freq_list (void); void l1pa_tcr_meas_process (xSignalHeaderRec *msg); T_CRES_LIST_PARAM *l1pa_get_free_cres_list_set (void); void l1pa_idle_interference_meas_process (xSignalHeaderRec *msg); void l1pa_transfer_interference_meas_process (xSignalHeaderRec *msg); void l1pa_idle_smscb_process (xSignalHeaderRec *msg); // External prototype void l1pa_send_int_meas_report(UWORD32 SignalCode, T_L1P_ITMEAS_IND *last_l1s_msg, T_L1A_INT_MEAS_PARAM *first_meas_ptr); void l1pa_send_confirmation(UWORD32 SignalCode, UWORD8 id); void l1pa_send_tbf_release_con(UWORD32 SignalCode, UWORD8 tbf_type); //#pragma DUPLICATE_FOR_INTERNAL_RAM_END #if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM > 1)) // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM == 2 //#pragma GSM_IDLE2_DUPLICATE_FOR_INTERNAL_RAM_START // KEEP IN EXTERNAL MEM otherwise /*-------------------------------------------------------*/ /* l1pa_task() */ /*-------------------------------------------------------*/ /* */ /* Description: */ /* ------------ */ /* L1PA (Layer 1 Asynchronous) task function. This */ /* function manages the GPRS interface between L3 and L1.*/ /* It is composed with a set of state machine, each */ /* machine handles a particular GSM functionality. When */ /* a message is received in L1_C1 message queue, it is */ /* submitted to every state machine. The one which are */ /* impacted by the message process it. At the end of */ /* "l1pa_task()" function, a balance routine is called, */ /* it enables L1S tasks consequently to the state machine*/ /* requests. */ /* */ /*-------------------------------------------------------*/ void l1pa_task(xSignalHeaderRec *msg) { UWORD8 process; // Clear L1PA "enable meas and tasks" variables. //--------------------------------------------- for(process=0; process<NBR_L1PA_PROCESSES; process++) { l1pa.l1pa_en_meas[process] = NO_TASK; } #if (GSM_IDLE_RAM != 0) if ((msg->SignalCode != L1P_PNP_INFO) && (msg->SignalCode != L1P_PEP_INFO)) #if (GSM_IDLE_RAM > 1) // GPF modified for GSM_IDLE_RAM -> SW still running in Internal RAM { #endif l1s.gsm_idle_ram_ctl.l1s_full_exec = TRUE; #endif // GSM_IDLE_RAM // Serving Cell Packet System Information Reading l1pa_serving_cell_pbcch_read_process(msg); // Neighbor Cell Packet System Information Reading l1pa_neighbor_cell_pbcch_read_process(msg); #if (GSM_IDLE_RAM <= 1) // GPF modified for GSM_IDLE_RAM -> SW still running in Internal RAM { // Serving Cell Packet Paging Reading l1pa_idle_paging_process(msg); } #endif // Cell reselection measurement process l1pa_cr_meas_process(msg); // Packet access proccess l1pa_access_process(msg); // Packet polling process l1pa_idle_packet_polling_process(msg); // Packet transfer process. l1pa_transfer_process(msg); // Neighbour Cell Measurement in Packet Transfer mode l1pa_tcr_meas_process(msg); // Intererence measurements in packet idle mode l1pa_idle_interference_meas_process(msg); // Intererence measurements in packet transfer mode l1pa_transfer_interference_meas_process(msg); #if (GSM_IDLE_RAM > 1) // GPF modified for GSM_IDLE_RAM -> SW still running in Internal RAM }else { // Serving Cell Packet Packet Idle Paging Reading l1pa_idle_paging_process(msg); } #endif } //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END // KEEP IN EXTERNAL MEM otherwise #endif /*-------------------------------------------------------*/ /* l1pa_access_process() */ /*-------------------------------------------------------*/ /* Description : This state machine handles the packet */ /* access to the network while in PACKET IDLE mode. */ /* */ /* Starting messages: MPHP_RA_REQ */ /* */ /* Subsequent messages: MPHP_RA_REQ */ /* */ /* Result messages (input): L1P_PRA_DONE */ /* */ /* Result messages (output): MPHP_RA_CON */ /* */ /* Reset message (input): MPHP_RA_STOP_REQ */ /* */ /* Reset message (input): MPHP_RA_STOP_CON */ /*-------------------------------------------------------*/ void l1pa_access_process(xSignalHeaderRec *msg) { enum states { RESET = 0, WAIT_INIT = 1, WAIT_RESULT = 2 }; UWORD8 *state = &l1pa.state[P_ACC]; UWORD32 SignalCode = msg->SignalCode; BOOL end_process = 0; while(!end_process) { switch(*state) { case RESET: { // Step in state machine. *state = WAIT_INIT; // Reset PRACH process. l1a_l1s_com.l1s_en_task[PRACH] = TASK_DISABLED; // Clear PRACH task enable flag. l1pa_l1ps_com.pra_info.prach_alloc = 0; } break; case WAIT_INIT: { if(SignalCode == MPHP_RA_REQ) // 1st Random access request message. //----------------------------------- { // Download Transmit power configuration. // Given value must be used on 1st TX. // TXPWR value supplied by L3 is the max. TX power level the MS may use in the given band l1s.applied_txpwr = ((T_MPHP_RA_REQ *)(msg->SigP))->txpwr; #if L1_R99 // Init PRACH process. // "rand" parameter chosen by protocol in range [1..4] for R99 l1pa_l1ps_com.pra_info.rand = ((T_MPHP_RA_REQ *)(msg->SigP))->rand; #else // "rand" parameter from msg is not used for the 1st PRACH. l1pa_l1ps_com.pra_info.rand = 1; // First PRACH has to be sent immediately #endif l1pa_l1ps_com.pra_info.channel_request_data = ((T_MPHP_RA_REQ *)(msg->SigP))->channel_request_data; l1pa_l1ps_com.pra_info.bs_prach_blks = ((T_MPHP_RA_REQ *)(msg->SigP))->bs_prach_blks; l1pa_l1ps_com.access_burst_type = ((T_MPHP_RA_REQ *)(msg->SigP))->access_burst_type; // Increment rand parameter by 4 in order to avoid conflict between SYNCHRO and // PRACH tasks when MPHP_START_PCCCH_REQ and MPHP_RA_REQ are // sent at the same time by L3 l1pa_l1ps_com.pra_info.rand+=4; if ((l1pa_l1ps_com.pra_info.bs_prach_blks == 0) || // no blocks allocated (l1pa_l1ps_com.pra_info.bs_prach_blks > 12)) // invalid number of blocks l1pa_l1ps_com.pra_info.prach_alloc = DYN_PRACH_ALLOC; // step in state machine. *state = WAIT_RESULT; // Change mode to connection establishment part 1. l1a_l1s_com.mode = CON_EST_MODE1; // Activate PRACH task (no semaphore for UL tasks). l1a_l1s_com.l1s_en_task[PRACH] = TASK_ENABLED; // Set PRACH task enable flag. } // end of process. end_process = 1; } break; case WAIT_RESULT: { if(SignalCode == L1P_RA_DONE) // Random access acknowledge message: PRACH sent. //----------------------------------------------- { // Forward result message to L3. l1a_send_result(MPHP_RA_CON, msg, GRRM1_QUEUE); // Change mode to connection establishment part 2. l1a_l1s_com.mode = CON_EST_MODE2; // end of process. return; } else if(SignalCode == MPHP_RA_REQ) // Random access message. //----------------------- { // REM: rand is added the msg content since its current content is the already // spent "slots" from the last PRACH sending. l1pa_l1ps_com.pra_info.rand += ((T_MPHP_RA_REQ *)(msg->SigP))->rand + 1; l1pa_l1ps_com.pra_info.channel_request_data = ((T_MPHP_RA_REQ *)(msg->SigP))->channel_request_data; l1pa_l1ps_com.pra_info.bs_prach_blks = ((T_MPHP_RA_REQ *)(msg->SigP))->bs_prach_blks; l1pa_l1ps_com.access_burst_type = ((T_MPHP_RA_REQ *)(msg->SigP))->access_burst_type; if ((l1pa_l1ps_com.pra_info.bs_prach_blks == 0) || // no blocks allocated (l1pa_l1ps_com.pra_info.bs_prach_blks > 12)) // invalid number of blocks l1pa_l1ps_com.pra_info.prach_alloc = DYN_PRACH_ALLOC; // else // l1pa_l1ps_com.pra_info.prach_alloc = FIX_PRACH_ALLOC; else l1pa_l1ps_com.pra_info.prach_alloc = 0; //must be reset for each burst sent // Activate PRACH task (no semaphore for UL tasks). l1a_l1s_com.l1s_en_task[PRACH] = TASK_ENABLED; // Set PRACH task enable flag. // end of process. return; } else if(SignalCode == MPHP_RA_STOP_REQ) // Request to STOP the LINK ACCESS procedure. //------------------------------------------- { UWORD8 i; // send confirmation l1a_send_confirmation(MPHP_RA_STOP_CON,GRRM1_QUEUE); // Store MAX TXPWR value to be used for first Tx PDCH blocks for(i = 0; i < 8; i++) { l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr[i] = l1s.applied_txpwr; } // This process must be reset. *state = RESET; } else if(SignalCode == MPHP_POLLING_RESPONSE_REQ) // Stop packet access when packet polling initiated. //-------------------------------------------------- { // Unacknowledged // This process must be reset. *state = RESET; } else // No action in this machine for other messages. //---------------------------------------------- { // End of process. end_process = 1; } } break; } // end of "switch". } // end of "while" } // end of procedure. /*-------------------------------------------------------*/ /* l1pa_cr_meas_process() */ /*-------------------------------------------------------*/ /* Description : This state machine handles periodic */ /* signal strength monitoring on carriers specified */ /* in a frequency list: BA(GPRS), NC_FREQUENCY_LIST, */ /* EXT_FREEQUENCY_LIST (respectively: cell reselection */ /* Network Control and Extended measurements. */ /* */ /* Starting messages: MPHP_CR_MEAS_REQ */ /* ------------------ */ /* L1 starts then the periodic FREQUENCY list receive */ /* level monitoring. */ /* */ /* Subsequent messages: MPHP_CR_MEAS_REQ */ /* -------------------- */ /* The frequency list is updated only when measures */ /* on all the carriers of the current list are */ /* performed. */ /* */ /* Result messages (input): L1P_RXLEV_PERIODIC_DONE */ /* ------------------------ */ /* This is a message reported to L1A from L1S. */ /* Reporting is done when last carrier of the frequency */ /* list is read. */ /* */ /* Result messages (output): MPHP_CR_MEAS_IND */ /* ------------------------- */ /* This is the periodic reporting message to L3. */ /* */ /* Reset messages (input): MPHP_CR_MEAS_STOP_REQ */ /* ----------------------- */ /* Frequency list measurement process is stopped by */ /* this message. */ /* */ /*-------------------------------------------------------*/ void l1pa_cr_meas_process(xSignalHeaderRec *msg) { enum states { RESET = 0, WAIT_INIT = 1, WAIT_RESULT = 2 }; UWORD8 *state = &l1pa.state[CR_MEAS]; UWORD32 SignalCode = msg->SignalCode; BOOL end_process = 0; while(!end_process) { switch(*state) { case RESET: { // step in state machine. *state = WAIT_INIT; // Reset P_CRMS_MEAS process. l1pa_l1ps_com.l1ps_en_meas &= P_CRMS_MEAS_MASK; // Reset Packet Cell Reselection Measurement enable flag. } break; case WAIT_INIT: { if(SignalCode == MPHP_CR_MEAS_REQ) // We receive the Frequency list to be monitored. //---------------------------------------------- { UWORD8 i; T_CRES_LIST_PARAM *free_list; // Set parameter synchro semaphore for P_CRMS_MEAS task. l1pa_l1ps_com.meas_param |= P_CRMS_MEAS; // Reset the frequency list structure. l1pa_reset_cr_freq_list(); // Get Ptr to the free Neighbour meas list. // The number of carriers in the list and the list // identification are initialized. free_list = l1pa_get_free_cres_list_set(); // Set number of carrier in the frequency list. free_list->nb_carrier = ((T_MPHP_CR_MEAS_REQ *)(msg->SigP))->nb_carrier; // Store ARFCN list in the Packet Cell Reselection structure. for(i=0;i<free_list->nb_carrier;i++) free_list->freq_list[i] = ((T_MPHP_CR_MEAS_REQ *)(msg->SigP))->radio_freq_no[i]; // Download Frequency list identifier. free_list->list_id = ((T_MPHP_CR_MEAS_REQ *)(msg->SigP))->list_id; // Set "flist" with new set of frequency list parameter l1pa_l1ps_com.cres_freq_list.flist = free_list; // Enable Packet Cell Reselection measurement task. l1pa.l1pa_en_meas[CR_MEAS] |= P_CRMS_MEAS; // step in state machine. *state = WAIT_RESULT; } // End of process. end_process = 1; } break; case WAIT_RESULT: { if(SignalCode == L1P_CR_MEAS_DONE) // One set of measurement has been completed. //--------------------------------------------- { // Forward result message to L3. l1a_send_result(MPHP_CR_MEAS_IND, msg, GRRM1_QUEUE); // End of process. end_process = 1; } else if((SignalCode == MPHP_CR_MEAS_STOP_REQ) || (SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1C_DEDIC_DONE)) // Request to STOP this activity. //------------------------------- { // send confirmation message l1a_send_confirmation(MPHP_CR_MEAS_STOP_CON,GRRM1_QUEUE); // This process must be reset. *state = RESET; } else if (SignalCode == MPHP_CR_MEAS_REQ) { // This process must be reset. *state = RESET; } else // No action in this machine for other messages. //---------------------------------------------- { // End of process. end_process = 1; } } break; } // end of "switch". } // end of "while" } // end of procedure. #if !((MOVE_IN_INTERNAL_RAM == 1) && (GSM_IDLE_RAM > 1)) // MOVE TO INTERNAL MEM IN CASE GSM_IDLE_RAM == 2 //#pragma GSM_IDLE2_DUPLICATE_FOR_INTERNAL_RAM_START // KEEP IN EXTERNAL MEM otherwise /*-------------------------------------------------------*/ /* l1pa_idle_paging_process() */ /*-------------------------------------------------------*/ /* */ /*-------------------------------------------------------*/ void l1pa_idle_paging_process(xSignalHeaderRec *msg) { enum states { RESET = 0, WAIT_INIT = 1, WAIT_MSG = 2 }; enum pg_mode { NORM_PG = 0, EXT_PG = 1, REORG_PG = 2 }; UWORD8 *state = &l1pa.state[PI_SCP]; UWORD32 SignalCode = msg->SignalCode; UWORD16 imsimod; UWORD16 split_pg_cycle; UWORD16 kcn; UWORD8 page_mode; BOOL end_process = 0; while(!end_process) { switch(*state) { case RESET: { // Step in state machine. *state = WAIT_INIT; // Disable serving cell tasks. l1a_l1s_com.l1s_en_task[PALLC] = TASK_DISABLED; // Reset PALLC (reorg) task enable flag. l1a_l1s_com.l1s_en_task[PNP] = TASK_DISABLED; // Reset PNP task enable flag. l1a_l1s_com.l1s_en_task[PEP] = TASK_DISABLED; // Reset PEP task enable flag. // No Paging => no gauging => no Deep sleep l1s.pw_mgr.enough_gaug = FALSE; // forbid Deep sleep } break; case WAIT_INIT: { if(SignalCode == MPHP_START_PCCCH_REQ) { // Set semaphores for any PCCCH reading tasks. l1a_l1s_com.task_param[PALLC] = SEMAPHORE_SET; l1a_l1s_com.task_param[PNP] = SEMAPHORE_SET; l1a_l1s_com.task_param[PEP] = SEMAPHORE_SET; // Request to enter in PACKET PAGING REORGANIZATION or NORMAL mode. //---------------------------------------------------------------- // The initial page mode in the Mobile Station shall be set to paging Reorganization // cf 04.08 section 3.3.2.1.1. however current implementation allows to init the Paging // procedure either in Reorganization or in Normal paging mode. // Download the PAGING PARAMETERS from the command message. page_mode = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->page_mode; imsimod = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->imsimod; kcn = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->kcn; split_pg_cycle = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->split_pg_cycle; l1pa_l1ps_com.pccch.bs_pag_blks_res = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->bs_pag_blks_res; l1pa_l1ps_com.pccch.bs_pbcch_blks = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->bs_pbcch_blks; l1pa_l1ps_com.pccch.frequency_list = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->frequency_list; l1pa_l1ps_com.pccch.packet_chn_desc = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->packet_chn_desc; l1a_l1s_com.Scell_info.pb = ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->pb << 2; // Pb format 7.1 // Number of paging blocks "available" on one PCCCH = number of ppch blocks per MF52 * 64 // = (12 - BS_PAG_BLKS_RES - BS_PBCCH_BLKS)*64 l1pa_l1ps_com.pccch.nb_ppch_per_mf52 = (12 - l1pa_l1ps_com.pccch.bs_pag_blks_res - (l1pa_l1ps_com.pccch.bs_pbcch_blks + 1)); // Compute M. l1pa_l1ps_com.pccch.pg_blks_avail = l1pa_l1ps_com.pccch.nb_ppch_per_mf52 * 64; // (IMSI mod 1000) div (KC*N) (Note: N = 1 for PCCCH) l1pa_l1ps_com.pccch.pg_offset = imsimod / kcn; // First Paging Group value: PAGING_GROUP = ((IMSI mod 1000) div ((KC*N)*N)) (for m = 0) l1pa_l1ps_com.pccch.first_pg_grp = (l1pa_l1ps_com.pccch.pg_offset % l1pa_l1ps_com.pccch.pg_blks_avail); // Split Paging computation = min (pg_blks_avail, SPLIT_PG_CYCLE) l1pa_l1ps_com.pccch.split_pg_value = Min(l1pa_l1ps_com.pccch.pg_blks_avail, split_pg_cycle); // Paging Period computation l1pa_l1ps_com.pccch.pnp_period = (64*52) / l1pa_l1ps_com.pccch.split_pg_value; // Rem: changing the paging parameters changes the place where "Periodic Packet // Measurement" task must be executed. It implies to set semaphore for P_CRMS task. l1pa_l1ps_com.meas_param |= P_CRMS_MEAS; // Layer 1 internal mode is set to IDLE MODE. l1a_l1s_com.mode = I_MODE; // In order to keep tn_difference and dl_tn consistent, we need to avoid // the execution of the SYNCHRO task with tn_difference updated and // dl_tn not yet updated (this can occur if we go in the HISR just after // the update of tn_difference). To do this the solution is to use the Semaphore // associated to the SYNCHRO task. SYNCHRO task will be schedule only if its // associated Semaphore is reset. // Note: Due to the specificity of the SYNCHRO task which can be enabled // by L1A state machines as by L1S processes, the semaphore can't followed // the generic rules of the Semaphore shared between L1A and L1S. // We must shift the mobile time setting to the timeslot provided by // ((T_MPHP_START_PCCCH_REQ *)(msg->SigP))->packet_chn_desc.timeslot_no parameter. // tn_difference -> loaded with the number of timeslot to shift. // dl_tn -> loaded with the new timeslot. l1a_l1s_com.task_param[SYNCHRO] = SEMAPHORE_SET; { l1a_l1s_com.tn_difference += l1pa_l1ps_com.pccch.packet_chn_desc.timeslot_no - l1a_l1s_com.dl_tn; l1a_l1s_com.dl_tn = l1pa_l1ps_com.pccch.packet_chn_desc.timeslot_no; // Select GPRS DSP Scheduler. l1a_l1s_com.dsp_scheduler_mode = GPRS_SCHEDULER; // Timing must be shifted to a new timeslot, enables SYNCHRO task.. l1a_l1s_com.l1s_en_task[SYNCHRO] = TASK_ENABLED; } l1a_l1s_com.task_param[SYNCHRO] = SEMAPHORE_RESET; // Note: The using of the semaphore associated to the SYNCHRO task can't be done // as it is for the other semaphores. This is due to the specificity of the SYNCHRO // task both touch by L1A and L1S. Here above the semaphore is set prior to touching // the SYNCHRO parameters and reset after. In L1S this semaphore is checked. If it's // seen SET then L1S will not execute SYNCHRO task nor modify its parameters. // Step in state machine. *state = WAIT_MSG; if(page_mode == REORG_PG) // Paging Reorganization mode... { // Enable Packet Paging Reorganisation tasks. l1a_l1s_com.l1s_en_task[PALLC] = TASK_ENABLED; l1a_l1s_com.l1s_en_task[PNP] = TASK_ENABLED; // End of process. end_process = 1; } else if(page_mode == NORM_PG) // Normal Paging mode... { // Enable Packet Paging tasks in mode "NORMAL". l1a_l1s_com.l1s_en_task[PNP] = TASK_ENABLED; // End of process. end_process = 1; } else // Extended Paging mode... { // Initialize Paging State for PAGING_GROUP computation (L1S part) l1pa_l1ps_com.pccch.epg_computation = PPCH_POS_NOT_COMP; // Enable Packet Paging tasks in mode "EXTENDED". l1a_l1s_com.l1s_en_task[PNP] = TASK_ENABLED; l1a_l1s_com.l1s_en_task[PEP] = TASK_ENABLED; // End of process. end_process = 1; } } // end of test on SignalCode == MPHP_START_PCCCH_REQ else // No action in this machine for other messages. //---------------------------------------------- { // End of process. end_process = 1; } } // end of case WAIT_INIT break; case WAIT_MSG: { if((SignalCode == L1P_PNP_INFO) || (SignalCode == L1P_PALLC_INFO) || (SignalCode == L1P_PEP_INFO)) // Paging Task results { // Forward result message to L3. l1a_send_result(MPHP_DATA_IND, msg, GRRM1_QUEUE); // End of process. return; } else if(SignalCode == MPHP_START_PCCCH_REQ) // New PCCCH configuration is provided. //-------------------------------------------------------- { // Step in state machine *state = RESET; } else if((SignalCode == MPHP_STOP_PCCCH_REQ) || (SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1C_DEDIC_DONE)) // Request to STOP any serving cell Packet Paging activity, OR // Packet Transfer has just started. // In both cases, PCCCH reading must be stopped. //-------------------------------------------------------- { // Send confirmation message to L3. l1a_send_confirmation(MPHP_STOP_PCCCH_CON,GRRM1_QUEUE); // This process must be reset. *state = RESET; } else if((SignalCode == L1P_SINGLE_BLOCK_CON) || (SignalCode == MPHP_SINGLE_BLOCK_CON)) // If Two Phase Access is ongoing: Packet Resource Request // msg has been sent to the network. PCCCH reading must be // stopped to let PDCH reading going. // REM: we must check both L1P/MPHP messages since an other // process could have renamed L1P into MPHP. //-------------------------------------------------------- { if(((T_MPHP_SINGLE_BLOCK_CON *)(msg->SigP))->purpose == TWO_PHASE_ACCESS) { // This process must be reset. *state = RESET; } else { // End of process. return; } } else // No action in this machine for other messages. //---------------------------------------------- { // End of process. return; } } // end of case WAIT_MSG break; } // end of switch } // end of while } // end of procedure //#pragma GSM_IDLE_DUPLICATE_FOR_INTERNAL_RAM_END #endif /*-------------------------------------------------------*/ /* l1pa_idle_packet_polling_process() */ /*-------------------------------------------------------*/ /* Description : . */ /* This state machine handles packet polling after */ /* initiation of the packet acces procedure, when a */ /* packet queuing notification is sent by the network */ /* */ /* Starting messages: MPHP_POLLING_RESPONSE_REQ */ /* */ /* Subsequent messages: */ /* */ /* Result messages (input): L1P_PRA_DONE */ /* */ /* Result messages (output): MPHP_POLLING_IND */ /* */ /* Reset message (input): */ /* */ /* Reset message (input): */ /*-------------------------------------------------------*/ void l1pa_idle_packet_polling_process(xSignalHeaderRec *msg) { enum states { RESET = 0, WAIT_INIT = 1, WAIT_RESULT = 2 }; UWORD8 *state = &l1pa.state[P_POLL]; UWORD32 SignalCode = msg->SignalCode; BOOL end_process = 0; while(!end_process) { switch(*state) { case RESET: { // Step in state machine. *state = WAIT_INIT; // Reset POLL process. l1a_l1s_com.l1s_en_task[POLL] = TASK_DISABLED; // Clear RAACC task enable flag. } break; case WAIT_INIT: { if(SignalCode == MPHP_POLLING_RESPONSE_REQ) // Polling response request for access procedure. //----------------------------------------------- { UWORD8 i; // Init POLL process. l1pa_l1ps_com.poll_info.pol_resp_type = ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->pol_resp_type; l1pa_l1ps_com.poll_info.fn = ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->fn; // TXPWR value supplied by L3 is the max. TX power level the MS may use in the given band l1s.applied_txpwr = ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->txpwr; // 1 RLC/MAC block is sent: // This is a special case, only possible if the MS has a valid TA available from a pending // assignment and is pooled for an RLC/MAC block. if (l1pa_l1ps_com.poll_info.pol_resp_type == CS1_TYPE_POLL) { for (i=0; i<24; i++) { // download 24 bytes from message l1pa_l1ps_com.poll_info.chan_req.cs1_data[i] = ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->channel_request_data[i]; } l1pa_l1ps_com.poll_info.timing_advance = ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->timing_advance; // Store MAX TXPWR value to be used for first POLL RESPONSE // if not already done by Packet Access process... for(i = 0; i < 8; i++) { l1pa_l1ps_com.transfer.dl_pwr_ctrl.txpwr[i] = l1s.applied_txpwr; } } // 4 identical PRACH are sent else { // UWORD16 = data[1]<<8 | data[0] l1pa_l1ps_com.poll_info.chan_req.prach_data[0] = ((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->channel_request_data[0]; l1pa_l1ps_com.poll_info.chan_req.prach_data[0] |= (((T_MPHP_POLLING_RESPONSE_REQ *)(msg->SigP))->channel_request_data[1] << 8); l1pa_l1ps_com.poll_info.timing_advance = 0; } // step in state machine. *state = WAIT_RESULT; // Change mode to connection establishment part 1. l1a_l1s_com.mode = CON_EST_MODE1; // Activate POLL task (no semaphore for UL tasks). // Enable Paging Reorg and Normal paging tasks. l1a_l1s_com.l1s_en_task[POLL] = TASK_ENABLED; // Set PRACH task enable flag. } // end of process. end_process = 1; } break; case WAIT_RESULT: { if(SignalCode == L1P_POLL_DONE) // Random access acqnowledge message. //----------------------------------- { // Forward result message to L3. l1a_send_result(MPHP_POLLING_IND, msg, GRRM1_QUEUE); // Change mode to connection establishment part 2. l1a_l1s_com.mode = CON_EST_MODE2; // This state machine has to be reset *state = RESET; // end of process. end_process = 1; } else // No action in this machine for other messages. //---------------------------------------------- { // End of process. end_process = 1; } } break; } // end of "switch". } // end of "while" } // end of procedure. /*-------------------------------------------------------*/ /* l1pa_transfer_process() */ /*-------------------------------------------------------*/ /* Description: */ /* ------------ */ /* */ /* Starting messages: */ /* ------------------ */ /* */ /* Subsequent messages: */ /* -------------------- */ /* */ /* Result messages (input): */ /* ------------------------ */ /* */ /* Result messages (output): */ /* ------------------------- */ /* */ /* Reset messages (input): */ /* ----------------------- */ /* */ /*-------------------------------------------------------*/ void l1pa_transfer_process(xSignalHeaderRec *msg) { enum states { RESET = 0, WAIT_MSG = 1 }; UWORD8 *state = &l1pa.state[TRANSFER]; UWORD32 SignalCode = msg->SignalCode; BOOL end_process = 0; while(!end_process) { switch(*state) { case RESET: { // Step in state machine. *state = WAIT_MSG; // Rise transfert parameter semaphore. l1pa_l1ps_com.transfer.semaphore = TRUE; } break; case WAIT_MSG: { switch(SignalCode) // switch on input message. //------------------------- { case MPHP_SINGLE_BLOCK_REQ: // Repeat fixed allocation. //------------------------- { T_TRANSFER_SET *free_set; UWORD8 purpose; UWORD8 i; // Rise transfert parameter semaphore to prevent L1S to use partial configuration. l1pa_l1ps_com.transfer.semaphore = TRUE; purpose = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->purpose; // Get Ptr to the free dedicated parameter set. // All important fields are initialised. free_set = l1pa_get_free_transfer_set(purpose); // Fill Transfer mode generic parameters. free_set->assignment_id = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->assignment_id; free_set->assignment_command = purpose; free_set->allocated_tbf = purpose; free_set->packet_ta = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->packet_ta; if((purpose == SINGLE_BLOCK_DL)||(purpose == SINGLE_BLOCK_UL)) { free_set->packet_ta.ta_index = 255; free_set->packet_ta.ta_tn = 255; } free_set->dl_pwr_ctl = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->dl_pwr_ctl; if (free_set->dl_pwr_ctl.p0 != 255) free_set->dl_pwr_ctl.p0 <<= 2; // P0 format 7.1 free_set->tsc = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->tsc; free_set->freq_param = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->freq_param; free_set->tbf_sti = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->tbf_sti; free_set->pc_meas_chan = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->pc_meas_chan; // Download access_burst_type l1pa_l1ps_com.transfer.psi_param.access_burst_type = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->access_burst_type; // Keep the same Pb factor l1pa_l1ps_com.transfer.psi_param.Scell_pb = l1a_l1s_com.Scell_info.pb; // Enable PSI param updating in order to update access_burst_type in L1S l1pa_l1ps_com.transfer.psi_param.psi_param_update_cmd = TRUE; // Fill single block specific parameters. for(i=0;i<23;i++) { l1pa_l1ps_com.transfer.single_block.data_array[i] = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->data_array[i]; } l1pa_l1ps_com.transfer.single_block.tn = ((T_MPHP_SINGLE_BLOCK_REQ *)(msg->SigP))->timeslot_number; l1pa_l1ps_com.transfer.single_block.dl_tn_to_restore = l1a_l1s_com.dl_tn; // Fill "synchro_timeslot" which will be the frame synchro slot. free_set->ul_tbf_synchro_timeslot = l1pa_l1ps_com.transfer.single_block.tn; free_set->transfer_synchro_timeslot = l1pa_l1ps_com.transfer.single_block.tn; // Step in state machine. *state = WAIT_MSG; // Store signalcode. free_set->SignalCode = MPHP_SINGLE_BLOCK_REQ; // Clear transfer parameter semaphore to let L1S use the new parameters. l1pa_l1ps_com.transfer.semaphore = FALSE; // end of process. end_process = 1; } break; case MPHP_ASSIGNMENT_REQ: // Assignement message. //--------------------- { static int count =0; T_TRANSFER_SET *free_set; UWORD8 assignment_command; UWORD8 timeslot_alloc; UWORD8 timeslot; /* TCS211 reconstruction, =0 in TCS3 */ // TBF_changes #if FF_TBF BOOL pseudo_tbf_two_phase_acc; // Special case for two phase access (single or multi allocation): // It is handled as a pseudo UL TBF using a fixed allocation. // Still needs to be flagged to preempt TBF establishment switch in // transfer manager. if (((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->assignment_command == TWO_PHASE_ACCESS) { ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->assignment_command = UL_TBF; pseudo_tbf_two_phase_acc = TRUE; } else pseudo_tbf_two_phase_acc = FALSE; #endif count++ ; // Rise transfert parameter semaphore to prevent L1S to use partial configuration. l1pa_l1ps_com.transfer.semaphore = TRUE; assignment_command = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->assignment_command; // Get Ptr to the free dedicated parameter set. // All important fields are initialised. free_set = l1pa_get_free_transfer_set(assignment_command); // Download message containt. free_set->assignment_id = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->assignment_id; free_set->assignment_command = assignment_command; free_set->multislot_class = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->multislot_class; free_set->dl_pwr_ctl = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->dl_pwr_ctl; if (free_set->dl_pwr_ctl.p0 != 255) free_set->dl_pwr_ctl.p0 <<= 2; // P0 format 7.1 free_set->packet_ta = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->packet_ta; free_set->tsc = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->tsc; free_set->freq_param = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->freq_param; free_set->mac_mode = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->mac_mode; free_set->tbf_sti = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->tbf_sti; free_set->interf_meas_enable = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->interf_meas_enable; free_set->pc_meas_chan = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->pc_meas_chan; // TBF_changes #if FF_TBF // Two phase access condition is stored in FSET structure to be // transfered in ASET for transfer mode manager use. free_set->pseudo_tbf_two_phase_acc = pseudo_tbf_two_phase_acc; #endif // Download access_burst_type l1pa_l1ps_com.transfer.psi_param.access_burst_type = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->access_burst_type; // Keep the same Pb factor l1pa_l1ps_com.transfer.psi_param.Scell_pb = l1a_l1s_com.Scell_info.pb; // Enable PSI param updating in order to update access_burst_type in L1S l1pa_l1ps_com.transfer.psi_param.psi_param_update_cmd = TRUE; switch(assignment_command) { case DL_TBF: { free_set->dl_tbf_alloc = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->dl_ressource_alloc; if((free_set->allocated_tbf == UL_TBF) || (free_set->allocated_tbf == BOTH_TBF)) free_set->allocated_tbf = BOTH_TBF; else free_set->allocated_tbf = DL_TBF; // Look for 1st allocated timeslot. // MSB=TS0...LSB=TS7 timeslot_alloc = free_set->dl_tbf_alloc.timeslot_alloc; timeslot = 0; while((timeslot<7) && !(timeslot_alloc & (0x80>>timeslot))) { timeslot++; } // Fill "synchro_timeslot" which will be the frame synchro slot. free_set->dl_tbf_synchro_timeslot = timeslot; free_set->transfer_synchro_timeslot = timeslot; } break; case UL_TBF: { *(free_set->ul_tbf_alloc) = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->ul_ressource_alloc; if((free_set->allocated_tbf == DL_TBF) || (free_set->allocated_tbf == BOTH_TBF)) free_set->allocated_tbf = BOTH_TBF; else free_set->allocated_tbf = UL_TBF; // Look for 1st allocated timeslot. // MSB=TS0...LSB=TS7 // Dynamic mode: the uplink PDCH are always monitored // The 1st allocated timeslot is a RX on the lowest numbered // timeslot allocated in uplink #if L1_EDA if((free_set->mac_mode == DYN_ALLOC) || (free_set->mac_mode == EXT_DYN_ALLOC)) #else if(free_set->mac_mode == DYN_ALLOC) #endif { timeslot_alloc = free_set->ul_tbf_alloc->timeslot_alloc; timeslot = 0; while((timeslot<7) && !(timeslot_alloc & (0x80>>timeslot))) { timeslot++; } } else // Fixed mode: the 1st allocated timeslot is the downlink control // timeslot allocated by the network, which is a timeslot allocated // in uplink if(free_set->mac_mode == FIX_ALLOC_NO_HALF) { timeslot = free_set->ul_tbf_alloc->fixed_alloc.ctrl_timeslot; } // Fill "synchro_timeslot" which will be the frame synchro slot. free_set->ul_tbf_synchro_timeslot = timeslot; free_set->transfer_synchro_timeslot = timeslot; } break; case BOTH_TBF: { free_set->dl_tbf_alloc = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->dl_ressource_alloc; *(free_set->ul_tbf_alloc) = ((T_MPHP_ASSIGNMENT_REQ *)(msg->SigP))->ul_ressource_alloc; free_set->allocated_tbf = BOTH_TBF; // Process the downlink TBF first allocated timeslot timeslot_alloc = free_set->dl_tbf_alloc.timeslot_alloc; timeslot = 0; while((timeslot<7) && !(timeslot_alloc & (0x80>>timeslot))) { timeslot++; } free_set->dl_tbf_synchro_timeslot = timeslot; // Process the uplink TBF first allocated timeslot // Dynamic mode: the uplink PDCH are always monitored // The 1st allocated timeslot is a RX on the lowest numbered // timeslot allocated in uplink #if L1_EDA if((free_set->mac_mode == DYN_ALLOC) || (free_set->mac_mode == EXT_DYN_ALLOC)) #else if(free_set->mac_mode == DYN_ALLOC) #endif { timeslot_alloc = free_set->ul_tbf_alloc->timeslot_alloc; timeslot = 0; while((timeslot<7) && !(timeslot_alloc & (0x80>>timeslot))) { timeslot++; } } else // Fixed mode: the 1st allocated timeslot is the downlink control // timeslot allocated by the network, which is a timeslot allocated // in uplink if(free_set->mac_mode == FIX_ALLOC_NO_HALF) { timeslot = free_set->ul_tbf_alloc->fixed_alloc.ctrl_timeslot; } free_set->ul_tbf_synchro_timeslot = timeslot; // Fill "synchro_timeslot" which will be the frame synchro slot. if (free_set->dl_tbf_synchro_timeslot > free_set->ul_tbf_synchro_timeslot) { free_set->transfer_synchro_timeslot = free_set->ul_tbf_synchro_timeslot; } else { free_set->transfer_synchro_timeslot = free_set->dl_tbf_synchro_timeslot; } } break; } // Cancel any pending release on the assigned TBF if (l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd == TRUE) { // If pending released TBF = assigned TBF or assigned TBF = BOTH if ((assignment_command == l1pa_l1ps_com.transfer.tbf_release_param.released_tbf) || (assignment_command == BOTH_TBF)) { /* * FreeCalypso TCS211 reconstruction: in the LoCosto version * the call to l1pa_send_tbl_release_con() came first, * but in the TCS211 object it comes after the two * assignments. */ // Cancel the TBF release order l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd = FALSE; l1pa_l1ps_com.transfer.tbf_release_param.released_tbf = NO_TBF; // Send a "TBF Release confirmation" msg to L3 : CQ 46842 l1pa_send_tbf_release_con(MPHP_TBF_RELEASE_CON,l1pa_l1ps_com.transfer.tbf_release_param.released_tbf); } // If BOTH TBF release order pending and no BOTH TBF assigned else if (l1pa_l1ps_com.transfer.tbf_release_param.released_tbf == BOTH_TBF) { // Keep the release of the TBF which is not assigned by this message if (assignment_command == DL_TBF) l1pa_l1ps_com.transfer.tbf_release_param.released_tbf = UL_TBF; else l1pa_l1ps_com.transfer.tbf_release_param.released_tbf = DL_TBF; } } // Step in state machine. *state = WAIT_MSG; // Store signalcode. free_set->SignalCode = MPHP_ASSIGNMENT_REQ; // Clear transfer parameter semaphore to let L1S use the new parameters. l1pa_l1ps_com.transfer.semaphore = FALSE; // end of process. end_process = 1; } break; case L1P_TRANSFER_DONE: // Switch to TRANSFER mode has been done. Send a Assignment confirmation // msg to L3. { l1pa_send_confirmation(MPHP_ASSIGNMENT_CON, ((T_L1P_TRANSFER_DONE *) msg->SigP)->assignment_id); // End of process. end_process = 1; } break; case MPHP_TBF_RELEASE_REQ: // TBF Release. //------------- { UWORD8 i; // Rise transfert parameter semaphore to prevent L1S to use partial configuration. l1pa_l1ps_com.transfer.semaphore = TRUE; // Cumulate with a possible TBF release request received during the same block period if (l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd == TRUE) { if (l1pa_l1ps_com.transfer.tbf_release_param.released_tbf != ((T_MPHP_TBF_RELEASE_REQ *)(msg->SigP))->tbf_type) { l1pa_l1ps_com.transfer.tbf_release_param.released_tbf = BOTH_TBF; } } else { // Enables the TBF release processing in L1S. l1pa_l1ps_com.transfer.tbf_release_param.tbf_release_cmd = TRUE; // Download msg info into L1PA_L1PS_COM. l1pa_l1ps_com.transfer.tbf_release_param.released_tbf = ((T_MPHP_TBF_RELEASE_REQ *)(msg->SigP))->tbf_type; } // Disable all pending TBFs those type is the same as the released TBF for(i = 0; i < 2; i++) { // Pending assignment if (l1pa_l1ps_com.transfer.fset[i]->SignalCode == MPHP_ASSIGNMENT_REQ) { #if !FF_TBF switch(l1pa_l1ps_com.transfer.tbf_release_param.released_tbf) #else UWORD8 released_tbf; // Special case if we got a request to release a two phase access TBF: // It is registered within FSET structure as an uplink TBF. If current // structure is pseudo TBF for two phase access, we process the request // like an uplink release, otherwise we skip it. released_tbf = l1pa_l1ps_com.transfer.tbf_release_param.released_tbf; if (released_tbf == TWO_PHASE_ACCESS) { if (l1pa_l1ps_com.transfer.fset[i]->pseudo_tbf_two_phase_acc) released_tbf = UL_TBF; else released_tbf = NO_TBF; } switch(released_tbf) #endif // FF_TBF { case UL_TBF: { if (l1pa_l1ps_com.transfer.fset[i]->allocated_tbf == UL_TBF) { l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF; l1pa_l1ps_com.transfer.fset[i]->SignalCode = NULL; } if (l1pa_l1ps_com.transfer.fset[i]->allocated_tbf == BOTH_TBF) { l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = DL_TBF; } } break; case DL_TBF: { if (l1pa_l1ps_com.transfer.fset[i]->allocated_tbf == DL_TBF) { l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF; l1pa_l1ps_com.transfer.fset[i]->SignalCode = NULL; } if (l1pa_l1ps_com.transfer.fset[i]->allocated_tbf == BOTH_TBF) { l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = UL_TBF; } } break; case BOTH_TBF: { l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF; l1pa_l1ps_com.transfer.fset[i]->SignalCode = NULL; } break; } // End of switch "tbf_release" } // End if SignalCode = MPHP_ASSIGNMENT_REQ or MPHP_REPEAT_UL_FIXED_ALLOC } // End "for" // Clear transfer parameter semaphore to let L1S use the new parameters. l1pa_l1ps_com.transfer.semaphore = FALSE; // end of process. end_process = 1; } break; case L1P_TBF_RELEASED: // TBF has been release by L1S. Send a "TBF Release confirmation" // msg to L3 { // Send confirmation message to L3. l1pa_send_tbf_release_con(MPHP_TBF_RELEASE_CON,((T_L1P_TBF_RELEASED *)(msg->SigP))->tbf_type); // End of process. end_process = 1; } break; case MPHP_STOP_SINGLE_BLOCK_REQ: // Stop SINGLE block activity. //---------------------------- { UWORD8 i; // Rise transfert parameter semaphore to prevent L1S to use partial configuration. l1pa_l1ps_com.transfer.semaphore = TRUE; // Disable SINGLE task. l1a_l1s_com.l1s_en_task[SINGLE] = TASK_DISABLED; // No more TBF... // Disable PDTCH task. l1a_l1s_com.l1s_en_task[PDTCH] = TASK_DISABLED; // Disable PTCCH task. l1a_l1s_com.l1s_en_task[PTCCH] = TASK_DISABLED; // Free the active set. l1pa_l1ps_com.transfer.aset->allocated_tbf = NO_TBF; // Send confirmation message to L3. l1a_send_confirmation(MPHP_STOP_SINGLE_BLOCK_CON,GRRM1_QUEUE); // disable all pending TBF those type is a single block for(i = 0; i < 2; i++) { // check for pending single block req (MPHP_SINGLE_BLOCK_REQ) if (l1pa_l1ps_com.transfer.fset[i]->SignalCode == MPHP_SINGLE_BLOCK_REQ) { // disable the fset corresponding to single blocks l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF; l1pa_l1ps_com.transfer.fset[i]->SignalCode = NULL; } } // This process must be reset. *state = RESET; // end of process. end_process = 1; } break; case MPHP_PDCH_RELEASE_REQ: // PDCH Release. //-------------- { // Rise transfert parameter semaphore to prevent L1S to use partial configuration. l1pa_l1ps_com.transfer.semaphore = TRUE; // Enables the PDCH release processing in L1S. l1pa_l1ps_com.transfer.pdch_release_param.pdch_release_cmd = TRUE; // Download msg info into L1PA_L1PS_COM. l1pa_l1ps_com.transfer.pdch_release_param.timeslot_available = ((T_MPHP_PDCH_RELEASE_REQ *)(msg->SigP))->timeslot_available; l1pa_l1ps_com.transfer.pdch_release_param.assignment_id = ((T_MPHP_PDCH_RELEASE_REQ *)(msg->SigP))->assignment_id; // Clear transfer parameter semaphore to let L1S use the new parameters. l1pa_l1ps_com.transfer.semaphore = FALSE; // end of process. end_process = 1; } break; case L1P_PDCH_RELEASED: // PDCHs have been release by L1S. Send a "PDCH Release confirmation" // msg to L3 { // Send confirmation message to L3. l1pa_send_confirmation(MPHP_PDCH_RELEASE_CON, ((T_L1P_PDCH_RELEASE_CON *) msg->SigP)->assignment_id); // End of process. end_process = 1; } break; case MPHP_TIMING_ADVANCE_REQ: // TA configuration. //------------------ { // Rise transfert parameter semaphore to prevent L1S to use partial configuration. l1pa_l1ps_com.transfer.semaphore = TRUE; // Enables the timing advance update in L1S. l1pa_l1ps_com.transfer.ptcch.ta_update_cmd = TRUE; // Download message content. l1pa_l1ps_com.transfer.ptcch.packet_ta = ((T_MPHP_TIMING_ADVANCE_REQ *)(msg->SigP))->packet_ta; l1pa_l1ps_com.transfer.ptcch.assignment_id = ((T_MPHP_TIMING_ADVANCE_REQ *)(msg->SigP))->assignment_id; // Clear transfer parameter semaphore to let L1S use the new parameters. l1pa_l1ps_com.transfer.semaphore = FALSE; // end of process. end_process = 1; } break; case L1P_TA_CONFIG_DONE: // TA configuration done. //----------------------- { // Send confirmation message to L3. l1pa_send_confirmation(MPHP_TIMING_ADVANCE_CON, ((T_MPHP_TIMING_ADVANCE_CON *) msg->SigP)->assignment_id); // end of process. end_process = 1; } break; case MPHP_UPDATE_PSI_PARAM_REQ: // Update PSI Parameters. //---------------------- { // Download msg content l1pa_l1ps_com.transfer.psi_param.Scell_pb = ((T_MPHP_UPDATE_PSI_PARAM_REQ *)(msg->SigP))->pb << 2; // Pb format 7.1 l1pa_l1ps_com.transfer.psi_param.access_burst_type = ((T_MPHP_UPDATE_PSI_PARAM_REQ *)(msg->SigP))->access_burst_type; l1pa_l1ps_com.transfer.psi_param.psi_param_update_cmd = TRUE; // send confirmation message l1a_send_confirmation(MPHP_UPDATE_PSI_PARAM_CON,GRRM1_QUEUE); // end of process. end_process = 1; } break; case L1P_PACCH_INFO: // Two Phase Access is ongoing: Packet Resource Request // msg has been sent to the network. CCCH reading must be // stopped to let PDCH reading going. //-------------------------------------------------------- { // Forward result message to RR. l1a_send_result(MPHP_DATA_IND, msg, GRRM1_QUEUE); // end of process. end_process = 1; } break; case L1P_SINGLE_BLOCK_CON: // Two Phase Access is ongoing: Packet Resource Request // msg has been sent to the network. CCCH reading must be // stopped to let PDCH reading going. //-------------------------------------------------------- { // Forward result message to RR. l1a_send_result(MPHP_SINGLE_BLOCK_CON, msg, GRRM1_QUEUE); // This process must be reset. *state = RESET; // end of process. end_process = 1; } break; case MPHP_REPEAT_UL_FIXED_ALLOC_REQ: // Repeat uplink fixed mode allocation bitmap //------------------------------------------- { // Rise transfert parameter semaphore to prevent L1S to use partial configuration. l1pa_l1ps_com.transfer.semaphore = TRUE; // If an UL TBF is running... if ((l1pa_l1ps_com.transfer.aset->allocated_tbf == UL_TBF) || (l1pa_l1ps_com.transfer.aset->allocated_tbf == BOTH_TBF)) { // Download info. from message l1pa_l1ps_com.transfer.repeat_alloc = *((T_MPHP_REPEAT_UL_FIXED_ALLOC_REQ *) msg->SigP); } // Send confirmation if this message was a repeat allocation cancelling if (!((T_MPHP_REPEAT_UL_FIXED_ALLOC_REQ *) msg->SigP)->repeat_allocation) { l1a_send_confirmation(MPHP_REPEAT_UL_FIXED_ALLOC_CON,GRRM1_QUEUE); } else { UWORD8 i; // Disable all pending UL TBF for(i = 0; i < 2; i++) { // Pending assignment if (l1pa_l1ps_com.transfer.fset[i]->SignalCode == MPHP_ASSIGNMENT_REQ) { switch(l1pa_l1ps_com.transfer.fset[i]->allocated_tbf) { // Remove pending UL TBF case UL_TBF: { l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = NO_TBF; l1pa_l1ps_com.transfer.fset[i]->SignalCode = NULL; } break; // Change pending BOTH_TBF in pending DL_TBF case BOTH_TBF: { l1pa_l1ps_com.transfer.fset[i]->allocated_tbf = DL_TBF; } break; } // End of switch "allocated_tbf" } // End if SignalCode = MPHP_ASSIGNMENT_REQ } // End "for" } // Clear transfer parameter semaphore to let L1S use the new parameters. l1pa_l1ps_com.transfer.semaphore = FALSE; // end of process. end_process = 1; } break; case L1P_REPEAT_ALLOC_DONE: { // Send confirmation message to L3. l1a_send_confirmation(MPHP_REPEAT_UL_FIXED_ALLOC_CON,GRRM1_QUEUE); // end of process. end_process = 1; } break; default: // End of process. //---------------- { return; } } // end of switch(SignalCode) } // end of case WAIT_CONFIG. } // end of "switch". } // end of "while" } // end of procedure. /*-------------------------------------------------------*/ /* l1pa_serving_cell_pbcch_read_process() */ /*-------------------------------------------------------*/ /* Description : This state machine handles Packet */ /* serving cell PBCCH reading. */ /* */ /* Starting messages: MPHP_SCELL_PBCCH_REQ */ /* ------------------ */ /* */ /* L1 continuously reads the serving cell PBCCH */ /* as requested by the scheduling info (PSI1 repeat */ /* period and relative position. */ /* */ /* Result messages (input): L1C_PBCCHS_INFO */ /* ------------------------ */ /* System information data block from L1S. */ /* */ /* Reset messages (input): MPHP_SCELL_PBCCH_STOP_REQ */ /* ----------------------- */ /* */ /*-------------------------------------------------------*/ void l1pa_serving_cell_pbcch_read_process(xSignalHeaderRec *msg) { enum states { RESET = 0, WAIT_PBCCHS_CONFIG = 1, WAIT_PBCCHS_RESULT = 2, PBCCHS_CONFIG = 3 }; UWORD8 *state = &l1pa.state[SCPB]; UWORD32 SignalCode = msg->SignalCode; #define PbcchS l1pa_l1ps_com.pbcchs BOOL end_process = 0; while(!end_process) { switch(*state) { case RESET: { // Step in state machine. *state = WAIT_PBCCHS_CONFIG; // Reset PBCCHS process. l1a_l1s_com.l1s_en_task[PBCCHS] = TASK_DISABLED; // Clear PBCCHS task enable flag. } break; case WAIT_PBCCHS_CONFIG: { // Request to read Normal BCCH from serving cell. if(SignalCode == MPHP_SCELL_PBCCH_REQ) { #define MAX_PSI1_PERIOD 16 UWORD8 i; // Set semaphores for Serving Cell PBCCH reading task. l1a_l1s_com.task_param[PBCCHS] = SEMAPHORE_SET; // Download message content. //-------------------------- PbcchS.nbr_psi = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->nbr_psi; PbcchS.bs_pbcch_blks = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->bs_pbcch_blks; PbcchS.packet_chn_desc = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->packet_chn_desc; PbcchS.frequency_list = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->frequency_list; l1a_l1s_com.Scell_info.pb = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->pb << 2; // Pb format 7.1 PbcchS.psi1_repeat_period = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->psi1_repeat_period; // PBCCH Period is: MF52 * psi1_repeat_period PbcchS.pbcch_period = 52L * PbcchS.psi1_repeat_period; if(PbcchS.nbr_psi == 0) // Full PBCCH reading: Emulated throw "relative positions". //--------------------------------------------------------- { // Emulate full PBCCH reading throw "relative positions" and a repeat period // of 1 MF52. // bs_pbcch_blks= 0 -> Read B0 // bs_pbcch_blks= 1 -> Read B0,B6 // bs_pbcch_blks= 2 -> Read B0,B6,B3 // bs_pbcch_blks= 3 -> Read B0,B6,B3,B9 PbcchS.nbr_psi = PbcchS.bs_pbcch_blks+1; PbcchS.read_all_psi = TRUE; for(i=0;i<PbcchS.nbr_psi;i++) { ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->relative_position_array[i] = i; } } else // PBCCH reading: use provided "relative positions". //-------------------------------------------------- { PbcchS.read_all_psi = FALSE; } // Compute FN offset for each PSI. //-------------------------------- for(i=0;i<l1pa_l1ps_com.pbcchs.nbr_psi;i++) { WORD8 nbr_mf52; // Range 0..MAX_PSI1_PERIOD (can be negative along its estimation) UWORD8 nbr_rest; // Range 0..3 UWORD8 relative_position; // Range 0..4*MAX_PSI1_PERIOD UWORD8 psi_period; // psi1_repeat_period = 1 if nbr_psi = 0 relative_position = ((T_MPHP_SCELL_PBCCH_REQ *)(msg->SigP))->relative_position_array[i]; nbr_mf52 = relative_position / (PbcchS.bs_pbcch_blks+1); nbr_rest = relative_position % (PbcchS.bs_pbcch_blks+1); // Block B0 is a special case since CTRL phase occurs during // the MF52 before. if(nbr_rest == 0) { nbr_mf52 -= 1; // Set psi_period to 1 when all PSI have to be read (nbr_psi = 0) if(PbcchS.read_all_psi) psi_period = 1; else psi_period = PbcchS.psi1_repeat_period; if(nbr_mf52 < 0) nbr_mf52 += psi_period; } PbcchS.offset_array[i] = (nbr_mf52 * 52L) + PBCCH_POSITION[PbcchS.bs_pbcch_blks][nbr_rest]; PbcchS.relative_position_array[i] = relative_position; } // Step in state machine. *state = PBCCHS_CONFIG; } // No action in this machine for other messages. else { // End of process. return; } } break; case PBCCHS_CONFIG: { WORD8 tn_pbcch; // If PBCCH TS is inferior to L1 synchronization TS, the PBCCH reading // control must be done one frame in advance if (PbcchS.packet_chn_desc.timeslot_no < l1a_l1s_com.dl_tn) PbcchS.control_offset = TRUE; else PbcchS.control_offset = FALSE; // Set "change_synchro" flag to trigger L1S to change the synchro on fly // within PBCCHS and to restore current synchro when PBCCHS task is completed. if(((PbcchS.packet_chn_desc.timeslot_no - l1a_l1s_com.dl_tn + 8) % 8) >=4) { // L1S will make a intra PBCCHS task synchro to current TS + 4. PbcchS.change_synchro = TRUE; tn_pbcch = PbcchS.packet_chn_desc.timeslot_no - l1a_l1s_com.dl_tn - 4; } else { // L1S will NOT make the intra PBCCHS task synchro. PbcchS.change_synchro = FALSE; tn_pbcch = PbcchS.packet_chn_desc.timeslot_no - l1a_l1s_com.dl_tn; } if(tn_pbcch < 0) PbcchS.tn_pbcch = tn_pbcch + 8; else PbcchS.tn_pbcch = tn_pbcch; // Enable PBCCHS task. l1a_l1s_com.l1s_en_task[PBCCHS] = TASK_ENABLED; // Step in state machine. *state = WAIT_PBCCHS_RESULT; // End of process. end_process = 1; } break; case WAIT_PBCCHS_RESULT: { if(SignalCode == L1P_PBCCHS_INFO) // Serving cell BCCH reading result. //---------------------------------- { // Forward result message to L3. l1a_send_result(MPHP_DATA_IND, msg, GRRM1_QUEUE); // End of process. return; } else if(SignalCode == MPHP_SCELL_PBCCH_REQ) // Request to re-configure PBCCH reading. //-------------------------------------- { // Step in state machine. *state = WAIT_PBCCHS_CONFIG; } else if(SignalCode == MPHP_SCELL_PBCCH_STOP_REQ) // Request to STOP any serving cell pbcch activity. //------------------------------------------------ { // Send confirmation message to L3. l1a_send_confirmation(MPHP_SCELL_PBCCH_STOP_CON,GRRM1_QUEUE); // This process must be reset. *state = RESET; } else // End of packet transfer mode: test PDTCH to be sure that TBF downlink and uplink are released if((SignalCode == L1P_TBF_RELEASED) && (((T_L1P_TBF_RELEASED *)(msg->SigP))->released_all)) { // This process must be reset. *state = RESET; } else if ((SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1P_TBF_RELEASED) || //change of Time Slot (SignalCode == L1P_REPEAT_ALLOC_DONE) || (SignalCode == L1P_ALLOC_EXHAUST_DONE)) { // Clear PBCCHS task enable flag. l1a_l1s_com.l1s_en_task[PBCCHS] = TASK_DISABLED; // Set semaphores for Serving Cell PBCCH reading task. l1a_l1s_com.task_param[PBCCHS] = SEMAPHORE_SET; // l1a_l1s_com.dl_tn was changed. Check if a change synchro is needed *state = PBCCHS_CONFIG; // Step in state machine. } else // No action in this machine for other messages. //---------------------------------------------- { // End of process. return; } } break; } // end of "switch". } // end of "while" } // end of procedure. /*-------------------------------------------------------*/ /* l1pa_neighbor_cell_pbcch_read_process() */ /*-------------------------------------------------------*/ /* Description : This state machine handles Packet */ /* neighbor cell PBCCH reading. */ /* */ /* Starting messages: MPHP_NCELL_PBCCH_REQ */ /* ------------------ */ /* */ /* L1 continuously reads the neighbor cell PBCCH */ /* as requested by the scheduling info (PSI1 repeat */ /* period and relative position. */ /* */ /* Result messages (input): L1C_PBCCHN_INFO */ /* ------------------------ */ /* System information data block from L1S. */ /* */ /* Reset messages (input): MPHP_NCELL_PBCCH_STOP_REQ */ /* ----------------------- */ /* */ /*-------------------------------------------------------*/ void l1pa_neighbor_cell_pbcch_read_process(xSignalHeaderRec *msg) { enum states { RESET = 0, WAIT_PBCCHN_CONFIG = 1, WAIT_PBCCHN_RESULT = 2, PBCCHN_CONFIG = 3 }; UWORD8 *state = &l1pa.state[NCPB]; UWORD32 SignalCode = msg->SignalCode; #define PbcchN l1pa_l1ps_com.pbcchn static WORD32 fn_offset_mem; static WORD32 time_alignmt_mem; BOOL end_process = 0; while(!end_process) { switch(*state) { case RESET: { // Step in state machine. *state = WAIT_PBCCHN_CONFIG; // Reset PBCCHS process. l1a_l1s_com.l1s_en_task[PBCCHN_IDLE] = TASK_DISABLED; // Clear PBCCHN task enable flag used in IDLE mode l1a_l1s_com.l1s_en_task[PBCCHN_TRAN] = TASK_DISABLED; // Clear PBCCHN task enable flag used in Transfer Packet mode } break; case WAIT_PBCCHN_CONFIG: { // Request to read Normal PBCCH from neighbor cell. if(SignalCode == MPHP_NCELL_PBCCH_REQ) { #define MAX_PSI1_PERIOD 16 // Set semaphores for Neighbor Cell PBCCH reading task. l1a_l1s_com.task_param[PBCCHN_IDLE] = SEMAPHORE_SET; l1a_l1s_com.task_param[PBCCHN_TRAN] = SEMAPHORE_SET; // Download message content. //-------------------------- PbcchN.bcch_carrier = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->bcch_carrier; PbcchN.bs_pbcch_blks = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->bs_pbcch_blks; PbcchN.packet_chn_desc = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->packet_chn_desc; PbcchN.frequency_list = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->frequency_list; PbcchN.psi1_repeat_period = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->psi1_repeat_period; PbcchN.relative_position = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->relative_position; fn_offset_mem = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->fn_offset; time_alignmt_mem = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->time_alignment; PbcchN.pb = ((T_MPHP_NCELL_PBCCH_REQ *)(msg->SigP))->pb << 2; // Pb format 7.1 // PBCCH Period is: MF52 * psi1_repeat_period PbcchN.pbcch_period = 52L * PbcchN.psi1_repeat_period; // Compute FN offset. //------------------ { WORD8 nbr_mf52; // Range 0..MAX_PSI1_PERIOD (can be negative along its estimation) UWORD8 nbr_rest; // Range 0..3 UWORD8 relative_position; // Range 0..4*MAX_PSI1_PERIOD relative_position = PbcchN.relative_position; // number of PBCCH blocs nbr_mf52 = relative_position / (PbcchN.bs_pbcch_blks+1); nbr_rest = relative_position % (PbcchN.bs_pbcch_blks+1); // Block B0 is a special case since CTRL phase occurs during the MF52 before. if(nbr_rest == 0) { nbr_mf52 -= 1; if(nbr_mf52 < 0) nbr_mf52 += PbcchN.psi1_repeat_period; } PbcchN.offset = (nbr_mf52 * 52L) + PBCCH_POSITION[PbcchN.bs_pbcch_blks][nbr_rest]; // In case of idle mode if (l1a_l1s_com.mode != PACKET_TRANSFER_MODE) { PbcchN.offset -= 2 ; // because of the 2 frames for the measurement windows // note: PbcchN.offset can not be negative (PbcchN.offset > 12). } } // Step in state machine. *state = PBCCHN_CONFIG; } // No action in this machine for other messages. else { // End of process. return; } } break; case PBCCHN_CONFIG: { //================================================================================== // choose a relative base time in the neighbor cell in order to simplify the L1S scheduling. //================================================================================== PbcchN.fn_offset = fn_offset_mem; PbcchN.time_alignmt = time_alignmt_mem; //the new relative base time is set in order to have the Neighbor burst in position 0. //update with the burts position of the neighor cell : PbcchN.packet_chn_desc.timeslot_no //update according to the current serving cell synchro : l1a_l1s_com.dl_tn PbcchN.time_alignmt += (PbcchN.packet_chn_desc.timeslot_no - l1a_l1s_com.dl_tn ) * TN_WIDTH; // PbcchN.time_alignmt is in [-7TS..+16TS[. // more than 1 frame between the serving cell and the neighbor burst if ( PbcchN.time_alignmt >= 8*TN_WIDTH) { PbcchN.time_alignmt -= 8*TN_WIDTH; PbcchN.fn_offset --; } else if ( PbcchN.time_alignmt < 0) { PbcchN.time_alignmt += 8*TN_WIDTH; PbcchN.fn_offset ++; } // Set "change_synchro" flag to trigger L1S to change the synchro on fly // within PBCCHN and to restore current synchro when PBCCHN task is completed. if (PbcchN.time_alignmt >= 4 * TN_WIDTH) { PbcchN.time_alignmt -= 4 * TN_WIDTH; PbcchN.change_synchro = TRUE; } else PbcchN.change_synchro = FALSE; // In case of packet transfer mode if (l1a_l1s_com.mode == PACKET_TRANSFER_MODE) { // Enable Packet Transfer PBCCHN task l1a_l1s_com.l1s_en_task[PBCCHN_TRAN] = TASK_ENABLED; } // in case of Idle mode else { // Enable IDLE PBCCHN task l1a_l1s_com.l1s_en_task[PBCCHN_IDLE] = TASK_ENABLED; } // Step in state machine. *state = WAIT_PBCCHN_RESULT; // End of process. end_process = 1; } break; case WAIT_PBCCHN_RESULT: { if(SignalCode == L1P_PBCCHN_INFO) // Serving cell BCCH reading result. //---------------------------------- { // Forward result message to L3. l1a_send_result(MPHP_NCELL_PBCCH_IND, msg, GRRM1_QUEUE); // This process must be reset. *state = RESET; } else if(SignalCode == MPHP_NCELL_PBCCH_REQ) // Request to re-configure PBCCH reading. //-------------------------------------- { // Step in state machine. *state = WAIT_PBCCHN_CONFIG; } else if(SignalCode == MPHP_NCELL_PBCCH_STOP_REQ) // Request to STOP any serving cell pbcch activity. //------------------------------------------------ { // Send confirmation message to L3. l1a_send_confirmation(MPHP_NCELL_PBCCH_STOP_CON,GRRM1_QUEUE); // This process must be reset. *state = RESET; } else // End of packet transfer mode: test PDTCH to be sure that TBF downlink and uplink are released if((SignalCode == L1P_TBF_RELEASED) && (((T_L1P_TBF_RELEASED *)(msg->SigP))->released_all)) { // This process must be reset. *state = RESET; } else if ((SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1P_TBF_RELEASED) || //change of Time Slot (SignalCode == L1P_REPEAT_ALLOC_DONE) || (SignalCode == L1P_ALLOC_EXHAUST_DONE)) { // We consider only the case: packet Transfer => packet Transfer,the serving TS may be changed // For other cases such as Idle -> Transfer... decision not yet taken. // update the PBCCHN parameters // Clear PBCCHN_TRAN task disable flag. l1a_l1s_com.l1s_en_task[PBCCHN_TRAN] = TASK_DISABLED; // Set semaphores for Neighbor Cell PBCCH reading task. l1a_l1s_com.task_param[PBCCHN_TRAN] = SEMAPHORE_SET; // update the PBCCHN parameters *state = PBCCHN_CONFIG;// Step in state machine. } else // No action in this machine for other messages. //---------------------------------------------- { // End of process. return; } } break; } // end of "switch". } // end of "while" } // end of procedure. /*-------------------------------------------------------*/ /* l1pa_tcr_meas_process() */ /*-------------------------------------------------------*/ /* Description : This state machine handles Neigbor cell */ /* measurement process in Packet Transfer mode. */ /* Measurement are made on a specified frequency list. */ /* The process is started automatically by L1 (on receipt*/ /* of a L1P_TRANSFER_DONE message from L1S) and doesn't */ /* need to receive any message from L3. */ /* In order to update the frequency list, a */ /* MHPC_TCR_MEAS_REQ msg will be sent from L3 to L1 */ /* */ /* Starting messages: L1P_TRANSFER_DONE */ /* ------------------ */ /* L1 starts then measures on carriers specified in the */ /* frequency list. Measures are performed on every */ /* frames with the occurence of 1 measure per frame */ /* */ /* Subsequent messages: MPHP_TCR_MEAS_REQ */ /* -------------------- */ /* The update is not done asap but postponed until the */ /* end of the reporting period. Frequency list is */ /* updated with the new list. */ /* */ /* Result messages (input): L1P_TRANSFER_MEAS_DONE */ /* ------------------------ */ /* This is the periodic reporting message sent by L1S. */ /* The reporting is done every "reporting period". */ /* The beguining of the reporting period is arbitrary */ /* and starts when the Neigh Meas task is enabled. */ /* */ /* Result messages (output): MPHP_TCR_MEAS_IND */ /* ------------------------- */ /* This is the periodic reporting message to L3. */ /* */ /* Reset messages (input): MPHP_TCR_MEAS_STOP_REQ */ /* ----------------------- */ /* Frequency list neigbor cell measurement process in */ /* Packet Transfer mode is stopped by this message. */ /* */ /*-------------------------------------------------------*/ void l1pa_tcr_meas_process(xSignalHeaderRec *msg) { enum states { RESET = 0, WAIT_INIT = 1, WAIT_RESULT = 3 }; UWORD8 *state = &l1pa.state[TCR_MEAS]; UWORD32 SignalCode = msg->SignalCode; UWORD8 i; UWORD8 list_size; T_CRES_LIST_PARAM *free_list; BOOL end_process = 0; while(!end_process) { switch(*state) { case RESET: { // step in state machine. *state = WAIT_INIT; // Reset TCR_MEAS process. l1pa_l1ps_com.l1ps_en_meas &= P_TCRMS_MEAS_MASK; // Disable Neighbour Measurement task. } break; case WAIT_INIT: { if(SignalCode == L1P_TRANSFER_DONE) // We enter in Packet Transfer mode. //--------------------------------- { #if 0 /* FreeCalypso: the following code is not present in TCS211 */ #if (CODE_VERSION != SIMULATION) //no meas when entering in Transfer if no BA list initialized //stay in this state and wait for a MPHP_TCR_MEAS_REQ from L3 if((l1pa_l1ps_com.cres_freq_list.alist->nb_carrier == 0) && (l1pa_l1ps_com.tcr_freq_list.new_list_present == FALSE) && (l1a_l1s_com.ba_list.nbr_carrier == 0)) return; #endif #endif // Set parameter synchro semaphore for P_TCRMS_MEAS task. l1pa_l1ps_com.meas_param |= P_TCRMS_MEAS; // Reset Neighbour Cell measurement parameters. l1pa_l1ps_com.tcr_freq_list.tcr_next_to_ctrl = 0; l1pa_l1ps_com.tcr_freq_list.tcr_next_to_read = 0; l1pa_l1ps_com.tcr_freq_list.last_stored_tcr_to_read = 0; l1pa_l1ps_com.tcr_freq_list.first_pass_flag = TRUE; // Initialize counter used to report measurements l1pa_l1ps_com.tcr_freq_list.cres_meas_report = 0; // If no Packet Idle phase has been done and no BA(GPRS) list has been // downloaded, init BA(GPRS) list with BA list used in CS Idle mode. if((l1pa_l1ps_com.cres_freq_list.alist->nb_carrier == 0) && (l1pa_l1ps_com.tcr_freq_list.new_list_present == FALSE)) { // Get Ptr to the free Neighbour meas list. // The number of carriers in the list and the list // identification are initialized. free_list = l1pa_get_free_cres_list_set(); // Download new list within T_CRES_LIST_PARAM structure. free_list->nb_carrier = l1a_l1s_com.ba_list.nbr_carrier; for(i = 0; i < free_list->nb_carrier; i++) { free_list->freq_list[i] = l1a_l1s_com.ba_list.A[i].radio_freq; } free_list->list_id = l1a_l1s_com.ba_list.ba_id; // Set "flist" with Circuit Swithed BA frequency list parameters l1pa_l1ps_com.cres_freq_list.alist = free_list; } // Reset flags. l1pa_l1ps_com.tcr_freq_list.ms_ctrl = 0; l1pa_l1ps_com.tcr_freq_list.ms_ctrl_d = 0; l1pa_l1ps_com.tcr_freq_list.ms_ctrl_dd = 0; // Reset measures made on beacon frequency. l1pa_l1ps_com.tcr_freq_list.beacon_meas = 0; // Enable Packet Transfer Neighbour Measurement task. l1pa.l1pa_en_meas[TCR_MEAS] |= P_TCRMS_MEAS; // step in state machine. *state = WAIT_RESULT; } else if(SignalCode == MPHC_RXLEV_PERIODIC_REQ) // We receive the BA list to be monitored in Idle mode //---------------------------------------------------- { // When enter in Transfer the Idle list must be used // =>reset the packet Transfert list in order to use the Idle list l1pa_l1ps_com.cres_freq_list.alist->nb_carrier = 0; l1pa_l1ps_com.tcr_freq_list.new_list_present = FALSE; } #if 0 /* FreeCalypso: the following code is not present in TCS211 */ else if(SignalCode == MPHP_TCR_MEAS_REQ) // Restart Packet Transfer measurement in TBF after // MPHP_TCR_MEAS_STOP_REQ // ### Check reason why was missing (s921_bis note)... //---------------------------------------------------- { // Set parameter synchro semaphore for P_TCRMS_MEAS task. l1pa_l1ps_com.meas_param |= P_TCRMS_MEAS; free_list = l1pa_get_free_cres_list_set(); // Download new list within T_CRES_LIST_PARAM structure. free_list->nb_carrier = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->nb_carrier; for(i = 0; i < free_list->nb_carrier; i++) { free_list->freq_list[i] = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->radio_freq_no[i]; } free_list->list_id = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->list_id; // Set "flist" with Circuit Swithed BA frequency list parameters l1pa_l1ps_com.cres_freq_list.alist = free_list; // Reset Neighbour Cell measurement parameters. l1pa_l1ps_com.tcr_freq_list.tcr_next_to_ctrl = 0; l1pa_l1ps_com.tcr_freq_list.tcr_next_to_read = 0; l1pa_l1ps_com.tcr_freq_list.last_stored_tcr_to_read = 0; l1pa_l1ps_com.tcr_freq_list.first_pass_flag = TRUE; // Initialize counter used to report measurements l1pa_l1ps_com.tcr_freq_list.cres_meas_report = 0; // Reset flags. l1pa_l1ps_com.tcr_freq_list.ms_ctrl = 0; l1pa_l1ps_com.tcr_freq_list.ms_ctrl_d = 0; l1pa_l1ps_com.tcr_freq_list.ms_ctrl_dd = 0; // Reset measures made on beacon frequency. l1pa_l1ps_com.tcr_freq_list.beacon_meas = 0; // Enable Packet Transfer Neighbour Measurement task. l1pa.l1pa_en_meas[TCR_MEAS] |= P_TCRMS_MEAS; // step in state machine. *state = WAIT_RESULT; } #endif // End of process. end_process = 1; } break; case WAIT_RESULT: { switch(SignalCode) { case L1P_TCR_MEAS_DONE: // One reporting period has been completed. A set of measures is forward to L3. //----------------------------------------------------------------------------- { // Forward result message to L3. l1a_send_result(MPHP_TCR_MEAS_IND, msg, GRRM1_QUEUE); // End of process. end_process = 1; } break; case MPHP_TCR_MEAS_REQ: // Update of the parameters are postponed until end of the reporting period. // Parameters are saved in a double buffer. { // Reset present flag to avoid to mix 2 updates in case of // an update already pending within "l1pa_l1ps_com.cres_freq_list.flist". l1pa_l1ps_com.tcr_freq_list.new_list_present = FALSE; // Get Ptr to the free Neighbour meas list. // The number of carriers in the list and the list // identification are initialized. free_list = l1pa_get_free_cres_list_set(); // Download new list within T_CRES_LIST_PARAM structure. list_size = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->nb_carrier; free_list->nb_carrier = list_size; for(i = 0; i < list_size; i++) { free_list->freq_list[i] = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->radio_freq_no[i]; } free_list->list_id = ((T_MPHP_TCR_MEAS_REQ *)(msg->SigP))->list_id; // Set "flist" with new set of frequency list parameter l1pa_l1ps_com.cres_freq_list.flist = free_list; // Set present flag only when the list has been downloaded. l1pa_l1ps_com.tcr_freq_list.new_list_present = TRUE; // End of process. end_process = 1; } break; case L1P_TBF_RELEASED: { // Test if all TBF have been released // Then stop Neighbour Measurement process if(((T_L1P_TBF_RELEASED *)(msg->SigP))->released_all) { // This process must be reset. *state = RESET; } else { return; } } break; case MPHP_TCR_MEAS_STOP_REQ: // Note: A TBF stop do not imply a stop of the Neighbour Measurement process. // L3 has to send a MPHP_TCR_MEAS_STOP message to stop the measurement process. { // send confirmation message l1a_send_confirmation(MPHP_TCR_MEAS_STOP_CON,GRRM1_QUEUE); // This process must be reset. *state = RESET; } break; default: // No action in this machine for other messages. // Note: No action is performed on receipt of a L1P_TRANSFER_DONE // message. However a SYNCHRO task is programmed, which implies // a reset of measures related to the Serving Cell (cf. L1S). //-------------------------------------------------------------- { return; } } // end of switch(SignalCode) } break; } // end of "switch". } // end of "while" } // end of procedure. /*-------------------------------------------------------*/ /* l1pa_idle_interference_meas_process() */ /*-------------------------------------------------------*/ /* Description : */ /* */ /* Starting messages: MPHP_INT_MEAS_REQ */ /* */ /* This message requests signal strength measurements */ /* on several channels of a specific carrier. */ /* Measurements must be done on one search frame and one */ /* PTCCH frame. */ /* */ /* Result messages (input): L1PS_ITMEAS_IND */ /* */ /* This message is reported to L1A when signal strength */ /* has been measured on one idle frame (PTCCH or search) */ /* */ /* Result messages (output): MPHP_INT_MEAS_IND */ /* */ /* This message is reported to L3 when measurements have */ /* been done on two contiguous idle frames */ /* */ /* Reset message (input): MPHP_INT_MEAS_STOP_REQ */ /* */ /* Interference measurement processing is stopped by */ /* this message */ /*-------------------------------------------------------*/ void l1pa_idle_interference_meas_process(xSignalHeaderRec *msg) { enum states { RESET = 0, WAIT_INIT = 1, WAIT_1ST_RESULT = 2, WAIT_2ND_RESULT = 3 }; static T_L1A_INT_MEAS_PARAM int_meas_param; UWORD8 *state = &l1pa.state[PI_INT_MEAS]; UWORD32 SignalCode = msg->SignalCode; BOOL end_process = 0; while(!end_process) { switch(*state) { case RESET: { // Step in state machine. *state = WAIT_INIT; // Reset ITMEAS process. l1a_l1s_com.l1s_en_task[ITMEAS] = TASK_DISABLED; // Clear ITMEAS task enable flag. } break; case WAIT_INIT: { // Interference measurement request //--------------------------------- if (SignalCode == MPHP_INT_MEAS_REQ) { UWORD8 bitmap,i; // Set semaphore l1a_l1s_com.task_param[ITMEAS] = SEMAPHORE_SET; // Download message content l1pa_l1ps_com.itmeas.packet_intm_freq_param = ((T_MPHP_INT_MEAS_REQ *)(msg->SigP))->packet_intm_freq_param; l1pa_l1ps_com.itmeas.multislot_class = ((T_MPHP_INT_MEAS_REQ *)(msg->SigP))->multislot_class; int_meas_param.id = ((T_MPHP_INT_MEAS_REQ *)(msg->SigP))->carrier_id; // Processing of the 2 possible measurement bitmaps //------------------------------------------------- // 1- Without Rx on the frame before l1pa_l1ps_com.itmeas.idle_tn_no_rx = ((T_MPHP_INT_MEAS_REQ *)(msg->SigP))->tn; // Trb respect after measurements // We consider that the timeslot on which the Layer 1 is synchronized is // always allocated on the frame after the idle frame. // For the Trb multi-slot class parameter respect, we must clear the bits at // the right of the interference measurement bitmap l1pa_l1ps_com.itmeas.idle_tn_no_rx &= (UWORD8) ~( 0xFF >> ( 8 + l1a_l1s_com.dl_tn - MS_CLASS[l1pa_l1ps_com.itmeas.multislot_class].trb)); // 2- With a Rx programmed on the frame before // Note: This Rx is always on the dl_tn l1pa_l1ps_com.itmeas.idle_tn_rx = l1pa_l1ps_com.itmeas.idle_tn_no_rx; // Trb respect before measurements // The timeslot on which the Layer 1 is synchronized is allocated on the frame // before the idle frame. // For the Trb multi-slot class parameter respect, we must clear the bits at // the left of the interference measurement bitmap bitmap = 0x80; i = 8 - l1a_l1s_com.dl_tn - MS_CLASS[l1pa_l1ps_com.itmeas.multislot_class].trb; if (i > 8) bitmap >>= (-i); else bitmap <<= i; for (i = 1; i<= MS_CLASS[l1pa_l1ps_com.itmeas.multislot_class].trb; i++) { l1pa_l1ps_com.itmeas.idle_tn_rx &= (UWORD8) ~bitmap; bitmap <<= 1; } // Initialize parameters l1pa_l1ps_com.itmeas.position = ANY_IDLE_FRAME; // First measurement on any idle frame // Enable synchronous task l1a_l1s_com.l1s_en_task[ITMEAS] = TASK_ENABLED; // Step in state machine *state = WAIT_1ST_RESULT; // End of process end_process = 1; } // No action in this machine for other messages. else { // End of process. end_process = 1; } } break; case WAIT_1ST_RESULT: { // Reporting of 1st measurement session //------------------------------------- if (SignalCode == L1P_ITMEAS_IND) { UWORD8 i; // Set semaphore l1a_l1s_com.task_param[ITMEAS] = SEMAPHORE_SET; // Save interference measurements for(i=0; i<8; i++) int_meas_param.rxlev[i] = ((T_L1P_ITMEAS_IND *)(msg->SigP))->rxlev[i]; // Save bitmap int_meas_param.meas_bitmap = ((T_L1P_ITMEAS_IND *)(msg->SigP))->meas_bitmap; // Save reported fn int_meas_param.fn = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn; // Position = complement of reported position if (((T_L1P_ITMEAS_IND *)(msg->SigP))->position == PTCCH_FRAME) l1pa_l1ps_com.itmeas.position = SEARCH_FRAME; else l1pa_l1ps_com.itmeas.position = PTCCH_FRAME; // Enable ITMEAS l1a_l1s_com.l1s_en_task[ITMEAS] = TASK_ENABLED; // Step in state machine *state = WAIT_2ND_RESULT; // End of process return; } else if (SignalCode == MPHP_INT_MEAS_STOP_REQ) { // Send confirmation l1a_send_confirmation(MPHP_INT_MEAS_STOP_CON,GRRM1_QUEUE); // Reset process *state = RESET; } // No action in this machine for other messages. else { // End of process return; } } break; case WAIT_2ND_RESULT: { // Reporting subsequent measurement session //----------------------------------------- if (SignalCode == L1P_ITMEAS_IND) { // At least one measurement session has already been reported //----------------------------------------------------------- UWORD32 reported_fn; // Check fn // The two measurement sessions must be done in two contiguous idle frames // Modulo if (((T_L1P_ITMEAS_IND *)(msg->SigP))->fn < int_meas_param.fn) { reported_fn = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn + MAX_FN; } else { reported_fn = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn; } // The two last measurement sessions are enough close if ((reported_fn - int_meas_param.fn) == 13) { // Build and send result msg to L3. l1pa_send_int_meas_report(MPHP_INT_MEAS_IND, ((T_L1P_ITMEAS_IND *)(msg->SigP)), &int_meas_param); // Only one measurement session per request *state = RESET; } // The two last measurement sessions aren't enough close else { // 1st measurement result is no more valid, second result // must replace it: this is achieved by WAIT_1ST_RESULT state!!! // Step in state machine *state = WAIT_1ST_RESULT; } } else if (SignalCode == MPHP_INT_MEAS_STOP_REQ) { // Send confirmation l1a_send_confirmation(MPHP_INT_MEAS_STOP_CON,GRRM1_QUEUE); // Reset process *state = RESET; } // No action in this machine for other messages. else { // End of process return; } } break; } // End of "switch" } // End of "while" } // End of "procedure" /*-------------------------------------------------------*/ /* l1pa_transfer_interference_meas_process() */ /*-------------------------------------------------------*/ /* Description : */ /* */ /* Starting messages: L1P_TRANFSER_DONE */ /* */ /* Interference measurement processing starts each time */ /* a new starting time occurs if the interference */ /* measurements are enabled */ /* Measurements must be done on one search frame and one */ /* PTCCH frame. */ /* */ /* Result messages (input): L1PS_ITMEAS_IND */ /* */ /* This message is reported to L1A when signal strength */ /* has been measured on one idle frame (PTCCH or search) */ /* */ /* Result messages (output): MPHP_TINT_MEAS_IND */ /* */ /* This message is reported to L3 when measurements have */ /* been done on two idle frames as close as possible */ /* */ /* Reset message (input): L1P_TBF_RELEASED */ /* */ /* Interference measurement processing is stopped when */ /* all TBF are released */ /*-------------------------------------------------------*/ void l1pa_transfer_interference_meas_process(xSignalHeaderRec *msg) { /* Bitmaps used for the processing of full_allocation */ /*----------------------------------------------------*/ const UWORD8 FULL_ALLOCATION[9]= { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; enum states { RESET = 0, WAIT_INIT = 1, CONFIG = 2, WAIT_1ST_RESULT = 3, WAIT_2ND_RESULT = 4 }; static T_L1A_INT_MEAS_PARAM int_meas_param; UWORD8 *state = &l1pa.state[PT_INT_MEAS]; UWORD32 SignalCode = msg->SignalCode; BOOL end_process = 0; while(!end_process) { switch(*state) { case RESET: { // Step in state machine. *state = WAIT_INIT; // Reset ITMEAS process. l1a_l1s_com.l1s_en_task[ITMEAS] = TASK_DISABLED; // Clear ITMEAS task enable flag. } break; case WAIT_INIT: { // New channel assignment //----------------------- if ((SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1P_REPEAT_ALLOC_DONE) || (SignalCode == L1P_ALLOC_EXHAUST_DONE)) { *state = CONFIG; } // No action in this machine for other messages. else { // End of process. return; } } break; case CONFIG: { // Rise transfert parameter semaphore to prevent L1S to use partial configuration. l1pa_l1ps_com.transfer.semaphore = TRUE; // If the interference measurements are disabled if (l1pa_l1ps_com.transfer.aset->interf_meas_enable == FALSE) { *state = WAIT_INIT; } else { // Set semaphore l1a_l1s_com.task_param[ITMEAS] = SEMAPHORE_SET; // Initialize parameters l1pa_l1ps_com.itmeas.position = ANY_IDLE_FRAME; // First measurement on any idle frame // Save assignment ID for the interference measurements reporting message int_meas_param.id = l1pa_l1ps_com.transfer.aset->assignment_id; // Processing of the measurement bitmap l1pa_l1ps_com.itmeas.meas_bitmap = (UWORD8) FULL_ALLOCATION[MS_CLASS[l1pa_l1ps_com.transfer.aset->multislot_class].rx] >> l1a_l1s_com.dl_tn; // Enable synchronous task l1a_l1s_com.l1s_en_task[ITMEAS] = TASK_ENABLED; // Step in state machine *state = WAIT_1ST_RESULT; } // Clear transfer parameter semaphore to let L1S use the new parameters. l1pa_l1ps_com.transfer.semaphore = FALSE; // End of process. end_process = 1; } break; case WAIT_1ST_RESULT: { // Reporting of 1st measurement session //------------------------------------- if (SignalCode == L1P_ITMEAS_IND) { UWORD8 i; // Set semaphore l1a_l1s_com.task_param[ITMEAS] = SEMAPHORE_SET; // Save interference measurements for(i=0; i<8; i++) int_meas_param.rxlev[i] = ((T_L1P_ITMEAS_IND *)(msg->SigP))->rxlev[i]; // Save bitmap int_meas_param.meas_bitmap = ((T_L1P_ITMEAS_IND *)(msg->SigP))->meas_bitmap; // Save reported fn int_meas_param.fn = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn; // Position = complement of reported position if (((T_L1P_ITMEAS_IND *)(msg->SigP))->position == PTCCH_FRAME) l1pa_l1ps_com.itmeas.position = SEARCH_FRAME; else l1pa_l1ps_com.itmeas.position = PTCCH_FRAME; // Enable ITMEAS l1a_l1s_com.l1s_en_task[ITMEAS] = TASK_ENABLED; // Step in state machine *state = WAIT_2ND_RESULT; // End of process return; } else if (SignalCode == L1P_TRANSFER_DONE) // The starting time of a new TBF occurs { // Reset process *state = RESET; } else if (SignalCode == L1P_TBF_RELEASED) // A TBF has been released { // No remaining TBF if(((T_L1P_TBF_RELEASED *)(msg->SigP))->released_all) { // Reset process *state = RESET; } else { // Enable a new measurement session *state = CONFIG; } } else if (SignalCode == L1P_PDCH_RELEASED) // PDCH have been released { // Enable a new measurement session *state = CONFIG; } // No action in this machine for other messages. else { // End of process return; } } break; case WAIT_2ND_RESULT: { // Reporting subsequent measurement session //----------------------------------------- if (SignalCode == L1P_ITMEAS_IND) { // At least one measurement session has already been reported //----------------------------------------------------------- UWORD32 reported_fn; // Check fn // The two measurement sessions must be done in two contiguous idle frames // Modulo if (((T_L1P_ITMEAS_IND *)(msg->SigP))->fn < int_meas_param.fn) { reported_fn = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn + MAX_FN; } else { reported_fn = ((T_L1P_ITMEAS_IND *)(msg->SigP))->fn; } // The two last measurement sessions are enough close if ((reported_fn - int_meas_param.fn) <= 104) { // Build and send result msg to L3. l1pa_send_int_meas_report(MPHP_TINT_MEAS_IND, ((T_L1P_ITMEAS_IND *)(msg->SigP)), &int_meas_param); // Enable a new measurement session *state = CONFIG; } // The two last measurement sessions aren't enough close else { // 1st measurement result is no more valid, second result // must replace it: this is achieved by WAIT_1ST_RESULT state!!! // Step in state machine *state = WAIT_1ST_RESULT; } } else // New channel assignment //----------------------- if ((SignalCode == L1P_TRANSFER_DONE) || (SignalCode == L1P_REPEAT_ALLOC_DONE) || (SignalCode == L1P_ALLOC_EXHAUST_DONE)) { // Reset process *state = RESET; } else if (SignalCode == L1P_TBF_RELEASED) // A TBF has been released { // No remaining TBF if(((T_L1P_TBF_RELEASED *)(msg->SigP))->released_all) { // Reset process *state = RESET; } else { // Enable a new measurement session *state = CONFIG; } } else if (SignalCode == L1P_PDCH_RELEASED) // PDCH have been released { // Enable a new measurement session *state = CONFIG; } // No action in this machine for other messages. else { // End of process return; } } break; } // End of "switch" } // End of "while" } // End of "procedure" //#pragma DUPLICATE_FOR_INTERNAL_RAM_START #endif //#pragma DUPLICATE_FOR_INTERNAL_RAM_END