@ -52,6 +52,7 @@ rrc::rrc()
{
{
n310_cnt = 0 ;
n310_cnt = 0 ;
n311_cnt = 0 ;
n311_cnt = 0 ;
serving_cell = new cell_t ( ) ;
}
}
static void liblte_rrc_handler ( void * ctx , char * str ) {
static void liblte_rrc_handler ( void * ctx , char * str ) {
@ -89,8 +90,6 @@ void rrc::init(phy_interface_rrc *phy_,
state = RRC_STATE_IDLE ;
state = RRC_STATE_IDLE ;
si_acquire_state = SI_ACQUIRE_IDLE ;
si_acquire_state = SI_ACQUIRE_IDLE ;
bzero ( known_cells , MAX_KNOWN_CELLS * sizeof ( cell_t ) ) ;
thread_running = true ;
thread_running = true ;
start ( ) ;
start ( ) ;
@ -210,13 +209,13 @@ void rrc::run_thread() {
* Cell is selected when all SIBs downloaded or applied .
* Cell is selected when all SIBs downloaded or applied .
*/
*/
if ( phy - > sync_status ( ) ) {
if ( phy - > sync_status ( ) ) {
if ( ! current _cell- > has_valid_sib1 ) {
if ( ! serving _cell- > has_valid_sib1 ) {
si_acquire_state = SI_ACQUIRE_SIB1 ;
si_acquire_state = SI_ACQUIRE_SIB1 ;
sysinfo_index = 0 ;
sysinfo_index = 0 ;
} else if ( ! current _cell- > has_valid_sib2 ) {
} else if ( ! serving _cell- > has_valid_sib2 ) {
si_acquire_state = SI_ACQUIRE_SIB2 ;
si_acquire_state = SI_ACQUIRE_SIB2 ;
} else {
} else {
apply_sib2_configs ( & current _cell- > sib2 ) ;
apply_sib2_configs ( & serving _cell- > sib2 ) ;
si_acquire_state = SI_ACQUIRE_IDLE ;
si_acquire_state = SI_ACQUIRE_IDLE ;
state = RRC_STATE_CELL_SELECTED ;
state = RRC_STATE_CELL_SELECTED ;
}
}
@ -228,6 +227,7 @@ void rrc::run_thread() {
rrc_log - > info ( " RRC Cell Selecting: timeout expired. Starting Cell Search... \n " ) ;
rrc_log - > info ( " RRC Cell Selecting: timeout expired. Starting Cell Search... \n " ) ;
plmn_select_timeout = 0 ;
plmn_select_timeout = 0 ;
select_cell_timeout = 0 ;
select_cell_timeout = 0 ;
serving_cell - > in_sync = false ;
phy - > cell_search_start ( ) ;
phy - > cell_search_start ( ) ;
}
}
}
}
@ -254,7 +254,7 @@ void rrc::run_thread() {
} else {
} else {
rrc_log - > info ( " RRC Cell Selected: Starting paging and going to IDLE... \n " ) ;
rrc_log - > info ( " RRC Cell Selected: Starting paging and going to IDLE... \n " ) ;
mac - > pcch_start_rx ( ) ;
mac - > pcch_start_rx ( ) ;
state = RRC_STATE_ ID LE;
state = RRC_STATE_ LEAVE_CONNECTED ;
}
}
break ;
break ;
case RRC_STATE_CONNECTING :
case RRC_STATE_CONNECTING :
@ -287,25 +287,7 @@ void rrc::run_thread() {
break ;
break ;
case RRC_STATE_LEAVE_CONNECTED :
case RRC_STATE_LEAVE_CONNECTED :
usleep ( 60000 ) ;
usleep ( 60000 ) ;
rrc_log - > console ( " RRC IDLE \n " ) ;
leave_connected ( ) ;
rrc_log - > info ( " Leaving RRC_CONNECTED state \n " ) ;
drb_up = false ;
measurements . reset ( ) ;
pdcp - > reset ( ) ;
rlc - > reset ( ) ;
phy - > reset ( ) ;
mac - > reset ( ) ;
set_phy_default ( ) ;
set_mac_default ( ) ;
mac_timers - > timer_get ( t310 ) - > stop ( ) ;
mac_timers - > timer_get ( t311 ) - > stop ( ) ;
if ( phy - > sync_status ( ) ) {
// Instruct MAC to look for P-RNTI
mac - > pcch_start_rx ( ) ;
// Instruct PHY to measure serving cell for cell reselection
phy - > meas_start ( phy - > get_current_earfcn ( ) , phy - > get_current_pci ( ) ) ;
}
// Move to RRC_IDLE
// Move to RRC_IDLE
state = RRC_STATE_IDLE ;
state = RRC_STATE_IDLE ;
break ;
break ;
@ -370,19 +352,19 @@ void rrc::run_si_acquisition_procedure()
break ;
break ;
case SI_ACQUIRE_SIB2 :
case SI_ACQUIRE_SIB2 :
// Instruct MAC to look for next SIB
// Instruct MAC to look for next SIB
if ( sysinfo_index < current _cell- > sib1 . N_sched_info ) {
if ( sysinfo_index < serving _cell- > sib1 . N_sched_info ) {
si_win_len = liblte_rrc_si_window_length_num [ current _cell- > sib1 . si_window_length ] ;
si_win_len = liblte_rrc_si_window_length_num [ serving _cell- > sib1 . si_window_length ] ;
x = sysinfo_index * si_win_len ;
x = sysinfo_index * si_win_len ;
sf = x % 10 ;
sf = x % 10 ;
offset = x / 10 ;
offset = x / 10 ;
tti = mac - > get_current_tti ( ) ;
tti = mac - > get_current_tti ( ) ;
period = liblte_rrc_si_periodicity_num [ current _cell- > sib1 . sched_info [ sysinfo_index ] . si_periodicity ] ;
period = liblte_rrc_si_periodicity_num [ serving _cell- > sib1 . sched_info [ sysinfo_index ] . si_periodicity ] ;
si_win_start = sib_start_tti ( tti , period , offset , sf ) ;
si_win_start = sib_start_tti ( tti , period , offset , sf ) ;
if ( tti > last_win_start + 10 ) {
if ( tti > last_win_start + 10 ) {
last_win_start = si_win_start ;
last_win_start = si_win_start ;
si_win_len = liblte_rrc_si_window_length_num [ current _cell- > sib1 . si_window_length ] ;
si_win_len = liblte_rrc_si_window_length_num [ serving _cell- > sib1 . si_window_length ] ;
mac - > bcch_start_rx ( si_win_start , si_win_len ) ;
mac - > bcch_start_rx ( si_win_start , si_win_len ) ;
rrc_log - > debug ( " Instructed MAC to search for system info, win_start=%d, win_len=%d \n " ,
rrc_log - > debug ( " Instructed MAC to search for system info, win_start=%d, win_len=%d \n " ,
@ -421,19 +403,15 @@ void rrc::run_si_acquisition_procedure()
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint16_t rrc : : get_mcc ( ) {
uint16_t rrc : : get_mcc ( ) {
if ( current_cell ) {
if ( serving_cell - > sib1 . N_plmn_ids > 0 ) {
if ( current_cell - > sib1 . N_plmn_ids > 0 ) {
return serving_cell - > sib1 . plmn_id [ 0 ] . id . mcc ;
return current_cell - > sib1 . plmn_id [ 0 ] . id . mcc ;
}
}
}
return 0 ;
return 0 ;
}
}
uint16_t rrc : : get_mnc ( ) {
uint16_t rrc : : get_mnc ( ) {
if ( current_cell ) {
if ( serving_cell - > sib1 . N_plmn_ids > 0 ) {
if ( current_cell - > sib1 . N_plmn_ids > 0 ) {
return serving_cell - > sib1 . plmn_id [ 0 ] . id . mnc ;
return current_cell - > sib1 . plmn_id [ 0 ] . id . mnc ;
}
}
}
return 0 ;
return 0 ;
}
}
@ -468,188 +446,261 @@ void rrc::plmn_select_rrc(LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_id) {
// Sort cells according to RSRP
// Sort cells according to RSRP
selected_plmn_id = plmn_id ;
selected_plmn_id = plmn_id ;
last_selected_cell = - 1 ;
select_cell_timeout = 0 ;
select_cell_timeout = 0 ;
state = RRC_STATE_CELL_SELECTING ;
state = RRC_STATE_CELL_SELECTING ;
select_next_cell_in_plmn ( ) ;
}
}
} else {
} else {
rrc_log - > warning ( " Requested PLMN select in incorrect state %s \n " , rrc_state_text [ state ] ) ;
rrc_log - > warning ( " Requested PLMN select in incorrect state %s \n " , rrc_state_text [ state ] ) ;
}
}
}
}
void rrc : : set_serving_cell ( uint32_t earfcn , uint32_t pci ) {
int cell_idx = find_neighbour_cell ( earfcn , pci ) ;
if ( cell_idx > = 0 ) {
set_serving_cell ( cell_idx ) ;
} else {
rrc_log - > error ( " Setting serving cell: Unkonwn cell with earfcn=%d, PCI=%d \n " , earfcn , pci ) ;
}
}
void rrc : : set_serving_cell ( uint32_t cell_idx ) {
if ( cell_idx < neighbour_cells . size ( ) )
{
// Remove future serving cell from neighbours to make space for current serving cell
cell_t * new_serving_cell = neighbour_cells [ cell_idx ] ;
if ( ! new_serving_cell ) {
rrc_log - > error ( " Setting serving cell. Index %d is empty \n " , cell_idx ) ;
return ;
}
neighbour_cells . erase ( std : : remove ( neighbour_cells . begin ( ) , neighbour_cells . end ( ) , neighbour_cells [ cell_idx ] ) , neighbour_cells . end ( ) ) ;
// Move serving cell to neighbours list
if ( serving_cell - > is_valid ( ) ) {
// Make sure it does not exist already
int serving_idx = find_neighbour_cell ( serving_cell - > earfcn , serving_cell - > phy_cell . id ) ;
if ( serving_idx > = 0 & & ( uint32_t ) serving_idx < neighbour_cells . size ( ) ) {
printf ( " Error serving cell is already in the neighbour list. Removing it \n " ) ;
neighbour_cells . erase ( std : : remove ( neighbour_cells . begin ( ) , neighbour_cells . end ( ) , neighbour_cells [ serving_idx ] ) , neighbour_cells . end ( ) ) ;
}
// If not in the list, add it to the list of neighbours (sorted inside the function)
if ( ! add_neighbour_cell ( serving_cell ) ) {
rrc_log - > info ( " Serving cell not added to list of neighbours. Worse than current neighbours \n " ) ;
}
}
// Set new serving cell
serving_cell = new_serving_cell ;
rrc_log - > info ( " Setting serving cell idx=%d, earfcn=%d, PCI=%d, nof_neighbours=%d \n " ,
cell_idx , serving_cell - > earfcn , serving_cell - > phy_cell . id , neighbour_cells . size ( ) ) ;
} else {
rrc_log - > error ( " Setting invalid serving cell idx %d \n " , cell_idx ) ;
}
}
void rrc : : select_next_cell_in_plmn ( ) {
void rrc : : select_next_cell_in_plmn ( ) {
for ( uint32_t i = last_selected_cell + 1 ; i < MAX_KNOWN_CELLS & & known_cells [ i ] . earfcn ; i + + ) {
// Neighbour cells are sorted in descending order of RSRP
for ( uint32_t j = 0 ; j < known_cells [ i ] . sib1 . N_plmn_ids ; j + + ) {
for ( uint32_t i = 0 ; i < neighbour_cells . size ( ) ; i + + ) {
if ( known_cells [ i ] . sib1 . plmn_id [ j ] . id . mcc = = selected_plmn_id . mcc | |
if ( neighbour_cells [ i ] - > plmn_equals ( selected_plmn_id ) & &
known_cells [ i ] . sib1 . plmn_id [ j ] . id . mnc = = selected_plmn_id . mnc ) {
neighbour_cells [ i ] - > in_sync ) // matches S criteria
rrc_log - > info ( " Selecting cell PCI=%d, EARFCN=%d, Cell ID=0x%x \n " ,
{
known_cells [ i ] . phy_cell . id , known_cells [ i ] . earfcn ,
// Try to select Cell
known_cells [ i ] . sib1 . cell_id ) ;
if ( phy - > cell_select ( neighbour_cells [ i ] - > earfcn , neighbour_cells [ i ] - > phy_cell ) ) {
rrc_log - > console ( " Select cell: PCI=%d, EARFCN=%d, Cell ID=0x%x \n " ,
set_serving_cell ( i ) ;
known_cells [ i ] . phy_cell . id , known_cells [ i ] . earfcn ,
rrc_log - > info ( " Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x \n " ,
known_cells [ i ] . sib1 . cell_id ) ;
serving_cell - > phy_cell . id , serving_cell - > earfcn ,
// Check that cell satisfies S criteria
serving_cell - > sib1 . cell_id ) ;
if ( known_cells [ i ] . in_sync ) { // %% rsrp > S dbm
rrc_log - > console ( " Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x \n " ,
// Try to select Cell
serving_cell - > phy_cell . id , serving_cell - > earfcn ,
if ( phy - > cell_select ( known_cells [ i ] . earfcn , known_cells [ i ] . phy_cell ) )
serving_cell - > sib1 . cell_id ) ;
{
} else {
last_selected_cell = i ;
// Set to out-of-sync if can't synchronize
current_cell = & known_cells [ i ] ;
neighbour_cells [ i ] - > in_sync = false ;
rrc_log - > info ( " Selected cell PCI=%d, EARFCN=%d, Cell ID=0x%x, addr=0x%x \n " ,
rrc_log - > warning ( " Selecting cell EARFCN=%d, Cell ID=0x%x. \n " ,
current_cell - > phy_cell . id , current_cell - > earfcn ,
neighbour_cells [ i ] - > earfcn , neighbour_cells [ i ] - > sib1 . cell_id ) ;
current_cell - > sib1 . cell_id , current_cell ) ;
return ;
} else {
rrc_log - > warning ( " Selecting cell EARFCN=%d, Cell ID=0x%x. \n " ,
known_cells [ i ] . earfcn , known_cells [ i ] . sib1 . cell_id ) ;
}
}
}
}
return ;
}
}
}
}
rrc_log - > info ( " No more known cells. Starting again \n " ) ;
rrc_log - > info ( " No more known cells. Starting again \n " ) ;
last_selected_cell = - 1 ;
}
}
void rrc : : new_phy_meas ( float rsrp , float rsrq , uint32_t tti , uint32_t earfcn , uint32_t pci ) {
void rrc : : new_phy_meas ( float rsrp , float rsrq , uint32_t tti , int earfcn_i , int pci_i ) {
if ( earfcn_i < 0 | | pci_i < 0 ) {
earfcn_i = serving_cell - > earfcn ;
pci_i = serving_cell - > phy_cell . id ;
}
uint32_t earfcn = ( uint32_t ) earfcn_i ;
uint32_t pci = ( uint32_t ) pci_i ;
// Measurements in RRC_CONNECTED go through measuremnt class to log reports etc.
if ( state ! = RRC_STATE_IDLE ) {
if ( state ! = RRC_STATE_IDLE ) {
measurements . new_phy_meas ( earfcn , pci , rsrp , rsrq , tti ) ;
measurements . new_phy_meas ( earfcn , pci , rsrp , rsrq , tti ) ;
// Measurements in RRC_IDLE update serving cell and check for reselection
} else {
} else {
// If measurement is of the serving cell, evaluate cell reselection criteria
if ( ( earfcn = = phy - > get_current_earfcn ( ) & & pci = = phy - > get_current_pci ( ) ) | | ( earfcn = = 0 & & pci = = 0 ) ) {
// Update serving cell
if ( serving_cell - > equals ( earfcn , pci ) ) {
cell_reselection_eval ( rsrp , rsrq ) ;
cell_reselection_eval ( rsrp , rsrq ) ;
current_cell - > rsrp = rsrp ;
serving_cell - > rsrp = rsrp ;
rrc_log - > info ( " MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d \n " , rsrp , rsrq , tti ) ;
rrc_log - > info ( " MEAS: New measurement serving cell in IDLE, rsrp=%f, rsrq=%f, tti=%d \n " , rsrp , rsrq , tti ) ;
} else {
// Add/update cell measurement
srslte_cell_t cell ;
phy - > get_current_cell ( & cell , NULL ) ;
cell . id = pci ;
add_new_cell ( earfcn , cell , rsrp ) ;
rrc_log - > info ( " MEAS: New measurement PCI=%d, RSRP=%.1f dBm. \n " , pci , rsrp ) ;
// Or update/add neighbour cell
} else {
if ( add_neighbour_cell ( earfcn , pci , rsrp ) ) {
rrc_log - > info ( " MEAS: New measurement neighbour in IDLE, PCI=%d, RSRP=%.1f dBm. \n " , pci , rsrp ) ;
} else {
rrc_log - > info ( " MEAS: Neighbour Cell in IDLE PCI=%d, RSRP=%.1f dBm not added. Worse than current neighbours \n " , pci , rsrp ) ;
}
}
}
srslte_cell_t best_cell ;
// Verify cell selection criteria with strongest neighbour cell (always first)
uint32_t best_cell_idx = find_best_cell ( phy - > get_current_earfcn ( ) , & best_cell ) ;
if ( cell_selection_eval ( neighbour_cells [ 0 ] - > rsrp ) & &
neighbour_cells [ 0 ] - > rsrp > serving_cell - > rsrp + 5 )
// Verify cell selection criteria
if ( cell_selection_eval ( known_cells [ best_cell_idx ] . rsrp ) & &
known_cells [ best_cell_idx ] . rsrp > current_cell - > rsrp + 5 & &
best_cell . id ! = phy - > get_current_pci ( ) )
{
{
rrc_log - > info ( " Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm \n " , best_cell . id , known_cells [ best_cell_idx ] . rsrp ) ;
set_serving_cell ( 0 ) ;
rrc_log - > info ( " Selecting best neighbour cell PCI=%d, rsrp=%.1f dBm \n " , serving_cell - > phy_cell . id , serving_cell - > rsrp ) ;
state = RRC_STATE_CELL_SELECTING ;
state = RRC_STATE_CELL_SELECTING ;
current_cell = & known_cells [ best_cell_idx ] ;
phy - > cell_select ( serving_cell - > earfcn , serving_cell - > phy_cell ) ;
phy - > cell_select ( phy - > get_current_earfcn ( ) , best_cell ) ;
}
}
}
}
}
}
void rrc : : cell_found ( uint32_t earfcn , srslte_cell_t phy_cell , float rsrp ) {
void rrc : : cell_found ( uint32_t earfcn , srslte_cell_t phy_cell , float rsrp ) {
// find if cell_id-earfcn combination already exists
bool found = false ;
for ( uint32_t i = 0 ; i < MAX_KNOWN_CELLS & & known_cells [ i ] . earfcn ; i + + ) {
int cell_idx = - 1 ;
if ( earfcn = = known_cells [ i ] . earfcn & & phy_cell . id = = known_cells [ i ] . phy_cell . id ) {
current_cell = & known_cells [ i ] ;
if ( serving_cell - > equals ( earfcn , phy_cell . id ) ) {
current_cell - > rsrp = rsrp ;
serving_cell - > rsrp = rsrp ;
current_cell - > in_sync = true ;
serving_cell - > in_sync = true ;
rrc_log - > info ( " Updating cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm \n " , current_cell - > earfcn ,
found = true ;
current_cell - > phy_cell . id , current_cell - > rsrp ) ;
} else {
// Check if cell is in our list of neighbour cells
if ( ! current_cell - > has_valid_sib1 ) {
cell_idx = find_neighbour_cell ( earfcn , phy_cell . id ) ;
si_acquire_state = SI_ACQUIRE_SIB1 ;
if ( cell_idx > = 0 ) {
} else if ( state = = RRC_STATE_PLMN_SELECTION ) {
set_serving_cell ( cell_idx ) ;
for ( uint32_t j = 0 ; j < current_cell - > sib1 . N_plmn_ids ; j + + ) {
serving_cell - > rsrp = rsrp ;
nas - > plmn_found ( current_cell - > sib1 . plmn_id [ j ] . id , current_cell - > sib1 . tracking_area_code ) ;
serving_cell - > in_sync = true ;
}
found = true ;
usleep ( 5000 ) ;
}
phy - > cell_search_next ( ) ;
}
if ( found ) {
if ( ! serving_cell - > has_valid_sib1 ) {
si_acquire_state = SI_ACQUIRE_SIB1 ;
} else if ( state = = RRC_STATE_PLMN_SELECTION ) {
for ( uint32_t j = 0 ; j < serving_cell - > sib1 . N_plmn_ids ; j + + ) {
nas - > plmn_found ( serving_cell - > sib1 . plmn_id [ j ] . id , serving_cell - > sib1 . tracking_area_code ) ;
}
}
return ;
usleep ( 5000 ) ;
phy - > cell_search_next ( ) ;
}
} else {
// add to list of known cells and set current_cell
if ( ! add_neighbour_cell ( earfcn , phy_cell , rsrp ) ) {
rrc_log - > info ( " No more space for neighbour cells (detected cell RSRP=%.1f dBm worse than current %d neighbours) \n " ,
rsrp , NOF_NEIGHBOUR_CELLS ) ;
usleep ( 5000 ) ;
phy - > cell_search_next ( ) ;
} else {
set_serving_cell ( earfcn , phy_cell . id ) ;
si_acquire_state = SI_ACQUIRE_SIB1 ;
}
}
}
// add to list of known cells and set current_cell
current_cell = add_new_cell ( earfcn , phy_cell , rsrp ) ;
if ( ! current_cell ) {
current_cell = & known_cells [ 0 ] ;
rrc_log - > error ( " Couldn't add new cell \n " ) ;
return ;
}
}
si_acquire_state = SI_ACQUIRE_SIB1 ;
rrc_log - > info ( " %s %s cell EARFCN=%d, PCI=%d, RSRP=%.1f dBm \n " ,
found ? " Updating " : " Adding " ,
cell_idx > = 0 ? " neighbour " : " serving " ,
serving_cell - > earfcn ,
serving_cell - > phy_cell . id ,
serving_cell - > rsrp ) ;
}
rrc_log - > info ( " New Cell: PCI=%d, PRB=%d, Ports=%d, EARFCN=%d, RSRP=%.1f dBm, addr=0x%x \n " ,
bool sort_rsrp ( cell_t * u1 , cell_t * u2 ) {
current_cell - > phy_cell . id , current_cell - > phy_cell . nof_prb , current_cell - > phy_cell . nof_ports ,
return ! u1 - > greater ( u2 ) ;
current_cell - > earfcn , current_cell - > rsrp , current_cell ) ;
}
}
uint32_t rrc : : find_best_cell ( uint32_t earfcn , srslte_cell_t * cell ) {
// Sort neighbour cells by decreasing order of RSRP
float best_rsrp = - INFINITY ;
void rrc : : sort_neighbour_cells ( ) {
uint32_t best_cell_idx = 0 ;
for ( int i = 0 ; i < MAX_KNOWN_CELLS ; i + + ) {
for ( uint32_t i = 1 ; i < neighbour_cells . size ( ) ; i + + ) {
if ( known_cells [ i ] . earfcn = = earfcn ) {
if ( neighbour_cells [ i ] - > in_sync = = false ) {
if ( known_cells [ i ] . rsrp > best_rsrp ) {
rrc_log - > info ( " Removing neighbour cell PCI=%d, out_of_sync \n " , neighbour_cells [ i ] - > phy_cell . id ) ;
best_rsrp = known_cells [ i ] . rsrp ;
neighbour_cells . erase ( std : : remove ( neighbour_cells . begin ( ) , neighbour_cells . end ( ) , neighbour_cells [ i ] ) , neighbour_cells . end ( ) ) ;
best_cell_idx = i ;
}
}
}
}
}
if ( cell ) {
memcpy ( cell , & known_cells [ best_cell_idx ] . phy_cell , sizeof ( srslte_cell_t ) ) ;
std : : sort ( neighbour_cells . begin ( ) , neighbour_cells . end ( ) , sort_rsrp ) ;
char ordered [ 512 ] ;
int n = 0 ;
n + = snprintf ( ordered , 512 , " [pci=%d, rsrsp=%.2f " , neighbour_cells [ 0 ] - > phy_cell . id , neighbour_cells [ 0 ] - > rsrp ) ;
for ( uint32_t i = 1 ; i < neighbour_cells . size ( ) ; i + + ) {
n + = snprintf ( & ordered [ n ] , 512 - n , " | pci=%d, rsrp=%.2f " , neighbour_cells [ i ] - > phy_cell . id , neighbour_cells [ i ] - > rsrp ) ;
}
}
return best_cell_idx ;
rrc_log - > info ( " Sorted neighbour cells: %s] \n " , ordered ) ;
}
}
rrc : : cell_t * rrc : : add_new_cell ( uint32_t earfcn , srslte_cell_t phy_cell , float rsrp ) {
bool rrc : : add_neighbour_cell ( cell_t * new_cell ) {
if ( earfcn = = 0 ) {
bool ret = false ;
return NULL ;
if ( neighbour_cells . size ( ) < NOF_NEIGHBOUR_CELLS - 1 ) {
ret = true ;
} else if ( ! neighbour_cells [ neighbour_cells . size ( ) - 1 ] - > greater ( new_cell ) ) {
// Delete old one
delete neighbour_cells [ neighbour_cells . size ( ) - 1 ] ;
neighbour_cells . erase ( std : : remove ( neighbour_cells . begin ( ) , neighbour_cells . end ( ) , neighbour_cells [ neighbour_cells . size ( ) - 1 ] ) , neighbour_cells . end ( ) ) ;
ret = true ;
}
}
int idx = find_cell_idx ( earfcn , phy_cell . id ) ;
if ( ret ) {
if ( idx > = 0 ) {
neighbour_cells . push_back ( new_cell ) ;
known_cells [ idx ] . rsrp = rsrp ;
return & known_cells [ idx ] ;
}
}
rrc_log - > info ( " Added neighbour cell EARFCN=%d, PCI=%d, nof_neighbours=%d \n " ,
new_cell - > earfcn , new_cell - > phy_cell . id , neighbour_cells . size ( ) ) ;
sort_neighbour_cells ( ) ;
return ret ;
}
// if does not exist, find empty slot
// If only neighbour PCI is provided, copy full cell from serving cell
int i = 0 ;
bool rrc : : add_neighbour_cell ( uint32_t earfcn , uint32_t pci , float rsrp ) {
while ( i < MAX_KNOWN_CELLS & & known_cells [ i ] . earfcn ) {
srslte_cell_t serving_phy ;
i + + ;
serving_phy = serving_cell - > phy_cell ;
}
serving_phy . id = pci ;
if ( i = = MAX_KNOWN_CELLS ) {
return add_neighbour_cell ( earfcn , serving_phy , rsrp ) ;
rrc_log - > error ( " Can't add more cells \n " ) ;
}
return NULL ;
bool rrc : : add_neighbour_cell ( uint32_t earfcn , srslte_cell_t phy_cell , float rsrp ) {
if ( earfcn = = 0 ) {
earfcn = serving_cell - > earfcn ;
}
}
known_cells [ i ] . phy_cell = phy_cell ;
// First check if already exists
known_cells [ i ] . rsrp = rsrp ;
int cell_idx = find_neighbour_cell ( earfcn , phy_cell . id ) ;
known_cells [ i ] . earfcn = earfcn ;
known_cells [ i ] . has_valid_sib1 = false ;
known_cells [ i ] . has_valid_sib2 = false ;
known_cells [ i ] . has_valid_sib3 = false ;
return & known_cells [ i ] ;
}
void rrc : : add_neighbour_cell ( uint32_t earfcn , uint32_t pci , float rsrp ) {
rrc_log - > info ( " Adding PCI=%d, earfcn=%d, cell_idx=%d \n " , phy_cell . id , earfcn , cell_idx ) ;
int idx = find_cell_idx ( earfcn , pci ) ;
if ( idx > = 0 ) {
// If exists, update RSRP, sort again and return
known_cells [ idx ] . rsrp = rsrp ;
if ( cell_idx > = 0 ) {
return ;
neighbour_cells [ cell_idx ] - > rsrp = rsrp ;
sort_neighbour_cells ( ) ;
return true ;
}
}
rrc_log - > info ( " Added neighbour cell earfcn=%d, pci=%d, rsrp=%f \n " , earfcn , pci , rsrp ) ;
// If not, create a new one
cell_t * new_cell = new cell_t ( phy_cell , earfcn , rsrp ) ;
srslte_cell_t cell ;
return add_neighbour_cell ( new_cell ) ;
cell = current_cell - > phy_cell ;
cell . id = pci ;
add_new_cell ( earfcn , cell , rsrp ) ;
}
}
int rrc : : find_ cell_idx ( uint32_t earfcn , uint32_t pci ) {
int rrc : : find_neighbour_cell ( uint32_t earfcn , uint32_t pci ) {
for ( uint32_t i = 0 ; i < MAX_KNOWN_CELLS ; i + + ) {
for ( uint32_t i = 0 ; i < neighbour_cells. size ( ) ; i + + ) {
if ( earfcn = = known_cells [ i ] . earfcn & & pci = = known_cells [ i ] . phy_cell . id ) {
if ( neighbour_cells[ i ] - > equals ( earfcn , pci ) ) {
return ( int ) i ;
return ( int ) i ;
}
}
}
}
@ -720,24 +771,28 @@ float rrc::get_squal(float Qqualmeas) {
*
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Detection of physical layer problems (5.3.11.1)
// Detection of physical layer problems in RRC_CONNECTED (5.3.11.1)
void rrc : : out_of_sync ( ) {
void rrc : : out_of_sync ( ) {
current_cell - > in_sync = false ;
serving_cell - > in_sync = false ;
if ( ! mac_timers - > timer_get ( t311 ) - > is_running ( ) & & ! mac_timers - > timer_get ( t310 ) - > is_running ( ) ) {
if ( state = = RRC_STATE_CONNECTED ) {
n310_cnt + + ;
if ( ! mac_timers - > timer_get ( t311 ) - > is_running ( ) & & ! mac_timers - > timer_get ( t310 ) - > is_running ( ) ) {
if ( n310_cnt = = N310 ) {
n310_cnt + + ;
mac_timers - > timer_get ( t310 ) - > reset ( ) ;
if ( n310_cnt = = N310 ) {
mac_timers - > timer_get ( t310 ) - > run ( ) ;
mac_timers - > timer_get ( t310 ) - > reset ( ) ;
n310_cnt = 0 ;
mac_timers - > timer_get ( t310 ) - > run ( ) ;
phy - > sync_reset ( ) ;
n310_cnt = 0 ;
rrc_log - > info ( " Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer \n " , N310 ) ;
phy - > sync_reset ( ) ;
rrc_log - > info ( " Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer \n " , N310 ) ;
}
}
}
} else {
phy - > sync_reset ( ) ;
}
}
}
}
// Recovery of physical layer problems (5.3.11.2)
// Recovery of physical layer problems (5.3.11.2)
void rrc : : in_sync ( ) {
void rrc : : in_sync ( ) {
current _cell- > in_sync = true ;
serving _cell- > in_sync = true ;
if ( mac_timers - > timer_get ( t310 ) - > is_running ( ) ) {
if ( mac_timers - > timer_get ( t310 ) - > is_running ( ) ) {
n311_cnt + + ;
n311_cnt + + ;
if ( n311_cnt = = N311 ) {
if ( n311_cnt = = N311 ) {
@ -861,7 +916,7 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
uint8_t * msg_ptr = varShortMAC ;
uint8_t * msg_ptr = varShortMAC ;
// ASN.1 encode byte-aligned VarShortMAC-Input
// ASN.1 encode byte-aligned VarShortMAC-Input
liblte_rrc_pack_cell_identity_ie ( current _cell- > sib1 . cell_id , & msg_ptr ) ;
liblte_rrc_pack_cell_identity_ie ( serving _cell- > sib1 . cell_id , & msg_ptr ) ;
msg_ptr = & varShortMAC [ 4 ] ;
msg_ptr = & varShortMAC [ 4 ] ;
liblte_rrc_pack_phys_cell_id_ie ( phy - > get_current_pci ( ) , & msg_ptr ) ;
liblte_rrc_pack_phys_cell_id_ie ( phy - > get_current_pci ( ) , & msg_ptr ) ;
msg_ptr = & varShortMAC [ 4 + 2 ] ;
msg_ptr = & varShortMAC [ 4 + 2 ] ;
@ -869,7 +924,7 @@ void rrc::send_con_restablish_request(LIBLTE_RRC_CON_REEST_REQ_CAUSE_ENUM cause,
srslte_bit_pack_vector ( varShortMAC , varShortMAC_packed , ( 4 + 2 + 4 ) * 8 ) ;
srslte_bit_pack_vector ( varShortMAC , varShortMAC_packed , ( 4 + 2 + 4 ) * 8 ) ;
rrc_log - > info ( " Generated varShortMAC: cellId=0x%x, PCI=%d, rnti=%d \n " ,
rrc_log - > info ( " Generated varShortMAC: cellId=0x%x, PCI=%d, rnti=%d \n " ,
current _cell- > sib1 . cell_id , phy - > get_current_pci ( ) , crnti ) ;
serving _cell- > sib1 . cell_id , phy - > get_current_pci ( ) , crnti ) ;
// Compute MAC-I
// Compute MAC-I
uint8_t mac_key [ 4 ] ;
uint8_t mac_key [ 4 ] ;
@ -958,6 +1013,8 @@ void rrc::send_con_setup_complete(byte_buffer_t *nas_msg) {
memcpy ( ul_dcch_msg . msg . rrc_con_setup_complete . dedicated_info_nas . msg , nas_msg - > msg , nas_msg - > N_bytes ) ;
memcpy ( ul_dcch_msg . msg . rrc_con_setup_complete . dedicated_info_nas . msg , nas_msg - > msg , nas_msg - > N_bytes ) ;
ul_dcch_msg . msg . rrc_con_setup_complete . dedicated_info_nas . N_bytes = nas_msg - > N_bytes ;
ul_dcch_msg . msg . rrc_con_setup_complete . dedicated_info_nas . N_bytes = nas_msg - > N_bytes ;
pool - > deallocate ( nas_msg ) ;
send_ul_dcch_msg ( ) ;
send_ul_dcch_msg ( ) ;
}
}
@ -995,9 +1052,9 @@ bool rrc::ho_prepare() {
if ( pending_mob_reconf ) {
if ( pending_mob_reconf ) {
rrc_log - > info ( " Processing HO command to target PCell=%d \n " , mob_reconf . mob_ctrl_info . target_pci ) ;
rrc_log - > info ( " Processing HO command to target PCell=%d \n " , mob_reconf . mob_ctrl_info . target_pci ) ;
int cell_idx = find_cell_idx ( phy - > get_current_earfcn ( ) , mob_reconf . mob_ctrl_info . target_pci ) ;
int target_cell_idx = find_neighbour_cell ( serving_cell - > earfcn , mob_reconf . mob_ctrl_info . target_pci ) ;
if ( cell_idx < 0 ) {
if ( target_ cell_idx < 0 ) {
rrc_log - > error ( " Could not find target cell pci=%d\n " , mob_reconf . mob_ctrl_info . target_pci ) ;
rrc_log - > error ( " Could not find target cell earfcn=%d, pci=%d\n " , serving_cell - > earfcn , mob_reconf . mob_ctrl_info . target_pci ) ;
return false ;
return false ;
}
}
@ -1005,16 +1062,12 @@ bool rrc::ho_prepare() {
mac_timers - > timer_get ( t310 ) - > stop ( ) ;
mac_timers - > timer_get ( t310 ) - > stop ( ) ;
mac_timers - > timer_get ( t304 ) - > set ( this , liblte_rrc_t304_num [ mob_reconf . mob_ctrl_info . t304 ] ) ;
mac_timers - > timer_get ( t304 ) - > set ( this , liblte_rrc_t304_num [ mob_reconf . mob_ctrl_info . t304 ] ) ;
if ( mob_reconf . mob_ctrl_info . carrier_freq_eutra_present & &
if ( mob_reconf . mob_ctrl_info . carrier_freq_eutra_present & &
mob_reconf . mob_ctrl_info . carrier_freq_eutra . dl_carrier_freq ! = current _cell- > earfcn ) {
mob_reconf . mob_ctrl_info . carrier_freq_eutra . dl_carrier_freq ! = serving _cell- > earfcn ) {
rrc_log - > warning ( " Received mobilityControlInfo for inter-frequency handover \n " ) ;
rrc_log - > warning ( " Received mobilityControlInfo for inter-frequency handover \n " ) ;
}
}
// Save cell and current configuration
// Save serving cell and current configuration
ho_src_cell_idx = find_cell_idx ( phy - > get_current_earfcn ( ) , phy - > get_current_pci ( ) ) ;
ho_src_cell = * serving_cell ;
if ( ho_src_cell_idx < 0 ) {
rrc_log - > error ( " Source cell not found in known cells. Reconnecting to cell 0 in case of failure \n " ) ;
ho_src_cell_idx = 0 ;
}
phy - > get_config ( & ho_src_phy_cfg ) ;
phy - > get_config ( & ho_src_phy_cfg ) ;
mac - > get_config ( & ho_src_mac_cfg ) ;
mac - > get_config ( & ho_src_mac_cfg ) ;
mac_interface_rrc : : ue_rnti_t uernti ;
mac_interface_rrc : : ue_rnti_t uernti ;
@ -1031,9 +1084,9 @@ bool rrc::ho_prepare() {
mac - > set_ho_rnti ( mob_reconf . mob_ctrl_info . new_ue_id , mob_reconf . mob_ctrl_info . target_pci ) ;
mac - > set_ho_rnti ( mob_reconf . mob_ctrl_info . new_ue_id , mob_reconf . mob_ctrl_info . target_pci ) ;
apply_rr_config_common_dl ( & mob_reconf . mob_ctrl_info . rr_cnfg_common ) ;
apply_rr_config_common_dl ( & mob_reconf . mob_ctrl_info . rr_cnfg_common ) ;
rrc_log - > info ( " Selecting new cell pci=%d \n " , known_cells[ cell_idx ] . phy_cell . id ) ;
rrc_log - > info ( " Selecting new cell pci=%d \n " , neighbour_cells[ target_cell_idx ] - > phy_cell . id ) ;
if ( ! phy - > cell_handover ( known_cells[ cell_idx ] . phy_cell ) ) {
if ( ! phy - > cell_handover ( neighbour_cells[ target_cell_idx ] - > phy_cell ) ) {
rrc_log - > error ( " Could not synchronize with target cell pci=%d \n " , known_cells[ cell_idx ] . phy_cell . id ) ;
rrc_log - > error ( " Could not synchronize with target cell pci=%d \n " , neighbour_cells[ target_cell_idx ] - > phy_cell . id ) ;
return false ;
return false ;
}
}
@ -1108,8 +1161,8 @@ void rrc::ho_ra_completed(bool ra_successful) {
void rrc : : ho_failed ( ) {
void rrc : : ho_failed ( ) {
// Instruct PHY to resync with source PCI
// Instruct PHY to resync with source PCI
if ( ! phy - > cell_handover ( known_cells[ ho_src_cell_idx] . phy_cell ) ) {
if ( ! phy - > cell_handover ( ho_src_cell. phy_cell ) ) {
rrc_log - > error ( " Could not synchronize with target cell pci=%d \n " , known_cells[ ho_src_cell_idx] . phy_cell . id ) ;
rrc_log - > error ( " Could not synchronize with target cell pci=%d \n " , ho_src_cell. phy_cell . id ) ;
return ;
return ;
}
}
@ -1163,14 +1216,37 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGU
}
}
}
}
/* Actions upon reception of RRCConnectionRelease 5.3.8.3 */
/* Actions upon reception of RRCConnectionRelease 5.3.8.3 */
void rrc : : rrc_connection_release ( ) {
void rrc : : rrc_connection_release ( ) {
// Save idleModeMobilityControlInfo, etc.
// Save idleModeMobilityControlInfo, etc.
state = RRC_STATE_LEAVE_CONNECTED ;
state = RRC_STATE_LEAVE_CONNECTED ;
rrc_log - > console ( " Received RRC Connection Release \n " ) ;
rrc_log - > console ( " Received RRC Connection Release \n " ) ;
}
}
/* Actions upon leaving RRC_CONNECTED 5.3.12 */
void rrc : : leave_connected ( )
{
rrc_log - > console ( " RRC IDLE \n " ) ;
rrc_log - > info ( " Leaving RRC_CONNECTED state \n " ) ;
drb_up = false ;
measurements . reset ( ) ;
pdcp - > reset ( ) ;
rlc - > reset ( ) ;
phy - > reset ( ) ;
mac - > reset ( ) ;
set_phy_default ( ) ;
set_mac_default ( ) ;
mac_timers - > timer_get ( t301 ) - > stop ( ) ;
mac_timers - > timer_get ( t310 ) - > stop ( ) ;
mac_timers - > timer_get ( t311 ) - > stop ( ) ;
mac_timers - > timer_get ( t304 ) - > stop ( ) ;
if ( phy - > sync_status ( ) ) {
// Instruct MAC to look for P-RNTI
mac - > pcch_start_rx ( ) ;
// Instruct PHY to measure serving cell for cell reselection
phy - > meas_start ( phy - > get_current_earfcn ( ) , phy - > get_current_pci ( ) ) ;
}
}
@ -1211,24 +1287,24 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
rrc_log - > info ( " Processing SIB: %d \n " , liblte_rrc_sys_info_block_type_num [ dlsch_msg . sibs [ i ] . sib_type ] ) ;
rrc_log - > info ( " Processing SIB: %d \n " , liblte_rrc_sys_info_block_type_num [ dlsch_msg . sibs [ i ] . sib_type ] ) ;
if ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 = = dlsch_msg . sibs [ i ] . sib_type & & SI_ACQUIRE_SIB1 = = si_acquire_state ) {
if ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1 = = dlsch_msg . sibs [ i ] . sib_type & & SI_ACQUIRE_SIB1 = = si_acquire_state ) {
memcpy ( & current _cell- > sib1 , & dlsch_msg . sibs [ i ] . sib . sib1 , sizeof ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT ) ) ;
memcpy ( & serving _cell- > sib1 , & dlsch_msg . sibs [ i ] . sib . sib1 , sizeof ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT ) ) ;
current _cell- > has_valid_sib1 = true ;
serving _cell- > has_valid_sib1 = true ;
handle_sib1 ( ) ;
handle_sib1 ( ) ;
} else if ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 = = dlsch_msg . sibs [ i ] . sib_type & & ! current _cell- > has_valid_sib2 ) {
} else if ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2 = = dlsch_msg . sibs [ i ] . sib_type & & ! serving _cell- > has_valid_sib2 ) {
memcpy ( & current _cell- > sib2 , & dlsch_msg . sibs [ i ] . sib . sib2 , sizeof ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT ) ) ;
memcpy ( & serving _cell- > sib2 , & dlsch_msg . sibs [ i ] . sib . sib2 , sizeof ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT ) ) ;
current _cell- > has_valid_sib2 = true ;
serving _cell- > has_valid_sib2 = true ;
handle_sib2 ( ) ;
handle_sib2 ( ) ;
} else if ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 = = dlsch_msg . sibs [ i ] . sib_type & & ! current _cell- > has_valid_sib3 ) {
} else if ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3 = = dlsch_msg . sibs [ i ] . sib_type & & ! serving _cell- > has_valid_sib3 ) {
memcpy ( & current _cell- > sib3 , & dlsch_msg . sibs [ i ] . sib . sib3 , sizeof ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT ) ) ;
memcpy ( & serving _cell- > sib3 , & dlsch_msg . sibs [ i ] . sib . sib3 , sizeof ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT ) ) ;
current _cell- > has_valid_sib3 = true ;
serving _cell- > has_valid_sib3 = true ;
handle_sib3 ( ) ;
handle_sib3 ( ) ;
} else if ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 = = dlsch_msg . sibs [ i ] . sib_type & & ! current _cell- > has_valid_sib13 ) {
} else if ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13 = = dlsch_msg . sibs [ i ] . sib_type & & ! serving _cell- > has_valid_sib13 ) {
memcpy ( & current _cell- > sib13 , & dlsch_msg . sibs [ 0 ] . sib . sib13 , sizeof ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT ) ) ;
memcpy ( & serving _cell- > sib13 , & dlsch_msg . sibs [ 0 ] . sib . sib13 , sizeof ( LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT ) ) ;
current _cell- > has_valid_sib13 = true ;
serving _cell- > has_valid_sib13 = true ;
handle_sib13 ( ) ;
handle_sib13 ( ) ;
}
}
}
}
if ( current _cell- > has_valid_sib2 ) {
if ( serving _cell- > has_valid_sib2 ) {
sysinfo_index + + ;
sysinfo_index + + ;
}
}
}
}
@ -1236,16 +1312,16 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
void rrc : : handle_sib1 ( )
void rrc : : handle_sib1 ( )
{
{
rrc_log - > info ( " SIB1 received, CellID=%d, si_window=%d, sib2_period=%d \n " ,
rrc_log - > info ( " SIB1 received, CellID=%d, si_window=%d, sib2_period=%d \n " ,
current _cell- > sib1 . cell_id & 0xfff ,
serving _cell- > sib1 . cell_id & 0xfff ,
liblte_rrc_si_window_length_num [ current _cell- > sib1 . si_window_length ] ,
liblte_rrc_si_window_length_num [ serving _cell- > sib1 . si_window_length ] ,
liblte_rrc_si_periodicity_num [ current _cell- > sib1 . sched_info [ 0 ] . si_periodicity ] ) ;
liblte_rrc_si_periodicity_num [ serving _cell- > sib1 . sched_info [ 0 ] . si_periodicity ] ) ;
// Print SIB scheduling info
// Print SIB scheduling info
uint32_t i , j ;
uint32_t i , j ;
for ( i = 0 ; i < current _cell- > sib1 . N_sched_info ; i + + ) {
for ( i = 0 ; i < serving _cell- > sib1 . N_sched_info ; i + + ) {
for ( j = 0 ; j < current _cell- > sib1 . sched_info [ i ] . N_sib_mapping_info ; j + + ) {
for ( j = 0 ; j < serving _cell- > sib1 . sched_info [ i ] . N_sib_mapping_info ; j + + ) {
LIBLTE_RRC_SIB_TYPE_ENUM t = current _cell- > sib1 . sched_info [ i ] . sib_mapping_info [ j ] . sib_type ;
LIBLTE_RRC_SIB_TYPE_ENUM t = serving _cell- > sib1 . sched_info [ i ] . sib_mapping_info [ j ] . sib_type ;
LIBLTE_RRC_SI_PERIODICITY_ENUM p = current _cell- > sib1 . sched_info [ i ] . si_periodicity ;
LIBLTE_RRC_SI_PERIODICITY_ENUM p = serving _cell- > sib1 . sched_info [ i ] . si_periodicity ;
rrc_log - > debug ( " SIB scheduling info, sib_type=%d, si_periodicity=%d \n " ,
rrc_log - > debug ( " SIB scheduling info, sib_type=%d, si_periodicity=%d \n " ,
liblte_rrc_sib_type_num [ t ] ,
liblte_rrc_sib_type_num [ t ] ,
liblte_rrc_si_periodicity_num [ p ] ) ;
liblte_rrc_si_periodicity_num [ p ] ) ;
@ -1253,16 +1329,16 @@ void rrc::handle_sib1()
}
}
// Set TDD Config
// Set TDD Config
if ( current _cell- > sib1 . tdd ) {
if ( serving _cell- > sib1 . tdd ) {
phy - > set_config_tdd ( & current _cell- > sib1 . tdd_cnfg ) ;
phy - > set_config_tdd ( & serving _cell- > sib1 . tdd_cnfg ) ;
}
}
current _cell- > has_valid_sib1 = true ;
serving _cell- > has_valid_sib1 = true ;
// Send PLMN and TAC to NAS
// Send PLMN and TAC to NAS
std : : stringstream ss ;
std : : stringstream ss ;
for ( uint32_t i = 0 ; i < current _cell- > sib1 . N_plmn_ids ; i + + ) {
for ( uint32_t i = 0 ; i < serving _cell- > sib1 . N_plmn_ids ; i + + ) {
nas - > plmn_found ( current _cell- > sib1 . plmn_id [ i ] . id , current _cell- > sib1 . tracking_area_code ) ;
nas - > plmn_found ( serving _cell- > sib1 . plmn_id [ i ] . id , serving _cell- > sib1 . tracking_area_code ) ;
}
}
// Jump to next state
// Jump to next state
@ -1285,7 +1361,7 @@ void rrc::handle_sib2()
{
{
rrc_log - > info ( " SIB2 received \n " ) ;
rrc_log - > info ( " SIB2 received \n " ) ;
apply_sib2_configs ( & current _cell- > sib2 ) ;
apply_sib2_configs ( & serving _cell- > sib2 ) ;
}
}
@ -1293,7 +1369,7 @@ void rrc::handle_sib3()
{
{
rrc_log - > info ( " SIB3 received \n " ) ;
rrc_log - > info ( " SIB3 received \n " ) ;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT * sib3 = & current _cell- > sib3 ;
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT * sib3 = & serving _cell- > sib3 ;
// cellReselectionInfoCommon
// cellReselectionInfoCommon
cell_resel_cfg . q_hyst = liblte_rrc_q_hyst_num [ sib3 - > q_hyst ] ;
cell_resel_cfg . q_hyst = liblte_rrc_q_hyst_num [ sib3 - > q_hyst ] ;
@ -1315,9 +1391,9 @@ void rrc::handle_sib13()
{
{
rrc_log - > info ( " SIB13 received \n " ) ;
rrc_log - > info ( " SIB13 received \n " ) ;
// mac->set_config_mbsfn_sib13(& current _cell->sib13.mbsfn_area_info_list_r9[0],
// mac->set_config_mbsfn_sib13(& serving _cell->sib13.mbsfn_area_info_list_r9[0],
// current _cell->sib13.mbsfn_area_info_list_r9_size,
// serving _cell->sib13.mbsfn_area_info_list_r9_size,
// & current _cell->sib13.mbsfn_notification_config);
// & serving _cell->sib13.mbsfn_notification_config);
}
}
@ -1497,7 +1573,7 @@ void rrc::parse_dl_ccch(byte_buffer_t *pdu) {
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ :
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_REJ :
rrc_log - > info ( " Connection Reject received. Wait time: %d \n " ,
rrc_log - > info ( " Connection Reject received. Wait time: %d \n " ,
dl_ccch_msg . msg . rrc_con_rej . wait_time ) ;
dl_ccch_msg . msg . rrc_con_rej . wait_time ) ;
state = RRC_STATE_ ID LE;
state = RRC_STATE_ LEAVE_CONNECTED ;
break ;
break ;
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP :
case LIBLTE_RRC_DL_CCCH_MSG_TYPE_RRC_CON_SETUP :
rrc_log - > info ( " Connection Setup received \n " ) ;
rrc_log - > info ( " Connection Setup received \n " ) ;
@ -1605,7 +1681,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) {
*
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void rrc : : enable_capabilities ( ) {
void rrc : : enable_capabilities ( ) {
bool enable_ul_64 = args . ue_category > = 5 & & current _cell- > sib2 . rr_config_common_sib . pusch_cnfg . enable_64_qam ;
bool enable_ul_64 = args . ue_category > = 5 & & serving _cell- > sib2 . rr_config_common_sib . pusch_cnfg . enable_64_qam ;
rrc_log - > info ( " %s 64QAM PUSCH \n " , enable_ul_64 ? " Enabling " : " Disabling " ) ;
rrc_log - > info ( " %s 64QAM PUSCH \n " , enable_ul_64 ? " Enabling " : " Disabling " ) ;
phy - > set_config_64qam_en ( enable_ul_64 ) ;
phy - > set_config_64qam_en ( enable_ul_64 ) ;
}
}
@ -2270,14 +2346,20 @@ void rrc::rrc_meas::L3_filter(meas_value_t *value, float values[NOF_MEASUREMENTS
void rrc : : rrc_meas : : new_phy_meas ( uint32_t earfcn , uint32_t pci , float rsrp , float rsrq , uint32_t tti )
void rrc : : rrc_meas : : new_phy_meas ( uint32_t earfcn , uint32_t pci , float rsrp , float rsrq , uint32_t tti )
{
{
float values [ NOF_MEASUREMENTS ] = { rsrp , rsrq } ;
float values [ NOF_MEASUREMENTS ] = { rsrp , rsrq } ;
// This indicates serving cell
// This indicates serving cell
if ( earfcn = = 0 ) {
if ( parent- > serving_cell - > equals ( earfcn , pci ) ) {
log_h - > info ( " MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d \n " , rsrp , rsrq , tti ) ;
log_h - > info ( " MEAS: New measurement serving cell, rsrp=%f, rsrq=%f, tti=%d \n " , rsrp , rsrq , tti ) ;
L3_filter ( & pcell_measurement , values ) ;
L3_filter ( & pcell_measurement , values ) ;
// Update serving cell measurement
parent - > serving_cell - > rsrp = rsrp ;
} else {
} else {
// Add to known cells
// Add to list of neighbour cells
parent - > add_neighbour_cell ( earfcn , pci , rsrp ) ;
parent - > add_neighbour_cell ( earfcn , pci , rsrp ) ;
log_h - > info ( " MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d \n " , earfcn , pci , rsrp , rsrq , tti ) ;
log_h - > info ( " MEAS: New measurement earfcn=%d, pci=%d, rsrp=%f, rsrq=%f, tti=%d \n " , earfcn , pci , rsrp , rsrq , tti ) ;
@ -2297,8 +2379,6 @@ void rrc::rrc_meas::new_phy_meas(uint32_t earfcn, uint32_t pci, float rsrp, floa
return ;
return ;
}
}
}
}
parent - > rrc_log - > warning ( " MEAS: Received measurement from unknown EARFCN=%d \n " , earfcn ) ;
}
}
}
}
@ -2349,8 +2429,8 @@ void rrc::rrc_meas::generate_report(uint32_t meas_id)
report - > pcell_rsrp_result = value_to_range ( RSRP , pcell_measurement . ms [ RSRP ] ) ;
report - > pcell_rsrp_result = value_to_range ( RSRP , pcell_measurement . ms [ RSRP ] ) ;
report - > pcell_rsrq_result = value_to_range ( RSRQ , pcell_measurement . ms [ RSRQ ] ) ;
report - > pcell_rsrq_result = value_to_range ( RSRQ , pcell_measurement . ms [ RSRQ ] ) ;
log_h - > console ( " MEAS: Generate report MeasId=%d, rsrp=%f rsrq=%f\n " ,
log_h - > info ( " MEAS: Generate report MeasId=%d, nof_reports_send=%d, Pcell rsrp=%f rsrq=%f\n " ,
report - > meas_id , pcell_measurement. ms [ RSRP ] , pcell_measurement . ms [ RSRQ ] ) ;
report - > meas_id , m- > nof_reports_sent , pcell_measurement. ms [ RSRP ] , pcell_measurement . ms [ RSRQ ] ) ;
// TODO: report up to 8 best cells
// TODO: report up to 8 best cells
for ( std : : map < uint32_t , meas_value_t > : : iterator cell = m - > cell_values . begin ( ) ; cell ! = m - > cell_values . end ( ) ; + + cell )
for ( std : : map < uint32_t , meas_value_t > : : iterator cell = m - > cell_values . begin ( ) ; cell ! = m - > cell_values . end ( ) ; + + cell )
@ -2365,7 +2445,7 @@ void rrc::rrc_meas::generate_report(uint32_t meas_id)
rc - > meas_result . rsrp_result = value_to_range ( RSRP , cell - > second . ms [ RSRP ] ) ;
rc - > meas_result . rsrp_result = value_to_range ( RSRP , cell - > second . ms [ RSRP ] ) ;
rc - > meas_result . rsrq_result = value_to_range ( RSRQ , cell - > second . ms [ RSRQ ] ) ;
rc - > meas_result . rsrq_result = value_to_range ( RSRQ , cell - > second . ms [ RSRQ ] ) ;
log_h - > info ( " MEAS: Add neigh=%d, pci=%d, rsrp=%f, rsrq=%f\n " ,
log_h - > info ( " MEAS: Add ing to report neighbour =%d, pci=%d, rsrp=%f, rsrq=%f\n " ,
report - > meas_result_neigh_cells . eutra . n_result , rc - > phys_cell_id ,
report - > meas_result_neigh_cells . eutra . n_result , rc - > phys_cell_id ,
cell - > second . ms [ RSRP ] , cell - > second . ms [ RSRQ ] ) ;
cell - > second . ms [ RSRP ] , cell - > second . ms [ RSRQ ] ) ;
@ -2585,10 +2665,14 @@ void rrc::rrc_meas::remove_meas_report(uint32_t report_id) {
}
}
void rrc : : rrc_meas : : remove_meas_id ( uint32_t measId ) {
void rrc : : rrc_meas : : remove_meas_id ( uint32_t measId ) {
mac_timers - > timer_get ( active [ measId ] . periodic_timer ) - > stop ( ) ;
if ( active . count ( measId ) ) {
mac_timers - > timer_release_id ( active [ measId ] . periodic_timer ) ;
mac_timers - > timer_get ( active [ measId ] . periodic_timer ) - > stop ( ) ;
log_h - > info ( " MEAS: Removed measId=%d \n " , measId ) ;
mac_timers - > timer_release_id ( active [ measId ] . periodic_timer ) ;
active . erase ( measId ) ;
log_h - > info ( " MEAS: Removed measId=%d \n " , measId ) ;
active . erase ( measId ) ;
} else {
log_h - > warning ( " MEAS: Removing unexistent measId=%d \n " , measId ) ;
}
}
}
void rrc : : rrc_meas : : remove_meas_id ( std : : map < uint32_t , meas_t > : : iterator it ) {
void rrc : : rrc_meas : : remove_meas_id ( std : : map < uint32_t , meas_t > : : iterator it ) {
@ -2726,15 +2810,17 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg)
for ( uint32_t i = 0 ; i < cfg - > meas_id_to_add_mod_list . N_meas_id ; i + + ) {
for ( uint32_t i = 0 ; i < cfg - > meas_id_to_add_mod_list . N_meas_id ; i + + ) {
LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_STRUCT * measId = & cfg - > meas_id_to_add_mod_list . meas_id_list [ i ] ;
LIBLTE_RRC_MEAS_ID_TO_ADD_MOD_STRUCT * measId = & cfg - > meas_id_to_add_mod_list . meas_id_list [ i ] ;
// Stop the timer if the entry exists or create the timer if not
// Stop the timer if the entry exists or create the timer if not
bool is_new = false ;
if ( active . count ( measId - > meas_id ) ) {
if ( active . count ( measId - > meas_id ) ) {
mac_timers - > timer_get ( active [ measId - > meas_id ] . periodic_timer ) - > stop ( ) ;
mac_timers - > timer_get ( active [ measId - > meas_id ] . periodic_timer ) - > stop ( ) ;
} else {
} else {
is_new = true ;
active [ measId - > meas_id ] . periodic_timer = mac_timers - > timer_get_unique_id ( ) ;
active [ measId - > meas_id ] . periodic_timer = mac_timers - > timer_get_unique_id ( ) ;
}
}
active [ measId - > meas_id ] . object_id = measId - > meas_obj_id ;
active [ measId - > meas_id ] . object_id = measId - > meas_obj_id ;
active [ measId - > meas_id ] . report_id = measId - > rep_cnfg_id ;
active [ measId - > meas_id ] . report_id = measId - > rep_cnfg_id ;
log_h - > info ( " MEAS: Added measId=%d, measObjectId=%d, reportConfigId=%d\n " ,
log_h - > info ( " MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d\n " ,
measId- > meas_id , measId - > meas_obj_id , measId - > rep_cnfg_id ) ;
is_new? " Added " : " Updated " , measId- > meas_id , measId - > meas_obj_id , measId - > rep_cnfg_id ) ;
}
}
}
}